From 53b256f1e314b6464b0a379922b2c66dc8a4895b Mon Sep 17 00:00:00 2001 From: Jianxiong Pan Date: Tue, 1 Mar 2022 19:22:52 +0800 Subject: [PATCH] mm: add user fault debug support. [1/2] PD#SWPL-73676 Problem: need user fault debug support. Solution: add user fault debug support. Verify: local. Change-Id: I6f48a5ec1cb75b276a15f6791ec09f2a2ed5d159 Signed-off-by: Jianxiong Pan --- arch/arm/kernel/process.c | 13 +++++++++++++ arch/arm/kernel/traps.c | 22 ++++++++++++++++++++++ arch/arm/mm/fault.c | 18 ++++++++++++++++++ arch/arm64/kernel/process.c | 10 ++++++++++ arch/arm64/kernel/traps.c | 25 +++++++++++++++++++++++++ arch/arm64/mm/fault.c | 4 ++++ 6 files changed, 92 insertions(+) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 0e2d3051741e..9a0ebce3ecf0 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_USER_FAULT +#include +#endif #include "signal.h" @@ -127,6 +130,9 @@ void __show_regs(struct pt_regs *regs) printk("PC is at %pS\n", (void *)instruction_pointer(regs)); printk("LR is at %pS\n", (void *)regs->ARM_lr); +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_user_fault_info(regs, 0, 0); +#endif printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n", regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr); printk("sp : %08lx ip : %08lx fp : %08lx\n", @@ -148,6 +154,10 @@ void __show_regs(struct pt_regs *regs) buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; buf[4] = '\0'; +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_vmalloc_pfn(regs); +#endif + #ifndef CONFIG_CPU_V7M { const char *segment; @@ -187,6 +197,9 @@ void __show_regs(struct pt_regs *regs) printk("Control: %08x%s\n", ctrl, buf); } #endif +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_extra_reg_data(regs); +#endif } void show_regs(struct pt_regs * regs) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 91e757bb054e..fb57dc568c6f 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -38,6 +38,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_USER_FAULT +#include +#endif static const char *handler[]= { @@ -51,7 +54,20 @@ static const char *handler[]= { void *vectors_page; #ifdef CONFIG_DEBUG_USER +#ifdef CONFIG_AMLOGIC_USER_FAULT +#define USER_DEBUG_UNDEFINED_INSTRUCTION BIT(0) +#define USER_DEBUG_SYSTEM_CALL BIT(1) +#define USER_DEBUG_INVALID_DATA_ABORT BIT(2) +#define USER_DEBUG_SIGSEGV_FAULT BIT(3) +#define USER_DEBUG_SIGBUS_FAULT BIT(14) +unsigned int user_debug = USER_DEBUG_UNDEFINED_INSTRUCTION | + USER_DEBUG_SYSTEM_CALL | + USER_DEBUG_INVALID_DATA_ABORT | + USER_DEBUG_SIGSEGV_FAULT | + USER_DEBUG_SIGBUS_FAULT; +#else unsigned int user_debug; +#endif static int __init user_debug_setup(char *str) { @@ -473,6 +489,9 @@ die_sig: if (user_debug & UDBG_UNDEFINED) { pr_info("%s (%d): undefined instruction: pc=%p\n", current->comm, task_pid_nr(current), pc); +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_debug_ratelimited(regs, 0); +#endif __show_regs(regs); dump_instr(KERN_INFO, regs); } @@ -517,6 +536,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason) { console_verbose(); +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_debug_ratelimited(regs, 0); +#endif pr_crit("Bad mode in %s handler detected\n", handler[reason]); die("Oops - bad mode", regs, 0); diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index af5177801fb1..8c92219f6a89 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -21,6 +21,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_USER_FAULT +#include +#endif #include "fault.h" @@ -142,13 +145,28 @@ __do_user_fault(unsigned long addr, unsigned int fsr, unsigned int sig, harden_branch_predictor(); #ifdef CONFIG_DEBUG_USER +#ifdef CONFIG_AMLOGIC_USER_FAULT + if (unhandled_signal(tsk, sig) && + (((user_debug & UDBG_SEGV) && sig == SIGSEGV) || + ((user_debug & UDBG_BUS) && sig == SIGBUS))) { +#else if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) || ((user_debug & UDBG_BUS) && (sig == SIGBUS))) { +#endif +#ifdef CONFIG_AMLOGIC_USER_FAULT + pr_info("%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", + tsk->comm, sig, addr, fsr); +#else pr_err("8<--- cut here ---\n"); pr_err("%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n", tsk->comm, sig, addr, fsr); +#endif show_pte(KERN_ERR, tsk->mm, addr); +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_debug_ratelimited(regs, 1); +#else show_regs(regs); +#endif } #endif #ifndef CONFIG_KUSER_HELPERS diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 873ef3850c91..ccacc9422ca9 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -57,6 +57,9 @@ #include #include #include +#ifdef CONFIG_AMLOGIC_USER_FAULT +#include +#endif #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) #include @@ -215,6 +218,10 @@ void __show_regs(struct pt_regs *regs) top_reg = 29; } +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_user_fault_info(regs, lr, sp); +#endif /* CONFIG_AMLOGIC_USER_FAULT */ + show_regs_print_info(KERN_DEFAULT); print_pstate(regs); @@ -241,6 +248,9 @@ void __show_regs(struct pt_regs *regs) pr_cont("\n"); } +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_extra_reg_data(regs); +#endif /* CONFIG_AMLOGIC_USER_FAULT */ } void show_regs(struct pt_regs *regs) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 44d733d782f3..629700c8fec4 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -48,6 +48,10 @@ #include +#ifdef CONFIG_AMLOGIC_USER_FAULT +#include +#endif + static bool __kprobes __check_eq(unsigned long pstate) { return (pstate & PSR_Z_BIT) != 0; @@ -146,7 +150,11 @@ pstate_check_t * const aarch32_opcode_cond_checks[16] = { __check_gt, __check_le, __check_al, __check_al }; +#ifndef CONFIG_AMLOGIC_USER_FAULT int show_unhandled_signals = 0; +#else +int show_unhandled_signals = 1; +#endif static void dump_kernel_instr(const char *lvl, struct pt_regs *regs) { @@ -249,9 +257,16 @@ static void arm64_show_signal(int signo, const char *str) struct pt_regs *regs = task_pt_regs(tsk); /* Leave if the signal won't be shown */ +#ifndef CONFIG_AMLOGIC_USER_FAULT if (!show_unhandled_signals || !unhandled_signal(tsk, signo) || !__ratelimit(&rs)) +#else + if (!show_unhandled_signals || + (!unhandled_signal(tsk, signo) && + !(show_unhandled_signals & 0xe)) || + !__ratelimit(&rs)) +#endif return; pr_info("%s[%d]: unhandled exception: ", tsk->comm, task_pid_nr(tsk)); @@ -262,6 +277,12 @@ static void arm64_show_signal(int signo, const char *str) print_vma_addr(KERN_CONT " in ", regs->pc); pr_cont("\n"); __show_regs(regs); +#ifdef CONFIG_AMLOGIC_USER_FAULT + pr_info("signo: %d\n", signo); + show_all_pfn(current, regs); + if (regs && kexec_should_crash(current) && (show_unhandled_signals & 4)) + crash_kexec(regs); +#endif } void arm64_force_sig_fault(int signo, int code, unsigned long far, @@ -848,6 +869,10 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned long esr) current->thread.fault_address = 0; current->thread.fault_code = esr; +#ifdef CONFIG_AMLOGIC_USER_FAULT + show_all_pfn(current, regs); +#endif /* CONFIG_AMLOGIC_USER_FAULT */ + arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, "Bad EL0 synchronous exception"); } diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index adb80a3f1e53..e9d7aefb49bd 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -46,6 +46,10 @@ #include +#ifdef CONFIG_AMLOGIC_USER_FAULT +#include +#endif + struct fault_info { int (*fn)(unsigned long far, unsigned long esr, struct pt_regs *regs);