aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2019-02-26 03:51:08 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2019-02-26 07:28:25 -0500
commitcbf2ba952a70399c972f2a2126a4ac6f79437f37 (patch)
tree9eeb7c98b7915885032123073fc6bf5f4046b766
parentccd477028a202993b9ddca5d2404fdaca3b7a55c (diff)
powerpc/64s: system reset interrupt preserve HSRRs
Code that uses HSRR registers is not required to clear MSR[RI] by convention, however the system reset NMI itself may use HSRR registers (e.g., to call OPAL) and clobber them. Rather than introduce the requirement to clear RI in order to use HSRRs, have system reset interrupt save and restore HSRRs. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/traps.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index eee8f843f3d6..a5757bef03cd 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -435,14 +435,32 @@ nonrecoverable:
435 435
436void system_reset_exception(struct pt_regs *regs) 436void system_reset_exception(struct pt_regs *regs)
437{ 437{
438 unsigned long hsrr0, hsrr1;
439 bool nested = in_nmi();
440 bool saved_hsrrs = false;
441
438 /* 442 /*
439 * Avoid crashes in case of nested NMI exceptions. Recoverability 443 * Avoid crashes in case of nested NMI exceptions. Recoverability
440 * is determined by RI and in_nmi 444 * is determined by RI and in_nmi
441 */ 445 */
442 bool nested = in_nmi();
443 if (!nested) 446 if (!nested)
444 nmi_enter(); 447 nmi_enter();
445 448
449 /*
450 * System reset can interrupt code where HSRRs are live and MSR[RI]=1.
451 * The system reset interrupt itself may clobber HSRRs (e.g., to call
452 * OPAL), so save them here and restore them before returning.
453 *
454 * Machine checks don't need to save HSRRs, as the real mode handler
455 * is careful to avoid them, and the regular handler is not delivered
456 * as an NMI.
457 */
458 if (cpu_has_feature(CPU_FTR_HVMODE)) {
459 hsrr0 = mfspr(SPRN_HSRR0);
460 hsrr1 = mfspr(SPRN_HSRR1);
461 saved_hsrrs = true;
462 }
463
446 hv_nmi_check_nonrecoverable(regs); 464 hv_nmi_check_nonrecoverable(regs);
447 465
448 __this_cpu_inc(irq_stat.sreset_irqs); 466 __this_cpu_inc(irq_stat.sreset_irqs);
@@ -492,6 +510,11 @@ out:
492 if (!(regs->msr & MSR_RI)) 510 if (!(regs->msr & MSR_RI))
493 nmi_panic(regs, "Unrecoverable System Reset"); 511 nmi_panic(regs, "Unrecoverable System Reset");
494 512
513 if (saved_hsrrs) {
514 mtspr(SPRN_HSRR0, hsrr0);
515 mtspr(SPRN_HSRR1, hsrr1);
516 }
517
495 if (!nested) 518 if (!nested)
496 nmi_exit(); 519 nmi_exit();
497 520