On 2024/11/6 17:23, Wupeng Ma wrote:
From: Ma Wupeng mawupeng1@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB0OV7
During arm64_do_kernel_sea, kernel will panic if no info is reported to kernel since apei_claim_sea will fail. However, for user task, sig fault can be send to which can avoid kernel panic.
Signed-off-by: Ma Wupeng mawupeng1@huawei.com
arch/arm64/mm/fault.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
--- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -870,6 +870,9 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) static bool arm64_do_kernel_sea(void __user *addr, unsigned int esr, struct pt_regs *regs, int sig, int code) { + unsigned long orig_pc = regs->pc; + int err; + if (!IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC)) return false;
@@ -879,13 +882,20 @@ static bool arm64_do_kernel_sea(void __user *addr, unsigned int esr, if (user_mode(regs)) return false;
- if (apei_claim_sea(regs) < 0) - return false; - if (!fixup_exception_mc(regs)) return false;
- if (current->flags & PF_KTHREAD) + err = apei_claim_sea(regs); + regs->pc = orig_pc; + + if (err) { + pr_emerg("apei claim sea failed. addr: %#lx, esr: %#x\n", + (unsigned long)addr, esr); + if (!current->mm) + return false; + } + + if (!current->mm) return true;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index a2c61725c176..67f7ae98af56 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -729,6 +729,9 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) static bool arm64_do_kernel_sea(void __user *addr, unsigned int esr, struct pt_regs *regs, int sig, int code) {
- unsigned long pc;
- int err;
- if (!IS_ENABLED(CONFIG_ARCH_HAS_COPY_MC)) return false;
@@ -738,12 +741,20 @@ static bool arm64_do_kernel_sea(void __user *addr, unsigned int esr, if (user_mode(regs)) return false;
- if (apei_claim_sea(regs) < 0)
return false;
pc = regs->pc; if (!fixup_exception_mc(regs)) return false;
err = apei_claim_sea(regs);
if (err < 0) {
pr_emerg("apei claim sea failed. addr: %#lx, esr: %#x\n",
(unsigned long)addr, esr);
if (!current->mm) {
regs->pc = pc;
return false;
}
}
if (current->flags & PF_KTHREAD) return true;