Commit e3b28831 authored by Ralf Baechle's avatar Ralf Baechle

MIPS: Set trap_no field in thread_struct on exception.

This reverts commit 7281cd22 and adds
actual functionality to use the field.
parent 8c576912
...@@ -275,6 +275,7 @@ struct thread_struct { ...@@ -275,6 +275,7 @@ struct thread_struct {
unsigned long cp0_badvaddr; /* Last user fault */ unsigned long cp0_badvaddr; /* Last user fault */
unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */
unsigned long error_code; unsigned long error_code;
unsigned long trap_nr;
#ifdef CONFIG_CPU_CAVIUM_OCTEON #ifdef CONFIG_CPU_CAVIUM_OCTEON
struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128))); struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128))); struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
...@@ -341,6 +342,7 @@ struct thread_struct { ...@@ -341,6 +342,7 @@ struct thread_struct {
.cp0_badvaddr = 0, \ .cp0_badvaddr = 0, \
.cp0_baduaddr = 0, \ .cp0_baduaddr = 0, \
.error_code = 0, \ .error_code = 0, \
.trap_nr = 0, \
/* \ /* \
* Platform specific cop2 registers(null if no COP2) \ * Platform specific cop2 registers(null if no COP2) \
*/ \ */ \
......
...@@ -128,6 +128,7 @@ void output_thread_defines(void) ...@@ -128,6 +128,7 @@ void output_thread_defines(void)
thread.cp0_baduaddr); thread.cp0_baduaddr);
OFFSET(THREAD_ECODE, task_struct, \ OFFSET(THREAD_ECODE, task_struct, \
thread.error_code); thread.error_code);
OFFSET(THREAD_TRAPNO, task_struct, thread.trap_nr);
BLANK(); BLANK();
} }
......
...@@ -370,11 +370,6 @@ void show_registers(struct pt_regs *regs) ...@@ -370,11 +370,6 @@ void show_registers(struct pt_regs *regs)
set_fs(old_fs); set_fs(old_fs);
} }
static int regs_to_trapnr(struct pt_regs *regs)
{
return (regs->cp0_cause >> 2) & 0x1f;
}
static DEFINE_RAW_SPINLOCK(die_lock); static DEFINE_RAW_SPINLOCK(die_lock);
void __noreturn die(const char *str, struct pt_regs *regs) void __noreturn die(const char *str, struct pt_regs *regs)
...@@ -384,7 +379,7 @@ void __noreturn die(const char *str, struct pt_regs *regs) ...@@ -384,7 +379,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)
oops_enter(); oops_enter();
if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_nr,
SIGSEGV) == NOTIFY_STOP) SIGSEGV) == NOTIFY_STOP)
sig = 0; sig = 0;
...@@ -470,7 +465,7 @@ asmlinkage void do_be(struct pt_regs *regs) ...@@ -470,7 +465,7 @@ asmlinkage void do_be(struct pt_regs *regs)
printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
data ? "Data" : "Instruction", data ? "Data" : "Instruction",
field, regs->cp0_epc, field, regs->regs[31]); field, regs->cp0_epc, field, regs->regs[31]);
if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), if (notify_die(DIE_OOPS, "bus error", regs, 0, current->thread.trap_nr,
SIGBUS) == NOTIFY_STOP) SIGBUS) == NOTIFY_STOP)
goto out; goto out;
...@@ -826,7 +821,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) ...@@ -826,7 +821,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
int sig; int sig;
prev_state = exception_enter(); prev_state = exception_enter();
if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), if (notify_die(DIE_FP, "FP exception", regs, 0, current->thread.trap_nr,
SIGFPE) == NOTIFY_STOP) SIGFPE) == NOTIFY_STOP)
goto out; goto out;
...@@ -882,11 +877,12 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, ...@@ -882,11 +877,12 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
char b[40]; char b[40];
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) if (kgdb_ll_trap(DIE_TRAP, str, regs, code, current->thread.trap_nr,
SIGTRAP) == NOTIFY_STOP)
return; return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), if (notify_die(DIE_TRAP, str, regs, code, current->thread.trap_nr,
SIGTRAP) == NOTIFY_STOP) SIGTRAP) == NOTIFY_STOP)
return; return;
...@@ -948,6 +944,7 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -948,6 +944,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
prev_state = exception_enter(); prev_state = exception_enter();
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
u16 instr[2]; u16 instr[2];
...@@ -989,13 +986,13 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -989,13 +986,13 @@ asmlinkage void do_bp(struct pt_regs *regs)
switch (bcode) { switch (bcode) {
case BRK_KPROBE_BP: case BRK_KPROBE_BP:
if (notify_die(DIE_BREAK, "debug", regs, bcode, if (notify_die(DIE_BREAK, "debug", regs, bcode,
regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
goto out; goto out;
else else
break; break;
case BRK_KPROBE_SSTEPBP: case BRK_KPROBE_SSTEPBP:
if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode,
regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
goto out; goto out;
else else
break; break;
...@@ -1028,6 +1025,7 @@ asmlinkage void do_tr(struct pt_regs *regs) ...@@ -1028,6 +1025,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
set_fs(get_ds()); set_fs(get_ds());
prev_state = exception_enter(); prev_state = exception_enter();
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (get_isa16_mode(regs->cp0_epc)) { if (get_isa16_mode(regs->cp0_epc)) {
if (__get_user(instr[0], (u16 __user *)(epc + 0)) || if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
__get_user(instr[1], (u16 __user *)(epc + 2))) __get_user(instr[1], (u16 __user *)(epc + 2)))
...@@ -1094,8 +1092,9 @@ asmlinkage void do_ri(struct pt_regs *regs) ...@@ -1094,8 +1092,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
no_r2_instr: no_r2_instr:
prev_state = exception_enter(); prev_state = exception_enter();
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), if (notify_die(DIE_RI, "RI Fault", regs, 0, current->thread.trap_nr,
SIGILL) == NOTIFY_STOP) SIGILL) == NOTIFY_STOP)
goto out; goto out;
...@@ -1444,8 +1443,9 @@ asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr) ...@@ -1444,8 +1443,9 @@ asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
enum ctx_state prev_state; enum ctx_state prev_state;
prev_state = exception_enter(); prev_state = exception_enter();
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0, if (notify_die(DIE_MSAFP, "MSA FP exception", regs, 0,
regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) current->thread.trap_nr, SIGFPE) == NOTIFY_STOP)
goto out; goto out;
/* Clear MSACSR.Cause before enabling interrupts */ /* Clear MSACSR.Cause before enabling interrupts */
......
...@@ -57,12 +57,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, ...@@ -57,12 +57,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
/* /*
* This is to notify the fault handler of the kprobes. The * This is to notify the fault handler of the kprobes.
* exception code is redundant as it is also carried in REGS,
* but we pass it anyhow.
*/ */
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1, if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1,
(regs->cp0_cause >> 2) & 0x1f, SIGSEGV) == NOTIFY_STOP) current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
return; return;
#endif #endif
...@@ -224,6 +222,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, ...@@ -224,6 +222,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
print_vma_addr(" ", regs->regs[31]); print_vma_addr(" ", regs->regs[31]);
pr_info("\n"); pr_info("\n");
} }
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
info.si_signo = SIGSEGV; info.si_signo = SIGSEGV;
info.si_errno = 0; info.si_errno = 0;
/* info.si_code has been set above */ /* info.si_code has been set above */
...@@ -282,6 +281,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, ...@@ -282,6 +281,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
field, (unsigned long) regs->cp0_epc, field, (unsigned long) regs->cp0_epc,
field, (unsigned long) regs->regs[31]); field, (unsigned long) regs->regs[31]);
#endif #endif
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
tsk->thread.cp0_badvaddr = address; tsk->thread.cp0_badvaddr = address;
info.si_signo = SIGBUS; info.si_signo = SIGBUS;
info.si_errno = 0; info.si_errno = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment