X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=arch%2Fpowerpc%2Fkernel%2Ftraps.c;h=d9f10f2fc372b2ebde2bb24dbbb82267383295d7;hb=363e065c02b1273364d5356711a83e7f548fc0c8;hp=3c668078e524fefb03c628dd1fd986d8745f092d;hpb=b4bc7b53ccfa0cb793591ba11af49db8f1bc5a4d;p=pandora-kernel.git diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 3c668078e524..d9f10f2fc372 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -55,9 +55,6 @@ #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 @@ -150,13 +147,9 @@ int die(const char *str, struct pt_regs *regs, long err) if (in_interrupt()) panic("Fatal exception in interrupt"); - if (panic_on_oops) { -#ifdef CONFIG_PPC64 - printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); - ssleep(5); -#endif + if (panic_on_oops) panic("Fatal exception"); - } + do_exit(err); return 0; @@ -215,6 +208,19 @@ void system_reset_exception(struct pt_regs *regs) die("System Reset", regs, SIGABRT); + /* + * Some CPUs when released from the debugger will execute this path. + * These CPUs entered the debugger via a soft-reset. If the CPU was + * hung before entering the debugger it will return to the hung + * state when exiting this function. This causes a problem in + * kdump since the hung CPU(s) will not respond to the IPI sent + * from kdump. To prevent the problem we call crash_kexec_secondary() + * here. If a kdump had not been initiated or we exit the debugger + * with the "exit and recover" command (x) crash_kexec_secondary() + * will return after 5ms and the CPU returns to its previous state. + */ + crash_kexec_secondary(regs); + /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable System Reset"); @@ -579,19 +585,22 @@ static void parse_fpe(struct pt_regs *regs) #define INST_MFSPR_PVR_MASK 0xfc1fffff #define INST_DCBA 0x7c0005ec -#define INST_DCBA_MASK 0x7c0007fe +#define INST_DCBA_MASK 0xfc0007fe #define INST_MCRXR 0x7c000400 -#define INST_MCRXR_MASK 0x7c0007fe +#define INST_MCRXR_MASK 0xfc0007fe #define INST_STRING 0x7c00042a -#define INST_STRING_MASK 0x7c0007fe -#define INST_STRING_GEN_MASK 0x7c00067e +#define INST_STRING_MASK 0xfc0007fe +#define INST_STRING_GEN_MASK 0xfc00067e #define INST_LSWI 0x7c0004aa #define INST_LSWX 0x7c00042a #define INST_STSWI 0x7c0005aa #define INST_STSWX 0x7c00052a +#define INST_POPCNTB 0x7c0000f4 +#define INST_POPCNTB_MASK 0xfc0007fe + static int emulate_string_inst(struct pt_regs *regs, u32 instword) { u8 rT = (instword >> 21) & 0x1f; @@ -660,6 +669,23 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) return 0; } +static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword) +{ + u32 ra,rs; + unsigned long tmp; + + ra = (instword >> 16) & 0x1f; + rs = (instword >> 21) & 0x1f; + + tmp = regs->gpr[rs]; + tmp = tmp - ((tmp >> 1) & 0x5555555555555555ULL); + tmp = (tmp & 0x3333333333333333ULL) + ((tmp >> 2) & 0x3333333333333333ULL); + tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0fULL; + regs->gpr[ra] = tmp; + + return 0; +} + static int emulate_instruction(struct pt_regs *regs) { u32 instword; @@ -697,6 +723,11 @@ static int emulate_instruction(struct pt_regs *regs) if ((instword & INST_STRING_GEN_MASK) == INST_STRING) return emulate_string_inst(regs, instword); + /* Emulate the popcntb (Population Count Bytes) instruction. */ + if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) { + return emulate_popcntb_inst(regs, instword); + } + return -EINVAL; }