xmon can be entered via sreset NMI (from a management sreset, or an NMI IPI), which can interrupt OPAL. xmon will then issue OPAL calls to read and write the console, which re-enter OPAL and will destroy the OPAL stack. So xmon must not attempt to recover in this case.
Signed-off-by: Nicholas Piggin <npig...@gmail.com> -- Skiboot at the moment will spew messages about re-entrant call detected and things will go bad from there. I have some patches for it that allow a few calls through that allow the console to work from xmon, obviously still not recoverable. --- arch/powerpc/include/asm/opal.h | 2 ++ arch/powerpc/platforms/powernv/opal.c | 5 +++++ arch/powerpc/xmon/xmon.c | 14 ++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 12e70fb58700..b7efd9b0c720 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -27,6 +27,8 @@ extern struct kobject *opal_kobj; /* /ibm,opal */ extern struct device_node *opal_node; +bool in_opal_text(u64 address); + /* API functions */ int64_t opal_invalid_call(void); int64_t opal_npu_destroy_context(uint64_t phb_id, uint64_t pid, uint64_t bdf); diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index c15182765ff5..88627b59ea2e 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -64,6 +64,11 @@ static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX]; static uint32_t opal_heartbeat; static struct task_struct *kopald_tsk; +bool in_opal_text(u64 address) +{ + return (address >= opal.base && address < opal.base + opal.size); +} + void opal_configure_cores(void) { u64 reinit_flags = 0; diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 82e1a3ee6e0f..482709933c46 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -510,6 +510,20 @@ static int xmon_core(struct pt_regs *regs, int fromipi) xmon_fault_jmp[cpu] = recurse_jmp; + if (firmware_has_feature(FW_FEATURE_OPAL)) { + if (in_opal_text(regs->nip)) { + printf("WARNING: cpu 0x%x stopped in OPAL, cannot recover\n", cpu); + regs->msr &= ~MSR_RI; + /* + * It should be possible to return to OPAL if we + * didn't do anything else here, but xmon makes + * re-entrant OPAL calls to print console, which will + * trash the OPAL stack. So we have to mark ourselves + * as non-recoverable here. + */ + } + } + bp = NULL; if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT)) bp = at_breakpoint(regs->nip); -- 2.16.1