powerpc/booke64: Use SPRG7 for VDSO
authorScott Wood <scottwood@freescale.com>
Mon, 10 Mar 2014 22:29:38 +0000 (17:29 -0500)
committerScott Wood <scottwood@freescale.com>
Thu, 20 Mar 2014 00:57:14 +0000 (19:57 -0500)
Previously SPRG3 was marked for use by both VDSO and critical
interrupts (though critical interrupts were not fully implemented).

In commit 8b64a9dfb091f1eca8b7e58da82f1e7d1d5fe0ad ("powerpc/booke64:
Use SPRG0/3 scratch for bolted TLB miss & crit int"), Mihai Caraman
made an attempt to resolve this conflict by restoring the VDSO value
early in the critical interrupt, but this has some issues:

 - It's incompatible with EXCEPTION_COMMON which restores r13 from the
   by-then-overwritten scratch (this cost me some debugging time).
 - It forces critical exceptions to be a special case handled
   differently from even machine check and debug level exceptions.
 - It didn't occur to me that it was possible to make this work at all
   (by doing a final "ld r13, PACA_EXCRIT+EX_R13(r13)") until after
   I made (most of) this patch. :-)

It might be worth investigating using a load rather than SPRG on return
from all exceptions (except TLB misses where the scratch never leaves
the SPRG) -- it could save a few cycles.  Until then, let's stick with
SPRG for all exceptions.

Since we cannot use SPRG4-7 for scratch without corrupting the state of
a KVM guest, move VDSO to SPRG7 on book3e.  Since neither SPRG4-7 nor
critical interrupts exist on book3s, SPRG3 is still used for VDSO
there.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Cc: Mihai Caraman <mihai.caraman@freescale.com>
Cc: Anton Blanchard <anton@samba.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: kvm-ppc@vger.kernel.org
12 files changed:
arch/powerpc/include/asm/exception-64e.h
arch/powerpc/include/asm/kvm_booke_hv_asm.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vdso32/getcpu.S
arch/powerpc/kernel/vdso64/getcpu.S
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/bookehv_interrupts.S

index 51fa43e536b917c08c5870525c9a81063c1448e2..e73452f090192f6eca59597d199a729126c9c0fc 100644 (file)
@@ -46,9 +46,8 @@
 #define EX_CR          (1 * 8)
 #define EX_R10         (2 * 8)
 #define EX_R11         (3 * 8)
-#define EX_R13         (4 * 8)
-#define EX_R14         (5 * 8)
-#define EX_R15         (6 * 8)
+#define EX_R14         (4 * 8)
+#define EX_R15         (5 * 8)
 
 /*
  * The TLB miss exception uses different slots.
index 3a79f53257125a4daf05e5546893eb8821606c3d..c3e3fd53a3a992f1ebd75e96adab7439c8c8e9a1 100644 (file)
  *   *(r8 + GPR11) = saved r11
  *
  * 64-bit host
- * Expected inputs (GEN/GDBELL/DBG/MC exception types):
+ * Expected inputs (GEN/GDBELL/DBG/CRIT/MC exception types):
  *  r10 = saved CR
  *  r13 = PACA_POINTER
  *  *(r13 + PACA_EX##type + EX_R10) = saved r10
  *  *(r13 + PACA_EX##type + EX_R11) = saved r11
  *  SPRN_SPRG_##type##_SCRATCH = saved r13
- *
-  * Expected inputs (CRIT exception type):
- *  r10 = saved CR
- *  r13 = PACA_POINTER
- *  *(r13 + PACA_EX##type + EX_R10) = saved r10
- *  *(r13 + PACA_EX##type + EX_R11) = saved r11
- *  *(r13 + PACA_EX##type + EX_R13) = saved r13
  *
  * Expected inputs (TLB exception type):
  *  r10 = saved CR
index 9c5dbc3833fbc65976ba17e60eec04f234f8e631..948f01a04cc39d253036781464e920b0bff2f9e8 100644 (file)
@@ -146,7 +146,7 @@ struct paca_struct {
        u8 io_sync;                     /* writel() needs spin_unlock sync */
        u8 irq_work_pending;            /* IRQ_WORK interrupt while soft-disable */
        u8 nap_state_lost;              /* NV GPR values lost in power7_idle */
-       u64 sprg3;                      /* Saved user-visible sprg */
+       u64 sprg_vdso;                  /* Saved user-visible sprg */
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        u64 tm_scratch;                 /* TM scratch area for reclaim */
 #endif
index bf0fb4db08553dbd9410e0058ddedf76c094e457..f7251c2dc0498f7c9a4f6532f18f05b133257d02 100644 (file)
 #define SPRN_SPRG3     0x113   /* Special Purpose Register General 3 */
 #define SPRN_USPRG3    0x103   /* SPRG3 userspace read */
 #define SPRN_SPRG4     0x114   /* Special Purpose Register General 4 */
+#define SPRN_USPRG4    0x104   /* SPRG4 userspace read */
 #define SPRN_SPRG5     0x115   /* Special Purpose Register General 5 */
+#define SPRN_USPRG5    0x105   /* SPRG5 userspace read */
 #define SPRN_SPRG6     0x116   /* Special Purpose Register General 6 */
+#define SPRN_USPRG6    0x106   /* SPRG6 userspace read */
 #define SPRN_SPRG7     0x117   /* Special Purpose Register General 7 */
+#define SPRN_USPRG7    0x107   /* SPRG7 userspace read */
 #define SPRN_SRR0      0x01A   /* Save/Restore Register 0 */
 #define SPRN_SRR1      0x01B   /* Save/Restore Register 1 */
 #define   SRR1_ISI_NOPT                0x40000000 /* ISI: Not found in hash */
  * 64-bit embedded
  *     - SPRG0 generic exception scratch
  *     - SPRG2 TLB exception stack
- *     - SPRG3 critical exception scratch and
- *        CPU and NUMA node for VDSO getcpu (user visible)
+ *     - SPRG3 critical exception scratch (user visible, sorry!)
  *     - SPRG4 unused (user visible)
  *     - SPRG6 TLB miss scratch (user visible, sorry !)
- *     - SPRG7 critical exception scratch
+ *     - SPRG7 CPU and NUMA node for VDSO getcpu (user visible)
  *     - SPRG8 machine check exception scratch
  *     - SPRG9 debug exception scratch
  *
 #define SPRN_SPRG_SCRATCH0     SPRN_SPRG2
 #define SPRN_SPRG_HPACA                SPRN_HSPRG0
 #define SPRN_SPRG_HSCRATCH0    SPRN_HSPRG1
+#define SPRN_SPRG_VDSO_READ    SPRN_USPRG3
+#define SPRN_SPRG_VDSO_WRITE   SPRN_SPRG3
 
 #define GET_PACA(rX)                                   \
        BEGIN_FTR_SECTION_NESTED(66);                   \
 #define SPRN_SPRG_TLB_SCRATCH  SPRN_SPRG6
 #define SPRN_SPRG_GEN_SCRATCH  SPRN_SPRG0
 #define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH
+#define SPRN_SPRG_VDSO_READ    SPRN_USPRG7
+#define SPRN_SPRG_VDSO_WRITE   SPRN_SPRG7
 
 #define SET_PACA(rX)   mtspr   SPRN_SPRG_PACA,rX
 #define GET_PACA(rX)   mfspr   rX,SPRN_SPRG_PACA
index b5aacf72ae6f5db492a374c93ad2b505558e81c5..dba8140ebc20b8d425bafabe5a0edf57bea2e1bb 100644 (file)
@@ -253,7 +253,7 @@ int main(void)
        DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
        DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
        DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
-       DEFINE(PACA_SPRG3, offsetof(struct paca_struct, sprg3));
+       DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso));
 #endif /* CONFIG_PPC64 */
 
        /* RTAS */
index 41380a424108895918b1e2e8d8581046bf6ec0e8..89e1133b018544c15aca3a87c535cf61e0886c38 100644 (file)
@@ -55,7 +55,6 @@
        mfspr   r13,SPRN_SPRG_PACA;     /* get PACA */                      \
        std     r10,PACA_EX##type+EX_R10(r13);                              \
        std     r11,PACA_EX##type+EX_R11(r13);                              \
-       PROLOG_STORE_RESTORE_SCRATCH_##type;                                \
        mfcr    r10;                    /* save CR */                       \
        mfspr   r11,SPRN_##type##_SRR1;/* what are we coming from */        \
        DO_KVM  intnum,SPRN_##type##_SRR1;    /* KVM hook */                \
 #define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)                       \
        EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
 
-/*
- * Store user-visible scratch in PACA exception slots and restore proper value
- */
-#define PROLOG_STORE_RESTORE_SCRATCH_GEN
-#define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
-#define PROLOG_STORE_RESTORE_SCRATCH_DBG
-#define PROLOG_STORE_RESTORE_SCRATCH_MC
-
-#define PROLOG_STORE_RESTORE_SCRATCH_CRIT                                  \
-       mfspr   r10,SPRN_SPRG_CRIT_SCRATCH;     /* get r13 */               \
-       std     r10,PACA_EXCRIT+EX_R13(r13);                                \
-       ld      r11,PACA_SPRG3(r13);                                        \
-       mtspr   SPRN_SPRG_CRIT_SCRATCH,r11;
-
 /* Variants of the "addition" argument for the prolog
  */
 #define PROLOG_ADDITION_NONE_GEN(n)
@@ -529,7 +514,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        mtcr    r10
        ld      r10,PACA_EXCRIT+EX_R10(r13)     /* restore registers */
        ld      r11,PACA_EXCRIT+EX_R11(r13)
-       ld      r13,PACA_EXCRIT+EX_R13(r13)
+       mfspr   r13,SPRN_SPRG_CRIT_SCRATCH
        rfci
 
        /* Normal debug exception */
@@ -542,7 +527,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        /* Now we mash up things to make it look like we are coming on a
         * normal exception
         */
-       ld      r15,PACA_EXCRIT+EX_R13(r13)
+       mfspr   r15,SPRN_SPRG_CRIT_SCRATCH
        mtspr   SPRN_SPRG_GEN_SCRATCH,r15
        mfspr   r14,SPRN_DBSR
        EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
index 094e45c16a17032e36e33f3ef1fb5182fb4dd958..ce74c335a6a405b03e8400a72b74e1fc7227b56f 100644 (file)
@@ -715,8 +715,8 @@ int vdso_getcpu_init(void)
        unsigned long cpu, node, val;
 
        /*
-        * SPRG3 contains the CPU in the bottom 16 bits and the NUMA node in
-        * the next 16 bits. The VDSO uses this to implement getcpu().
+        * SPRG_VDSO contains the CPU in the bottom 16 bits and the NUMA node
+        * in the next 16 bits.  The VDSO uses this to implement getcpu().
         */
        cpu = get_cpu();
        WARN_ON_ONCE(cpu > 0xffff);
@@ -725,8 +725,8 @@ int vdso_getcpu_init(void)
        WARN_ON_ONCE(node > 0xffff);
 
        val = (cpu & 0xfff) | ((node & 0xffff) << 16);
-       mtspr(SPRN_SPRG3, val);
-       get_paca()->sprg3 = val;
+       mtspr(SPRN_SPRG_VDSO_WRITE, val);
+       get_paca()->sprg_vdso = val;
 
        put_cpu();
 
index 47afd08c90f7fd3f934beafb9398d106099e7f40..23eb9a9441bdad612481a7d1b2fcf12dd17a7ed3 100644 (file)
@@ -29,7 +29,7 @@
  */
 V_FUNCTION_BEGIN(__kernel_getcpu)
   .cfi_startproc
-       mfspr   r5,SPRN_USPRG3
+       mfspr   r5,SPRN_SPRG_VDSO_READ
        cmpdi   cr0,r3,0
        cmpdi   cr1,r4,0
        clrlwi  r6,r5,16
index 47afd08c90f7fd3f934beafb9398d106099e7f40..23eb9a9441bdad612481a7d1b2fcf12dd17a7ed3 100644 (file)
@@ -29,7 +29,7 @@
  */
 V_FUNCTION_BEGIN(__kernel_getcpu)
   .cfi_startproc
-       mfspr   r5,SPRN_USPRG3
+       mfspr   r5,SPRN_SPRG_VDSO_READ
        cmpdi   cr0,r3,0
        cmpdi   cr1,r4,0
        clrlwi  r6,r5,16
index e66d4ec04d953a78a314b43a3a07f47ca27f5ae7..fbfca5778b0ba0f774c2edef4a68d49ea85cfc8e 100644 (file)
@@ -75,8 +75,8 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 
        /* Restore SPRG3 */
-       ld      r3,PACA_SPRG3(r13)
-       mtspr   SPRN_SPRG3,r3
+       ld      r3,PACA_SPRG_VDSO(r13)
+       mtspr   SPRN_SPRG_VDSO_WRITE,r3
 
        /* Reload the host's PMU registers */
        ld      r3, PACALPPACAPTR(r13)  /* is the host using the PMU? */
index f779450cb07c728681ede6d566ef85920117337e..3533c999194a3db8d835d570bd7f4d86bb494bbb 100644 (file)
@@ -153,8 +153,8 @@ kvm_start_lightweight:
         * Reload kernel SPRG3 value.
         * No need to save guest value as usermode can't modify SPRG3.
         */
-       ld      r3, PACA_SPRG3(r13)
-       mtspr   SPRN_SPRG3, r3
+       ld      r3, PACA_SPRG_VDSO(r13)
+       mtspr   SPRN_SPRG_VDSO_WRITE, r3
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
        /* R7 = vcpu */
index e4185f6b3309af4cf51d5990f766647c88e9a5a2..99635a37c78c6cc4d73bb20306c418b5602e910e 100644 (file)
        stw     r10, VCPU_CR(r4)
        PPC_STL r11, VCPU_GPR(R4)(r4)
        PPC_STL r5, VCPU_GPR(R5)(r4)
-       .if \type == EX_CRIT
-       PPC_LL  r5, (\paca_ex + EX_R13)(r13)
-       .else
        mfspr   r5, \scratch
-       .endif
        PPC_STL r6, VCPU_GPR(R6)(r4)
        PPC_STL r8, VCPU_GPR(R8)(r4)
        PPC_STL r9, VCPU_GPR(R9)(r4)
@@ -435,10 +431,16 @@ _GLOBAL(kvmppc_resume_host)
        PPC_STL r5, VCPU_LR(r4)
        mfspr   r7, SPRN_SPRG5
        stw     r3, VCPU_VRSAVE(r4)
+#ifdef CONFIG_64BIT
+       PPC_LL  r3, PACA_SPRG_VDSO(r13)
+#endif
        PPC_STD(r6, VCPU_SHARED_SPRG4, r11)
        mfspr   r8, SPRN_SPRG6
        PPC_STD(r7, VCPU_SHARED_SPRG5, r11)
        mfspr   r9, SPRN_SPRG7
+#ifdef CONFIG_64BIT
+       mtspr   SPRN_SPRG_VDSO_WRITE, r3
+#endif
        PPC_STD(r8, VCPU_SHARED_SPRG6, r11)
        mfxer   r3
        PPC_STD(r9, VCPU_SHARED_SPRG7, r11)