int cpu_machinecheck(struct cpu_user_regs *regs) { int recover = 0; u32 dsisr = mfdsisr(); if (regs->msr & MCK_SRR1_RI) recover = 1; printk("MACHINE CHECK: %s Recoverable\n", recover ? "IS": "NOT"); if (mck_cpu_stats[mfpir()] != 0) printk("While in CI IO\n"); show_backtrace_regs(regs); printk("SRR1: 0x%016lx\n", regs->msr); if (regs->msr & MCK_SRR1_INSN_FETCH_UNIT) printk("42: Exception caused by Instruction Fetch Unit (IFU)\n" " detection of a hardware uncorrectable error (UE).\n"); if (regs->msr & MCK_SRR1_LOAD_STORE) printk("43: Exception caused by load/store detection of error\n" " (see DSISR)\n"); switch (regs->msr & MCK_SRR1_CAUSE_MASK) { case 0: printk("0b00: Likely caused by an asynchronous machine check,\n" " see SCOM Asynchronous Machine Check Register\n"); cpu_scom_AMCR(); break; case MCK_SRR1_CAUSE_SLB_PAR: printk("0b01: Exception caused by an SLB parity error detected\n" " while translating an instruction fetch address.\n"); break; case MCK_SRR1_CAUSE_TLB_PAR: printk("0b10: Exception caused by a TLB parity error detected\n" " while translating an instruction fetch address.\n"); break; case MCK_SRR1_CAUSE_UE: printk("0b11: Exception caused by a hardware uncorrectable\n" " error (UE) detected while doing a reload of an\n" " instruction-fetch TLB tablewalk.\n"); break; } printk("\nDSISR: 0x%08x\n", dsisr); if (dsisr & MCK_DSISR_UE) printk("16: Exception caused by a UE deferred error\n" " (DAR is undefined).\n"); if (dsisr & MCK_DSISR_UE_TABLE_WALK) printk("17: Exception caused by a UE deferred error\n" " during a tablewalk (D-side).\n"); if (dsisr & MCK_DSISR_L1_DCACHE_PAR) printk("18: Exception was caused by a software recoverable\n" " parity error in the L1 D-cache.\n"); if (dsisr & MCK_DSISR_L1_DCACHE_TAG_PAR) printk("19: Exception was caused by a software recoverable\n" " parity error in the L1 D-cache tag.\n"); if (dsisr & MCK_DSISR_D_ERAT_PAR) printk("20: Exception was caused by a software recoverable parity\n" " error in the D-ERAT.\n"); if (dsisr & MCK_DSISR_TLB_PAR) printk("21: Exception was caused by a software recoverable parity\n" " error in the TLB.\n"); if (dsisr & MCK_DSISR_SLB_PAR) { printk("23: Exception was caused by an SLB parity error (may not be\n" " recoverable). This condition could occur if the\n" " effective segment ID (ESID) fields of two or more SLB\n" " entries contain the same value.\n"); dump_segments(0); } return 0; /* for now lets not recover */ }
/* * generate a backtrace of the kernel stack */ void show_backtrace(struct pt_regs *frame, unsigned long sp) { struct pt_regs *frame0; unsigned long tos = 0, stop = 0, base; int format; base = ((((unsigned long) frame) + 8191) & ~8191) - sizeof(struct user_context); frame0 = (struct pt_regs *) base; if (sp) { tos = sp; stop = (unsigned long) frame; } printk("\nProcess %s (pid: %d)\n\n", current->comm, current->pid); for (;;) { /* dump stack segment between frames */ //printk("%08lx -> %08lx\n", tos, stop); format = 0; while (tos < stop) { if (format == 0) printk(" %04lx :", tos & 0xffff); printk(" %08lx", *(unsigned long *) tos); tos += 4; format++; if (format == 8) { printk("\n"); format = 0; } } if (format > 0) printk("\n"); /* dump frame 0 outside of the loop */ if (frame == frame0) break; tos = frame->sp; if (((unsigned long) frame) + sizeof(*frame) != tos) { printk("-- TOS %08lx does not follow frame %p --\n", tos, frame); break; } show_backtrace_regs(frame); /* dump the stack between this frame and the next */ stop = (unsigned long) frame->next_frame; if (stop != base && (stop < tos || stop > base || (stop < base && stop + sizeof(*frame) > base) || stop & 3)) { printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n", stop, tos, base); break; } /* move to next frame */ frame = frame->next_frame; } /* we can always dump frame 0, even if the rest of the stack is corrupt */ show_backtrace_regs(frame0); } /* end show_backtrace() */
void show_backtrace(struct pt_regs *frame, unsigned long sp) { struct pt_regs *frame0; unsigned long tos = 0, stop = 0, base; int format; base = ((((unsigned long) frame) + 8191) & ~8191) - sizeof(struct user_context); frame0 = (struct pt_regs *) base; if (sp) { tos = sp; stop = (unsigned long) frame; } printk("\nProcess %s (pid: %d)\n\n", current->comm, current->pid); for (;;) { /* */ // format = 0; while (tos < stop) { if (format == 0) printk(" %04lx :", tos & 0xffff); printk(" %08lx", *(unsigned long *) tos); tos += 4; format++; if (format == 8) { printk("\n"); format = 0; } } if (format > 0) printk("\n"); /* */ if (frame == frame0) break; tos = frame->sp; if (((unsigned long) frame) + sizeof(*frame) != tos) { printk("-- TOS %08lx does not follow frame %p --\n", tos, frame); break; } show_backtrace_regs(frame); /* */ stop = (unsigned long) frame->next_frame; if (stop != base && (stop < tos || stop > base || (stop < base && stop + sizeof(*frame) > base) || stop & 3)) { printk("-- next_frame %08lx is invalid (range %08lx-%08lx) --\n", stop, tos, base); break; } /* */ frame = frame->next_frame; } /* */ show_backtrace_regs(frame0); } /* */