aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/processor.h5
-rw-r--r--arch/powerpc/include/asm/reg.h4
-rw-r--r--arch/powerpc/kernel/asm-offsets.c3
-rw-r--r--arch/powerpc/kernel/head_booke.h42
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S49
5 files changed, 63 insertions, 40 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index d50c2b6d9bc3..eb11a446720e 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -20,6 +20,7 @@
20 20
21#ifndef __ASSEMBLY__ 21#ifndef __ASSEMBLY__
22#include <linux/compiler.h> 22#include <linux/compiler.h>
23#include <linux/cache.h>
23#include <asm/ptrace.h> 24#include <asm/ptrace.h>
24#include <asm/types.h> 25#include <asm/types.h>
25 26
@@ -156,6 +157,10 @@ struct thread_struct {
156#endif 157#endif
157 struct pt_regs *regs; /* Pointer to saved register state */ 158 struct pt_regs *regs; /* Pointer to saved register state */
158 mm_segment_t fs; /* for get_fs() validation */ 159 mm_segment_t fs; /* for get_fs() validation */
160#ifdef CONFIG_BOOKE
161 /* BookE base exception scratch space; align on cacheline */
162 unsigned long normsave[8] ____cacheline_aligned;
163#endif
159#ifdef CONFIG_PPC32 164#ifdef CONFIG_PPC32
160 void *pgdir; /* root of page-table tree */ 165 void *pgdir; /* root of page-table tree */
161#endif 166#endif
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index c5cae0dd176c..213d1d712499 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -872,8 +872,8 @@
872#define SPRN_SPRG_WSCRATCH2 SPRN_SPRG4W 872#define SPRN_SPRG_WSCRATCH2 SPRN_SPRG4W
873#define SPRN_SPRG_RSCRATCH3 SPRN_SPRG5R 873#define SPRN_SPRG_RSCRATCH3 SPRN_SPRG5R
874#define SPRN_SPRG_WSCRATCH3 SPRN_SPRG5W 874#define SPRN_SPRG_WSCRATCH3 SPRN_SPRG5W
875#define SPRN_SPRG_RSCRATCH_MC SPRN_SPRG6R 875#define SPRN_SPRG_RSCRATCH_MC SPRN_SPRG1
876#define SPRN_SPRG_WSCRATCH_MC SPRN_SPRG6W 876#define SPRN_SPRG_WSCRATCH_MC SPRN_SPRG1
877#define SPRN_SPRG_RSCRATCH4 SPRN_SPRG7R 877#define SPRN_SPRG_RSCRATCH4 SPRN_SPRG7R
878#define SPRN_SPRG_WSCRATCH4 SPRN_SPRG7W 878#define SPRN_SPRG_WSCRATCH4 SPRN_SPRG7W
879#ifdef CONFIG_E200 879#ifdef CONFIG_E200
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 36e1c8a29be8..c98144f6f04e 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -82,6 +82,9 @@ int main(void)
82 DEFINE(KSP, offsetof(struct thread_struct, ksp)); 82 DEFINE(KSP, offsetof(struct thread_struct, ksp));
83 DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit)); 83 DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
84 DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); 84 DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
85#ifdef CONFIG_BOOKE
86 DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
87#endif
85 DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); 88 DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
86 DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); 89 DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
87 DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); 90 DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index a0bf158c8b47..fc921bf62e15 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -20,33 +20,43 @@
20 addi reg,reg,val@l 20 addi reg,reg,val@l
21#endif 21#endif
22 22
23/*
24 * Macro used to get to thread save registers.
25 * Note that entries 0-3 are used for the prolog code, and the remaining
26 * entries are available for specific exception use in the event a handler
27 * requires more than 4 scratch registers.
28 */
29#define THREAD_NORMSAVE(offset) (THREAD_NORMSAVES + (offset * 4))
30
23#define NORMAL_EXCEPTION_PROLOG \ 31#define NORMAL_EXCEPTION_PROLOG \
24 mtspr SPRN_SPRG_WSCRATCH0,r10;/* save two registers to work with */\ 32 mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \
25 mtspr SPRN_SPRG_WSCRATCH1,r11; \ 33 mfspr r10, SPRN_SPRG_THREAD; \
26 mtspr SPRN_SPRG_WSCRATCH2,r1; \ 34 stw r11, THREAD_NORMSAVE(0)(r10); \
27 mfcr r10; /* save CR in r10 for now */\ 35 stw r13, THREAD_NORMSAVE(2)(r10); \
36 mfcr r13; /* save CR in r13 for now */\
28 mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ 37 mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
29 andi. r11,r11,MSR_PR; \ 38 andi. r11,r11,MSR_PR; \
39 mr r11, r1; \
30 beq 1f; \ 40 beq 1f; \
31 mfspr r1,SPRN_SPRG_THREAD; /* if from user, start at top of */\ 41 /* if from user, start at top of this thread's kernel stack */ \
32 lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ 42 lwz r11, THREAD_INFO-THREAD(r10); \
33 ALLOC_STACK_FRAME(r1, THREAD_SIZE); \ 43 ALLOC_STACK_FRAME(r11, THREAD_SIZE); \
341: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ 441 : subi r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */ \
35 mr r11,r1; \ 45 stw r13, _CCR(r11); /* save various registers */ \
36 stw r10,_CCR(r11); /* save various registers */\
37 stw r12,GPR12(r11); \ 46 stw r12,GPR12(r11); \
38 stw r9,GPR9(r11); \ 47 stw r9,GPR9(r11); \
39 mfspr r10,SPRN_SPRG_RSCRATCH0; \ 48 mfspr r13, SPRN_SPRG_RSCRATCH0; \
40 stw r10,GPR10(r11); \ 49 stw r13, GPR10(r11); \
41 mfspr r12,SPRN_SPRG_RSCRATCH1; \ 50 lwz r12, THREAD_NORMSAVE(0)(r10); \
42 stw r12,GPR11(r11); \ 51 stw r12,GPR11(r11); \
52 lwz r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */ \
43 mflr r10; \ 53 mflr r10; \
44 stw r10,_LINK(r11); \ 54 stw r10,_LINK(r11); \
45 mfspr r10,SPRN_SPRG_RSCRATCH2; \
46 mfspr r12,SPRN_SRR0; \ 55 mfspr r12,SPRN_SRR0; \
47 stw r10,GPR1(r11); \ 56 stw r1, GPR1(r11); \
48 mfspr r9,SPRN_SRR1; \ 57 mfspr r9,SPRN_SRR1; \
49 stw r10,0(r11); \ 58 stw r1, 0(r11); \
59 mr r1, r11; \
50 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ 60 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
51 stw r0,GPR0(r11); \ 61 stw r0,GPR0(r11); \
52 lis r10, STACK_FRAME_REGS_MARKER@ha;/* exception frame marker */ \ 62 lis r10, STACK_FRAME_REGS_MARKER@ha;/* exception frame marker */ \
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 5ecf54cfa7d4..985638d5f6c4 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -346,11 +346,12 @@ interrupt_base:
346 /* Data TLB Error Interrupt */ 346 /* Data TLB Error Interrupt */
347 START_EXCEPTION(DataTLBError) 347 START_EXCEPTION(DataTLBError)
348 mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */ 348 mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
349 mtspr SPRN_SPRG_WSCRATCH1, r11 349 mfspr r10, SPRN_SPRG_THREAD
350 mtspr SPRN_SPRG_WSCRATCH2, r12 350 stw r11, THREAD_NORMSAVE(0)(r10)
351 mtspr SPRN_SPRG_WSCRATCH3, r13 351 stw r12, THREAD_NORMSAVE(1)(r10)
352 mfcr r11 352 stw r13, THREAD_NORMSAVE(2)(r10)
353 mtspr SPRN_SPRG_WSCRATCH4, r11 353 mfcr r13
354 stw r13, THREAD_NORMSAVE(3)(r10)
354 mfspr r10, SPRN_DEAR /* Get faulting address */ 355 mfspr r10, SPRN_DEAR /* Get faulting address */
355 356
356 /* If we are faulting a kernel address, we have to use the 357 /* If we are faulting a kernel address, we have to use the
@@ -416,11 +417,12 @@ interrupt_base:
416 /* The bailout. Restore registers to pre-exception conditions 417 /* The bailout. Restore registers to pre-exception conditions
417 * and call the heavyweights to help us out. 418 * and call the heavyweights to help us out.
418 */ 419 */
419 mfspr r11, SPRN_SPRG_RSCRATCH4 420 mfspr r10, SPRN_SPRG_THREAD
421 lwz r11, THREAD_NORMSAVE(3)(r10)
420 mtcr r11 422 mtcr r11
421 mfspr r13, SPRN_SPRG_RSCRATCH3 423 lwz r13, THREAD_NORMSAVE(2)(r10)
422 mfspr r12, SPRN_SPRG_RSCRATCH2 424 lwz r12, THREAD_NORMSAVE(1)(r10)
423 mfspr r11, SPRN_SPRG_RSCRATCH1 425 lwz r11, THREAD_NORMSAVE(0)(r10)
424 mfspr r10, SPRN_SPRG_RSCRATCH0 426 mfspr r10, SPRN_SPRG_RSCRATCH0
425 b DataStorage 427 b DataStorage
426 428
@@ -432,11 +434,12 @@ interrupt_base:
432 */ 434 */
433 START_EXCEPTION(InstructionTLBError) 435 START_EXCEPTION(InstructionTLBError)
434 mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */ 436 mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */
435 mtspr SPRN_SPRG_WSCRATCH1, r11 437 mfspr r10, SPRN_SPRG_THREAD
436 mtspr SPRN_SPRG_WSCRATCH2, r12 438 stw r11, THREAD_NORMSAVE(0)(r10)
437 mtspr SPRN_SPRG_WSCRATCH3, r13 439 stw r12, THREAD_NORMSAVE(1)(r10)
438 mfcr r11 440 stw r13, THREAD_NORMSAVE(2)(r10)
439 mtspr SPRN_SPRG_WSCRATCH4, r11 441 mfcr r13
442 stw r13, THREAD_NORMSAVE(3)(r10)
440 mfspr r10, SPRN_SRR0 /* Get faulting address */ 443 mfspr r10, SPRN_SRR0 /* Get faulting address */
441 444
442 /* If we are faulting a kernel address, we have to use the 445 /* If we are faulting a kernel address, we have to use the
@@ -496,11 +499,12 @@ interrupt_base:
496 /* The bailout. Restore registers to pre-exception conditions 499 /* The bailout. Restore registers to pre-exception conditions
497 * and call the heavyweights to help us out. 500 * and call the heavyweights to help us out.
498 */ 501 */
499 mfspr r11, SPRN_SPRG_RSCRATCH4 502 mfspr r10, SPRN_SPRG_THREAD
503 lwz r11, THREAD_NORMSAVE(3)(r10)
500 mtcr r11 504 mtcr r11
501 mfspr r13, SPRN_SPRG_RSCRATCH3 505 lwz r13, THREAD_NORMSAVE(2)(r10)
502 mfspr r12, SPRN_SPRG_RSCRATCH2 506 lwz r12, THREAD_NORMSAVE(1)(r10)
503 mfspr r11, SPRN_SPRG_RSCRATCH1 507 lwz r11, THREAD_NORMSAVE(0)(r10)
504 mfspr r10, SPRN_SPRG_RSCRATCH0 508 mfspr r10, SPRN_SPRG_RSCRATCH0
505 b InstructionStorage 509 b InstructionStorage
506 510
@@ -621,11 +625,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
621 tlbwe 625 tlbwe
622 626
623 /* Done...restore registers and get out of here. */ 627 /* Done...restore registers and get out of here. */
624 mfspr r11, SPRN_SPRG_RSCRATCH4 628 mfspr r10, SPRN_SPRG_THREAD
629 lwz r11, THREAD_NORMSAVE(3)(r10)
625 mtcr r11 630 mtcr r11
626 mfspr r13, SPRN_SPRG_RSCRATCH3 631 lwz r13, THREAD_NORMSAVE(2)(r10)
627 mfspr r12, SPRN_SPRG_RSCRATCH2 632 lwz r12, THREAD_NORMSAVE(1)(r10)
628 mfspr r11, SPRN_SPRG_RSCRATCH1 633 lwz r11, THREAD_NORMSAVE(0)(r10)
629 mfspr r10, SPRN_SPRG_RSCRATCH0 634 mfspr r10, SPRN_SPRG_RSCRATCH0
630 rfi /* Force context change */ 635 rfi /* Force context change */
631 636