diff options
-rw-r--r-- | asm/head.S | 29 | ||||
-rw-r--r-- | core/init.c | 15 | ||||
-rw-r--r-- | include/skiboot.h | 2 |
3 files changed, 46 insertions, 0 deletions
@@ -479,6 +479,35 @@ call_relocate: .long 0xa6037b7d; /* mtsrr1 r11 */ \ .long 0x2400004c /* rfid */ +.global enable_machine_check +enable_machine_check: + mflr %r0 + bcl 20,31,$+4 +0: mflr %r3 + addi %r3,%r3,(1f - 0b) + mtspr SPR_HSRR0,%r3 + mfmsr %r3 + ori %r3,%r3,MSR_ME + mtspr SPR_HSRR1,%r3 + hrfid +1: mtlr %r0 + blr + +.global disable_machine_check +disable_machine_check: + mflr %r0 + bcl 20,31,$+4 +0: mflr %r3 + addi %r3,%r3,(1f - 0b) + mtspr SPR_HSRR0,%r3 + mfmsr %r3 + li %r4,MSR_ME + andc %r3,%r3,%r4 + mtspr SPR_HSRR1,%r3 + hrfid +1: mtlr %r0 + blr + pm_save_regs: SAVE_GPR(2,%r1) SAVE_GPR(14,%r1) diff --git a/core/init.c b/core/init.c index 36cf28d..5736d33 100644 --- a/core/init.c +++ b/core/init.c @@ -809,9 +809,24 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) */ clear_console(); + /* + * Some boot firmwares enter OPAL with MSR[ME]=1, as they presumably + * handle machine checks until we take over. As we overwrite the + * previous exception vectors with our own handlers, disable MSR[ME]. + * This could be done atomically by patching in a branch then patching + * it out last, but that's a lot of effort. + */ + disable_machine_check(); + /* Copy all vectors down to 0 */ copy_exception_vectors(); + /* + * Enable MSR[ME] bit so we can take MCEs. We don't currently + * recover, but we print some useful information. + */ + enable_machine_check(); + /* Setup a NULL catcher to catch accidental NULL ptr calls */ setup_branch_null_catcher(); diff --git a/include/skiboot.h b/include/skiboot.h index fd751dc..d1de10a 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -332,6 +332,8 @@ extern void fast_sleep_exit(void); extern void fake_rtc_init(void); /* Assembly in head.S */ +extern void disable_machine_check(void); +extern void enable_machine_check(void); extern void enter_p8_pm_state(bool winkle); extern void enter_p9_pm_state(uint64_t psscr); extern void enter_p9_pm_lite_state(uint64_t psscr); |