diff options
-rw-r--r-- | arch/s390/include/asm/hugetlb.h | 5 | ||||
-rw-r--r-- | arch/s390/mm/gmap.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/hugetlbpage.c | 24 |
3 files changed, 30 insertions, 1 deletions
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h index 9c5fc50204dd..2d1afa58a4b6 100644 --- a/arch/s390/include/asm/hugetlb.h +++ b/arch/s390/include/asm/hugetlb.h | |||
@@ -37,7 +37,10 @@ static inline int prepare_hugepage_range(struct file *file, | |||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | #define arch_clear_hugepage_flags(page) do { } while (0) | 40 | static inline void arch_clear_hugepage_flags(struct page *page) |
41 | { | ||
42 | clear_bit(PG_arch_1, &page->flags); | ||
43 | } | ||
41 | 44 | ||
42 | static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr, | 45 | static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr, |
43 | pte_t *ptep, unsigned long sz) | 46 | pte_t *ptep, unsigned long sz) |
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index a8e32e60226b..a6738c0c4499 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c | |||
@@ -2553,6 +2553,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr, | |||
2553 | { | 2553 | { |
2554 | pmd_t *pmd = (pmd_t *)pte; | 2554 | pmd_t *pmd = (pmd_t *)pte; |
2555 | unsigned long start, end; | 2555 | unsigned long start, end; |
2556 | struct page *page = pmd_page(*pmd); | ||
2556 | 2557 | ||
2557 | /* | 2558 | /* |
2558 | * The write check makes sure we do not set a key on shared | 2559 | * The write check makes sure we do not set a key on shared |
@@ -2567,6 +2568,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr, | |||
2567 | start = pmd_val(*pmd) & HPAGE_MASK; | 2568 | start = pmd_val(*pmd) & HPAGE_MASK; |
2568 | end = start + HPAGE_SIZE - 1; | 2569 | end = start + HPAGE_SIZE - 1; |
2569 | __storage_key_init_range(start, end); | 2570 | __storage_key_init_range(start, end); |
2571 | set_bit(PG_arch_1, &page->flags); | ||
2570 | return 0; | 2572 | return 0; |
2571 | } | 2573 | } |
2572 | 2574 | ||
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index e804090f4470..b0246c705a19 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c | |||
@@ -123,6 +123,29 @@ static inline pte_t __rste_to_pte(unsigned long rste) | |||
123 | return pte; | 123 | return pte; |
124 | } | 124 | } |
125 | 125 | ||
126 | static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste) | ||
127 | { | ||
128 | struct page *page; | ||
129 | unsigned long size, paddr; | ||
130 | |||
131 | if (!mm_uses_skeys(mm) || | ||
132 | rste & _SEGMENT_ENTRY_INVALID) | ||
133 | return; | ||
134 | |||
135 | if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) { | ||
136 | page = pud_page(__pud(rste)); | ||
137 | size = PUD_SIZE; | ||
138 | paddr = rste & PUD_MASK; | ||
139 | } else { | ||
140 | page = pmd_page(__pmd(rste)); | ||
141 | size = PMD_SIZE; | ||
142 | paddr = rste & PMD_MASK; | ||
143 | } | ||
144 | |||
145 | if (!test_and_set_bit(PG_arch_1, &page->flags)) | ||
146 | __storage_key_init_range(paddr, paddr + size - 1); | ||
147 | } | ||
148 | |||
126 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | 149 | void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, |
127 | pte_t *ptep, pte_t pte) | 150 | pte_t *ptep, pte_t pte) |
128 | { | 151 | { |
@@ -137,6 +160,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |||
137 | rste |= _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE; | 160 | rste |= _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE; |
138 | else | 161 | else |
139 | rste |= _SEGMENT_ENTRY_LARGE; | 162 | rste |= _SEGMENT_ENTRY_LARGE; |
163 | clear_huge_pte_skeys(mm, rste); | ||
140 | pte_val(*ptep) = rste; | 164 | pte_val(*ptep) = rste; |
141 | } | 165 | } |
142 | 166 | ||