Linux Audio

Check our new training course

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