summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/mce.c7
-rw-r--r--arch/powerpc/kernel/traps.c14
2 files changed, 20 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index 8077b5fb18a7..be7e3f92a7b5 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -574,6 +574,9 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);
long machine_check_early(struct pt_regs *regs)
{
long handled = 0;
+ bool nested = in_nmi();
+ if (!nested)
+ nmi_enter();
hv_nmi_check_nonrecoverable(regs);
@@ -582,6 +585,10 @@ long machine_check_early(struct pt_regs *regs)
*/
if (ppc_md.machine_check_early)
handled = ppc_md.machine_check_early(regs);
+
+ if (!nested)
+ nmi_exit();
+
return handled;
}
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3fca22276bb1..9f6852322e59 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -823,7 +823,19 @@ int machine_check_generic(struct pt_regs *regs)
void machine_check_exception(struct pt_regs *regs)
{
int recover = 0;
- bool nested = in_nmi();
+ bool nested;
+
+ /*
+ * BOOK3S_64 does not call this handler as a non-maskable interrupt
+ * (it uses its own early real-mode handler to handle the MCE proper
+ * and then raises irq_work to call this handler when interrupts are
+ * enabled). Set nested = true for this case, which just makes it avoid
+ * the nmi_enter/exit.
+ */
+ if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) || in_nmi())
+ nested = true;
+ else
+ nested = false;
if (!nested)
nmi_enter();