aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/hugetlbpage.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/hugetlbpage.c')
-rw-r--r--arch/s390/mm/hugetlbpage.c24
1 files changed, 24 insertions, 0 deletions
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