]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/powerpc/kernel/head_booke.h
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-artful-kernel.git] / arch / powerpc / kernel / head_booke.h
1 #ifndef __HEAD_BOOKE_H__
2 #define __HEAD_BOOKE_H__
3
4 #include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
5 /*
6 * Macros used for common Book-e exception handling
7 */
8
9 #define SET_IVOR(vector_number, vector_label) \
10 li r26,vector_label@l; \
11 mtspr SPRN_IVOR##vector_number,r26; \
12 sync
13
14 #if (THREAD_SHIFT < 15)
15 #define ALLOC_STACK_FRAME(reg, val) \
16 addi reg,reg,val
17 #else
18 #define ALLOC_STACK_FRAME(reg, val) \
19 addis reg,reg,val@ha; \
20 addi reg,reg,val@l
21 #endif
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
31 #define NORMAL_EXCEPTION_PROLOG \
32 mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \
33 mfspr r10, SPRN_SPRG_THREAD; \
34 stw r11, THREAD_NORMSAVE(0)(r10); \
35 stw r13, THREAD_NORMSAVE(2)(r10); \
36 mfcr r13; /* save CR in r13 for now */\
37 mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
38 andi. r11,r11,MSR_PR; \
39 mr r11, r1; \
40 beq 1f; \
41 /* if from user, start at top of this thread's kernel stack */ \
42 lwz r11, THREAD_INFO-THREAD(r10); \
43 ALLOC_STACK_FRAME(r11, THREAD_SIZE); \
44 1 : subi r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */ \
45 stw r13, _CCR(r11); /* save various registers */ \
46 stw r12,GPR12(r11); \
47 stw r9,GPR9(r11); \
48 mfspr r13, SPRN_SPRG_RSCRATCH0; \
49 stw r13, GPR10(r11); \
50 lwz r12, THREAD_NORMSAVE(0)(r10); \
51 stw r12,GPR11(r11); \
52 lwz r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */ \
53 mflr r10; \
54 stw r10,_LINK(r11); \
55 mfspr r12,SPRN_SRR0; \
56 stw r1, GPR1(r11); \
57 mfspr r9,SPRN_SRR1; \
58 stw r1, 0(r11); \
59 mr r1, r11; \
60 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
61 stw r0,GPR0(r11); \
62 lis r10, STACK_FRAME_REGS_MARKER@ha;/* exception frame marker */ \
63 addi r10, r10, STACK_FRAME_REGS_MARKER@l; \
64 stw r10, 8(r11); \
65 SAVE_4GPRS(3, r11); \
66 SAVE_2GPRS(7, r11)
67
68 /* To handle the additional exception priority levels on 40x and Book-E
69 * processors we allocate a stack per additional priority level.
70 *
71 * On 40x critical is the only additional level
72 * On 44x/e500 we have critical and machine check
73 * On e200 we have critical and debug (machine check occurs via critical)
74 *
75 * Additionally we reserve a SPRG for each priority level so we can free up a
76 * GPR to use as the base for indirect access to the exception stacks. This
77 * is necessary since the MMU is always on, for Book-E parts, and the stacks
78 * are offset from KERNELBASE.
79 *
80 * There is some space optimization to be had here if desired. However
81 * to allow for a common kernel with support for debug exceptions either
82 * going to critical or their own debug level we aren't currently
83 * providing configurations that micro-optimize space usage.
84 */
85
86 #define MC_STACK_BASE mcheckirq_ctx
87 #define CRIT_STACK_BASE critirq_ctx
88
89 /* only on e500mc/e200 */
90 #define DBG_STACK_BASE dbgirq_ctx
91
92 #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
93
94 #ifdef CONFIG_SMP
95 #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
96 mfspr r8,SPRN_PIR; \
97 slwi r8,r8,2; \
98 addis r8,r8,level##_STACK_BASE@ha; \
99 lwz r8,level##_STACK_BASE@l(r8); \
100 addi r8,r8,EXC_LVL_FRAME_OVERHEAD;
101 #else
102 #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
103 lis r8,level##_STACK_BASE@ha; \
104 lwz r8,level##_STACK_BASE@l(r8); \
105 addi r8,r8,EXC_LVL_FRAME_OVERHEAD;
106 #endif
107
108 /*
109 * Exception prolog for critical/machine check exceptions. This is a
110 * little different from the normal exception prolog above since a
111 * critical/machine check exception can potentially occur at any point
112 * during normal exception processing. Thus we cannot use the same SPRG
113 * registers as the normal prolog above. Instead we use a portion of the
114 * critical/machine check exception stack at low physical addresses.
115 */
116 #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
117 mtspr SPRN_SPRG_WSCRATCH_##exc_level,r8; \
118 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
119 stw r9,GPR9(r8); /* save various registers */\
120 mfcr r9; /* save CR in r9 for now */\
121 stw r10,GPR10(r8); \
122 stw r11,GPR11(r8); \
123 stw r9,_CCR(r8); /* save CR on stack */\
124 mfspr r10,exc_level_srr1; /* check whether user or kernel */\
125 andi. r10,r10,MSR_PR; \
126 mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\
127 lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
128 addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\
129 beq 1f; \
130 /* COMING FROM USER MODE */ \
131 stw r9,_CCR(r11); /* save CR */\
132 lwz r10,GPR10(r8); /* copy regs from exception stack */\
133 lwz r9,GPR9(r8); \
134 stw r10,GPR10(r11); \
135 lwz r10,GPR11(r8); \
136 stw r9,GPR9(r11); \
137 stw r10,GPR11(r11); \
138 b 2f; \
139 /* COMING FROM PRIV MODE */ \
140 1: lwz r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r11); \
141 lwz r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r11); \
142 stw r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r8); \
143 stw r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r8); \
144 lwz r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11); \
145 stw r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8); \
146 mr r11,r8; \
147 2: mfspr r8,SPRN_SPRG_RSCRATCH_##exc_level; \
148 stw r12,GPR12(r11); /* save various registers */\
149 mflr r10; \
150 stw r10,_LINK(r11); \
151 mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
152 stw r12,_DEAR(r11); /* since they may have had stuff */\
153 mfspr r9,SPRN_ESR; /* in them at the point where the */\
154 stw r9,_ESR(r11); /* exception was taken */\
155 mfspr r12,exc_level_srr0; \
156 stw r1,GPR1(r11); \
157 mfspr r9,exc_level_srr1; \
158 stw r1,0(r11); \
159 mr r1,r11; \
160 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
161 stw r0,GPR0(r11); \
162 SAVE_4GPRS(3, r11); \
163 SAVE_2GPRS(7, r11)
164
165 #define CRITICAL_EXCEPTION_PROLOG \
166 EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
167 #define DEBUG_EXCEPTION_PROLOG \
168 EXC_LEVEL_EXCEPTION_PROLOG(DBG, SPRN_DSRR0, SPRN_DSRR1)
169 #define MCHECK_EXCEPTION_PROLOG \
170 EXC_LEVEL_EXCEPTION_PROLOG(MC, SPRN_MCSRR0, SPRN_MCSRR1)
171
172 /*
173 * Exception vectors.
174 */
175 #define START_EXCEPTION(label) \
176 .align 5; \
177 label:
178
179 #define FINISH_EXCEPTION(func) \
180 bl transfer_to_handler_full; \
181 .long func; \
182 .long ret_from_except_full
183
184 #define EXCEPTION(n, label, hdlr, xfer) \
185 START_EXCEPTION(label); \
186 NORMAL_EXCEPTION_PROLOG; \
187 addi r3,r1,STACK_FRAME_OVERHEAD; \
188 xfer(n, hdlr)
189
190 #define CRITICAL_EXCEPTION(n, label, hdlr) \
191 START_EXCEPTION(label); \
192 CRITICAL_EXCEPTION_PROLOG; \
193 addi r3,r1,STACK_FRAME_OVERHEAD; \
194 EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
195 NOCOPY, crit_transfer_to_handler, \
196 ret_from_crit_exc)
197
198 #define MCHECK_EXCEPTION(n, label, hdlr) \
199 START_EXCEPTION(label); \
200 MCHECK_EXCEPTION_PROLOG; \
201 mfspr r5,SPRN_ESR; \
202 stw r5,_ESR(r11); \
203 addi r3,r1,STACK_FRAME_OVERHEAD; \
204 EXC_XFER_TEMPLATE(hdlr, n+4, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
205 NOCOPY, mcheck_transfer_to_handler, \
206 ret_from_mcheck_exc)
207
208 #define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \
209 li r10,trap; \
210 stw r10,_TRAP(r11); \
211 lis r10,msr@h; \
212 ori r10,r10,msr@l; \
213 copyee(r10, r9); \
214 bl tfer; \
215 .long hdlr; \
216 .long ret
217
218 #define COPY_EE(d, s) rlwimi d,s,0,16,16
219 #define NOCOPY(d, s)
220
221 #define EXC_XFER_STD(n, hdlr) \
222 EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
223 ret_from_except_full)
224
225 #define EXC_XFER_LITE(n, hdlr) \
226 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
227 ret_from_except)
228
229 #define EXC_XFER_EE(n, hdlr) \
230 EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
231 ret_from_except_full)
232
233 #define EXC_XFER_EE_LITE(n, hdlr) \
234 EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
235 ret_from_except)
236
237 /* Check for a single step debug exception while in an exception
238 * handler before state has been saved. This is to catch the case
239 * where an instruction that we are trying to single step causes
240 * an exception (eg ITLB/DTLB miss) and thus the first instruction of
241 * the exception handler generates a single step debug exception.
242 *
243 * If we get a debug trap on the first instruction of an exception handler,
244 * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
245 * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
246 * The exception handler was handling a non-critical interrupt, so it will
247 * save (and later restore) the MSR via SPRN_CSRR1, which will still have
248 * the MSR_DE bit set.
249 */
250 #define DEBUG_DEBUG_EXCEPTION \
251 START_EXCEPTION(DebugDebug); \
252 DEBUG_EXCEPTION_PROLOG; \
253 \
254 /* \
255 * If there is a single step or branch-taken exception in an \
256 * exception entry sequence, it was probably meant to apply to \
257 * the code where the exception occurred (since exception entry \
258 * doesn't turn off DE automatically). We simulate the effect \
259 * of turning off DE on entry to an exception handler by turning \
260 * off DE in the DSRR1 value and clearing the debug status. \
261 */ \
262 mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
263 andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
264 beq+ 2f; \
265 \
266 lis r10,KERNELBASE@h; /* check if exception in vectors */ \
267 ori r10,r10,KERNELBASE@l; \
268 cmplw r12,r10; \
269 blt+ 2f; /* addr below exception vectors */ \
270 \
271 lis r10,DebugDebug@h; \
272 ori r10,r10,DebugDebug@l; \
273 cmplw r12,r10; \
274 bgt+ 2f; /* addr above exception vectors */ \
275 \
276 /* here it looks like we got an inappropriate debug exception. */ \
277 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \
278 lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
279 mtspr SPRN_DBSR,r10; \
280 /* restore state and get out */ \
281 lwz r10,_CCR(r11); \
282 lwz r0,GPR0(r11); \
283 lwz r1,GPR1(r11); \
284 mtcrf 0x80,r10; \
285 mtspr SPRN_DSRR0,r12; \
286 mtspr SPRN_DSRR1,r9; \
287 lwz r9,GPR9(r11); \
288 lwz r12,GPR12(r11); \
289 mtspr SPRN_SPRG_WSCRATCH_DBG,r8; \
290 BOOKE_LOAD_EXC_LEVEL_STACK(DBG); /* r8 points to the debug stack */ \
291 lwz r10,GPR10(r8); \
292 lwz r11,GPR11(r8); \
293 mfspr r8,SPRN_SPRG_RSCRATCH_DBG; \
294 \
295 PPC_RFDI; \
296 b .; \
297 \
298 /* continue normal handling for a debug exception... */ \
299 2: mfspr r4,SPRN_DBSR; \
300 addi r3,r1,STACK_FRAME_OVERHEAD; \
301 EXC_XFER_TEMPLATE(DebugException, 0x2008, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
302
303 #define DEBUG_CRIT_EXCEPTION \
304 START_EXCEPTION(DebugCrit); \
305 CRITICAL_EXCEPTION_PROLOG; \
306 \
307 /* \
308 * If there is a single step or branch-taken exception in an \
309 * exception entry sequence, it was probably meant to apply to \
310 * the code where the exception occurred (since exception entry \
311 * doesn't turn off DE automatically). We simulate the effect \
312 * of turning off DE on entry to an exception handler by turning \
313 * off DE in the CSRR1 value and clearing the debug status. \
314 */ \
315 mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
316 andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
317 beq+ 2f; \
318 \
319 lis r10,KERNELBASE@h; /* check if exception in vectors */ \
320 ori r10,r10,KERNELBASE@l; \
321 cmplw r12,r10; \
322 blt+ 2f; /* addr below exception vectors */ \
323 \
324 lis r10,DebugCrit@h; \
325 ori r10,r10,DebugCrit@l; \
326 cmplw r12,r10; \
327 bgt+ 2f; /* addr above exception vectors */ \
328 \
329 /* here it looks like we got an inappropriate debug exception. */ \
330 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
331 lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
332 mtspr SPRN_DBSR,r10; \
333 /* restore state and get out */ \
334 lwz r10,_CCR(r11); \
335 lwz r0,GPR0(r11); \
336 lwz r1,GPR1(r11); \
337 mtcrf 0x80,r10; \
338 mtspr SPRN_CSRR0,r12; \
339 mtspr SPRN_CSRR1,r9; \
340 lwz r9,GPR9(r11); \
341 lwz r12,GPR12(r11); \
342 mtspr SPRN_SPRG_WSCRATCH_CRIT,r8; \
343 BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
344 lwz r10,GPR10(r8); \
345 lwz r11,GPR11(r8); \
346 mfspr r8,SPRN_SPRG_RSCRATCH_CRIT; \
347 \
348 rfci; \
349 b .; \
350 \
351 /* continue normal handling for a critical exception... */ \
352 2: mfspr r4,SPRN_DBSR; \
353 addi r3,r1,STACK_FRAME_OVERHEAD; \
354 EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
355
356 #define DATA_STORAGE_EXCEPTION \
357 START_EXCEPTION(DataStorage) \
358 NORMAL_EXCEPTION_PROLOG; \
359 mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
360 stw r5,_ESR(r11); \
361 mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \
362 EXC_XFER_EE_LITE(0x0300, handle_page_fault)
363
364 #define INSTRUCTION_STORAGE_EXCEPTION \
365 START_EXCEPTION(InstructionStorage) \
366 NORMAL_EXCEPTION_PROLOG; \
367 mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
368 stw r5,_ESR(r11); \
369 mr r4,r12; /* Pass SRR0 as arg2 */ \
370 li r5,0; /* Pass zero as arg3 */ \
371 EXC_XFER_EE_LITE(0x0400, handle_page_fault)
372
373 #define ALIGNMENT_EXCEPTION \
374 START_EXCEPTION(Alignment) \
375 NORMAL_EXCEPTION_PROLOG; \
376 mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \
377 stw r4,_DEAR(r11); \
378 addi r3,r1,STACK_FRAME_OVERHEAD; \
379 EXC_XFER_EE(0x0600, alignment_exception)
380
381 #define PROGRAM_EXCEPTION \
382 START_EXCEPTION(Program) \
383 NORMAL_EXCEPTION_PROLOG; \
384 mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \
385 stw r4,_ESR(r11); \
386 addi r3,r1,STACK_FRAME_OVERHEAD; \
387 EXC_XFER_STD(0x0700, program_check_exception)
388
389 #define DECREMENTER_EXCEPTION \
390 START_EXCEPTION(Decrementer) \
391 NORMAL_EXCEPTION_PROLOG; \
392 lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \
393 mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \
394 addi r3,r1,STACK_FRAME_OVERHEAD; \
395 EXC_XFER_LITE(0x0900, timer_interrupt)
396
397 #define FP_UNAVAILABLE_EXCEPTION \
398 START_EXCEPTION(FloatingPointUnavailable) \
399 NORMAL_EXCEPTION_PROLOG; \
400 beq 1f; \
401 bl load_up_fpu; /* if from user, just load it up */ \
402 b fast_exception_return; \
403 1: addi r3,r1,STACK_FRAME_OVERHEAD; \
404 EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
405
406 #ifndef __ASSEMBLY__
407 struct exception_regs {
408 unsigned long mas0;
409 unsigned long mas1;
410 unsigned long mas2;
411 unsigned long mas3;
412 unsigned long mas6;
413 unsigned long mas7;
414 unsigned long srr0;
415 unsigned long srr1;
416 unsigned long csrr0;
417 unsigned long csrr1;
418 unsigned long dsrr0;
419 unsigned long dsrr1;
420 unsigned long saved_ksp_limit;
421 };
422
423 /* ensure this structure is always sized to a multiple of the stack alignment */
424 #define STACK_EXC_LVL_FRAME_SIZE _ALIGN_UP(sizeof (struct exception_regs), 16)
425
426 #endif /* __ASSEMBLY__ */
427 #endif /* __HEAD_BOOKE_H__ */