aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/head_booke.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/head_booke.h')
-rw-r--r--arch/powerpc/kernel/head_booke.h126
1 files changed, 85 insertions, 41 deletions
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h
index aefafc6330c9..fce2df988504 100644
--- a/arch/powerpc/kernel/head_booke.h
+++ b/arch/powerpc/kernel/head_booke.h
@@ -43,9 +43,7 @@
43 SAVE_2GPRS(7, r11) 43 SAVE_2GPRS(7, r11)
44 44
45/* To handle the additional exception priority levels on 40x and Book-E 45/* To handle the additional exception priority levels on 40x and Book-E
46 * processors we allocate a 4k stack per additional priority level. The various 46 * processors we allocate a stack per additional priority level.
47 * head_xxx.S files allocate space (exception_stack_top) for each priority's
48 * stack times the number of CPUs
49 * 47 *
50 * On 40x critical is the only additional level 48 * On 40x critical is the only additional level
51 * On 44x/e500 we have critical and machine check 49 * On 44x/e500 we have critical and machine check
@@ -61,36 +59,37 @@
61 * going to critical or their own debug level we aren't currently 59 * going to critical or their own debug level we aren't currently
62 * providing configurations that micro-optimize space usage. 60 * providing configurations that micro-optimize space usage.
63 */ 61 */
64#ifdef CONFIG_44x
65#define NUM_EXCEPTION_LVLS 2
66#else
67#define NUM_EXCEPTION_LVLS 3
68#endif
69#define BOOKE_EXCEPTION_STACK_SIZE (4096 * NUM_EXCEPTION_LVLS)
70 62
71/* CRIT_SPRG only used in critical exception handling */ 63/* CRIT_SPRG only used in critical exception handling */
72#define CRIT_SPRG SPRN_SPRG2 64#define CRIT_SPRG SPRN_SPRG2
73/* MCHECK_SPRG only used in machine check exception handling */ 65/* MCHECK_SPRG only used in machine check exception handling */
74#define MCHECK_SPRG SPRN_SPRG6W 66#define MCHECK_SPRG SPRN_SPRG6W
75 67
76#define MCHECK_STACK_TOP (exception_stack_top - 4096) 68#define MCHECK_STACK_BASE mcheckirq_ctx
77#define CRIT_STACK_TOP (exception_stack_top) 69#define CRIT_STACK_BASE critirq_ctx
78 70
79/* only on e200 for now */ 71/* only on e500mc/e200 */
80#define DEBUG_STACK_TOP (exception_stack_top - 8192) 72#define DEBUG_STACK_BASE dbgirq_ctx
73#ifdef CONFIG_PPC_E500MC
74#define DEBUG_SPRG SPRN_SPRG9
75#else
81#define DEBUG_SPRG SPRN_SPRG6W 76#define DEBUG_SPRG SPRN_SPRG6W
77#endif
78
79#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
82 80
83#ifdef CONFIG_SMP 81#ifdef CONFIG_SMP
84#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ 82#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
85 mfspr r8,SPRN_PIR; \ 83 mfspr r8,SPRN_PIR; \
86 mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ 84 slwi r8,r8,2; \
87 neg r8,r8; \ 85 addis r8,r8,level##_STACK_BASE@ha; \
88 addis r8,r8,level##_STACK_TOP@ha; \ 86 lwz r8,level##_STACK_BASE@l(r8); \
89 addi r8,r8,level##_STACK_TOP@l 87 addi r8,r8,EXC_LVL_FRAME_OVERHEAD;
90#else 88#else
91#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ 89#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
92 lis r8,level##_STACK_TOP@h; \ 90 lis r8,level##_STACK_BASE@ha; \
93 ori r8,r8,level##_STACK_TOP@l 91 lwz r8,level##_STACK_BASE@l(r8); \
92 addi r8,r8,EXC_LVL_FRAME_OVERHEAD;
94#endif 93#endif
95 94
96/* 95/*
@@ -104,22 +103,36 @@
104#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ 103#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
105 mtspr exc_level##_SPRG,r8; \ 104 mtspr exc_level##_SPRG,r8; \
106 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ 105 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
107 stw r10,GPR10-INT_FRAME_SIZE(r8); \ 106 stw r9,GPR9(r8); /* save various registers */\
108 stw r11,GPR11-INT_FRAME_SIZE(r8); \ 107 mfcr r9; /* save CR in r9 for now */\
109 mfcr r10; /* save CR in r10 for now */\ 108 stw r10,GPR10(r8); \
110 mfspr r11,exc_level_srr1; /* check whether user or kernel */\ 109 stw r11,GPR11(r8); \
111 andi. r11,r11,MSR_PR; \ 110 stw r9,_CCR(r8); /* save CR on stack */\
112 mr r11,r8; \ 111 mfspr r10,exc_level_srr1; /* check whether user or kernel */\
113 mfspr r8,exc_level##_SPRG; \ 112 andi. r10,r10,MSR_PR; \
114 beq 1f; \
115 /* COMING FROM USER MODE */ \
116 mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ 113 mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
117 lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ 114 lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
118 addi r11,r11,THREAD_SIZE; \ 115 addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\
1191: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ 116 beq 1f; \
120 stw r10,_CCR(r11); /* save various registers */\ 117 /* COMING FROM USER MODE */ \
121 stw r12,GPR12(r11); \ 118 stw r9,_CCR(r11); /* save CR */\
119 lwz r10,GPR10(r8); /* copy regs from exception stack */\
120 lwz r9,GPR9(r8); \
121 stw r10,GPR10(r11); \
122 lwz r10,GPR11(r8); \
122 stw r9,GPR9(r11); \ 123 stw r9,GPR9(r11); \
124 stw r10,GPR11(r11); \
125 b 2f; \
126 /* COMING FROM PRIV MODE */ \
1271: lwz r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r11); \
128 lwz r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r11); \
129 stw r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r8); \
130 stw r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r8); \
131 lwz r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11); \
132 stw r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8); \
133 mr r11,r8; \
1342: mfspr r8,exc_level##_SPRG; \
135 stw r12,GPR12(r11); /* save various registers */\
123 mflr r10; \ 136 mflr r10; \
124 stw r10,_LINK(r11); \ 137 stw r10,_LINK(r11); \
125 mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ 138 mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
@@ -231,7 +244,7 @@ label:
231 * the code where the exception occurred (since exception entry \ 244 * the code where the exception occurred (since exception entry \
232 * doesn't turn off DE automatically). We simulate the effect \ 245 * doesn't turn off DE automatically). We simulate the effect \
233 * of turning off DE on entry to an exception handler by turning \ 246 * of turning off DE on entry to an exception handler by turning \
234 * off DE in the CSRR1 value and clearing the debug status. \ 247 * off DE in the DSRR1 value and clearing the debug status. \
235 */ \ 248 */ \
236 mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ 249 mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
237 andis. r10,r10,DBSR_IC@h; \ 250 andis. r10,r10,DBSR_IC@h; \
@@ -262,17 +275,17 @@ label:
262 lwz r12,GPR12(r11); \ 275 lwz r12,GPR12(r11); \
263 mtspr DEBUG_SPRG,r8; \ 276 mtspr DEBUG_SPRG,r8; \
264 BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ 277 BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \
265 lwz r10,GPR10-INT_FRAME_SIZE(r8); \ 278 lwz r10,GPR10(r8); \
266 lwz r11,GPR11-INT_FRAME_SIZE(r8); \ 279 lwz r11,GPR11(r8); \
267 mfspr r8,DEBUG_SPRG; \ 280 mfspr r8,DEBUG_SPRG; \
268 \ 281 \
269 RFDI; \ 282 RFDI; \
270 b .; \ 283 b .; \
271 \ 284 \
272 /* continue normal handling for a critical exception... */ \ 285 /* continue normal handling for a debug exception... */ \
2732: mfspr r4,SPRN_DBSR; \ 2862: mfspr r4,SPRN_DBSR; \
274 addi r3,r1,STACK_FRAME_OVERHEAD; \ 287 addi r3,r1,STACK_FRAME_OVERHEAD; \
275 EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc) 288 EXC_XFER_TEMPLATE(DebugException, 0x2008, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
276 289
277#define DEBUG_CRIT_EXCEPTION \ 290#define DEBUG_CRIT_EXCEPTION \
278 START_EXCEPTION(DebugCrit); \ 291 START_EXCEPTION(DebugCrit); \
@@ -315,8 +328,8 @@ label:
315 lwz r12,GPR12(r11); \ 328 lwz r12,GPR12(r11); \
316 mtspr CRIT_SPRG,r8; \ 329 mtspr CRIT_SPRG,r8; \
317 BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ 330 BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
318 lwz r10,GPR10-INT_FRAME_SIZE(r8); \ 331 lwz r10,GPR10(r8); \
319 lwz r11,GPR11-INT_FRAME_SIZE(r8); \ 332 lwz r11,GPR11(r8); \
320 mfspr r8,CRIT_SPRG; \ 333 mfspr r8,CRIT_SPRG; \
321 \ 334 \
322 rfci; \ 335 rfci; \
@@ -327,6 +340,14 @@ label:
327 addi r3,r1,STACK_FRAME_OVERHEAD; \ 340 addi r3,r1,STACK_FRAME_OVERHEAD; \
328 EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) 341 EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
329 342
343#define DATA_STORAGE_EXCEPTION \
344 START_EXCEPTION(DataStorage) \
345 NORMAL_EXCEPTION_PROLOG; \
346 mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
347 stw r5,_ESR(r11); \
348 mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \
349 EXC_XFER_EE_LITE(0x0300, handle_page_fault)
350
330#define INSTRUCTION_STORAGE_EXCEPTION \ 351#define INSTRUCTION_STORAGE_EXCEPTION \
331 START_EXCEPTION(InstructionStorage) \ 352 START_EXCEPTION(InstructionStorage) \
332 NORMAL_EXCEPTION_PROLOG; \ 353 NORMAL_EXCEPTION_PROLOG; \
@@ -363,8 +384,31 @@ label:
363#define FP_UNAVAILABLE_EXCEPTION \ 384#define FP_UNAVAILABLE_EXCEPTION \
364 START_EXCEPTION(FloatingPointUnavailable) \ 385 START_EXCEPTION(FloatingPointUnavailable) \
365 NORMAL_EXCEPTION_PROLOG; \ 386 NORMAL_EXCEPTION_PROLOG; \
366 bne load_up_fpu; /* if from user, just load it up */ \ 387 beq 1f; \
367 addi r3,r1,STACK_FRAME_OVERHEAD; \ 388 bl load_up_fpu; /* if from user, just load it up */ \
389 b fast_exception_return; \
3901: addi r3,r1,STACK_FRAME_OVERHEAD; \
368 EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) 391 EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
369 392
393#ifndef __ASSEMBLY__
394struct exception_regs {
395 unsigned long mas0;
396 unsigned long mas1;
397 unsigned long mas2;
398 unsigned long mas3;
399 unsigned long mas6;
400 unsigned long mas7;
401 unsigned long srr0;
402 unsigned long srr1;
403 unsigned long csrr0;
404 unsigned long csrr1;
405 unsigned long dsrr0;
406 unsigned long dsrr1;
407 unsigned long saved_ksp_limit;
408};
409
410/* ensure this structure is always sized to a multiple of the stack alignment */
411#define STACK_EXC_LVL_FRAME_SIZE _ALIGN_UP(sizeof (struct exception_regs), 16)
412
413#endif /* __ASSEMBLY__ */
370#endif /* __HEAD_BOOKE_H__ */ 414#endif /* __HEAD_BOOKE_H__ */