aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/hugetlb.h5
-rw-r--r--arch/s390/mm/gmap.c2
-rw-r--r--arch/s390/mm/hugetlbpage.c24
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) 40static inline void arch_clear_hugepage_flags(struct page *page)
41{
42 clear_bit(PG_arch_1, &page->flags);
43}
41 44
42static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr, 45static 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
126static 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
126void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, 149void 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