powerpc/85xx: Save scratch registers to thread info instead of using SPRGs.
authorAshish Kalra <Ashish.Kalra@freescale.com>
Fri, 22 Apr 2011 21:48:27 +0000 (16:48 -0500)
committerKumar Gala <galak@kernel.crashing.org>
Thu, 23 Jun 2011 02:44:55 +0000 (21:44 -0500)
We expect this is actually faster, and we end up needing more space than we
can get from the SPRGs in some instances.  This is also useful when running
as a guest OS - SPRGs4-7 do not have guest versions.

8 slots are allocated in thread_info for this even though we only actually
use 4 of them - this allows space for future code to have more scratch
space (and we know we'll need it for things like hugetlb).

Signed-off-by: Ashish Kalra <Ashish.Kalra@freescale.com>
Signed-off-by: Becky Bruce <beckyb@kernel.crashing.org>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/head_booke.h
arch/powerpc/kernel/head_fsl_booke.S

index d50c2b6d9bc31f4bff44e9e7b8edb085cbac367e..eb11a446720e0b4cbc2e2917e409781a4c43ad0f 100644 (file)
@@ -20,6 +20,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/compiler.h>
+#include <linux/cache.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
@@ -156,6 +157,10 @@ struct thread_struct {
 #endif
        struct pt_regs  *regs;          /* Pointer to saved register state */
        mm_segment_t    fs;             /* for get_fs() validation */
+#ifdef CONFIG_BOOKE
+       /* BookE base exception scratch space; align on cacheline */
+       unsigned long   normsave[8] ____cacheline_aligned;
+#endif
 #ifdef CONFIG_PPC32
        void            *pgdir;         /* root of page-table tree */
 #endif
index c5cae0dd176c300d2dddb86a36a018653e2aab40..213d1d712499c31c929fa37b7b1a9bf7e863b4fe 100644 (file)
 #define SPRN_SPRG_WSCRATCH2    SPRN_SPRG4W
 #define SPRN_SPRG_RSCRATCH3    SPRN_SPRG5R
 #define SPRN_SPRG_WSCRATCH3    SPRN_SPRG5W
-#define SPRN_SPRG_RSCRATCH_MC  SPRN_SPRG6R
-#define SPRN_SPRG_WSCRATCH_MC  SPRN_SPRG6W
+#define SPRN_SPRG_RSCRATCH_MC  SPRN_SPRG1
+#define SPRN_SPRG_WSCRATCH_MC  SPRN_SPRG1
 #define SPRN_SPRG_RSCRATCH4    SPRN_SPRG7R
 #define SPRN_SPRG_WSCRATCH4    SPRN_SPRG7W
 #ifdef CONFIG_E200
index 36e1c8a29be885c498e04b77b2f11e683221e08d..c98144f6f04e5fa5c9e4d4371fdc9d5ac425ffa7 100644 (file)
@@ -82,6 +82,9 @@ int main(void)
        DEFINE(KSP, offsetof(struct thread_struct, ksp));
        DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
        DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
+#ifdef CONFIG_BOOKE
+       DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
+#endif
        DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
        DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
        DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
index a0bf158c8b4781e9f70d18710a52b2a6d4e089e2..fc921bf62e159189eba0b2a5314a75022be9dd46 100644 (file)
        addi    reg,reg,val@l
 #endif
 
+/*
+ * Macro used to get to thread save registers.
+ * Note that entries 0-3 are used for the prolog code, and the remaining
+ * entries are available for specific exception use in the event a handler
+ * requires more than 4 scratch registers.
+ */
+#define THREAD_NORMSAVE(offset)        (THREAD_NORMSAVES + (offset * 4))
+
 #define NORMAL_EXCEPTION_PROLOG                                                     \
-       mtspr   SPRN_SPRG_WSCRATCH0,r10;/* save two registers to work with */\
-       mtspr   SPRN_SPRG_WSCRATCH1,r11;                                     \
-       mtspr   SPRN_SPRG_WSCRATCH2,r1;                                      \
-       mfcr    r10;                    /* save CR in r10 for now          */\
+       mtspr   SPRN_SPRG_WSCRATCH0, r10;       /* save one register */      \
+       mfspr   r10, SPRN_SPRG_THREAD;                                       \
+       stw     r11, THREAD_NORMSAVE(0)(r10);                                \
+       stw     r13, THREAD_NORMSAVE(2)(r10);                                \
+       mfcr    r13;                    /* save CR in r13 for now          */\
        mfspr   r11,SPRN_SRR1;          /* check whether user or kernel    */\
        andi.   r11,r11,MSR_PR;                                              \
+       mr      r11, r1;                                                     \
        beq     1f;                                                          \
-       mfspr   r1,SPRN_SPRG_THREAD;    /* if from user, start at top of   */\
-       lwz     r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-       ALLOC_STACK_FRAME(r1, THREAD_SIZE);                                  \
-1:     subi    r1,r1,INT_FRAME_SIZE;   /* Allocate an exception frame     */\
-       mr      r11,r1;                                                      \
-       stw     r10,_CCR(r11);          /* save various registers          */\
+       /* if from user, start at top of this thread's kernel stack */       \
+       lwz     r11, THREAD_INFO-THREAD(r10);                                \
+       ALLOC_STACK_FRAME(r11, THREAD_SIZE);                                 \
+1 :    subi    r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */     \
+       stw     r13, _CCR(r11);         /* save various registers */         \
        stw     r12,GPR12(r11);                                              \
        stw     r9,GPR9(r11);                                                \
-       mfspr   r10,SPRN_SPRG_RSCRATCH0;                                        \
-       stw     r10,GPR10(r11);                                              \
-       mfspr   r12,SPRN_SPRG_RSCRATCH1;                                     \
+       mfspr   r13, SPRN_SPRG_RSCRATCH0;                                    \
+       stw     r13, GPR10(r11);                                             \
+       lwz     r12, THREAD_NORMSAVE(0)(r10);                                \
        stw     r12,GPR11(r11);                                              \
+       lwz     r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */              \
        mflr    r10;                                                         \
        stw     r10,_LINK(r11);                                              \
-       mfspr   r10,SPRN_SPRG_RSCRATCH2;                                     \
        mfspr   r12,SPRN_SRR0;                                               \
-       stw     r10,GPR1(r11);                                               \
+       stw     r1GPR1(r11);                                               \
        mfspr   r9,SPRN_SRR1;                                                \
-       stw     r10,0(r11);                                                  \
+       stw     r1, 0(r11);                                                  \
+       mr      r1, r11;                                                     \
        rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
        stw     r0,GPR0(r11);                                                \
        lis     r10, STACK_FRAME_REGS_MARKER@ha;/* exception frame marker */ \
index 5ecf54cfa7d47d774c78c754e08e7713edb214cc..985638d5f6c450f007c29e9e7f563d371530abbd 100644 (file)
@@ -346,11 +346,12 @@ interrupt_base:
        /* Data TLB Error Interrupt */
        START_EXCEPTION(DataTLBError)
        mtspr   SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
-       mtspr   SPRN_SPRG_WSCRATCH1, r11
-       mtspr   SPRN_SPRG_WSCRATCH2, r12
-       mtspr   SPRN_SPRG_WSCRATCH3, r13
-       mfcr    r11
-       mtspr   SPRN_SPRG_WSCRATCH4, r11
+       mfspr   r10, SPRN_SPRG_THREAD
+       stw     r11, THREAD_NORMSAVE(0)(r10)
+       stw     r12, THREAD_NORMSAVE(1)(r10)
+       stw     r13, THREAD_NORMSAVE(2)(r10)
+       mfcr    r13
+       stw     r13, THREAD_NORMSAVE(3)(r10)
        mfspr   r10, SPRN_DEAR          /* Get faulting address */
 
        /* If we are faulting a kernel address, we have to use the
@@ -416,11 +417,12 @@ interrupt_base:
        /* The bailout.  Restore registers to pre-exception conditions
         * and call the heavyweights to help us out.
         */
-       mfspr   r11, SPRN_SPRG_RSCRATCH4
+       mfspr   r10, SPRN_SPRG_THREAD
+       lwz     r11, THREAD_NORMSAVE(3)(r10)
        mtcr    r11
-       mfspr   r13, SPRN_SPRG_RSCRATCH3
-       mfspr   r12, SPRN_SPRG_RSCRATCH2
-       mfspr   r11, SPRN_SPRG_RSCRATCH1
+       lwz     r13, THREAD_NORMSAVE(2)(r10)
+       lwz     r12, THREAD_NORMSAVE(1)(r10)
+       lwz     r11, THREAD_NORMSAVE(0)(r10)
        mfspr   r10, SPRN_SPRG_RSCRATCH0
        b       DataStorage
 
@@ -432,11 +434,12 @@ interrupt_base:
         */
        START_EXCEPTION(InstructionTLBError)
        mtspr   SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
-       mtspr   SPRN_SPRG_WSCRATCH1, r11
-       mtspr   SPRN_SPRG_WSCRATCH2, r12
-       mtspr   SPRN_SPRG_WSCRATCH3, r13
-       mfcr    r11
-       mtspr   SPRN_SPRG_WSCRATCH4, r11
+       mfspr   r10, SPRN_SPRG_THREAD
+       stw     r11, THREAD_NORMSAVE(0)(r10)
+       stw     r12, THREAD_NORMSAVE(1)(r10)
+       stw     r13, THREAD_NORMSAVE(2)(r10)
+       mfcr    r13
+       stw     r13, THREAD_NORMSAVE(3)(r10)
        mfspr   r10, SPRN_SRR0          /* Get faulting address */
 
        /* If we are faulting a kernel address, we have to use the
@@ -496,11 +499,12 @@ interrupt_base:
        /* The bailout.  Restore registers to pre-exception conditions
         * and call the heavyweights to help us out.
         */
-       mfspr   r11, SPRN_SPRG_RSCRATCH4
+       mfspr   r10, SPRN_SPRG_THREAD
+       lwz     r11, THREAD_NORMSAVE(3)(r10)
        mtcr    r11
-       mfspr   r13, SPRN_SPRG_RSCRATCH3
-       mfspr   r12, SPRN_SPRG_RSCRATCH2
-       mfspr   r11, SPRN_SPRG_RSCRATCH1
+       lwz     r13, THREAD_NORMSAVE(2)(r10)
+       lwz     r12, THREAD_NORMSAVE(1)(r10)
+       lwz     r11, THREAD_NORMSAVE(0)(r10)
        mfspr   r10, SPRN_SPRG_RSCRATCH0
        b       InstructionStorage
 
@@ -621,11 +625,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
        tlbwe
 
        /* Done...restore registers and get out of here.  */
-       mfspr   r11, SPRN_SPRG_RSCRATCH4
+       mfspr   r10, SPRN_SPRG_THREAD
+       lwz     r11, THREAD_NORMSAVE(3)(r10)
        mtcr    r11
-       mfspr   r13, SPRN_SPRG_RSCRATCH3
-       mfspr   r12, SPRN_SPRG_RSCRATCH2
-       mfspr   r11, SPRN_SPRG_RSCRATCH1
+       lwz     r13, THREAD_NORMSAVE(2)(r10)
+       lwz     r12, THREAD_NORMSAVE(1)(r10)
+       lwz     r11, THREAD_NORMSAVE(0)(r10)
        mfspr   r10, SPRN_SPRG_RSCRATCH0
        rfi                                     /* Force context change */