]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
powerpc/64s: Fix system reset interrupt winkle wakeups
authorNicholas Piggin <npiggin@gmail.com>
Wed, 2 Nov 2016 06:57:01 +0000 (17:57 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Sat, 12 Nov 2016 09:12:42 +0000 (20:12 +1100)
Wakeups from winkle set the low bit of the HSPRG0 register, to
distinguish it from other sleep states. This is also the PACA pointer.
The system reset exception handler fails to mask this bit away before
using this value before using it as the PACA pointer.

Fix this by adding a new type of exception prolog macro where we already
have the PACA set in r13, and have the system reset vector mask it out.
The winkle wakeup handler will store the masked value back into HSPRG0.

Fixes: fb479e44a9e2 ("powerpc/64s: relocation, register save fixes for system reset interrupt")
Cc: stable@vger.kernel.org # v3.0+
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/kernel/exceptions-64s.S

index 84d49b197c3298be4308f1db00af86439635702f..3ce43664eadf622001173a74b650ad83dde086c3 100644 (file)
@@ -158,14 +158,17 @@ BEGIN_FTR_SECTION_NESTED(943)                                             \
        std     ra,offset(r13);                                         \
 END_FTR_SECTION_NESTED(ftr,ftr,943)
 
-#define EXCEPTION_PROLOG_0(area)                                       \
-       GET_PACA(r13);                                                  \
+#define EXCEPTION_PROLOG_0_PACA(area)                                  \
        std     r9,area+EX_R9(r13);     /* save r9 */                   \
        OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);                     \
        HMT_MEDIUM;                                                     \
        std     r10,area+EX_R10(r13);   /* save r10 - r12 */            \
        OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR)
 
+#define EXCEPTION_PROLOG_0(area)                                       \
+       GET_PACA(r13);                                                  \
+       EXCEPTION_PROLOG_0_PACA(area)
+
 #define __EXCEPTION_PROLOG_1(area, extra, vec)                         \
        OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR);         \
        OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR);          \
@@ -196,6 +199,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
        EXCEPTION_PROLOG_1(area, extra, vec);                           \
        EXCEPTION_PROLOG_PSERIES_1(label, h);
 
+/* Have the PACA in r13 already */
+#define EXCEPTION_PROLOG_PSERIES_PACA(area, label, h, extra, vec)      \
+       EXCEPTION_PROLOG_0_PACA(area);                                  \
+       EXCEPTION_PROLOG_1(area, extra, vec);                           \
+       EXCEPTION_PROLOG_PSERIES_1(label, h);
+
 #define __KVMTEST(h, n)                                                        \
        lbz     r10,HSTATE_IN_GUEST(r13);                               \
        cmpwi   r10,0;                                                  \
index 08ba447a4b3dae99676c8b42b8c6deea1866b042..1ba82ea9023093ae3d58eedba4b9542bae137047 100644 (file)
@@ -116,7 +116,9 @@ EXC_VIRT_NONE(0x4000, 0x4100)
 
 EXC_REAL_BEGIN(system_reset, 0x100, 0x200)
        SET_SCRATCH0(r13)
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+       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,
                                 IDLETEST, 0x100)
 
 EXC_REAL_END(system_reset, 0x100, 0x200)
@@ -124,6 +126,9 @@ EXC_VIRT_NONE(0x4100, 0x4200)
 
 #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
 
        li      r0,PNV_THREAD_RUNNING
@@ -169,7 +174,7 @@ EXC_REAL_BEGIN(machine_check, 0x200, 0x300)
        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 HSPGR0 would be set
+        * inside machine check. If yes, then last bit of HSPRG0 would be set
         * to 1. Hence clear it unconditionally.
         */
        GET_PACA(r13)
@@ -388,7 +393,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
        /*
         * 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 HSPGR0
+        * 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.