MIPS: Set trap_no field in thread_struct on exception.
authorRalf Baechle <ralf@linux-mips.org>
Tue, 28 Jul 2015 18:37:43 +0000 (20:37 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 3 Sep 2015 10:08:04 +0000 (12:08 +0200)
This reverts commit 7281cd22973008a782860e48ed8d85d00204168c and adds
actual functionality to use the field.

arch/mips/include/asm/processor.h
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/traps.c
arch/mips/mm/fault.c

index 9b3b48e..59ee6dc 100644 (file)
@@ -275,6 +275,7 @@ struct thread_struct {
        unsigned long cp0_badvaddr;     /* Last user fault */
        unsigned long cp0_baduaddr;     /* Last kernel fault accessing USEG */
        unsigned long error_code;
+       unsigned long trap_nr;
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
        struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
        struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
@@ -341,6 +342,7 @@ struct thread_struct {
        .cp0_badvaddr           = 0,                            \
        .cp0_baduaddr           = 0,                            \
        .error_code             = 0,                            \
+       .trap_nr                = 0,                            \
        /*                                                      \
         * Platform specific cop2 registers(null if no COP2)    \
         */                                                     \
index 3706091..154e203 100644 (file)
@@ -128,6 +128,7 @@ void output_thread_defines(void)
               thread.cp0_baduaddr);
        OFFSET(THREAD_ECODE, task_struct, \
               thread.error_code);
+       OFFSET(THREAD_TRAPNO, task_struct, thread.trap_nr);
        BLANK();
 }
 
index da0b318..cea964d 100644 (file)
@@ -370,11 +370,6 @@ void show_registers(struct pt_regs *regs)
        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);
 
 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();
 
-       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)
                sig = 0;
 
@@ -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",
               data ? "Data" : "Instruction",
               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)
                goto out;
 
@@ -826,7 +821,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
        int sig;
 
        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)
                goto out;
 
@@ -882,11 +877,12 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
        char b[40];
 
 #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;
 #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)
                return;
 
@@ -948,6 +944,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
                set_fs(KERNEL_DS);
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (get_isa16_mode(regs->cp0_epc)) {
                u16 instr[2];
 
@@ -989,13 +986,13 @@ asmlinkage void do_bp(struct pt_regs *regs)
        switch (bcode) {
        case BRK_KPROBE_BP:
                if (notify_die(DIE_BREAK, "debug", regs, bcode,
-                              regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+                              current->thread.trap_nr, SIGTRAP) == NOTIFY_STOP)
                        goto out;
                else
                        break;
        case BRK_KPROBE_SSTEPBP:
                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;
                else
                        break;
@@ -1028,6 +1025,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
                set_fs(get_ds());
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        if (get_isa16_mode(regs->cp0_epc)) {
                if (__get_user(instr[0], (u16 __user *)(epc + 0)) ||
                    __get_user(instr[1], (u16 __user *)(epc + 2)))
@@ -1094,8 +1092,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
 no_r2_instr:
 
        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)
                goto out;
 
@@ -1444,8 +1443,9 @@ asmlinkage void do_msa_fpe(struct pt_regs *regs, unsigned int msacsr)
        enum ctx_state prev_state;
 
        prev_state = exception_enter();
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        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;
 
        /* Clear MSACSR.Cause before enabling interrupts */
index 852a41c..4b88fa0 100644 (file)
@@ -57,12 +57,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
 
 #ifdef CONFIG_KPROBES
        /*
-        * This is to notify the fault handler of the kprobes.  The
-        * exception code is redundant as it is also carried in REGS,
-        * but we pass it anyhow.
+        * This is to notify the fault handler of the kprobes.
         */
        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;
 #endif
 
@@ -224,6 +222,7 @@ bad_area_nosemaphore:
                        print_vma_addr(" ", regs->regs[31]);
                        pr_info("\n");
                }
+               current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
                info.si_signo = SIGSEGV;
                info.si_errno = 0;
                /* info.si_code has been set above */
@@ -282,6 +281,7 @@ do_sigbus:
                       field, (unsigned long) regs->cp0_epc,
                       field, (unsigned long) regs->regs[31]);
 #endif
+       current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        tsk->thread.cp0_badvaddr = address;
        info.si_signo = SIGBUS;
        info.si_errno = 0;