Merge tag 'locks-v4.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton...
[sfrench/cifs-2.6.git] / arch / s390 / mm / hugetlbpage.c
index e804090f4470fce93446cdde89cd5170d6c25644..b0246c705a192aac8462ee99f7a7e32081a9c6ce 100644 (file)
@@ -123,6 +123,29 @@ static inline pte_t __rste_to_pte(unsigned long rste)
        return pte;
 }
 
+static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
+{
+       struct page *page;
+       unsigned long size, paddr;
+
+       if (!mm_uses_skeys(mm) ||
+           rste & _SEGMENT_ENTRY_INVALID)
+               return;
+
+       if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
+               page = pud_page(__pud(rste));
+               size = PUD_SIZE;
+               paddr = rste & PUD_MASK;
+       } else {
+               page = pmd_page(__pmd(rste));
+               size = PMD_SIZE;
+               paddr = rste & PMD_MASK;
+       }
+
+       if (!test_and_set_bit(PG_arch_1, &page->flags))
+               __storage_key_init_range(paddr, paddr + size - 1);
+}
+
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                     pte_t *ptep, pte_t pte)
 {
@@ -137,6 +160,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
                rste |= _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE;
        else
                rste |= _SEGMENT_ENTRY_LARGE;
+       clear_huge_pte_skeys(mm, rste);
        pte_val(*ptep) = rste;
 }