powerpc/64s/exception: machine check move unrecoverable handling out of line
authorNicholas Piggin <npiggin@gmail.com>
Fri, 2 Aug 2019 10:56:39 +0000 (20:56 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 30 Aug 2019 00:32:36 +0000 (10:32 +1000)
Similarly to the previous change, all callers of the unrecoverable
handler run relocated so can reach it with a direct branch. This makes
it easy to move out of line, which makes the "normal" path less
cluttered and easier to follow.

MSR[ME] manipulation still requires the rfi, so that is moved out of
line to its own function.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190802105709.27696-15-npiggin@gmail.com
arch/powerpc/kernel/exceptions-64s.S

index bbbcab88cf78a6b7de74a7c593cb8ba4471d89b3..af18d0f1d4ab3ebcfa2b79d35b8a5515fc098250 100644 (file)
@@ -992,9 +992,9 @@ EXC_COMMON_BEGIN(machine_check_early_common)
        bne     1f
        /* First machine check entry */
        ld      r1,PACAMCEMERGSP(r13)   /* Use MC emergency stack */
-1:     subi    r1,r1,INT_FRAME_SIZE    /* alloc stack frame */
-       /* Limit nested MCE to level 4 to avoid stack overflow */
-       bge     cr1,2f                  /* Check if we hit limit of 4 */
+1:     /* Limit nested MCE to level 4 to avoid stack overflow */
+       bgt     cr1,unrecoverable_mce   /* Check if we hit limit of 4 */
+       subi    r1,r1,INT_FRAME_SIZE    /* alloc stack frame */
 
        EXCEPTION_PROLOG_COMMON_1()
        /* We don't touch AMR here, we never go to virtual mode */
@@ -1013,21 +1013,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
        mtmsrd  r10,1
        b       machine_check_handle_early
 
-2:
-       /* Stack overflow. Stay on emergency stack and panic.
-        * Keep the ME bit off while panic-ing, so that if we hit
-        * another machine check we checkstop.
-        */
-       addi    r1,r1,INT_FRAME_SIZE    /* go back to previous stack frame */
-       ld      r11,PACAKMSR(r13)
-       LOAD_HANDLER(r12, unrecover_mce)
-       li      r10,MSR_ME
-       andc    r11,r11,r10             /* Turn off MSR_ME */
-       mtspr   SPRN_SRR0,r12
-       mtspr   SPRN_SRR1,r11
-       RFI_TO_KERNEL
-       b       .       /* prevent speculative execution */
-
 EXC_COMMON_BEGIN(machine_check_common)
        /*
         * Machine check is different because we use a different
@@ -1141,32 +1126,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
         * If yes, then stay on emergency stack and panic.
         */
        andi.   r11,r12,MSR_RI
-       bne     2f
-1:     mfspr   r11,SPRN_SRR0
-       LOAD_HANDLER(r10,unrecover_mce)
-       mtspr   SPRN_SRR0,r10
-       ld      r10,PACAKMSR(r13)
-       /*
-        * We are going down. But there are chances that we might get hit by
-        * another MCE during panic path and we may run into unstable state
-        * with no way out. Hence, turn ME bit off while going down, so that
-        * when another MCE is hit during panic path, system will checkstop
-        * and hypervisor will get restarted cleanly by SP.
-        */
-       li      r3,MSR_ME
-       andc    r10,r10,r3              /* Turn off MSR_ME */
-       mtspr   SPRN_SRR1,r10
-       RFI_TO_KERNEL
-       b       .
-2:
+       beq     unrecoverable_mce
+
        /*
         * Check if we have successfully handled/recovered from error, if not
         * then stay on emergency stack and panic.
         */
        ld      r3,RESULT(r1)   /* Load result */
        cmpdi   r3,0            /* see if we handled MCE successfully */
-
-       beq     1b              /* if !handled then panic */
+       beq     unrecoverable_mce /* if !handled then panic */
 
        /*
         * Return from MC interrupt.
@@ -1189,17 +1157,35 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
        EXCEPTION_PROLOG_1 EXC_STD, PACA_EXMC, 1, 0x200, 1, 1, 0
        EXCEPTION_PROLOG_2_REAL machine_check_common, EXC_STD, 0
 
-EXC_COMMON_BEGIN(unrecover_mce)
+EXC_COMMON_BEGIN(unrecoverable_mce)
+       /*
+        * We are going down. But there are chances that we might get hit by
+        * another MCE during panic path and we may run into unstable state
+        * with no way out. Hence, turn ME bit off while going down, so that
+        * when another MCE is hit during panic path, system will checkstop
+        * and hypervisor will get restarted cleanly by SP.
+        */
+BEGIN_FTR_SECTION
+       li      r10,0 /* clear MSR_RI */
+       mtmsrd  r10,1
+       bl      disable_machine_check
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+       ld      r10,PACAKMSR(r13)
+       li      r3,MSR_ME
+       andc    r10,r10,r3
+       mtmsrd  r10
+
        /* Invoke machine_check_exception to print MCE event and panic. */
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      machine_check_exception
+
        /*
-        * We will not reach here. Even if we did, there is no way out. Call
-        * unrecoverable_exception and die.
+        * We will not reach here. Even if we did, there is no way out.
+        * Call unrecoverable_exception and die.
         */
-1:     addi    r3,r1,STACK_FRAME_OVERHEAD
+       addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      unrecoverable_exception
-       b       1b
+       b       .
 
 
 EXC_REAL_BEGIN(data_access, 0x300, 0x80)
@@ -2282,6 +2268,21 @@ enable_machine_check:
 1:     mtlr    r0
        blr
 
+/* MSR[RI] should be clear because this uses SRR[01] */
+disable_machine_check:
+       mflr    r0
+       bcl     20,31,$+4
+0:     mflr    r3
+       addi    r3,r3,(1f - 0b)
+       mtspr   SPRN_SRR0,r3
+       mfmsr   r3
+       li      r4,MSR_ME
+       andc    r3,r3,r4
+       mtspr   SPRN_SRR1,r3
+       RFI_TO_KERNEL
+1:     mtlr    r0
+       blr
+
 /*
  * Hash table stuff
  */