]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/kernel/exceptions-64s.S
Merge tag 'powerpc-4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[karo-tx-linux.git] / arch / powerpc / kernel / exceptions-64s.S
index 6353019966e6a3bd15afa32d7318c47810a1d8e9..a9312b52fe6fdc5336e82cdd55f5f86b2729c6e3 100644 (file)
@@ -116,9 +116,11 @@ EXC_VIRT_NONE(0x4000, 0x100)
 
 EXC_REAL_BEGIN(system_reset, 0x100, 0x100)
        SET_SCRATCH0(r13)
-       GET_PACA(r13)
-       clrrdi  r13,r13,1 /* Last bit of HSPRG0 is set if waking from winkle */
-       EXCEPTION_PROLOG_PSERIES_PACA(PACA_EXGEN, system_reset_common, EXC_STD,
+       /*
+        * MSR_RI is not enabled, because PACA_EXNMI and nmi stack is
+        * being used, so a nested NMI exception would corrupt it.
+        */
+       EXCEPTION_PROLOG_PSERIES_NORI(PACA_EXNMI, system_reset_common, EXC_STD,
                                 IDLETEST, 0x100)
 
 EXC_REAL_END(system_reset, 0x100, 0x100)
@@ -126,34 +128,37 @@ EXC_VIRT_NONE(0x4100, 0x100)
 
 #ifdef CONFIG_PPC_P7_NAP
 EXC_COMMON_BEGIN(system_reset_idle_common)
-BEGIN_FTR_SECTION
-       GET_PACA(r13) /* Restore HSPRG0 to get the winkle bit in r13 */
-END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
-       bl      pnv_restore_hyp_resource
+       b       pnv_powersave_wakeup
+#endif
 
-       li      r0,PNV_THREAD_RUNNING
-       stb     r0,PACA_THREAD_IDLE_STATE(r13)  /* Clear thread state */
+EXC_COMMON_BEGIN(system_reset_common)
+       /*
+        * Increment paca->in_nmi then enable MSR_RI. SLB or MCE will be able
+        * to recover, but nested NMI will notice in_nmi and not recover
+        * because of the use of the NMI stack. in_nmi reentrancy is tested in
+        * system_reset_exception.
+        */
+       lhz     r10,PACA_IN_NMI(r13)
+       addi    r10,r10,1
+       sth     r10,PACA_IN_NMI(r13)
+       li      r10,MSR_RI
+       mtmsrd  r10,1
 
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
-       li      r0,KVM_HWTHREAD_IN_KERNEL
-       stb     r0,HSTATE_HWTHREAD_STATE(r13)
-       /* Order setting hwthread_state vs. testing hwthread_req */
-       sync
-       lbz     r0,HSTATE_HWTHREAD_REQ(r13)
-       cmpwi   r0,0
-       beq     1f
-       BRANCH_TO_KVM(r10, kvm_start_guest)
-1:
-#endif
+       mr      r10,r1
+       ld      r1,PACA_NMI_EMERG_SP(r13)
+       subi    r1,r1,INT_FRAME_SIZE
+       EXCEPTION_COMMON_NORET_STACK(PACA_EXNMI, 0x100,
+                       system_reset, system_reset_exception,
+                       ADD_NVGPRS;ADD_RECONCILE)
 
-       /* Return SRR1 from power7_nap() */
-       mfspr   r3,SPRN_SRR1
-       blt     cr3,2f
-       b       pnv_wakeup_loss
-2:     b       pnv_wakeup_noloss
-#endif
+       /*
+        * The stack is no longer in use, decrement in_nmi.
+        */
+       lhz     r10,PACA_IN_NMI(r13)
+       subi    r10,r10,1
+       sth     r10,PACA_IN_NMI(r13)
 
-EXC_COMMON(system_reset_common, 0x100, system_reset_exception)
+       b       ret_from_except
 
 #ifdef CONFIG_PPC_PSERIES
 /*
@@ -161,8 +166,9 @@ EXC_COMMON(system_reset_common, 0x100, system_reset_exception)
  */
 TRAMP_REAL_BEGIN(system_reset_fwnmi)
        SET_SCRATCH0(r13)               /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
-                                NOTEST, 0x100)
+       /* See comment at system_reset exception */
+       EXCEPTION_PROLOG_PSERIES_NORI(PACA_EXNMI, system_reset_common,
+                                               EXC_STD, NOTEST, 0x100)
 #endif /* CONFIG_PPC_PSERIES */
 
 
@@ -172,14 +178,6 @@ EXC_REAL_BEGIN(machine_check, 0x200, 0x100)
         * vector
         */
        SET_SCRATCH0(r13)               /* save r13 */
-       /*
-        * Running native on arch 2.06 or later, we may wakeup from winkle
-        * inside machine check. If yes, then last bit of HSPRG0 would be set
-        * to 1. Hence clear it unconditionally.
-        */
-       GET_PACA(r13)
-       clrrdi  r13,r13,1
-       SET_PACA(r13)
        EXCEPTION_PROLOG_0(PACA_EXMC)
 BEGIN_FTR_SECTION
        b       machine_check_powernv_early
@@ -212,6 +210,12 @@ BEGIN_FTR_SECTION
         * NOTE: We are here with MSR_ME=0 (off), which means we risk a
         * checkstop if we get another machine check exception before we do
         * rfid with MSR_ME=1.
+        *
+        * This interrupt can wake directly from idle. If that is the case,
+        * the machine check is handled then the idle wakeup code is called
+        * to restore state. In that case, the POWER9 DD1 idle PACA workaround
+        * is not applied in the early machine check code, which will cause
+        * bugs.
         */
        mr      r11,r1                  /* Save r1 */
        lhz     r10,PACA_IN_MCE(r13)
@@ -268,20 +272,11 @@ machine_check_fwnmi:
 machine_check_pSeries_0:
        EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST_PR, 0x200)
        /*
-        * The following is essentially EXCEPTION_PROLOG_PSERIES_1 with the
-        * difference that MSR_RI is not enabled, because PACA_EXMC is being
-        * used, so nested machine check corrupts it. machine_check_common
-        * enables MSR_RI.
+        * MSR_RI is not enabled, because PACA_EXMC is being used, so a
+        * nested machine check corrupts it. machine_check_common enables
+        * MSR_RI.
         */
-       ld      r10,PACAKMSR(r13)
-       xori    r10,r10,MSR_RI
-       mfspr   r11,SPRN_SRR0
-       LOAD_HANDLER(r12, machine_check_common)
-       mtspr   SPRN_SRR0,r12
-       mfspr   r12,SPRN_SRR1
-       mtspr   SPRN_SRR1,r10
-       rfid
-       b       .       /* prevent speculative execution */
+       EXCEPTION_PROLOG_PSERIES_1_NORI(machine_check_common, EXC_STD)
 
 TRAMP_KVM_SKIP(PACA_EXMC, 0x200)
 
@@ -340,6 +335,37 @@ EXC_COMMON_BEGIN(machine_check_common)
        /* restore original r1. */                      \
        ld      r1,GPR1(r1)
 
+#ifdef CONFIG_PPC_P7_NAP
+/*
+ * This is an idle wakeup. Low level machine check has already been
+ * done. Queue the event then call the idle code to do the wake up.
+ */
+EXC_COMMON_BEGIN(machine_check_idle_common)
+       bl      machine_check_queue_event
+
+       /*
+        * We have not used any non-volatile GPRs here, and as a rule
+        * most exception code including machine check does not.
+        * Therefore PACA_NAPSTATELOST does not need to be set. Idle
+        * wakeup will restore volatile registers.
+        *
+        * Load the original SRR1 into r3 for pnv_powersave_wakeup_mce.
+        *
+        * Then decrement MCE nesting after finishing with the stack.
+        */
+       ld      r3,_MSR(r1)
+
+       lhz     r11,PACA_IN_MCE(r13)
+       subi    r11,r11,1
+       sth     r11,PACA_IN_MCE(r13)
+
+       /* Turn off the RI bit because SRR1 is used by idle wakeup code. */
+       /* Recoverability could be improved by reducing the use of SRR1. */
+       li      r11,0
+       mtmsrd  r11,1
+
+       b       pnv_powersave_wakeup_mce
+#endif
        /*
         * Handle machine check early in real mode. We come here with
         * ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
@@ -352,6 +378,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
        bl      machine_check_early
        std     r3,RESULT(r1)   /* Save result */
        ld      r12,_MSR(r1)
+
 #ifdef CONFIG_PPC_P7_NAP
        /*
         * Check if thread was in power saving mode. We come here when any
@@ -362,48 +389,14 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
         *
         * Go back to nap/sleep/winkle mode again if (b) is true.
         */
-       rlwinm. r11,r12,47-31,30,31     /* Was it in power saving mode? */
-       beq     4f                      /* No, it wasn;t */
-       /* Thread was in power saving mode. Go back to nap again. */
-       cmpwi   r11,2
-       blt     3f
-       /* Supervisor/Hypervisor state loss */
-       li      r0,1
-       stb     r0,PACA_NAPSTATELOST(r13)
-3:     bl      machine_check_queue_event
-       MACHINE_CHECK_HANDLER_WINDUP
-       GET_PACA(r13)
-       ld      r1,PACAR1(r13)
-       /*
-        * Check what idle state this CPU was in and go back to same mode
-        * again.
-        */
-       lbz     r3,PACA_THREAD_IDLE_STATE(r13)
-       cmpwi   r3,PNV_THREAD_NAP
-       bgt     10f
-       IDLE_STATE_ENTER_SEQ_NORET(PPC_NAP)
-       /* No return */
-10:
-       cmpwi   r3,PNV_THREAD_SLEEP
-       bgt     2f
-       IDLE_STATE_ENTER_SEQ_NORET(PPC_SLEEP)
-       /* No return */
-
-2:
-       /*
-        * Go back to winkle. Please note that this thread was woken up in
-        * machine check from winkle and have not restored the per-subcore
-        * state. Hence before going back to winkle, set last bit of HSPRG0
-        * to 1. This will make sure that if this thread gets woken up
-        * again at reset vector 0x100 then it will get chance to restore
-        * the subcore state.
-        */
-       ori     r13,r13,1
-       SET_PACA(r13)
-       IDLE_STATE_ENTER_SEQ_NORET(PPC_WINKLE)
-       /* No return */
+       BEGIN_FTR_SECTION
+       rlwinm. r11,r12,47-31,30,31
+       beq-    4f
+       BRANCH_TO_COMMON(r10, machine_check_idle_common)
 4:
+       END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 #endif
+
        /*
         * Check if we are coming from hypervisor userspace. If yes then we
         * continue in host kernel in V mode to deliver the MC event.
@@ -968,17 +961,12 @@ EXC_VIRT_NONE(0x4e60, 0x20)
 TRAMP_KVM_HV(PACA_EXGEN, 0xe60)
 TRAMP_REAL_BEGIN(hmi_exception_early)
        EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, 0xe60)
-       mr      r10,r1                  /* Save r1                      */
-       ld      r1,PACAEMERGSP(r13)     /* Use emergency stack          */
+       mr      r10,r1                  /* Save r1 */
+       ld      r1,PACAEMERGSP(r13)     /* Use emergency stack for realmode */
        subi    r1,r1,INT_FRAME_SIZE    /* alloc stack frame            */
-       std     r9,_CCR(r1)             /* save CR in stackframe        */
        mfspr   r11,SPRN_HSRR0          /* Save HSRR0 */
-       std     r11,_NIP(r1)            /* save HSRR0 in stackframe     */
-       mfspr   r12,SPRN_HSRR1          /* Save SRR1 */
-       std     r12,_MSR(r1)            /* save SRR1 in stackframe      */
-       std     r10,0(r1)               /* make stack chain pointer     */
-       std     r0,GPR0(r1)             /* save r0 in stackframe        */
-       std     r10,GPR1(r1)            /* save r1 in stackframe        */
+       mfspr   r12,SPRN_HSRR1          /* Save HSRR1 */
+       EXCEPTION_PROLOG_COMMON_1()
        EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN)
        EXCEPTION_PROLOG_COMMON_3(0xe60)
        addi    r3,r1,STACK_FRAME_OVERHEAD