OSDN Git Service

UPSTREAM: MIPS: traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'
authorMaciej W. Rozycki <macro@imgtec.com>
Fri, 4 Mar 2016 01:44:28 +0000 (01:44 +0000)
committerGreg Kroah-Hartman <gregkh@google.com>
Mon, 5 Feb 2018 16:58:31 +0000 (08:58 -0800)
Follow our own rules set in <asm/siginfo.h> for SIGTRAP signals issued
from `do_watch' and `do_trap_or_bp' by setting the signal code to
TRAP_HWBKPT and TRAP_BRKPT respectively, for Watch exceptions and for
those Breakpoint exceptions whose originating BREAK instruction's code
does not have a special meaning.  Keep Trap exceptions unaffected as
these are not debug events.

No existing user software is expected to examine signal codes for these
signals as SI_KERNEL has been always used here.  This change makes the
MIPS port more like other Linux ports, which reduces the complexity and
provides for performance improvement in GDB.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
Cc: Pedro Alves <palves@redhat.com>
Cc: Luis Machado <lgustavo@codesourcery.com>
Cc: linux-mips@linux-mips.org
Cc: gdb@sourceware.org
Patchwork: https://patchwork.linux-mips.org/patch/12758/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
(cherry picked from commit 3b143cca6e1397188f507a6c727f4108861ceb8b)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
arch/mips/include/asm/mips-r2-to-r6-emul.h
arch/mips/kernel/mips-r2-to-r6-emul.c
arch/mips/kernel/traps.c

index 1f6ea83..20621e1 100644 (file)
@@ -79,7 +79,7 @@ struct r2_decoder_table {
 };
 
 
-extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
                          const char *str);
 
 #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
index a7a9f7c..66db838 100644 (file)
@@ -941,42 +941,42 @@ repeat:
                switch (rt) {
                case tgei_op:
                        if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
-                               do_trap_or_bp(regs, 0, "TGEI");
+                               do_trap_or_bp(regs, 0, 0, "TGEI");
 
                        MIPS_R2_STATS(traps);
 
                        break;
                case tgeiu_op:
                        if (regs->regs[rs] >= MIPSInst_UIMM(inst))
-                               do_trap_or_bp(regs, 0, "TGEIU");
+                               do_trap_or_bp(regs, 0, 0, "TGEIU");
 
                        MIPS_R2_STATS(traps);
 
                        break;
                case tlti_op:
                        if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
-                               do_trap_or_bp(regs, 0, "TLTI");
+                               do_trap_or_bp(regs, 0, 0, "TLTI");
 
                        MIPS_R2_STATS(traps);
 
                        break;
                case tltiu_op:
                        if (regs->regs[rs] < MIPSInst_UIMM(inst))
-                               do_trap_or_bp(regs, 0, "TLTIU");
+                               do_trap_or_bp(regs, 0, 0, "TLTIU");
 
                        MIPS_R2_STATS(traps);
 
                        break;
                case teqi_op:
                        if (regs->regs[rs] == MIPSInst_SIMM(inst))
-                               do_trap_or_bp(regs, 0, "TEQI");
+                               do_trap_or_bp(regs, 0, 0, "TEQI");
 
                        MIPS_R2_STATS(traps);
 
                        break;
                case tnei_op:
                        if (regs->regs[rs] != MIPSInst_SIMM(inst))
-                               do_trap_or_bp(regs, 0, "TNEI");
+                               do_trap_or_bp(regs, 0, 0, "TNEI");
 
                        MIPS_R2_STATS(traps);
 
index 1332740..e921540 100644 (file)
@@ -56,6 +56,7 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
+#include <asm/siginfo.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
@@ -873,7 +874,7 @@ out:
        exception_exit(prev_state);
 }
 
-void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
        const char *str)
 {
        siginfo_t info = { 0 };
@@ -930,7 +931,13 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
        default:
                scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
                die_if_kernel(b, regs);
-               force_sig(SIGTRAP, current);
+               if (si_code) {
+                       info.si_signo = SIGTRAP;
+                       info.si_code = si_code;
+                       force_sig_info(SIGTRAP, &info, current);
+               } else {
+                       force_sig(SIGTRAP, current);
+               }
        }
 }
 
@@ -1014,7 +1021,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
                break;
        }
 
-       do_trap_or_bp(regs, bcode, "Break");
+       do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
 
 out:
        set_fs(seg);
@@ -1056,7 +1063,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
                        tcode = (opcode >> 6) & ((1 << 10) - 1);
        }
 
-       do_trap_or_bp(regs, tcode, "Trap");
+       do_trap_or_bp(regs, tcode, 0, "Trap");
 
 out:
        set_fs(seg);
@@ -1507,6 +1514,7 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
  */
 asmlinkage void do_watch(struct pt_regs *regs)
 {
+       siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
        enum ctx_state prev_state;
        u32 cause;
 
@@ -1527,7 +1535,7 @@ asmlinkage void do_watch(struct pt_regs *regs)
        if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
                mips_read_watch_registers();
                local_irq_enable();
-               force_sig(SIGTRAP, current);
+               force_sig_info(SIGTRAP, &info, current);
        } else {
                mips_clear_watch_registers();
                local_irq_enable();