diff options
-rw-r--r-- | arch/powerpc/include/asm/processor.h | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_booke.h | 42 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_fsl_booke.S | 49 |
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); \ |
34 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ | 44 | 1 : 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 | ||