OSDN Git Service

s390/mm: make pmd/pud_bad() report large entries as bad
authorGerald Schaefer <gerald.schaefer@de.ibm.com>
Fri, 6 Sep 2019 20:00:50 +0000 (22:00 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Thu, 31 Oct 2019 16:20:53 +0000 (17:20 +0100)
The semantics of pmd/pud_bad() expect that large entries are reported as
bad, but we also check large entries for sanity.

There is currently no issue with this wrong behaviour, but let's conform
to the semantics by reporting large pmd/pud entries as bad, in order to
prevent future issues.

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

Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/include/asm/pgtable.h

index 5ff98d7..a1bf8d7 100644 (file)
@@ -266,11 +266,9 @@ static inline int is_module_addr(void *addr)
 #endif
 
 #define _REGION_ENTRY_BITS      0xfffffffffffff22fUL
-#define _REGION_ENTRY_BITS_LARGE 0xffffffff8000fe2fUL
 
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_BITS                    0xfffffffffffffe33UL
-#define _SEGMENT_ENTRY_BITS_LARGE              0xfffffffffff0ff33UL
 #define _SEGMENT_ENTRY_HARDWARE_BITS           0xfffffffffffffe30UL
 #define _SEGMENT_ENTRY_HARDWARE_BITS_LARGE     0xfffffffffff00730UL
 #define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address       */
@@ -699,10 +697,8 @@ static inline int pmd_large(pmd_t pmd)
 
 static inline int pmd_bad(pmd_t pmd)
 {
-       if ((pmd_val(pmd) & _SEGMENT_ENTRY_TYPE_MASK) > 0)
+       if ((pmd_val(pmd) & _SEGMENT_ENTRY_TYPE_MASK) > 0 || pmd_large(pmd))
                return 1;
-       if (pmd_large(pmd))
-               return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0;
        return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
 }
 
@@ -710,12 +706,10 @@ static inline int pud_bad(pud_t pud)
 {
        unsigned long type = pud_val(pud) & _REGION_ENTRY_TYPE_MASK;
 
-       if (type > _REGION_ENTRY_TYPE_R3)
+       if (type > _REGION_ENTRY_TYPE_R3 || pud_large(pud))
                return 1;
        if (type < _REGION_ENTRY_TYPE_R3)
                return 0;
-       if (pud_large(pud))
-               return (pud_val(pud) & ~_REGION_ENTRY_BITS_LARGE) != 0;
        return (pud_val(pud) & ~_REGION_ENTRY_BITS) != 0;
 }