diff options
Diffstat (limited to 'arch/s390/mm/hugetlbpage.c')
| -rw-r--r-- | arch/s390/mm/hugetlbpage.c | 24 |
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 | ||
| 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 | ||
