xref: /netbsd/sys/arch/powerpc/ibm4xx/trap_subr.S (revision c4a72b64)
1/*	$NetBSD: trap_subr.S,v 1.5 2002/08/02 03:46:42 chs 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	.data
86	.align	4
87intstk:
88	.space	INTSTK		/* interrupt stack */
89
90GLOBAL(intr_depth)
91	.long	-1		/* in-use marker */
92
93	.comm	spillstk,SPILLSTK,8
94
95#if defined(MULTIPROCESSOR)
96#define	GET_PCB(rX)	\
97	GET_CPUINFO(rX);	\
98	lwz	rX,CI_CURPCB(rX)
99#else
100#define GET_PCB(x)	\
101	lis	1,_C_LABEL(curpcb)@ha; \
102	lwz	1,_C_LABEL(curpcb)@l(1)
103#endif
104
105#define	STANDARD_PROLOG(savearea)	\
106	mtsprg	1,1;			/* save SP */ 		\
107	stmw	28,savearea(0);		/* free r28-r31 */	\
108	mflr	28;			/* save LR */		\
109	mfcr	29;			/* save CR */		\
110	mfsrr1	31; /* Test whether we already had PR set */	\
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#define	CRITICAL_PROLOG(savearea)	\
118	mtsprg	1,1;			/* save SP */ 		\
119	stmw	28,savearea(0);		/* free r28-r31 */	\
120	mflr	28;			/* save LR */		\
121	mfcr	29;			/* save CR */		\
122	mfsrr2	30; /* Fake a standard trap */			\
123	mtsrr0	30;						\
124	mfsrr3	31; /* Test whether we already had PR set */	\
125	mtsrr1	31;						\
126	mtcr	31;						\
127	bc	4,17,1f;	/* branch if PSL_PR is clear */	\
128	GET_PCB(1);						\
129	addi	1,1,USPACE;	/* stack is top of user struct */ \
1301:
131
132
133/* Standard handler saves r1,r28-31,LR,CR, sets up the stack and calls s_trap */
134#define STANDARD_EXC_HANDLER(name)\
135	.globl	_C_LABEL(name ## trap),_C_LABEL(name ## size) ;	\
136_C_LABEL(name ## trap):						\
137	STANDARD_PROLOG(tempsave);				\
138	bla	s_trap  ;					\
139_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
140
141/* Access exceptions also need DEAR and ESR saved */
142#define ACCESS_EXC_HANDLER(name)\
143	.globl	_C_LABEL(name ## trap),_C_LABEL(name ## size) ;	\
144_C_LABEL(name ## trap):						\
145	STANDARD_PROLOG(tempsave);				\
146	mfdear	30;						\
147	mfesr	31;						\
148	stmw	30,16+tempsave(0);				\
149	bla	s_trap  ;					\
150_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
151
152/* Maybe this should call ddb.... */
153#define CRITICAL_EXC_HANDLER(name)\
154	.globl	_C_LABEL(name ## trap),_C_LABEL(name ## size) ;	\
155_C_LABEL(name ## trap):						\
156	CRITICAL_PROLOG(tempsave);				\
157	bla	s_trap  ;					\
158_C_LABEL(name ## size) = .-_C_LABEL(name ## trap)
159
160/*
161 * This code gets copied to all the trap vectors
162 * (except ISI/DSI, ALI, the interrupts, and possibly the debugging
163 * traps when using IPKDB).
164 */
165	.text
166	STANDARD_EXC_HANDLER(default)
167	ACCESS_EXC_HANDLER(ali)
168	ACCESS_EXC_HANDLER(dsi)
169	ACCESS_EXC_HANDLER(isi)
170	STANDARD_EXC_HANDLER(debug)
171	CRITICAL_EXC_HANDLER(mchk)
172
173/*
174 * This one for the external interrupt handler.
175 */
176	.globl	_C_LABEL(extint),_C_LABEL(extsize)
177_C_LABEL(extint):
178	mtsprg	1,1			/* save SP */
179	stmw	28,tempsave(0)		/* free r28-r31 */
180	mflr	28			/* save LR */
181	mfcr	29			/* save CR */
182	mfxer	30			/* save XER */
183	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
184	addi	1,1,intstk+INTSTK@l
185	lwz	31,0(1)			/* were we already running on intstk? */
186	addic.	31,31,1
187	stw	31,0(1)
188	beq	1f
189	mfsprg	1,1			/* yes, get old SP */
1901:
191	ba	extintr
192_C_LABEL(extsize) = .-_C_LABEL(extint)
193
194
195#ifdef DDB
196#define	ddbsave	0xde0		/* primary save area for DDB */
197/*
198 * In case of DDB we want a separate trap catcher for it
199 */
200	.local	ddbstk
201	.comm	ddbstk,INTSTK,8		/* ddb stack */
202
203	.globl	_C_LABEL(ddblow),_C_LABEL(ddbsize)
204_C_LABEL(ddblow):
205	mtsprg	1,1			/* save SP */
206	stmw	28,ddbsave(0)		/* free r28-r31 */
207	mflr	28			/* save LR */
208	mfcr	29			/* save CR */
209	lis	1,ddbstk+INTSTK@ha	/* get new SP */
210	addi	1,1,ddbstk+INTSTK@l
211	bla	ddbtrap
212_C_LABEL(ddbsize) = .-_C_LABEL(ddblow)
213#endif	/* DDB */
214
215#ifdef IPKDB
216#define	ipkdbsave	0xde0		/* primary save area for IPKDB */
217/*
218 * In case of IPKDB we want a separate trap catcher for it
219 */
220
221	.local	ipkdbstk
222	.comm	ipkdbstk,INTSTK,8		/* ipkdb stack */
223
224	.globl	_C_LABEL(ipkdblow),_C_LABEL(ipkdbsize)
225_C_LABEL(ipkdblow):
226	mtsprg	1,1			/* save SP */
227	stmw	28,ipkdbsave(0)		/* free r28-r31 */
228	mflr	28			/* save LR */
229	mfcr	29			/* save CR */
230	lis	1,ipkdbstk+INTSTK@ha	/* get new SP */
231	addi	1,1,ipkdbstk+INTSTK@l
232	bla	ipkdbtrap
233_C_LABEL(ipkdbsize) = .-_C_LABEL(ipkdblow)
234#endif	/* IPKDB */
235
236#ifdef DEBUG
237#define TRAP_IF_ZERO(r)	tweqi	r,0
238#else
239#define TRAP_IF_ZERO(r)
240#endif
241
242/*
243 * FRAME_SETUP assumes:
244 *	SPRG1		SP (1)
245 *	savearea	r28-r31,DEAR,ESR (DEAR & ESR only for DSI traps)
246 *	28		LR
247 *	29		CR
248 *	1		kernel stack
249 *	LR		trap type
250 *	SRR0/1		as at start of trap
251 */
252#define	FRAME_SETUP(savearea)						\
253/* Have to enable translation to allow access of kernel stack: */	\
254	mfsrr0	30;							\
255	mfsrr1	31;							\
256	stmw	30,savearea+24(0);					\
257	mfpid	30;							\
258	li	31,KERNEL_PID;						\
259	mtpid	31;							\
260	mfmsr	31;							\
261	ori	31,31,(PSL_DR|PSL_IR)@l;				\
262	mtmsr	31;							\
263	isync;								\
264	mfsprg	31,1;							\
265	stwu	31,-FRAMELEN(1);					\
266	stw	30,FRAME_PID+8(1);					\
267	stw	0,FRAME_0+8(1);						\
268	stw	31,FRAME_1+8(1);					\
269	stw	28,FRAME_LR+8(1);					\
270	stw	29,FRAME_CR+8(1);					\
271	lmw	28,savearea(0);						\
272	stmw	2,FRAME_2+8(1);						\
273	lmw	28,savearea+16(0);					\
274	mfxer	3;							\
275	mfctr	4;							\
276	mflr	5;							\
277	andi.	5,5,0xff00;						\
278	stw	3,FRAME_XER+8(1);					\
279	stw	4,FRAME_CTR+8(1);					\
280	stw	5,FRAME_EXC+8(1);					\
281	stw	28,FRAME_DEAR+8(1);					\
282	stw	29,FRAME_ESR+8(1);					\
283	stw	30,FRAME_SRR0+8(1);					\
284	stw	31,FRAME_SRR1+8(1)
285
286#define	FRAME_LEAVE(savearea)						\
287/* Now restore regs: */							\
288	lwz	3,FRAME_PID+8(1);					\
289	lwz	4,FRAME_SRR1+8(1);					\
290	bl	_C_LABEL(ctx_setup);					\
291	TRAP_IF_ZERO(r3);						\
292	stw	3,FRAME_PID+8(1);					\
293	lmw	26,FRAME_LR+8(1);					\
294	mtlr	26;							\
295	mtcr	27;							\
296	mtxer	28;							\
297	mtctr	29;							\
298	mtsrr0	30;							\
299	mtsrr1	31;							\
300	lmw	2,FRAME_2+8(1);						\
301	lwz	0,FRAME_0+8(1);						\
302	stmw	29,savearea(0);						\
303	lwz	30,FRAME_PID+8(1);					\
304	lwz	1,FRAME_1+8(1);						\
305	mfmsr	31;							\
306	li	29,(PSL_DR|PSL_IR)@l;					\
307	andc	31,31,29;						\
308	mfcr	29;							\
309	mtcr	29;							\
310	mtmsr	31;							\
311	isync;								\
312	TRAP_IF_ZERO(r30);						\
313	mtpid	30;							\
314	lmw	29,savearea(0)
315
316realtrap:	/* entry point after IPKDB is done with exception */
317	/* Test whether we already had PR set */
318	mfsrr1	1
319	mtcr	1
320	mfsprg	1,1			/* restore SP (might have been
321					   overwritten) */
322	bc	4,17,s_trap		/* branch if PSL_PR is false */
323	lis	1,_C_LABEL(curpcb)@ha
324	lwz	1,_C_LABEL(curpcb)@l(1)
325	addi	1,1,USPACE		/* stack is top of user struct */
326/*
327 * Now the common trap catching code.
328 */
329s_trap:
330	FRAME_SETUP(tempsave)
331/* Now we can recover interrupts again: */
332trapagain:
333	wrteei	1			/* Enable interrupts */
334/* Call C trap code: */
335	addi	3,1,8
336	bl	_C_LABEL(trap)
337	.globl	_C_LABEL(trapexit)
338_C_LABEL(trapexit):
339	/* Disable interrupts: */
340	wrteei	0
341	/* Test AST pending: */
342	lwz	5,FRAME_SRR1+8(1)
343	mtcr	5
344	bc	4,17,1f			/* branch if PSL_PR is false */
345#if defined(MULTIPROCESSOR)
346	GET_CPUINFO(3)
347	lwz	4,CI_ASTPENDING(3)
348#else
349	lis	3,_C_LABEL(astpending)@ha
350	lwz	4,_C_LABEL(astpending)@l(3)
351#endif
352	andi.	4,4,1
353	beq	1f
354	li	6,EXC_AST
355	stw	6,FRAME_EXC+8(1)
356	b	trapagain
3571:
358	FRAME_LEAVE(exitsave)
359	rfi
360	ba	.	/* Protect against prefetch */
361
362
363
364	.globl	_C_LABEL(sctrap),_C_LABEL(scsize)
365_C_LABEL(sctrap):
366	STANDARD_PROLOG(tempsave);
367	bla	s_sctrap
368_C_LABEL(scsize) = .-_C_LABEL(sctrap)
369
370s_sctrap:
371	FRAME_SETUP(tempsave)
372/* Now we can recover interrupts again: */
373	wrteei	1			/* Enable interrupts */
374/* Call the appropriate syscall handler: */
375	addi	3,1,8
376	lis	4,_C_LABEL(curproc)@ha
377	lwz	4,_C_LABEL(curproc)@l(4)
378	lwz	4,P_MD_SYSCALL@l(4)
379	mtctr	4
380	bctrl
381/* Disable interrupts: */
382	wrteei	0
383/* Test AST pending: */
384	lwz	5,FRAME_SRR1+8(1)
385	mtcr	5
386	bc	4,17,1f			/* branch if PSL_PR is false */
387#if defined(MULTIPROCESSOR)
388	GET_CPUINFO(3)
389	lwz	4,CI_ASTPENDING(3)
390#else
391	lis	3,_C_LABEL(astpending)@ha
392	lwz	4,_C_LABEL(astpending)@l(3)
393#endif
394	andi.	4,4,1
395	beq	1f
396	li	6,EXC_AST
397	stw	6,FRAME_EXC+8(1)
398	b	trapagain
3991:
400	FRAME_LEAVE(exitsave)
401	rfi
402	ba	.	/* Protect against prefetch */
403
404
405/*
406 * External interrupt second level handler
407 */
408
409#define	INTRENTER							\
410/* Save non-volatile registers: */					\
411	stwu	1,-92(1);		/* temporarily */		\
412	stw	0,84(1);						\
413	mfsprg	0,1;			/* get original SP */		\
414	stw	0,0(1);			/* and store it */		\
415	stw	3,80(1);						\
416	stw	4,76(1);						\
417	stw	5,72(1);						\
418	stw	6,68(1);						\
419	stw	7,64(1);						\
420	stw	8,60(1);						\
421	stw	9,56(1);						\
422	stw	10,52(1);						\
423	stw	11,48(1);						\
424	stw	12,44(1);						\
425	stw	28,40(1);		/* saved LR */			\
426	stw	29,36(1);		/* saved CR */			\
427	stw	30,32(1);		/* saved XER */			\
428	lmw	28,tempsave(0);		/* restore r28-r31 */		\
429	mfctr	6;							\
430	lis	5,_C_LABEL(intr_depth)@ha;				\
431	lwz	5,_C_LABEL(intr_depth)@l(5);				\
432	mfsrr0	4;							\
433	mfsrr1	3;							\
434	stw	6,28(1);						\
435	stw	5,20(1);						\
436	stw	4,12(1);						\
437	stw	3,8(1);							\
438	mfpid	0;			/* get currect PID register */  \
439	stw	0,88(1)	;						\
440	li	0, KERNEL_PID;						\
441	mtpid	0;							\
442/* interrupts are recoverable here, and enable translation */		\
443	mfmsr	5;							\
444	ori	5,5,(PSL_IR|PSL_DR);					\
445	mtmsr	5;							\
446	isync
447
448	.globl	_C_LABEL(extint_call)
449extintr:
450	INTRENTER
451_C_LABEL(extint_call):
452	bl	_C_LABEL(extint_call)	/* to be filled in later */
453
454intr_exit:
455/* Disable interrupts (should already be disabled) and MMU here: */
456	wrteei	0
457	isync
458	lwz	3,88(1)
459	lwz	4,8(1)			/* Load srr1 */
460	bl	_C_LABEL(ctx_setup)	/* Get proper ctx */
461	mfmsr	5
462	lis	4,(PSL_EE|PSL_DR|PSL_IR)@h
463	ori	4,4,(PSL_EE|PSL_DR|PSL_IR)@l
464	andc	5,5,4
465	mtmsr	5
466	isync
467	mtpid	3			/* Load CTX */
468
469/* restore possibly overwritten registers: */
470	lwz	12,44(1)
471	lwz	11,48(1)
472	lwz	10,52(1)
473	lwz	9,56(1)
474	lwz	8,60(1)
475	lwz	7,64(1)
476	lwz	6,8(1)
477	lwz	5,12(1)
478	lwz	4,28(1)
479	lwz	3,32(1)
480	mtsrr1	6
481	mtsrr0	5
482	mtctr	4
483	mtxer	3
484/* Returning to user mode? */
485	mtcr	6			/* saved SRR1 */
486	bc	4,17,1f			/* branch if PSL_PR is false */
487
488#if defined(MULTIPROCESSOR)
489	lwz	4,CI_ASTPENDING(4)	 /* Test AST pending */
490#else
491	lis	3,_C_LABEL(astpending)@ha /* Test AST pending */
492	lwz	4,_C_LABEL(astpending)@l(3)
493#endif
494	andi.	4,4,1
495	beq	1f
496/* Setup for entry to realtrap: */
497	lwz	3,0(1)			/* get saved SP */
498	mtsprg	1,3
499	li	6,EXC_AST
500	stmw	28,tempsave(0)		/* establish tempsave again */
501	mtlr	6
502	lwz	28,40(1)		/* saved LR */
503	lwz	29,36(1)		/* saved CR */
504	lwz	6,68(1)
505	lwz	5,72(1)
506	lwz	4,76(1)
507	lwz	3,80(1)
508	lwz	0,84(1)
509	lis	30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
510	lwz	31,_C_LABEL(intr_depth)@l(30)
511	addi	31,31,-1
512	stw	31,_C_LABEL(intr_depth)@l(30)
513	b	realtrap
5141:
515/* Here is the normal exit of extintr: */
516	lwz	5,36(1)
517	lwz	6,40(1)
518	mtcr	5
519	mtlr	6
520	lwz	6,68(1)
521	lwz	5,72(1)
522	lis	3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
523	lwz	4,_C_LABEL(intr_depth)@l(3)
524	addi	4,4,-1
525	stw	4,_C_LABEL(intr_depth)@l(3)
526	lwz	4,76(1)
527	lwz	3,80(1)
528	lwz	0,84(1)
529	lwz	1,0(1)
530	rfi
531	ba	.	/* Protect against prefetch */
532
533/*
534 * PIT interrupt handler.
535 */
536	.align	5
537_C_LABEL(pitint):
538	mtsprg	1,1			/* save SP */
539	stmw	28,tempsave(0)		/* free r28-r31 */
540	mflr	28			/* save LR */
541	mfcr	29			/* save CR */
542	mfxer	30			/* save XER */
543	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
544	addi	1,1,intstk+INTSTK@l
545	lwz	31,0(1)			/* were we already running on intstk? */
546	addic.	31,31,1
547	stw	31,0(1)
548	beq	1f
549	mfsprg	1,1			/* yes, get old SP */
5501:
551	INTRENTER
552	addi	3,1,8			/* intr frame */
553	bl	_C_LABEL(decr_intr)
554	b	intr_exit
555
556/*
557 * FIT interrupt handler.
558 */
559	.align	5
560fitint:
561	mtsprg	1,1			/* save SP */
562	stmw	28,tempsave(0)		/* free r28-r31 */
563	mflr	28			/* save LR */
564	mfcr	29			/* save CR */
565	mfxer	30			/* save XER */
566	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
567	addi	1,1,intstk+INTSTK@l
568	lwz	31,0(1)			/* were we already running on intstk? */
569	addic.	31,31,1
570	stw	31,0(1)
571	beq	1f
572	mfsprg	1,1			/* yes, get old SP */
5731:
574	INTRENTER
575	addi	3,1,8			/* intr frame */
576	bl	_C_LABEL(stat_intr)
577	b	intr_exit
578
579#ifdef DDB
580/*
581 * Deliberate entry to ddbtrap
582 */
583	.globl	_C_LABEL(ddb_trap)
584_C_LABEL(ddb_trap):
585	mtsprg	1,1
586	mfmsr	3
587	mtsrr1	3
588	wrteei	0			/* disable interrupts */
589	isync
590	stmw	28,ddbsave(0)
591	mflr	28
592	li	29,EXC_BPT
593	mtlr	29
594	mfcr	29
595	mtsrr0	28
596
597/*
598 * Now the ddb trap catching code.
599 */
600ddbtrap:
601	FRAME_SETUP(ddbsave)
602/* Call C trap code: */
603	addi	3,1,8
604	bl	_C_LABEL(ddb_trap_glue)
605	or.	3,3,3
606	bne	ddbleave
607/* This wasn't for DDB, so switch to real trap: */
608	lwz	3,FRAME_EXC+8(1)	/* save exception */
609	stw	3,ddbsave+12(0)
610	FRAME_LEAVE(ddbsave)
611	mtsprg	1,1			/* prepare for entrance to realtrap */
612	stmw	28,tempsave(0)
613	mflr	28
614	mfcr	29
615	lwz	31,ddbsave+12(0)
616	mtlr	31
617	b	realtrap
618ddbleave:
619	FRAME_LEAVE(ddbsave)
620	rfi
621	ba	.	/* Protect against prefetch */
622#endif /* DDB */
623
624#ifdef IPKDB
625/*
626 * Deliberate entry to ipkdbtrap
627 */
628	.globl	_C_LABEL(ipkdb_trap)
629_C_LABEL(ipkdb_trap):
630	mtsprg	1,1
631	mfmsr	3
632	mtsrr1	3
633	wrteei	0			/* disable interrupts */
634	isync
635	stmw	28,ipkdbsave(0)
636	mflr	28
637	li	29,EXC_BPT
638	mtlr	29
639	mfcr	29
640	mtsrr0	28
641
642/*
643 * Now the ipkdb trap catching code.
644 */
645ipkdbtrap:
646	FRAME_SETUP(ipkdbsave)
647/* Call C trap code: */
648	addi	3,1,8
649	bl	_C_LABEL(ipkdb_trap_glue)
650	or.	3,3,3
651	bne	ipkdbleave
652/* This wasn't for IPKDB, so switch to real trap: */
653	lwz	3,FRAME_EXC+8(1)	/* save exception */
654	stw	3,ipkdbsave+8(0)
655	FRAME_LEAVE(ipkdbsave)
656	mtsprg	1,1			/* prepare for entrance to realtrap */
657	stmw	28,tempsave(0)
658	mflr	28
659	mfcr	29
660	lwz	31,ipkdbsave+8(0)
661	mtlr	31
662	b	realtrap
663ipkdbleave:
664	FRAME_LEAVE(ipkdbsave)
665	rfi
666	ba	.	/* Protect against prefetch */
667
668ipkdbfault:
669	ba	_ipkdbfault
670_ipkdbfault:
671	mfsrr0	3
672	addi	3,3,4
673	mtsrr0	3
674	li	3,-1
675	rfi
676	ba	.	/* Protect against prefetch */
677
678/*
679 * int ipkdbfbyte(unsigned char *p)
680 */
681	.globl	_C_LABEL(ipkdbfbyte)
682_C_LABEL(ipkdbfbyte):
683	li	9,EXC_DSI		/* establish new fault routine */
684	lwz	5,0(9)
685	lis	6,ipkdbfault@ha
686	lwz	6,ipkdbfault@l(6)
687	stw	6,0(9)
688#ifdef	IPKDBUSERHACK
689#ifndef PPC_IBM4XX
690	lis	8,_C_LABEL(ipkdbsr)@ha
691	lwz	8,_C_LABEL(ipkdbsr)@l(8)
692	mtsr	USER_SR,8
693	isync
694#endif
695#endif
696	dcbst	0,9			/* flush data... */
697	sync
698	icbi	0,9			/* and instruction caches */
699	lbz	3,0(3)			/* fetch data */
700	stw	5,0(9)			/* restore previous fault handler */
701	dcbst	0,9			/* and flush data... */
702	sync
703	icbi	0,9			/* and instruction caches */
704	blr
705
706/*
707 * int ipkdbsbyte(unsigned char *p, int c)
708 */
709	.globl	_C_LABEL(ipkdbsbyte)
710_C_LABEL(ipkdbsbyte):
711	li	9,EXC_DSI		/* establish new fault routine */
712	lwz	5,0(9)
713	lis	6,ipkdbfault@ha
714	lwz	6,ipkdbfault@l(6)
715	stw	6,0(9)
716#ifdef	IPKDBUSERHACK
717#ifndef PPC_IBM4XX
718	lis	8,_C_LABEL(ipkdbsr)@ha
719	lwz	8,_C_LABEL(ipkdbsr)@l(8)
720	mtsr	USER_SR,8
721	isync
722#endif
723#endif
724	dcbst	0,9			/* flush data... */
725	sync
726	icbi	0,9			/* and instruction caches */
727	mr	6,3
728	xor	3,3,3
729	stb	4,0(6)
730	dcbst	0,6			/* Now do appropriate flushes
731					   to data... */
732	sync
733	icbi	0,6			/* and instruction caches */
734	stw	5,0(9)			/* restore previous fault handler */
735	dcbst	0,9			/* and flush data... */
736	sync
737	icbi	0,9			/* and instruction caches */
738	blr
739#endif	/* IPKDB */
740