Loading...
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __HEAD_BOOKE_H__
3#define __HEAD_BOOKE_H__
4
5#include <asm/ptrace.h> /* for STACK_FRAME_REGS_MARKER */
6#include <asm/kvm_asm.h>
7#include <asm/kvm_booke_hv_asm.h>
8
9#ifdef __ASSEMBLY__
10
11/*
12 * Macros used for common Book-e exception handling
13 */
14
15#define SET_IVOR(vector_number, vector_label) \
16 li r26,vector_label@l; \
17 mtspr SPRN_IVOR##vector_number,r26; \
18 sync
19
20#if (THREAD_SHIFT < 15)
21#define ALLOC_STACK_FRAME(reg, val) \
22 addi reg,reg,val
23#else
24#define ALLOC_STACK_FRAME(reg, val) \
25 addis reg,reg,val@ha; \
26 addi reg,reg,val@l
27#endif
28
29/*
30 * Macro used to get to thread save registers.
31 * Note that entries 0-3 are used for the prolog code, and the remaining
32 * entries are available for specific exception use in the event a handler
33 * requires more than 4 scratch registers.
34 */
35#define THREAD_NORMSAVE(offset) (THREAD_NORMSAVES + (offset * 4))
36
37#ifdef CONFIG_PPC_E500
38#define BOOKE_CLEAR_BTB(reg) \
39START_BTB_FLUSH_SECTION \
40 BTB_FLUSH(reg) \
41END_BTB_FLUSH_SECTION
42#else
43#define BOOKE_CLEAR_BTB(reg)
44#endif
45
46
47#define NORMAL_EXCEPTION_PROLOG(trapno, intno) \
48 mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \
49 mfspr r10, SPRN_SPRG_THREAD; \
50 stw r11, THREAD_NORMSAVE(0)(r10); \
51 stw r13, THREAD_NORMSAVE(2)(r10); \
52 mfcr r13; /* save CR in r13 for now */\
53 mfspr r11, SPRN_SRR1; \
54 DO_KVM BOOKE_INTERRUPT_##intno SPRN_SRR1; \
55 andi. r11, r11, MSR_PR; /* check whether user or kernel */\
56 LOAD_REG_IMMEDIATE(r11, MSR_KERNEL); \
57 mtmsr r11; \
58 mr r11, r1; \
59 beq 1f; \
60 BOOKE_CLEAR_BTB(r11) \
61 /* if from user, start at top of this thread's kernel stack */ \
62 lwz r11, TASK_STACK - THREAD(r10); \
63 ALLOC_STACK_FRAME(r11, THREAD_SIZE); \
641 : subi r11, r11, INT_FRAME_SIZE; /* Allocate exception frame */ \
65 stw r13, _CCR(r11); /* save various registers */ \
66 stw r12,GPR12(r11); \
67 stw r9,GPR9(r11); \
68 mfspr r13, SPRN_SPRG_RSCRATCH0; \
69 stw r13, GPR10(r11); \
70 lwz r12, THREAD_NORMSAVE(0)(r10); \
71 stw r12,GPR11(r11); \
72 lwz r13, THREAD_NORMSAVE(2)(r10); /* restore r13 */ \
73 mflr r10; \
74 stw r10,_LINK(r11); \
75 mfspr r12,SPRN_SRR0; \
76 stw r1, GPR1(r11); \
77 mfspr r9,SPRN_SRR1; \
78 stw r1, 0(r11); \
79 mr r1, r11; \
80 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
81 COMMON_EXCEPTION_PROLOG_END trapno
82
83.macro COMMON_EXCEPTION_PROLOG_END trapno
84 stw r0,GPR0(r1)
85 lis r10, STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
86 addi r10, r10, STACK_FRAME_REGS_MARKER@l
87 stw r10, STACK_INT_FRAME_MARKER(r1)
88 li r10, \trapno
89 stw r10,_TRAP(r1)
90 SAVE_GPRS(3, 8, r1)
91 SAVE_NVGPRS(r1)
92 stw r2,GPR2(r1)
93 stw r12,_NIP(r1)
94 stw r9,_MSR(r1)
95 mfctr r10
96 mfspr r2,SPRN_SPRG_THREAD
97 stw r10,_CTR(r1)
98 tovirt(r2, r2)
99 mfspr r10,SPRN_XER
100 addi r2, r2, -THREAD
101 stw r10,_XER(r1)
102 addi r3,r1,STACK_INT_FRAME_REGS
103.endm
104
105.macro prepare_transfer_to_handler
106#ifdef CONFIG_PPC_E500
107 andi. r12,r9,MSR_PR
108 bne 777f
109 bl prepare_transfer_to_handler
110777:
111#endif
112.endm
113
114.macro SYSCALL_ENTRY trapno intno srr1
115 mfspr r10, SPRN_SPRG_THREAD
116#ifdef CONFIG_KVM_BOOKE_HV
117BEGIN_FTR_SECTION
118 mtspr SPRN_SPRG_WSCRATCH0, r10
119 stw r11, THREAD_NORMSAVE(0)(r10)
120 stw r13, THREAD_NORMSAVE(2)(r10)
121 mfcr r13 /* save CR in r13 for now */
122 mfspr r11, SPRN_SRR1
123 mtocrf 0x80, r11 /* check MSR[GS] without clobbering reg */
124 bf 3, 1975f
125 b kvmppc_handler_\intno\()_\srr1
1261975:
127 mr r12, r13
128 lwz r13, THREAD_NORMSAVE(2)(r10)
129FTR_SECTION_ELSE
130 mfcr r12
131ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
132#else
133 mfcr r12
134#endif
135 mfspr r9, SPRN_SRR1
136 BOOKE_CLEAR_BTB(r11)
137 mr r11, r1
138 lwz r1, TASK_STACK - THREAD(r10)
139 rlwinm r12,r12,0,4,2 /* Clear SO bit in CR */
140 ALLOC_STACK_FRAME(r1, THREAD_SIZE - INT_FRAME_SIZE)
141 stw r12, _CCR(r1)
142 mfspr r12,SPRN_SRR0
143 stw r12,_NIP(r1)
144 b transfer_to_syscall /* jump to handler */
145.endm
146
147/* To handle the additional exception priority levels on 40x and Book-E
148 * processors we allocate a stack per additional priority level.
149 *
150 * On 40x critical is the only additional level
151 * On 44x/e500 we have critical and machine check
152 *
153 * Additionally we reserve a SPRG for each priority level so we can free up a
154 * GPR to use as the base for indirect access to the exception stacks. This
155 * is necessary since the MMU is always on, for Book-E parts, and the stacks
156 * are offset from KERNELBASE.
157 *
158 * There is some space optimization to be had here if desired. However
159 * to allow for a common kernel with support for debug exceptions either
160 * going to critical or their own debug level we aren't currently
161 * providing configurations that micro-optimize space usage.
162 */
163
164#define MC_STACK_BASE mcheckirq_ctx
165#define CRIT_STACK_BASE critirq_ctx
166
167/* only on e500mc */
168#define DBG_STACK_BASE dbgirq_ctx
169
170#ifdef CONFIG_SMP
171#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
172 mfspr r8,SPRN_PIR; \
173 slwi r8,r8,2; \
174 addis r8,r8,level##_STACK_BASE@ha; \
175 lwz r8,level##_STACK_BASE@l(r8); \
176 addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
177#else
178#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
179 lis r8,level##_STACK_BASE@ha; \
180 lwz r8,level##_STACK_BASE@l(r8); \
181 addi r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
182#endif
183
184/*
185 * Exception prolog for critical/machine check exceptions. This is a
186 * little different from the normal exception prolog above since a
187 * critical/machine check exception can potentially occur at any point
188 * during normal exception processing. Thus we cannot use the same SPRG
189 * registers as the normal prolog above. Instead we use a portion of the
190 * critical/machine check exception stack at low physical addresses.
191 */
192#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, trapno, intno, exc_level_srr0, exc_level_srr1) \
193 mtspr SPRN_SPRG_WSCRATCH_##exc_level,r8; \
194 BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
195 stw r9,GPR9(r8); /* save various registers */\
196 mfcr r9; /* save CR in r9 for now */\
197 stw r10,GPR10(r8); \
198 stw r11,GPR11(r8); \
199 stw r9,_CCR(r8); /* save CR on stack */\
200 mfspr r11,exc_level_srr1; /* check whether user or kernel */\
201 DO_KVM BOOKE_INTERRUPT_##intno exc_level_srr1; \
202 BOOKE_CLEAR_BTB(r10) \
203 andi. r11,r11,MSR_PR; \
204 LOAD_REG_IMMEDIATE(r11, MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)); \
205 mtmsr r11; \
206 mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\
207 lwz r11, TASK_STACK - THREAD(r11); /* this thread's kernel stack */\
208 addi r11,r11,THREAD_SIZE - INT_FRAME_SIZE; /* allocate stack frame */\
209 beq 1f; \
210 /* COMING FROM USER MODE */ \
211 stw r9,_CCR(r11); /* save CR */\
212 lwz r10,GPR10(r8); /* copy regs from exception stack */\
213 lwz r9,GPR9(r8); \
214 stw r10,GPR10(r11); \
215 lwz r10,GPR11(r8); \
216 stw r9,GPR9(r11); \
217 stw r10,GPR11(r11); \
218 b 2f; \
219 /* COMING FROM PRIV MODE */ \
2201: mr r11, r8; \
2212: mfspr r8,SPRN_SPRG_RSCRATCH_##exc_level; \
222 stw r12,GPR12(r11); /* save various registers */\
223 mflr r10; \
224 stw r10,_LINK(r11); \
225 mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
226 stw r12,_DEAR(r11); /* since they may have had stuff */\
227 mfspr r9,SPRN_ESR; /* in them at the point where the */\
228 stw r9,_ESR(r11); /* exception was taken */\
229 mfspr r12,exc_level_srr0; \
230 stw r1,GPR1(r11); \
231 mfspr r9,exc_level_srr1; \
232 stw r1,0(r11); \
233 mr r1,r11; \
234 rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
235 COMMON_EXCEPTION_PROLOG_END trapno
236
237#define SAVE_xSRR(xSRR) \
238 mfspr r0,SPRN_##xSRR##0; \
239 stw r0,_##xSRR##0(r1); \
240 mfspr r0,SPRN_##xSRR##1; \
241 stw r0,_##xSRR##1(r1)
242
243
244.macro SAVE_MMU_REGS
245#ifdef CONFIG_PPC_E500
246 mfspr r0,SPRN_MAS0
247 stw r0,MAS0(r1)
248 mfspr r0,SPRN_MAS1
249 stw r0,MAS1(r1)
250 mfspr r0,SPRN_MAS2
251 stw r0,MAS2(r1)
252 mfspr r0,SPRN_MAS3
253 stw r0,MAS3(r1)
254 mfspr r0,SPRN_MAS6
255 stw r0,MAS6(r1)
256#ifdef CONFIG_PHYS_64BIT
257 mfspr r0,SPRN_MAS7
258 stw r0,MAS7(r1)
259#endif /* CONFIG_PHYS_64BIT */
260#endif /* CONFIG_PPC_E500 */
261#ifdef CONFIG_44x
262 mfspr r0,SPRN_MMUCR
263 stw r0,MMUCR(r1)
264#endif
265.endm
266
267#define CRITICAL_EXCEPTION_PROLOG(trapno, intno) \
268 EXC_LEVEL_EXCEPTION_PROLOG(CRIT, trapno+2, intno, SPRN_CSRR0, SPRN_CSRR1)
269#define DEBUG_EXCEPTION_PROLOG(trapno) \
270 EXC_LEVEL_EXCEPTION_PROLOG(DBG, trapno+8, DEBUG, SPRN_DSRR0, SPRN_DSRR1)
271#define MCHECK_EXCEPTION_PROLOG(trapno) \
272 EXC_LEVEL_EXCEPTION_PROLOG(MC, trapno+4, MACHINE_CHECK, \
273 SPRN_MCSRR0, SPRN_MCSRR1)
274
275/*
276 * Guest Doorbell -- this is a bit odd in that uses GSRR0/1 despite
277 * being delivered to the host. This exception can only happen
278 * inside a KVM guest -- so we just handle up to the DO_KVM rather
279 * than try to fit this into one of the existing prolog macros.
280 */
281#define GUEST_DOORBELL_EXCEPTION \
282 START_EXCEPTION(GuestDoorbell); \
283 mtspr SPRN_SPRG_WSCRATCH0, r10; /* save one register */ \
284 mfspr r10, SPRN_SPRG_THREAD; \
285 stw r11, THREAD_NORMSAVE(0)(r10); \
286 mfspr r11, SPRN_SRR1; \
287 stw r13, THREAD_NORMSAVE(2)(r10); \
288 mfcr r13; /* save CR in r13 for now */\
289 DO_KVM BOOKE_INTERRUPT_GUEST_DBELL SPRN_GSRR1; \
290 trap
291
292/*
293 * Exception vectors.
294 */
295#define START_EXCEPTION(label) \
296 .align 5; \
297label:
298
299#define EXCEPTION(n, intno, label, hdlr) \
300 START_EXCEPTION(label); \
301 NORMAL_EXCEPTION_PROLOG(n, intno); \
302 prepare_transfer_to_handler; \
303 bl hdlr; \
304 b interrupt_return
305
306#define CRITICAL_EXCEPTION(n, intno, label, hdlr) \
307 START_EXCEPTION(label); \
308 CRITICAL_EXCEPTION_PROLOG(n, intno); \
309 SAVE_MMU_REGS; \
310 SAVE_xSRR(SRR); \
311 prepare_transfer_to_handler; \
312 bl hdlr; \
313 b ret_from_crit_exc
314
315#define MCHECK_EXCEPTION(n, label, hdlr) \
316 START_EXCEPTION(label); \
317 MCHECK_EXCEPTION_PROLOG(n); \
318 mfspr r5,SPRN_ESR; \
319 stw r5,_ESR(r11); \
320 SAVE_xSRR(DSRR); \
321 SAVE_xSRR(CSRR); \
322 SAVE_MMU_REGS; \
323 SAVE_xSRR(SRR); \
324 prepare_transfer_to_handler; \
325 bl hdlr; \
326 b ret_from_mcheck_exc
327
328/* Check for a single step debug exception while in an exception
329 * handler before state has been saved. This is to catch the case
330 * where an instruction that we are trying to single step causes
331 * an exception (eg ITLB/DTLB miss) and thus the first instruction of
332 * the exception handler generates a single step debug exception.
333 *
334 * If we get a debug trap on the first instruction of an exception handler,
335 * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
336 * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
337 * The exception handler was handling a non-critical interrupt, so it will
338 * save (and later restore) the MSR via SPRN_CSRR1, which will still have
339 * the MSR_DE bit set.
340 */
341#define DEBUG_DEBUG_EXCEPTION \
342 START_EXCEPTION(DebugDebug); \
343 DEBUG_EXCEPTION_PROLOG(2000); \
344 \
345 /* \
346 * If there is a single step or branch-taken exception in an \
347 * exception entry sequence, it was probably meant to apply to \
348 * the code where the exception occurred (since exception entry \
349 * doesn't turn off DE automatically). We simulate the effect \
350 * of turning off DE on entry to an exception handler by turning \
351 * off DE in the DSRR1 value and clearing the debug status. \
352 */ \
353 mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
354 andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
355 beq+ 2f; \
356 \
357 lis r10,interrupt_base@h; /* check if exception in vectors */ \
358 ori r10,r10,interrupt_base@l; \
359 cmplw r12,r10; \
360 blt+ 2f; /* addr below exception vectors */ \
361 \
362 lis r10,interrupt_end@h; \
363 ori r10,r10,interrupt_end@l; \
364 cmplw r12,r10; \
365 bgt+ 2f; /* addr above exception vectors */ \
366 \
367 /* here it looks like we got an inappropriate debug exception. */ \
3681: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \
369 lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
370 mtspr SPRN_DBSR,r10; \
371 /* restore state and get out */ \
372 lwz r10,_CCR(r11); \
373 lwz r0,GPR0(r11); \
374 lwz r1,GPR1(r11); \
375 mtcrf 0x80,r10; \
376 mtspr SPRN_DSRR0,r12; \
377 mtspr SPRN_DSRR1,r9; \
378 lwz r9,GPR9(r11); \
379 lwz r12,GPR12(r11); \
380 mtspr SPRN_SPRG_WSCRATCH_DBG,r8; \
381 BOOKE_LOAD_EXC_LEVEL_STACK(DBG); /* r8 points to the debug stack */ \
382 lwz r10,GPR10(r8); \
383 lwz r11,GPR11(r8); \
384 mfspr r8,SPRN_SPRG_RSCRATCH_DBG; \
385 \
386 PPC_RFDI; \
387 b .; \
388 \
389 /* continue normal handling for a debug exception... */ \
3902: mfspr r4,SPRN_DBSR; \
391 stw r4,_ESR(r11); /* DebugException takes DBSR in _ESR */\
392 SAVE_xSRR(CSRR); \
393 SAVE_MMU_REGS; \
394 SAVE_xSRR(SRR); \
395 prepare_transfer_to_handler; \
396 bl DebugException; \
397 b ret_from_debug_exc
398
399#define DEBUG_CRIT_EXCEPTION \
400 START_EXCEPTION(DebugCrit); \
401 CRITICAL_EXCEPTION_PROLOG(2000,DEBUG); \
402 \
403 /* \
404 * If there is a single step or branch-taken exception in an \
405 * exception entry sequence, it was probably meant to apply to \
406 * the code where the exception occurred (since exception entry \
407 * doesn't turn off DE automatically). We simulate the effect \
408 * of turning off DE on entry to an exception handler by turning \
409 * off DE in the CSRR1 value and clearing the debug status. \
410 */ \
411 mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
412 andis. r10,r10,(DBSR_IC|DBSR_BT)@h; \
413 beq+ 2f; \
414 \
415 lis r10,interrupt_base@h; /* check if exception in vectors */ \
416 ori r10,r10,interrupt_base@l; \
417 cmplw r12,r10; \
418 blt+ 2f; /* addr below exception vectors */ \
419 \
420 lis r10,interrupt_end@h; \
421 ori r10,r10,interrupt_end@l; \
422 cmplw r12,r10; \
423 bgt+ 2f; /* addr above exception vectors */ \
424 \
425 /* here it looks like we got an inappropriate debug exception. */ \
4261: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \
427 lis r10,(DBSR_IC|DBSR_BT)@h; /* clear the IC event */ \
428 mtspr SPRN_DBSR,r10; \
429 /* restore state and get out */ \
430 lwz r10,_CCR(r11); \
431 lwz r0,GPR0(r11); \
432 lwz r1,GPR1(r11); \
433 mtcrf 0x80,r10; \
434 mtspr SPRN_CSRR0,r12; \
435 mtspr SPRN_CSRR1,r9; \
436 lwz r9,GPR9(r11); \
437 lwz r12,GPR12(r11); \
438 mtspr SPRN_SPRG_WSCRATCH_CRIT,r8; \
439 BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
440 lwz r10,GPR10(r8); \
441 lwz r11,GPR11(r8); \
442 mfspr r8,SPRN_SPRG_RSCRATCH_CRIT; \
443 \
444 rfci; \
445 b .; \
446 \
447 /* continue normal handling for a critical exception... */ \
4482: mfspr r4,SPRN_DBSR; \
449 stw r4,_ESR(r11); /* DebugException takes DBSR in _ESR */\
450 SAVE_MMU_REGS; \
451 SAVE_xSRR(SRR); \
452 prepare_transfer_to_handler; \
453 bl DebugException; \
454 b ret_from_crit_exc
455
456#define DATA_STORAGE_EXCEPTION \
457 START_EXCEPTION(DataStorage) \
458 NORMAL_EXCEPTION_PROLOG(0x300, DATA_STORAGE); \
459 mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
460 stw r5,_ESR(r11); \
461 mfspr r4,SPRN_DEAR; /* Grab the DEAR */ \
462 stw r4, _DEAR(r11); \
463 prepare_transfer_to_handler; \
464 bl do_page_fault; \
465 b interrupt_return
466
467/*
468 * Instruction TLB Error interrupt handlers may call InstructionStorage
469 * directly without clearing ESR, so the ESR at this point may be left over
470 * from a prior interrupt.
471 *
472 * In any case, do_page_fault for BOOK3E does not use ESR and always expects
473 * dsisr to be 0. ESR_DST from a prior store in particular would confuse fault
474 * handling.
475 */
476#define INSTRUCTION_STORAGE_EXCEPTION \
477 START_EXCEPTION(InstructionStorage) \
478 NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \
479 li r5,0; /* Store 0 in regs->esr (dsisr) */ \
480 stw r5,_ESR(r11); \
481 stw r12, _DEAR(r11); /* Set regs->dear (dar) to SRR0 */ \
482 prepare_transfer_to_handler; \
483 bl do_page_fault; \
484 b interrupt_return
485
486#define ALIGNMENT_EXCEPTION \
487 START_EXCEPTION(Alignment) \
488 NORMAL_EXCEPTION_PROLOG(0x600, ALIGNMENT); \
489 mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \
490 stw r4,_DEAR(r11); \
491 prepare_transfer_to_handler; \
492 bl alignment_exception; \
493 REST_NVGPRS(r1); \
494 b interrupt_return
495
496#define PROGRAM_EXCEPTION \
497 START_EXCEPTION(Program) \
498 NORMAL_EXCEPTION_PROLOG(0x700, PROGRAM); \
499 mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \
500 stw r4,_ESR(r11); \
501 prepare_transfer_to_handler; \
502 bl program_check_exception; \
503 REST_NVGPRS(r1); \
504 b interrupt_return
505
506#define DECREMENTER_EXCEPTION \
507 START_EXCEPTION(Decrementer) \
508 NORMAL_EXCEPTION_PROLOG(0x900, DECREMENTER); \
509 lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \
510 mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \
511 prepare_transfer_to_handler; \
512 bl timer_interrupt; \
513 b interrupt_return
514
515#define FP_UNAVAILABLE_EXCEPTION \
516 START_EXCEPTION(FloatingPointUnavailable) \
517 NORMAL_EXCEPTION_PROLOG(0x800, FP_UNAVAIL); \
518 beq 1f; \
519 bl load_up_fpu; /* if from user, just load it up */ \
520 b fast_exception_return; \
5211: prepare_transfer_to_handler; \
522 bl kernel_fp_unavailable_exception; \
523 b interrupt_return
524
525#endif /* __ASSEMBLY__ */
526#endif /* __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); \
441 : 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 */ \
1401: 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; \
1472: 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; \
177label:
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. */ \
2771: 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... */ \
2992: 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. */ \
3301: 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... */ \
3522: 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; \
4031: addi r3,r1,STACK_FRAME_OVERHEAD; \
404 EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
405
406#ifndef __ASSEMBLY__
407struct 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__ */