From: Wang Kefeng wangkefeng.wang@huawei.com
mainline inclusion from mainline-v6.1 commit 73a0b6ee5d6269f92df43e1d09b3278a2886bf8a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8YLWW
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
------------------------------------------------------
This is a similar fixup like arm64 does, only handle translation faults in case of unexpected kfence report when alignment faults on ARM, see more from commit 0bb1fbffc631 ("arm64: mm: kfence: only handle translation faults").
Fixes: 75969686ec0d ("ARM: 9166/1: Support KFENCE for ARM") Signed-off-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Russell King (Oracle) rmk+kernel@armlinux.org.uk Signed-off-by: Nanyong Sun sunnanyong@huawei.com --- arch/arm/mm/fault.c | 18 ++++++++++++++++-- arch/arm/mm/fault.h | 9 ++++++--- 2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 91965fb043de..4c64d90155c1 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -118,6 +118,19 @@ static inline bool is_write_fault(unsigned int fsr) return (fsr & FSR_WRITE) && !(fsr & FSR_CM); }
+static inline bool is_translation_fault(unsigned int fsr) +{ + int fs = fsr_fs(fsr); +#ifdef CONFIG_ARM_LPAE + if ((fs & FS_MMU_NOLL_MASK) == FS_TRANS_NOLL) + return true; +#else + if (fs == FS_L1_TRANS || fs == FS_L2_TRANS) + return true; +#endif + return false; +} + static void die_kernel_fault(const char *msg, struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -153,7 +166,8 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, if (addr < PAGE_SIZE) { msg = "NULL pointer dereference"; } else { - if (kfence_handle_page_fault(addr, is_write_fault(fsr), regs)) + if (is_translation_fault(fsr) && + kfence_handle_page_fault(addr, is_write_fault(fsr), regs)) return;
msg = "paging request"; @@ -221,7 +235,7 @@ static inline bool is_permission_fault(unsigned int fsr) { int fs = fsr_fs(fsr); #ifdef CONFIG_ARM_LPAE - if ((fs & FS_PERM_NOLL_MASK) == FS_PERM_NOLL) + if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL) return true; #else if (fs == FS_L1_PERM || fs == FS_L2_PERM) diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h index 83b5ab32d7a4..54927ba1fa6e 100644 --- a/arch/arm/mm/fault.h +++ b/arch/arm/mm/fault.h @@ -14,8 +14,9 @@
#ifdef CONFIG_ARM_LPAE #define FSR_FS_AEA 17 +#define FS_TRANS_NOLL 0x4 #define FS_PERM_NOLL 0xC -#define FS_PERM_NOLL_MASK 0x3C +#define FS_MMU_NOLL_MASK 0x3C
static inline int fsr_fs(unsigned int fsr) { @@ -23,8 +24,10 @@ static inline int fsr_fs(unsigned int fsr) } #else #define FSR_FS_AEA 22 -#define FS_L1_PERM 0xD -#define FS_L2_PERM 0xF +#define FS_L1_TRANS 0x5 +#define FS_L2_TRANS 0x7 +#define FS_L1_PERM 0xD +#define FS_L2_PERM 0xF
static inline int fsr_fs(unsigned int fsr) {