From: Gerald Schaefer <gerald.schae...@de.ibm.com>

[ Upstream commit ac8372f3b4e41015549b331a4f350224661e7fc6 ]

On s390, the layout of normal and large ptes (i.e. pmds/puds) differs.
Therefore, set_huge_pte_at() does a conversion from a normal pte to
the corresponding large pmd/pud. So, when converting an empty pte, this
should result in an empty pmd/pud, which would return true for
pmd/pud_none().

However, after conversion we also mark the pmd/pud as large, and
therefore present. For empty ptes, this will result in an empty pmd/pud
that is also marked as large, and pmd/pud_none() would not return true.

There is currently no issue with this behaviour, as set_huge_pte_at()
does not seem to be called for empty ptes. It would be valid though, so
let's fix this by not marking empty ptes as large in set_huge_pte_at().

This was found by testing a patch from from Anshuman Khandual, which is
currently discussed on LKML ("mm/debug: Add more arch page table helper
tests").

Signed-off-by: Gerald Schaefer <gerald.schae...@de.ibm.com>
Signed-off-by: Vasily Gorbik <g...@linux.ibm.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 arch/s390/mm/hugetlbpage.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 5674710a4841..7dfae86afa47 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -159,10 +159,13 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long 
addr,
                rste &= ~_SEGMENT_ENTRY_NOEXEC;
 
        /* Set correct table type for 2G hugepages */
-       if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
-               rste |= _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE;
-       else
+       if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == 
_REGION_ENTRY_TYPE_R3) {
+               if (likely(pte_present(pte)))
+                       rste |= _REGION3_ENTRY_LARGE;
+               rste |= _REGION_ENTRY_TYPE_R3;
+       } else if (likely(pte_present(pte)))
                rste |= _SEGMENT_ENTRY_LARGE;
+
        clear_huge_pte_skeys(mm, rste);
        pte_val(*ptep) = rste;
 }
-- 
2.25.1



Reply via email to