Commit 3b143cca authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

MIPS: traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'

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: default avatarMaciej 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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 748ac56b
...@@ -79,7 +79,7 @@ struct r2_decoder_table { ...@@ -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); const char *str);
#ifndef CONFIG_MIPSR2_TO_R6_EMULATOR #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
......
...@@ -940,42 +940,42 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31) ...@@ -940,42 +940,42 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
switch (rt) { switch (rt) {
case tgei_op: case tgei_op:
if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst)) 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); MIPS_R2_STATS(traps);
break; break;
case tgeiu_op: case tgeiu_op:
if (regs->regs[rs] >= MIPSInst_UIMM(inst)) 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); MIPS_R2_STATS(traps);
break; break;
case tlti_op: case tlti_op:
if ((long)regs->regs[rs] < MIPSInst_SIMM(inst)) 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); MIPS_R2_STATS(traps);
break; break;
case tltiu_op: case tltiu_op:
if (regs->regs[rs] < MIPSInst_UIMM(inst)) 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); MIPS_R2_STATS(traps);
break; break;
case teqi_op: case teqi_op:
if (regs->regs[rs] == MIPSInst_SIMM(inst)) 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); MIPS_R2_STATS(traps);
break; break;
case tnei_op: case tnei_op:
if (regs->regs[rs] != MIPSInst_SIMM(inst)) 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); MIPS_R2_STATS(traps);
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/siginfo.h>
#include <asm/tlbdebug.h> #include <asm/tlbdebug.h>
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -871,7 +872,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) ...@@ -871,7 +872,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
exception_exit(prev_state); 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) const char *str)
{ {
siginfo_t info = { 0 }; siginfo_t info = { 0 };
...@@ -928,8 +929,14 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, ...@@ -928,8 +929,14 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
default: default:
scnprintf(b, sizeof(b), "%s instruction in kernel code", str); scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
die_if_kernel(b, regs); die_if_kernel(b, regs);
if (si_code) {
info.si_signo = SIGTRAP;
info.si_code = si_code;
force_sig_info(SIGTRAP, &info, current);
} else {
force_sig(SIGTRAP, current); force_sig(SIGTRAP, current);
} }
}
} }
asmlinkage void do_bp(struct pt_regs *regs) asmlinkage void do_bp(struct pt_regs *regs)
...@@ -1012,7 +1019,7 @@ asmlinkage void do_bp(struct pt_regs *regs) ...@@ -1012,7 +1019,7 @@ asmlinkage void do_bp(struct pt_regs *regs)
break; break;
} }
do_trap_or_bp(regs, bcode, "Break"); do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
out: out:
set_fs(seg); set_fs(seg);
...@@ -1054,7 +1061,7 @@ asmlinkage void do_tr(struct pt_regs *regs) ...@@ -1054,7 +1061,7 @@ asmlinkage void do_tr(struct pt_regs *regs)
tcode = (opcode >> 6) & ((1 << 10) - 1); tcode = (opcode >> 6) & ((1 << 10) - 1);
} }
do_trap_or_bp(regs, tcode, "Trap"); do_trap_or_bp(regs, tcode, 0, "Trap");
out: out:
set_fs(seg); set_fs(seg);
...@@ -1492,6 +1499,7 @@ asmlinkage void do_mdmx(struct pt_regs *regs) ...@@ -1492,6 +1499,7 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
*/ */
asmlinkage void do_watch(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; enum ctx_state prev_state;
u32 cause; u32 cause;
...@@ -1512,7 +1520,7 @@ asmlinkage void do_watch(struct pt_regs *regs) ...@@ -1512,7 +1520,7 @@ asmlinkage void do_watch(struct pt_regs *regs)
if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
mips_read_watch_registers(); mips_read_watch_registers();
local_irq_enable(); local_irq_enable();
force_sig(SIGTRAP, current); force_sig_info(SIGTRAP, &info, current);
} else { } else {
mips_clear_watch_registers(); mips_clear_watch_registers();
local_irq_enable(); local_irq_enable();
......
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