mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
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 <jianxiong.pan@amlogic.com>
This commit is contained in:
committed by
Dongjin Kim
parent
710268fbca
commit
53b256f1e3
@@ -33,6 +33,9 @@
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/tls.h>
|
||||
#include <asm/vdso.h>
|
||||
#ifdef CONFIG_AMLOGIC_USER_FAULT
|
||||
#include <linux/amlogic/user_fault.h>
|
||||
#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)
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#include <asm/tls.h>
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/opcodes.h>
|
||||
#ifdef CONFIG_AMLOGIC_USER_FAULT
|
||||
#include <linux/amlogic/user_fault.h>
|
||||
#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);
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <asm/system_misc.h>
|
||||
#include <asm/system_info.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#ifdef CONFIG_AMLOGIC_USER_FAULT
|
||||
#include <linux/amlogic/user_fault.h>
|
||||
#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
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/system_misc.h>
|
||||
#ifdef CONFIG_AMLOGIC_USER_FAULT
|
||||
#include <linux/amlogic/user_fault.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK)
|
||||
#include <linux/stackprotector.h>
|
||||
@@ -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)
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
|
||||
#include <trace/hooks/traps.h>
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_USER_FAULT
|
||||
#include <linux/amlogic/user_fault.h>
|
||||
#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");
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
|
||||
#include <trace/hooks/fault.h>
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_USER_FAULT
|
||||
#include <linux/amlogic/user_fault.h>
|
||||
#endif
|
||||
|
||||
struct fault_info {
|
||||
int (*fn)(unsigned long far, unsigned long esr,
|
||||
struct pt_regs *regs);
|
||||
|
||||
Reference in New Issue
Block a user