aboutsummaryrefslogtreecommitdiff
path: root/arch/avr32/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/kernel/traps.c')
-rw-r--r--arch/avr32/kernel/traps.c59
1 files changed, 25 insertions, 34 deletions
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index b835c4c0136..682b2478691 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -7,6 +7,7 @@
*/
#include <linux/bug.h>
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/kdebug.h>
@@ -23,7 +24,7 @@
static DEFINE_SPINLOCK(die_lock);
-void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
+void die(const char *str, struct pt_regs *regs, long err)
{
static int die_counter;
@@ -31,22 +32,25 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
spin_lock_irq(&die_lock);
bust_spinlocks(1);
- printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG,
+ printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n",
str, err, ++die_counter);
+
+ printk(KERN_EMERG);
+
#ifdef CONFIG_PREEMPT
- printk("PREEMPT ");
+ printk(KERN_CONT "PREEMPT ");
#endif
#ifdef CONFIG_FRAME_POINTER
- printk("FRAME_POINTER ");
+ printk(KERN_CONT "FRAME_POINTER ");
#endif
if (current_cpu_data.features & AVR32_FEATURE_OCD) {
unsigned long did = ocd_read(DID);
- printk("chip: 0x%03lx:0x%04lx rev %lu\n",
+ printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n",
(did >> 1) & 0x7ff,
(did >> 12) & 0x7fff,
(did >> 28) & 0xf);
} else {
- printk("cpu: arch %u r%u / core %u r%u\n",
+ printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n",
current_cpu_data.arch_type,
current_cpu_data.arch_revision,
current_cpu_data.cpu_type,
@@ -57,7 +61,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
show_regs_log_lvl(regs, KERN_EMERG);
show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
bust_spinlocks(0);
- add_taint(TAINT_DIE);
+ add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irq(&die_lock);
if (in_interrupt())
@@ -74,36 +78,23 @@ void _exception(long signr, struct pt_regs *regs, int code,
{
siginfo_t info;
- if (!user_mode(regs))
+ if (!user_mode(regs)) {
+ const struct exception_table_entry *fixup;
+
+ /* Are we prepared to handle this kernel fault? */
+ fixup = search_exception_tables(regs->pc);
+ if (fixup) {
+ regs->pc = fixup->fixup;
+ return;
+ }
die("Unhandled exception in kernel mode", regs, signr);
+ }
memset(&info, 0, sizeof(info));
info.si_signo = signr;
info.si_code = code;
info.si_addr = (void __user *)addr;
force_sig_info(signr, &info, current);
-
- /*
- * Init gets no signals that it doesn't have a handler for.
- * That's all very well, but if it has caused a synchronous
- * exception and we ignore the resulting signal, it will just
- * generate the same exception over and over again and we get
- * nowhere. Better to kill it and let the kernel panic.
- */
- if (is_global_init(current)) {
- __sighandler_t handler;
-
- spin_lock_irq(&current->sighand->siglock);
- handler = current->sighand->action[signr-1].sa.sa_handler;
- spin_unlock_irq(&current->sighand->siglock);
- if (handler == SIG_DFL) {
- /* init has generated a synchronous exception
- and it doesn't have a handler for the signal */
- printk(KERN_CRIT "init has generated signal %ld "
- "but has no handler for it\n", signr);
- do_exit(signr);
- }
- }
}
asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
@@ -116,15 +107,15 @@ asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
switch (ret) {
case NOTIFY_OK:
case NOTIFY_STOP:
- return;
+ break;
case NOTIFY_BAD:
die("Fatal Non-Maskable Interrupt", regs, SIGINT);
default:
+ printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n");
+ nmi_disable();
break;
}
-
- printk(KERN_ALERT "Got NMI, but nobody cared. Disabling...\n");
- nmi_disable();
+ nmi_exit();
}
asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)