diff options
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 064a5256469..fa6bd97b6b9 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -32,6 +32,7 @@ #include <linux/delay.h> #include <linux/kprobes.h> #include <linux/kexec.h> +#include <linux/backlight.h> #include <asm/kdebug.h> #include <asm/pgtable.h> @@ -51,9 +52,13 @@ #include <asm/firmware.h> #include <asm/processor.h> #endif +#include <asm/kexec.h> #ifdef CONFIG_PPC64 /* XXX */ #define _IO_BASE pci_io_base +#ifdef CONFIG_KEXEC +cpumask_t cpus_in_sr = CPU_MASK_NONE; +#endif #endif #ifdef CONFIG_DEBUGGER @@ -96,7 +101,7 @@ static DEFINE_SPINLOCK(die_lock); int die(const char *str, struct pt_regs *regs, long err) { - static int die_counter, crash_dump_start = 0; + static int die_counter; if (debugger(regs)) return 1; @@ -105,10 +110,18 @@ int die(const char *str, struct pt_regs *regs, long err) spin_lock_irq(&die_lock); bust_spinlocks(1); #ifdef CONFIG_PMAC_BACKLIGHT - if (machine_is(powermac)) { - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); + mutex_lock(&pmac_backlight_mutex); + if (machine_is(powermac) && pmac_backlight) { + struct backlight_properties *props; + + down(&pmac_backlight->sem); + props = pmac_backlight->props; + props->brightness = props->max_brightness; + props->power = FB_BLANK_UNBLANK; + props->update_status(pmac_backlight); + up(&pmac_backlight->sem); } + mutex_unlock(&pmac_backlight_mutex); #endif printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT @@ -128,21 +141,12 @@ int die(const char *str, struct pt_regs *regs, long err) print_modules(); show_regs(regs); bust_spinlocks(0); + spin_unlock_irq(&die_lock); - if (!crash_dump_start && kexec_should_crash(current)) { - crash_dump_start = 1; - spin_unlock_irq(&die_lock); + if (kexec_should_crash(current) || + kexec_sr_activated(smp_processor_id())) crash_kexec(regs); - /* NOTREACHED */ - } - spin_unlock_irq(&die_lock); - if (crash_dump_start) - /* - * Only for soft-reset: Other CPUs will be responded to an IPI - * sent by first kexec CPU. - */ - for(;;) - ; + crash_kexec_secondary(regs); if (in_interrupt()) panic("Fatal exception in interrupt"); @@ -206,6 +210,10 @@ void system_reset_exception(struct pt_regs *regs) return; } +#ifdef CONFIG_KEXEC + cpu_set(smp_processor_id(), cpus_in_sr); +#endif + die("System Reset", regs, SIGABRT); /* Must die if the interrupt is not recoverable */ @@ -658,7 +666,7 @@ static int emulate_instruction(struct pt_regs *regs) u32 instword; u32 rd; - if (!user_mode(regs)) + if (!user_mode(regs) || (regs->msr & MSR_LE)) return -EINVAL; CHECK_FULL_REGS(regs); @@ -805,9 +813,11 @@ void __kprobes program_check_exception(struct pt_regs *regs) void alignment_exception(struct pt_regs *regs) { - int fixed; + int fixed = 0; - fixed = fix_alignment(regs); + /* we don't implement logging of alignment exceptions */ + if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) + fixed = fix_alignment(regs); if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ |