powerpc/85xx: Save scratch registers to thread info instead of using SPRGs.

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>
This commit is contained in:
Ashish Kalra 2011-04-22 16:48:27 -05:00 committed by Kumar Gala
parent dc2c9c52b6
commit 1325a684b5
5 changed files with 63 additions and 40 deletions

View 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

View File

@ -872,8 +872,8 @@
#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

View 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));

View File

@ -20,33 +20,43 @@
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 r1, GPR1(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 */ \

View 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 */