aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2017-04-18 12:38:17 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2017-05-03 00:45:39 -0400
commitd93b0ac01a9ce276ec39644be47001873d3d183c (patch)
treefc9a6ccc58e0f8e925ba3f731beff5090f993d0b
parent3f2290e1b5192fdfa74f012220a8d90067beb076 (diff)
powerpc/book3s/mce: Move add_taint() later in virtual mode
machine_check_early() gets called in real mode. The very first time when add_taint() is called, it prints a warning which ends up calling opal call (that uses OPAL_CALL wrapper) for writing it to console. If we get a very first machine check while we are in opal we are doomed. OPAL_CALL overwrites the PACASAVEDMSR in r13 and in this case when we are done with MCE handling the original opal call will use this new MSR on it's way back to opal_return. This usually leads to unexpected behaviour or the kernel to panic. Instead move the add_taint() call later in the virtual mode where it is safe to call. This is broken with current FW level. We got lucky so far for not getting very first MCE hit while in OPAL. But easily reproducible on Mambo. Fixes: 27ea2c420cad ("powerpc: Set the correct kernel taint on machine check errors.") Cc: stable@vger.kernel.org # v4.2+ Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/mce.c2
-rw-r--r--arch/powerpc/kernel/traps.c4
2 files changed, 4 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index 16eb0b508761..5f9eada3519b 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -221,6 +221,8 @@ static void machine_check_process_queued_event(struct irq_work *work)
221{ 221{
222 int index; 222 int index;
223 223
224 add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
225
224 /* 226 /*
225 * For now just print it to console. 227 * For now just print it to console.
226 * TODO: log this error event to FSP or nvram. 228 * TODO: log this error event to FSP or nvram.
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6a81a451d767..d4e545d27ef9 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -323,8 +323,6 @@ long machine_check_early(struct pt_regs *regs)
323 323
324 __this_cpu_inc(irq_stat.mce_exceptions); 324 __this_cpu_inc(irq_stat.mce_exceptions);
325 325
326 add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
327
328 if (cur_cpu_spec && cur_cpu_spec->machine_check_early) 326 if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
329 handled = cur_cpu_spec->machine_check_early(regs); 327 handled = cur_cpu_spec->machine_check_early(regs);
330 return handled; 328 return handled;
@@ -758,6 +756,8 @@ void machine_check_exception(struct pt_regs *regs)
758 756
759 __this_cpu_inc(irq_stat.mce_exceptions); 757 __this_cpu_inc(irq_stat.mce_exceptions);
760 758
759 add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
760
761 /* See if any machine dependent calls. In theory, we would want 761 /* See if any machine dependent calls. In theory, we would want
762 * to call the CPU first, and call the ppc_md. one if the CPU 762 * to call the CPU first, and call the ppc_md. one if the CPU
763 * one returns a positive number. However there is existing code 763 * one returns a positive number. However there is existing code