mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
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:
parent
dc2c9c52b6
commit
1325a684b5
5 changed files with 63 additions and 40 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */ \
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue