powerpc: Fix fatal SLB miss when restoring PPR
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 5 Nov 2013 05:33:22 +0000 (16:33 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 6 Nov 2013 03:13:53 +0000 (14:13 +1100)
When restoring the PPR value, we incorrectly access the thread structure
at a time where MSR:RI is clear, which means we cannot recover from nested
faults. However the thread structure isn't covered by the "bolted" SLB
entries and thus accessing can fault.

This fixes it by splitting the code so that the PPR value is loaded into
a GPR before MSR:RI is cleared.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/kernel/entry_64.S

index 8deaaad3b32fcfa0c2bf0bd14434dcdfd411fe7a..3c1acc31a09280bdc8c706813879571587f3d75e 100644 (file)
@@ -406,13 +406,6 @@ BEGIN_FTR_SECTION_NESTED(945)                                              \
        std     ra,TASKTHREADPPR(rb);                                   \
 END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945)
 
-#define RESTORE_PPR(ra, rb)                                            \
-BEGIN_FTR_SECTION_NESTED(946)                                          \
-       ld      ra,PACACURRENT(r13);                                    \
-       ld      rb,TASKTHREADPPR(ra);                                   \
-       mtspr   SPRN_PPR,rb;    /* Restore PPR */                       \
-END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
-
 #endif
 
 /*
index 12679cd43e0c4600c52d87695145760501a78530..bbfb0294b3544072ac22b2fcfee486620ae1479e 100644 (file)
@@ -818,6 +818,12 @@ fast_exception_return:
        andi.   r0,r3,MSR_RI
        beq-    unrecov_restore
 
+       /* Load PPR from thread struct before we clear MSR:RI */
+BEGIN_FTR_SECTION
+       ld      r2,PACACURRENT(r13)
+       ld      r2,TASKTHREADPPR(r2)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+
        /*
         * Clear RI before restoring r13.  If we are returning to
         * userspace and we take an exception after restoring r13,
@@ -838,8 +844,10 @@ fast_exception_return:
         */
        andi.   r0,r3,MSR_PR
        beq     1f
+BEGIN_FTR_SECTION
+       mtspr   SPRN_PPR,r2     /* Restore PPR */
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        ACCOUNT_CPU_USER_EXIT(r2, r4)
-       RESTORE_PPR(r2, r4)
        REST_GPR(13, r1)
 1:
        mtspr   SPRN_SRR1,r3