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

Commit e3b28831 authored by Ralf Baechle's avatar Ralf Baechle
Browse files

MIPS: Set trap_no field in thread_struct on exception.

This reverts commit 7281cd22 and adds
actual functionality to use the field.
parent 8c576912
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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)	\
	 */							\
+1 −0
Original line number Diff line number Diff line
@@ -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();
}

+14 −14
Original line number Diff line number Diff line
@@ -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 */
+4 −4
Original line number Diff line number Diff line
@@ -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 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
			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 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
		       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;