Commit 2f4b829c625e ("arm64: Add support for hardware updates of the
access and dirty pte bits") introduced support for handling hardware
updates of the access flag and dirty status.

ptep_set_wrprotect is setting PTR_DIRTY if !PTE_RDONLY,
however by design it suppose to set PTE_DIRTY
only if (PTE_DBM && !PTE_RDONLY). This patch addes code to
test and set accordingly.

This patch fixes BUG,
kernel BUG at /build/linux-StrpB2/linux-4.4.0/fs/ext4/inode.c:2394!
Internal error: Oops - BUG: 0 [#1] SMP

on thunderx numa board, when ARM64_HW_AFDBM and NUMA_BALANCING are enabled.

note: this patch is not tested on platform which supports AFDBM.

Signed-off-by: Ganapatrao Kulkarni <gkulka...@caviumnetworks.com>
---
 arch/arm64/include/asm/pgtable.h | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index f506086..d396892 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -613,20 +613,24 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct 
*mm,
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long 
address, pte_t *ptep)
 {
-       pteval_t pteval;
+       pteval_t pteval, pteval2;
        unsigned long tmp;
 
        asm volatile("//        ptep_set_wrprotect\n"
-       "       prfm    pstl1strm, %2\n"
-       "1:     ldxr    %0, %2\n"
-       "       tst     %0, %4                  // check for hw dirty 
(!PTE_RDONLY)\n"
-       "       csel    %1, %3, xzr, eq         // set PTE_DIRTY|PTE_RDONLY if 
dirty\n"
-       "       orr     %0, %0, %1              // if !dirty, PTE_RDONLY is 
already set\n"
-       "       and     %0, %0, %5              // clear PTE_WRITE/PTE_DBM\n"
-       "       stxr    %w1, %0, %2\n"
+       "       prfm    pstl1strm, %3\n"
+       "1:     ldxr    %0, %3\n"
+       "       and     %2, %0, %4              //extract bits PTE_WRITE and 
PTE_RDONLY\n"
+       "       cmp     %2, %5                  // compare wth PTE_WRITE\n"
+       "       b.ne    2f\n"
+       "       orr     %0, %0, %8              // Set PTE_DIRTY if (PTE_DBM && 
!PTE_RDONLY)\n"
+       "2:     tst     %0, %6                  // check for !PTE_RDONLY\n"
+       "       csel    %1, %6, xzr, eq         // select PTE_RDONLY if 
!PTE_RDONLY\n"
+       "       orr     %0, %0, %1              // set PTE_RDONLY if 
!PTE_RDONLY\n"
+       "       and     %0, %0, %7              // clear PTE_WRITE/PTE_DBM\n"
+       "       stxr    %w1, %0, %3\n"
        "       cbnz    %w1, 1b\n"
-       : "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))
-       : "r" (PTE_DIRTY|PTE_RDONLY), "L" (PTE_RDONLY), "L" (~PTE_WRITE)
+       : "=&r" (pteval), "=&r" (tmp), "=&r" (pteval2), "+Q" (pte_val(*ptep))
+       : "r" (PTE_WRITE|PTE_RDONLY), "r" (PTE_WRITE), "r" (PTE_RDONLY), "L" 
(~PTE_WRITE), "L" (PTE_DIRTY)
        : "cc");
 }
 
-- 
1.8.1.4

Reply via email to