diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2008-04-30 05:17:22 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2008-06-02 15:56:06 -0400 |
commit | 369e757b65d4a5e49bae7cfaf671e784f891cfbe (patch) | |
tree | aa144c5db61f00384a552c33ace99c454fe5ea23 | |
parent | bcf0b0880710409420a4e3b15dbf4b9a63542c0b (diff) |
[POWERPC] Rework EXC_LEVEL_EXCEPTION_PROLOG code
* Cleanup the code a bit my allocating an INT_FRAME on our exception
stack there by make references go from GPR11-INT_FRAME_SIZE(r8) to
just GPR11(r8)
* simplify {lvl}_transfer_to_handler code by moving the copying of the
temp registers we use if we come from user space into the PROLOG
* If the exception came from kernel mode copy thread_info flags,
preempt, and task pointer from the process thread_info.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Acked-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 13 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_booke.h | 54 |
2 files changed, 35 insertions, 32 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 888a364043a8..c94aba54b5dd 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -44,29 +44,16 @@ | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #ifdef CONFIG_BOOKE | 46 | #ifdef CONFIG_BOOKE |
47 | #include "head_booke.h" | ||
48 | #define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \ | ||
49 | mtspr exc_level##_SPRG,r8; \ | ||
50 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \ | ||
51 | lwz r0,GPR10-INT_FRAME_SIZE(r8); \ | ||
52 | stw r0,GPR10(r11); \ | ||
53 | lwz r0,GPR11-INT_FRAME_SIZE(r8); \ | ||
54 | stw r0,GPR11(r11); \ | ||
55 | mfspr r8,exc_level##_SPRG | ||
56 | |||
57 | .globl mcheck_transfer_to_handler | 47 | .globl mcheck_transfer_to_handler |
58 | mcheck_transfer_to_handler: | 48 | mcheck_transfer_to_handler: |
59 | TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK) | ||
60 | b transfer_to_handler_full | 49 | b transfer_to_handler_full |
61 | 50 | ||
62 | .globl debug_transfer_to_handler | 51 | .globl debug_transfer_to_handler |
63 | debug_transfer_to_handler: | 52 | debug_transfer_to_handler: |
64 | TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG) | ||
65 | b transfer_to_handler_full | 53 | b transfer_to_handler_full |
66 | 54 | ||
67 | .globl crit_transfer_to_handler | 55 | .globl crit_transfer_to_handler |
68 | crit_transfer_to_handler: | 56 | crit_transfer_to_handler: |
69 | TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT) | ||
70 | /* fall through */ | 57 | /* fall through */ |
71 | #endif | 58 | #endif |
72 | 59 | ||
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index 9eacf4ca442a..b0874d228eaf 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h | |||
@@ -72,18 +72,20 @@ | |||
72 | #define DEBUG_STACK_BASE dbgirq_ctx | 72 | #define DEBUG_STACK_BASE dbgirq_ctx |
73 | #define DEBUG_SPRG SPRN_SPRG6W | 73 | #define DEBUG_SPRG SPRN_SPRG6W |
74 | 74 | ||
75 | #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE) | ||
76 | |||
75 | #ifdef CONFIG_SMP | 77 | #ifdef CONFIG_SMP |
76 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | 78 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ |
77 | mfspr r8,SPRN_PIR; \ | 79 | mfspr r8,SPRN_PIR; \ |
78 | slwi r8,r8,2; \ | 80 | slwi r8,r8,2; \ |
79 | addis r8,r8,level##_STACK_BASE@ha; \ | 81 | addis r8,r8,level##_STACK_BASE@ha; \ |
80 | lwz r8,level##_STACK_BASE@l(r8); \ | 82 | lwz r8,level##_STACK_BASE@l(r8); \ |
81 | addi r8,r8,THREAD_SIZE; | 83 | addi r8,r8,EXC_LVL_FRAME_OVERHEAD; |
82 | #else | 84 | #else |
83 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | 85 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ |
84 | lis r8,level##_STACK_BASE@ha; \ | 86 | lis r8,level##_STACK_BASE@ha; \ |
85 | lwz r8,level##_STACK_BASE@l(r8); \ | 87 | lwz r8,level##_STACK_BASE@l(r8); \ |
86 | addi r8,r8,THREAD_SIZE; | 88 | addi r8,r8,EXC_LVL_FRAME_OVERHEAD; |
87 | #endif | 89 | #endif |
88 | 90 | ||
89 | /* | 91 | /* |
@@ -97,22 +99,36 @@ | |||
97 | #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ | 99 | #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ |
98 | mtspr exc_level##_SPRG,r8; \ | 100 | mtspr exc_level##_SPRG,r8; \ |
99 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ | 101 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ |
100 | stw r10,GPR10-INT_FRAME_SIZE(r8); \ | 102 | stw r9,GPR9(r8); /* save various registers */\ |
101 | stw r11,GPR11-INT_FRAME_SIZE(r8); \ | 103 | mfcr r9; /* save CR in r9 for now */\ |
102 | mfcr r10; /* save CR in r10 for now */\ | 104 | stw r10,GPR10(r8); \ |
103 | mfspr r11,exc_level_srr1; /* check whether user or kernel */\ | 105 | stw r11,GPR11(r8); \ |
104 | andi. r11,r11,MSR_PR; \ | 106 | stw r9,_CCR(r8); /* save CR on stack */\ |
105 | mr r11,r8; \ | 107 | mfspr r10,exc_level_srr1; /* check whether user or kernel */\ |
106 | mfspr r8,exc_level##_SPRG; \ | 108 | andi. r10,r10,MSR_PR; \ |
107 | beq 1f; \ | ||
108 | /* COMING FROM USER MODE */ \ | ||
109 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ | 109 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ |
110 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ | 110 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ |
111 | addi r11,r11,THREAD_SIZE; \ | 111 | addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\ |
112 | 1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ | 112 | beq 1f; \ |
113 | stw r10,_CCR(r11); /* save various registers */\ | 113 | /* COMING FROM USER MODE */ \ |
114 | stw r12,GPR12(r11); \ | 114 | stw r9,_CCR(r11); /* save CR */\ |
115 | lwz r10,GPR10(r8); /* copy regs from exception stack */\ | ||
116 | lwz r9,GPR9(r8); \ | ||
117 | stw r10,GPR10(r11); \ | ||
118 | lwz r10,GPR11(r8); \ | ||
115 | stw r9,GPR9(r11); \ | 119 | stw r9,GPR9(r11); \ |
120 | stw r10,GPR11(r11); \ | ||
121 | b 2f; \ | ||
122 | /* COMING FROM PRIV MODE */ \ | ||
123 | 1: lwz r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r11); \ | ||
124 | lwz r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r11); \ | ||
125 | stw r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r8); \ | ||
126 | stw r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r8); \ | ||
127 | lwz r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11); \ | ||
128 | stw r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8); \ | ||
129 | mr r11,r8; \ | ||
130 | 2: mfspr r8,exc_level##_SPRG; \ | ||
131 | stw r12,GPR12(r11); /* save various registers */\ | ||
116 | mflr r10; \ | 132 | mflr r10; \ |
117 | stw r10,_LINK(r11); \ | 133 | stw r10,_LINK(r11); \ |
118 | mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ | 134 | mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ |
@@ -255,8 +271,8 @@ label: | |||
255 | lwz r12,GPR12(r11); \ | 271 | lwz r12,GPR12(r11); \ |
256 | mtspr DEBUG_SPRG,r8; \ | 272 | mtspr DEBUG_SPRG,r8; \ |
257 | BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ | 273 | BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ |
258 | lwz r10,GPR10-INT_FRAME_SIZE(r8); \ | 274 | lwz r10,GPR10(r8); \ |
259 | lwz r11,GPR11-INT_FRAME_SIZE(r8); \ | 275 | lwz r11,GPR11(r8); \ |
260 | mfspr r8,DEBUG_SPRG; \ | 276 | mfspr r8,DEBUG_SPRG; \ |
261 | \ | 277 | \ |
262 | RFDI; \ | 278 | RFDI; \ |
@@ -308,8 +324,8 @@ label: | |||
308 | lwz r12,GPR12(r11); \ | 324 | lwz r12,GPR12(r11); \ |
309 | mtspr CRIT_SPRG,r8; \ | 325 | mtspr CRIT_SPRG,r8; \ |
310 | BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ | 326 | BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ |
311 | lwz r10,GPR10-INT_FRAME_SIZE(r8); \ | 327 | lwz r10,GPR10(r8); \ |
312 | lwz r11,GPR11-INT_FRAME_SIZE(r8); \ | 328 | lwz r11,GPR11(r8); \ |
313 | mfspr r8,CRIT_SPRG; \ | 329 | mfspr r8,CRIT_SPRG; \ |
314 | \ | 330 | \ |
315 | rfci; \ | 331 | rfci; \ |