xref: /netbsd-src/sys/arch/powerpc/ibm4xx/trap_subr.S (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
1/*	$NetBSD: trap_subr.S,v 1.10 2005/12/11 12:18:42 christos Exp $	*/
2
3/*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed for the NetBSD Project by
20 *      Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
40 * Copyright (C) 1995, 1996 TooLs GmbH.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 *    notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 *    notice, this list of conditions and the following disclaimer in the
50 *    documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 *    must display the following acknowledgement:
53 *	This product includes software developed by TooLs GmbH.
54 * 4. The name of TooLs GmbH may not be used to endorse or promote products
55 *    derived from this software without specific prior written permission.
56 *
57 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
62 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
63 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
64 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
65 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
66 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68
69/*
70 * NOTICE: This is not a standalone file.  to use it, #include it in
71 * your port's locore.S, like so:
72 *
73 *	#include <powerpc/ibm4xx/trap_subr.S>
74 */
75
76/*
77 * Data used during primary/secondary traps/interrupts
78 */
79#define	tempsave	0x2e0	/* primary save area for trap handling */
80#define	disisave	0x3e0	/* primary save area for dsi/isi traps */
81#define	exitsave	0x4e0	/* use this so trap return does not conflict */
82/*
83 * XXX Interrupt and spill stacks need to be per-CPU.
84 */
85
86#define	GET_PCB(rX)	\
87	GET_CPUINFO(rX);	\
88	lwz	rX,CI_CURPCB(rX)
89
90#define	STANDARD_PROLOG(savearea)	\
91	mtsprg	1,1;			/* save SP */ 		\
92	stmw	28,savearea(0);		/* free r28-r31 */	\
93	mflr	28;			/* save LR */		\
94	mfcr	29;			/* save CR */		\
95	mfsrr1	31; /* Test whether we already had PR set */	\
96	mtcr	31;						\
97	bc	4,17,1f;	/* branch if PSL_PR is clear */	\
98	GET_PCB(1);						\
99	addi	1,1,USPACE;	/* stack is top of user struct */ \
1001:
101
102#define	CRITICAL_PROLOG(savearea)	\
103	mtsprg	1,1;			/* save SP */ 		\
104	stmw	28,savearea(0);		/* free r28-r31 */	\
105	mflr	28;			/* save LR */		\
106	mfcr	29;			/* save CR */		\
107	mfsrr2	30; /* Fake a standard trap */			\
108	mtsrr0	30;						\
109	mfsrr3	31; /* Test whether we already had PR set */	\
110	mtsrr1	31;						\
111	mtcr	31;						\
112	bc	4,17,1f;	/* branch if PSL_PR is clear */	\
113	GET_PCB(1);						\
114	addi	1,1,USPACE;	/* stack is top of user struct */ \
1151:
116
117
118/* Standard handler saves r1,r28-31,LR,CR, sets up the stack and calls s_trap */
119#define STANDARD_EXC_HANDLER(name)\
120	.globl	_C_LABEL(name ## trap),_C_LABEL(name ## size) ;	\
121_C_LABEL(name ## trap):						\
122	STANDARD_PROLOG(tempsave);				\
123	bla	s_trap  ;					\
124_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
125
126/* Access exceptions also need DEAR and ESR saved */
127#define ACCESS_EXC_HANDLER(name)\
128	.globl	_C_LABEL(name ## trap),_C_LABEL(name ## size) ;	\
129_C_LABEL(name ## trap):						\
130	STANDARD_PROLOG(tempsave);				\
131	mfdear	30;						\
132	mfesr	31;						\
133	stmw	30,16+tempsave(0);				\
134	bla	s_trap  ;					\
135_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
136
137/* Maybe this should call ddb.... */
138#define CRITICAL_EXC_HANDLER(name)\
139	.globl	_C_LABEL(name ## trap),_C_LABEL(name ## size) ;	\
140_C_LABEL(name ## trap):						\
141	CRITICAL_PROLOG(tempsave);				\
142	bla	s_trap  ;					\
143_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
144
145/*
146 * This code gets copied to all the trap vectors
147 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
148 * traps when using IPKDB).
149 */
150	.text
151	STANDARD_EXC_HANDLER(default)
152	ACCESS_EXC_HANDLER(ali)
153	ACCESS_EXC_HANDLER(dsi)
154	ACCESS_EXC_HANDLER(isi)
155	STANDARD_EXC_HANDLER(debug)
156	CRITICAL_EXC_HANDLER(mchk)
157
158/*
159 * This one for the external interrupt handler.
160 */
161	.globl	_C_LABEL(extint),_C_LABEL(extsize)
162_C_LABEL(extint):
163	mtsprg	1,1			/* save SP */
164	stmw	28,tempsave(0)		/* free r28-r31 */
165	mflr	28			/* save LR */
166	mfcr	29			/* save CR */
167	mfxer	30			/* save XER */
168	GET_CPUINFO(1)
169	lwz	31,CI_INTRDEPTH(1)	/* were we already running on intstk? */
170	addic.	31,31,1
171	stw	31,CI_INTRDEPTH(1)
172	lwz	1,CI_INTSTK(1)		/* get intstk */
173	beq	1f
174	mfsprg	1,1			/* yes, get old SP */
1751:
176	ba	extintr
177_C_LABEL(extsize) = .-_C_LABEL(extint)
178
179
180#ifdef DDB
181#define	ddbsave	0xde0		/* primary save area for DDB */
182/*
183 * In case of DDB we want a separate trap catcher for it
184 */
185	.local	ddbstk
186	.comm	ddbstk,INTSTK,8		/* ddb stack */
187
188	.globl	_C_LABEL(ddblow),_C_LABEL(ddbsize)
189_C_LABEL(ddblow):
190	mtsprg	1,1			/* save SP */
191	stmw	28,ddbsave(0)		/* free r28-r31 */
192	mflr	28			/* save LR */
193	mfcr	29			/* save CR */
194	lis	1,ddbstk+INTSTK@ha	/* get new SP */
195	addi	1,1,ddbstk+INTSTK@l
196	bla	ddbtrap
197_C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
198#endif	/* DDB */
199
200#ifdef IPKDB
201#define	ipkdbsave	0xde0		/* primary save area for IPKDB */
202/*
203 * In case of IPKDB we want a separate trap catcher for it
204 */
205
206	.local	ipkdbstk
207	.comm	ipkdbstk,INTSTK,8		/* ipkdb stack */
208
209	.globl	_C_LABEL(ipkdblow),_C_LABEL(ipkdbsize)
210_C_LABEL(ipkdblow):
211	mtsprg	1,1			/* save SP */
212	stmw	28,ipkdbsave(0)		/* free r28-r31 */
213	mflr	28			/* save LR */
214	mfcr	29			/* save CR */
215	lis	1,ipkdbstk+INTSTK@ha	/* get new SP */
216	addi	1,1,ipkdbstk+INTSTK@l
217	bla	ipkdbtrap
218_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow)
219#endif	/* IPKDB */
220
221#ifdef DEBUG
222#define TRAP_IF_ZERO(r)	tweqi	r,0
223#else
224#define TRAP_IF_ZERO(r)
225#endif
226
227/*
228 * FRAME_SETUP assumes:
229 *	SPRG1		SP (1)
230 *	savearea	r28-r31,DEAR,ESR (DEAR & ESR only for DSI traps)
231 *	28		LR
232 *	29		CR
233 *	1		kernel stack
234 *	LR		trap type
235 *	SRR0/1		as at start of trap
236 */
237#define	FRAME_SETUP(savearea)						\
238/* Have to enable translation to allow access of kernel stack: */	\
239	mfsrr0	30;							\
240	mfsrr1	31;							\
241	stmw	30,savearea+24(0);					\
242	mfpid	30;							\
243	li	31,KERNEL_PID;						\
244	mtpid	31;							\
245	mfmsr	31;							\
246	ori	31,31,(PSL_DR|PSL_IR)@l;				\
247	mtmsr	31;							\
248	isync;								\
249	mfsprg	31,1;							\
250	stwu	31,-FRAMELEN(1);					\
251	stw	30,FRAME_PID+8(1);					\
252	stw	0,FRAME_0+8(1);						\
253	stw	31,FRAME_1+8(1);					\
254	stw	28,FRAME_LR+8(1);					\
255	stw	29,FRAME_CR+8(1);					\
256	lmw	28,savearea(0);						\
257	stmw	2,FRAME_2+8(1);						\
258	lmw	28,savearea+16(0);					\
259	mfxer	3;							\
260	mfctr	4;							\
261	mflr	5;							\
262	andi.	5,5,0xff00;						\
263	stw	3,FRAME_XER+8(1);					\
264	stw	4,FRAME_CTR+8(1);					\
265	stw	5,FRAME_EXC+8(1);					\
266	stw	28,FRAME_DEAR+8(1);					\
267	stw	29,FRAME_ESR+8(1);					\
268	stw	30,FRAME_SRR0+8(1);					\
269	stw	31,FRAME_SRR1+8(1)
270
271#define	FRAME_LEAVE(savearea)						\
272/* Now restore regs: */							\
273	lwz	3,FRAME_PID+8(1);					\
274	lwz	4,FRAME_SRR1+8(1);					\
275	bl	_C_LABEL(ctx_setup);					\
276	TRAP_IF_ZERO(3);						\
277	stw	3,FRAME_PID+8(1);					\
278	lmw	26,FRAME_LR+8(1);					\
279	mtlr	26;							\
280	mtcr	27;							\
281	mtxer	28;							\
282	mtctr	29;							\
283	mtsrr0	30;							\
284	mtsrr1	31;							\
285	lmw	2,FRAME_2+8(1);						\
286	lwz	0,FRAME_0+8(1);						\
287	stmw	29,savearea(0);						\
288	lwz	30,FRAME_PID+8(1);					\
289	lwz	1,FRAME_1+8(1);						\
290	mfmsr	31;							\
291	li	29,(PSL_DR|PSL_IR)@l;					\
292	andc	31,31,29;						\
293	mfcr	29;							\
294	mtcr	29;							\
295	mtmsr	31;							\
296	isync;								\
297	TRAP_IF_ZERO(30);						\
298	mtpid	30;							\
299	lmw	29,savearea(0)
300
301realtrap:	/* entry point after IPKDB is done with exception */
302	/* Test whether we already had PR set */
303	mfsrr1	1
304	mtcr	1
305	mfsprg	1,1			/* restore SP (might have been
306					   overwritten) */
307	bc	4,17,s_trap		/* branch if PSL_PR is false */
308	GET_PCB(1)
309	addi	1,1,USPACE		/* stack is top of user struct */
310/*
311 * Now the common trap catching code.
312 */
313s_trap:
314	FRAME_SETUP(tempsave)
315/* Now we can recover interrupts again: */
316trapagain:
317	wrteei	1			/* Enable interrupts */
318/* Call C trap code: */
319	addi	3,1,8
320	bl	_C_LABEL(trap)
321	.globl	_C_LABEL(trapexit)
322_C_LABEL(trapexit):
323	/* Disable interrupts: */
324	wrteei	0
325	/* Test AST pending: */
326	lwz	5,FRAME_SRR1+8(1)
327	mtcr	5
328	bc	4,17,1f			/* branch if PSL_PR is false */
329	GET_CPUINFO(3)
330	lwz	4,CI_ASTPENDING(3)
331	andi.	4,4,1
332	beq	1f
333	li	6,EXC_AST
334	stw	6,FRAME_EXC+8(1)
335	b	trapagain
3361:
337	FRAME_LEAVE(exitsave)
338	rfi
339	ba	.	/* Protect against prefetch */
340
341
342
343	.globl	_C_LABEL(sctrap),_C_LABEL(scsize),_C_LABEL(sctrapexit)
344_C_LABEL(sctrap):
345	STANDARD_PROLOG(tempsave);
346	bla	s_sctrap
347_C_LABEL(scsize) = .-_C_LABEL(sctrap)
348
349s_sctrap:
350	FRAME_SETUP(tempsave)
351/* Now we can recover interrupts again: */
352	wrteei	1			/* Enable interrupts */
353/* Call the appropriate syscall handler: */
354	addi	3,1,8
355	GET_CPUINFO(4)
356	lwz	4,CI_CURLWP(4)
357	lwz	4,L_PROC(4)
358	lwz	4,P_MD_SYSCALL(4)
359	mtctr	4
360	bctrl
361_C_LABEL(sctrapexit):
362/* Disable interrupts: */
363	wrteei	0
364/* Test AST pending: */
365	lwz	5,FRAME_SRR1+8(1)
366	mtcr	5
367	bc	4,17,1f			/* branch if PSL_PR is false */
368	GET_CPUINFO(3)
369	lwz	4,CI_ASTPENDING(3)
370	andi.	4,4,1
371	beq	1f
372	li	6,EXC_AST
373	stw	6,FRAME_EXC+8(1)
374	b	trapagain
3751:
376	FRAME_LEAVE(exitsave)
377	rfi
378	ba	.	/* Protect against prefetch */
379
380
381/*
382 * External interrupt second level handler
383 */
384
385#define	INTRENTER							\
386/* Save non-volatile registers: */					\
387	stwu	1,-IFRAMELEN(1);	/* temporarily */		\
388	stw	0,IFRAME_R0(1);						\
389	mfsprg	0,1;			/* get original SP */		\
390	stw	0,IFRAME_R1(1);		/* and store it */		\
391	stw	3,IFRAME_R3(1);						\
392	stw	4,IFRAME_R4(1);						\
393	stw	5,IFRAME_R5(1);						\
394	stw	6,IFRAME_R6(1);						\
395	stw	7,IFRAME_R7(1);						\
396	stw	8,IFRAME_R8(1);						\
397	stw	9,IFRAME_R9(1);						\
398	stw	10,IFRAME_R10(1);					\
399	stw	11,IFRAME_R11(1);					\
400	stw	12,IFRAME_R12(1);					\
401	stw	28,IFRAME_LR(1);	/* saved LR */			\
402	stw	29,IFRAME_CR(1);	/* saved CR */			\
403	stw	30,IFRAME_XER(1);	/* saved XER */			\
404	lmw	28,tempsave(0);		/* restore r28-r31 */		\
405	mfctr	6;							\
406	GET_CPUINFO(5);							\
407	lwz	5,CI_INTRDEPTH(5);					\
408	mfsrr0	4;							\
409	mfsrr1	3;							\
410	stw	6,IFRAME_CTR(1);					\
411	stw	5,IFRAME_INTR_DEPTH(1);					\
412	stw	4,IFRAME_SRR0(1);					\
413	stw	3,IFRAME_SRR1(1);					\
414	mfpid	0;			/* get currect PID register */  \
415	stw	0,IFRAME_PID(1);					\
416	li	0,KERNEL_PID;						\
417	mtpid	0;							\
418/* interrupts are recoverable here, and enable translation */		\
419	mfmsr	5;							\
420	ori	5,5,(PSL_IR|PSL_DR);					\
421	mtmsr	5;							\
422	isync
423
424	.globl	_C_LABEL(extint_call)
425extintr:
426	INTRENTER
427_C_LABEL(extint_call):
428	bl	_C_LABEL(extint_call)	/* to be filled in later */
429
430intr_exit:
431/* Disable interrupts (should already be disabled) and MMU here: */
432	wrteei	0
433	isync
434	lwz	3,IFRAME_PID(1)
435	lwz	4,IFRAME_SRR1(1)	/* Load srr1 */
436	bl	_C_LABEL(ctx_setup)	/* Get proper ctx */
437	mfmsr	5
438	lis	4,(PSL_EE|PSL_DR|PSL_IR)@h
439	ori	4,4,(PSL_EE|PSL_DR|PSL_IR)@l
440	andc	5,5,4
441	mtmsr	5
442	isync
443	mtpid	3			/* Load CTX */
444
445/* restore possibly overwritten registers: */
446	lwz	12,IFRAME_R12(1)
447	lwz	11,IFRAME_R11(1)
448	lwz	10,IFRAME_R10(1)
449	lwz	9,IFRAME_R9(1)
450	lwz	8,IFRAME_R8(1)
451	lwz	7,IFRAME_R7(1)
452	lwz	6,IFRAME_SRR1(1)
453	lwz	5,IFRAME_SRR0(1)
454	lwz	4,IFRAME_CTR(1)
455	lwz	3,IFRAME_XER(1)
456	mtsrr1	6
457	mtsrr0	5
458	mtctr	4
459	mtxer	3
460/* Returning to user mode? */
461	GET_CPUINFO(5)
462	lwz	4,CI_INTRDEPTH(5)
463	addi	4,4,-1			/* adjust reentrancy count */
464	stw	4,CI_INTRDEPTH(5)
465	mtcr	6			/* saved SRR1 */
466	bc	4,17,1f			/* branch if PSL_PR is false */
467
468	lwz	4,CI_ASTPENDING(5)	 /* Test AST pending */
469	andi.	4,4,1
470	beq	1f
471/* Setup for entry to realtrap: */
472	lwz	3,0(1)			/* get saved SP */
473	mtsprg	1,3
474	li	6,EXC_AST
475	stmw	28,tempsave(0)		/* establish tempsave again */
476	mtlr	6
477	lwz	28,IFRAME_LR(1)		/* saved LR */
478	lwz	29,IFRAME_CR(1)		/* saved CR */
479	lwz	6,IFRAME_R6(1)
480	lwz	5,IFRAME_R5(1)
481	lwz	4,IFRAME_R4(1)
482	lwz	3,IFRAME_R3(1)
483	lwz	0,IFRAME_R0(1)
484	b	realtrap
4851:
486/* Here is the normal exit of extintr: */
487	lwz	5,IFRAME_CR(1)
488	lwz	6,IFRAME_LR(1)
489	mtcr	5
490	mtlr	6
491	lwz	6,IFRAME_R6(1)
492	lwz	5,IFRAME_R5(1)
493	lwz	4,IFRAME_R4(1)
494	lwz	3,IFRAME_R3(1)
495	lwz	0,IFRAME_R0(1)
496	lwz	1,IFRAME_R1(1)
497	rfi
498	ba	.	/* Protect against prefetch */
499
500/*
501 * PIT interrupt handler.
502 */
503	.align	5
504_C_LABEL(pitint):
505	mtsprg	1,1			/* save SP */
506	stmw	28,tempsave(0)		/* free r28-r31 */
507	mflr	28			/* save LR */
508	mfcr	29			/* save CR */
509	mfxer	30			/* save XER */
510	GET_CPUINFO(1)
511	lwz	31,CI_INTRDEPTH(1)	/* were we already running on intstk? */
512	addic.	31,31,1
513	stw	31,CI_INTRDEPTH(1)
514	lwz	1,CI_INTSTK(1)		/* get intstk */
515	beq	1f
516	mfsprg	1,1			/* yes, get old SP */
5171:
518	INTRENTER
519	addi	3,1,8			/* intr frame */
520	bl	_C_LABEL(decr_intr)
521	b	intr_exit
522
523/*
524 * FIT interrupt handler.
525 */
526	.align	5
527fitint:
528	mtsprg	1,1			/* save SP */
529	stmw	28,tempsave(0)		/* free r28-r31 */
530	mflr	28			/* save LR */
531	mfcr	29			/* save CR */
532	mfxer	30			/* save XER */
533	GET_CPUINFO(1)
534	lwz	31,CI_INTRDEPTH(1)	/* were we already running on intstk? */
535	addic.	31,31,1
536	stw	31,CI_INTRDEPTH(1)
537	lwz	1,CI_INTSTK(1)		/* get intstk */
538	beq	1f
539	mfsprg	1,1			/* yes, get old SP */
5401:
541	INTRENTER
542	addi	3,1,8			/* intr frame */
543	bl	_C_LABEL(stat_intr)
544	b	intr_exit
545
546#ifdef DDB
547/*
548 * Deliberate entry to ddbtrap
549 */
550	.globl	_C_LABEL(ddb_trap)
551_C_LABEL(ddb_trap):
552	mtsprg	1,1
553	mfmsr	3
554	mtsrr1	3
555	wrteei	0			/* disable interrupts */
556	isync
557	stmw	28,ddbsave(0)
558	mflr	28
559	li	29,EXC_BPT
560	mtlr	29
561	mfcr	29
562	mtsrr0	28
563
564/*
565 * Now the ddb trap catching code.
566 */
567ddbtrap:
568	FRAME_SETUP(ddbsave)
569/* Call C trap code: */
570	addi	3,1,8
571	bl	_C_LABEL(ddb_trap_glue)
572	or.	3,3,3
573	bne	ddbleave
574/* This wasn't for DDB, so switch to real trap: */
575	lwz	3,FRAME_EXC+8(1)	/* save exception */
576	stw	3,ddbsave+12(0)
577	FRAME_LEAVE(ddbsave)
578	mtsprg	1,1			/* prepare for entrance to realtrap */
579	stmw	28,tempsave(0)
580	mflr	28
581	mfcr	29
582	lwz	31,ddbsave+12(0)
583	mtlr	31
584	b	realtrap
585ddbleave:
586	FRAME_LEAVE(ddbsave)
587	rfi
588	ba	.	/* Protect against prefetch */
589#endif /* DDB */
590
591#ifdef IPKDB
592/*
593 * Deliberate entry to ipkdbtrap
594 */
595	.globl	_C_LABEL(ipkdb_trap)
596_C_LABEL(ipkdb_trap):
597	mtsprg	1,1
598	mfmsr	3
599	mtsrr1	3
600	wrteei	0			/* disable interrupts */
601	isync
602	stmw	28,ipkdbsave(0)
603	mflr	28
604	li	29,EXC_BPT
605	mtlr	29
606	mfcr	29
607	mtsrr0	28
608
609/*
610 * Now the ipkdb trap catching code.
611 */
612ipkdbtrap:
613	FRAME_SETUP(ipkdbsave)
614/* Call C trap code: */
615	addi	3,1,8
616	bl	_C_LABEL(ipkdb_trap_glue)
617	or.	3,3,3
618	bne	ipkdbleave
619/* This wasn't for IPKDB, so switch to real trap: */
620	lwz	3,FRAME_EXC+8(1)	/* save exception */
621	stw	3,ipkdbsave+8(0)
622	FRAME_LEAVE(ipkdbsave)
623	mtsprg	1,1			/* prepare for entrance to realtrap */
624	stmw	28,tempsave(0)
625	mflr	28
626	mfcr	29
627	lwz	31,ipkdbsave+8(0)
628	mtlr	31
629	b	realtrap
630ipkdbleave:
631	FRAME_LEAVE(ipkdbsave)
632	rfi
633	ba	.	/* Protect against prefetch */
634
635ipkdbfault:
636	ba	_ipkdbfault
637_ipkdbfault:
638	mfsrr0	3
639	addi	3,3,4
640	mtsrr0	3
641	li	3,-1
642	rfi
643	ba	.	/* Protect against prefetch */
644
645/*
646 * int ipkdbfbyte(unsigned char *p)
647 */
648	.globl	_C_LABEL(ipkdbfbyte)
649_C_LABEL(ipkdbfbyte):
650	li	9,EXC_DSI		/* establish new fault routine */
651	lwz	5,0(9)
652	lis	6,ipkdbfault@ha
653	lwz	6,ipkdbfault@l(6)
654	stw	6,0(9)
655#ifdef	IPKDBUSERHACK
656#ifndef PPC_IBM4XX
657	lis	8,_C_LABEL(ipkdbsr)@ha
658	lwz	8,_C_LABEL(ipkdbsr)@l(8)
659	mtsr	USER_SR,8
660	isync
661#endif
662#endif
663	dcbst	0,9			/* flush data... */
664	sync
665	icbi	0,9			/* and instruction caches */
666	lbz	3,0(3)			/* fetch data */
667	stw	5,0(9)			/* restore previous fault handler */
668	dcbst	0,9			/* and flush data... */
669	sync
670	icbi	0,9			/* and instruction caches */
671	blr
672
673/*
674 * int ipkdbsbyte(unsigned char *p, int c)
675 */
676	.globl	_C_LABEL(ipkdbsbyte)
677_C_LABEL(ipkdbsbyte):
678	li	9,EXC_DSI		/* establish new fault routine */
679	lwz	5,0(9)
680	lis	6,ipkdbfault@ha
681	lwz	6,ipkdbfault@l(6)
682	stw	6,0(9)
683#ifdef	IPKDBUSERHACK
684#ifndef PPC_IBM4XX
685	lis	8,_C_LABEL(ipkdbsr)@ha
686	lwz	8,_C_LABEL(ipkdbsr)@l(8)
687	mtsr	USER_SR,8
688	isync
689#endif
690#endif
691	dcbst	0,9			/* flush data... */
692	sync
693	icbi	0,9			/* and instruction caches */
694	mr	6,3
695	xor	3,3,3
696	stb	4,0(6)
697	dcbst	0,6			/* Now do appropriate flushes
698					   to data... */
699	sync
700	icbi	0,6			/* and instruction caches */
701	stw	5,0(9)			/* restore previous fault handler */
702	dcbst	0,9			/* and flush data... */
703	sync
704	icbi	0,9			/* and instruction caches */
705	blr
706#endif	/* IPKDB */
707