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

Commit a9221de6 authored by Russell King's avatar Russell King
Browse files

ARM: add notify_die() support



Kernel debuggers want to be informed of die() events, so that they
can take some action to allow the problem to be inspected.  Provide
the hook in a similar manner to x86.

Note that we currently don't implement the individual trap hooks.

Acked-by: default avatarJason Wessel <jason.wessel@windriver.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 2b0d8c25
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -73,8 +73,7 @@ extern unsigned int mem_fclk_21285;

struct pt_regs;

void die(const char *msg, struct pt_regs *regs, int err)
		__attribute__((noreturn));
void die(const char *msg, struct pt_regs *regs, int err);

struct siginfo;
void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
+25 −10
Original line number Diff line number Diff line
@@ -12,15 +12,17 @@
 *  'linux/arch/arm/lib/traps.S'.  Mostly a debugging aid, but will probably
 *  kill the offending process.
 */
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/personality.h>
#include <linux/kallsyms.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h>
#include <linux/kdebug.h>
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/uaccess.h>

#include <asm/atomic.h>
#include <asm/cacheflush.h>
@@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
#define S_SMP ""
#endif

static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
{
	struct task_struct *tsk = thread->task;
	static int die_counter;
	int ret;

	printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
	       str, err, ++die_counter);
	sysfs_printk_last_file();

	/* trap and error numbers are mostly meaningless on ARM */
	ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
	if (ret == NOTIFY_STOP)
		return ret;

	print_modules();
	__show_regs(regs);
	printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
@@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
		dump_backtrace(regs, tsk);
		dump_instr(KERN_EMERG, regs);
	}

	return ret;
}

DEFINE_SPINLOCK(die_lock);
@@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock);
/*
 * This function is protected against re-entrancy.
 */
NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
void die(const char *str, struct pt_regs *regs, int err)
{
	struct thread_info *thread = current_thread_info();
	int ret;

	oops_enter();

	spin_lock_irq(&die_lock);
	console_verbose();
	bust_spinlocks(1);
	__die(str, err, thread, regs);
	ret = __die(str, err, thread, regs);

	if (regs && kexec_should_crash(thread->task))
		crash_kexec(regs);

	bust_spinlocks(0);
	add_taint(TAINT_DIE);
	spin_unlock_irq(&die_lock);
@@ -267,10 +283,9 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)

	if (in_interrupt())
		panic("Fatal exception in interrupt");

	if (panic_on_oops)
		panic("Fatal exception");

	if (ret != NOTIFY_STOP)
		do_exit(SIGSEGV);
}