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 */
}
Esempio n. 2
0
/*
 * 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() */
Esempio n. 3
0
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);

} /*                      */