Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+6 −6
Original line number Diff line number Diff line
@@ -940,42 +940,42 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
		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);

+13 −5
Original line number Diff line number Diff line
@@ -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>
@@ -871,7 +872,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
	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 };
@@ -928,9 +929,15 @@ 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);
		if (si_code) {
			info.si_signo = SIGTRAP;
			info.si_code = si_code;
			force_sig_info(SIGTRAP, &info, current);
		} else {
			force_sig(SIGTRAP, current);
		}
	}
}

asmlinkage void do_bp(struct pt_regs *regs)
{
@@ -1012,7 +1019,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);
@@ -1054,7 +1061,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);
@@ -1492,6 +1499,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;

@@ -1512,7 +1520,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();