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