@@ -81,6 +81,7 @@ int main(void)
OFFSET(STACK_CR, stack_frame, cr);
OFFSET(STACK_XER, stack_frame, xer);
+ OFFSET(STACK_DSISR, stack_frame, dsisr);
OFFSET(STACK_CTR, stack_frame, ctr);
OFFSET(STACK_LR, stack_frame, lr);
OFFSET(STACK_PC, stack_frame, pc);
@@ -89,6 +90,7 @@ int main(void)
OFFSET(STACK_SRR1, stack_frame, srr1);
OFFSET(STACK_HSRR0, stack_frame, hsrr0);
OFFSET(STACK_HSRR1, stack_frame, hsrr1);
+ OFFSET(STACK_DAR, stack_frame, dar);
DEFINE(STACK_FRAMESIZE, sizeof(struct stack_frame));
return 0;
@@ -210,6 +210,10 @@ _exception:
std %r4,STACK_SRR1(%r1)
std %r5,STACK_HSRR0(%r1)
std %r6,STACK_HSRR1(%r1)
+ mfspr %r3,SPR_DSISR
+ mfspr %r4,SPR_DAR
+ stw %r3,STACK_DSISR(%r1)
+ std %r4,STACK_DAR(%r1)
mr %r3,%r1
LOAD_IMM64(%r4, SKIBOOT_BASE)
LOAD_IMM32(%r5, exception_entry_foo - __head)
@@ -21,17 +21,19 @@
#include <cpu.h>
#define REG "%016llx"
+#define REG32 "%08x"
#define REGS_PER_LINE 4
static void dump_regs(struct stack_frame *stack)
{
unsigned int i;
+ prerror("CFAR : "REG"\n", stack->cfar);
prerror("SRR0 : "REG" SRR1 : "REG"\n", stack->srr0, stack->srr1);
prerror("HSRR0: "REG" HSRR1: "REG"\n", stack->hsrr0, stack->hsrr1);
+ prerror("DSISR: "REG32" DAR : "REG"\n", stack->dsisr, stack->dar);
prerror("LR : "REG" CTR : "REG"\n", stack->lr, stack->ctr);
- prerror("CFAR : "REG"\n", stack->cfar);
- prerror("CR : %08x XER: %08x\n", stack->cr, stack->xer);
+ prerror("CR : "REG32" XER : "REG32"\n", stack->cr, stack->xer);
for (i = 0; i < 16; i++)
prerror("GPR%02d: "REG" GPR%02d: "REG"\n",
i, stack->gpr[i], i + 16, stack->gpr[i + 16]);
@@ -42,8 +44,39 @@ void exception_entry(struct stack_frame *stack) __noreturn;
void exception_entry(struct stack_frame *stack)
{
+ const size_t max = 320;
+ char buf[max];
+ size_t l;
+
prerror("***********************************************\n");
- prerror("Unexpected exception %llx !\n", stack->type);
+ if (stack->type == 0x200) {
+ l = 0;
+ l += snprintf(buf + l, max - l, "Fatal MCE at "REG" ", stack->srr0);
+ l += snprintf_symbol(buf + l, max - l, stack->srr0);
+ prerror("%s\n", buf);
+ } else {
+ uint64_t nip;
+ switch (stack->type) {
+ case 0x500:
+ case 0x980:
+ case 0xe00:
+ case 0xe20:
+ case 0xe40:
+ case 0xe60:
+ case 0xe80:
+ case 0xea0:
+ case 0xf80:
+ nip = stack->hsrr0;
+ break;
+ default:
+ nip = stack->srr0;
+ break;
+ }
+ l = 0;
+ l += snprintf(buf + l, max - l, "Fatal Exception 0x%llx at "REG" ", stack->type, nip);
+ l += snprintf_symbol(buf + l, max - l, nip);
+ prerror("%s\n", buf);
+ }
dump_regs(stack);
abort();
}
@@ -86,6 +86,7 @@ struct stack_frame {
*/
uint32_t cr;
uint32_t xer;
+ uint32_t dsisr;
uint64_t ctr;
uint64_t lr;
uint64_t pc;
@@ -94,6 +95,7 @@ struct stack_frame {
uint64_t srr1;
uint64_t hsrr0;
uint64_t hsrr1;
+ uint64_t dar;
} __attribute__((aligned(16)));
/* Backtrace */
Print DSISR and DAR, to help with deciphering machine check exceptions, and improve the output a bit, decode NIP symbol, improve alignment, etc. Also print a specific header for machine check, because we do expect to see these if there is a hardware failure. Before: [ 0.005968779,3] *********************************************** [ 0.005974102,3] Unexpected exception 200 ! [ 0.005978696,3] SRR0 : 000000003002ad80 SRR1 : 9000000000001000 [ 0.005985239,3] HSRR0: 00000000300027b4 HSRR1: 9000000030001000 [ 0.005991782,3] LR : 000000003002ad80 CTR : 0000000000000000 [ 0.005998130,3] CFAR : 00000000300b58bc [ 0.006002769,3] CR : 40000004 XER: 20000000 [ 0.006008069,3] GPR00: 000000003002ad80 GPR16: 0000000000000000 [ 0.006015170,3] GPR01: 0000000031c03bd0 GPR17: 0000000000000000 [...] After: [ 0.003287941,3] *********************************************** [ 0.003561769,3] Fatal MCE at 000000003002ad80 .nvram_init+0x24 [ 0.003579628,3] CFAR : 00000000300b5964 [ 0.003584268,3] SRR0 : 000000003002ad80 SRR1 : 9000000000001000 [ 0.003590812,3] HSRR0: 00000000300027b4 HSRR1: 9000000030001000 [ 0.003597355,3] DSISR: 00000000 DAR : 0000000000000000 [ 0.003603480,3] LR : 000000003002ad68 CTR : 0000000030093d80 [ 0.003609930,3] CR : 40000004 XER : 20000000 [ 0.003615698,3] GPR00: 00000000300149e8 GPR16: 0000000000000000 [ 0.003622799,3] GPR01: 0000000031c03bc0 GPR17: 0000000000000000 [...] Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- asm/asm-offsets.c | 2 ++ asm/head.S | 4 ++++ core/exceptions.c | 39 ++++++++++++++++++++++++++++++++++++--- include/stack.h | 2 ++ 4 files changed, 44 insertions(+), 3 deletions(-)