#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
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");
#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;
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;
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;
}
void alignment_exception(struct pt_regs *regs)
{
- int fixed = 0;
+ int sig, code, fixed = 0;
/* we don't implement logging of alignment exceptions */
if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
/* Operand address was bad */
if (fixed == -EFAULT) {
- if (user_mode(regs))
- _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
- else
- /* Search exception table */
- bad_page_fault(regs, regs->dar, SIGSEGV);
- return;
+ sig = SIGSEGV;
+ code = SEGV_ACCERR;
+ } else {
+ sig = SIGBUS;
+ code = BUS_ADRALN;
}
- _exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+ if (user_mode(regs))
+ _exception(sig, regs, code, regs->dar);
+ else
+ bad_page_fault(regs, regs->dar, sig);
}
void StackOverflow(struct pt_regs *regs)
void altivec_unavailable_exception(struct pt_regs *regs)
{
-#if !defined(CONFIG_ALTIVEC)
if (user_mode(regs)) {
/* A user program has executed an altivec instruction,
but this kernel doesn't support altivec. */
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
return;
}
-#endif
+
printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
"%lx at %lx\n", regs->trap, regs->nip);
die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);