Home | History | Annotate | Line # | Download | only in ibm4xx
trap_subr.S revision 1.2
      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
     87 intstk:
     88 	.space	INTSTK		/* interrupt stack */
     89 
     90 GLOBAL(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 */ \
    115 1:
    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 */ \
    130 1:
    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 */
    189 1:
    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 
    315 realtrap:	/* 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  */
    328 s_trap:
    329 	FRAME_SETUP(tempsave)
    330 /* Now we can recover interrupts again: */
    331 trapagain:
    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
    356 1:
    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)
    404 extintr:
    405 	INTRENTER
    406 _C_LABEL(extint_call):
    407 	bl	_C_LABEL(extint_call)	/* to be filled in later */
    408 
    409 intr_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
    469 1:
    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 */
    505 1:
    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
    515 fitint:
    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 */
    528 1:
    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  */
    555 ddbtrap:
    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
    573 ddbleave:
    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  */
    600 ipkdbtrap:
    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
    618 ipkdbleave:
    619 	FRAME_LEAVE(ipkdbsave)
    620 	rfi
    621 	ba	.	/* Protect against prefetch */
    622 
    623 ipkdbfault:
    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