Home | History | Annotate | Line # | Download | only in ibm4xx
trap_subr.S revision 1.10.50.1
      1 /*	$NetBSD: trap_subr.S,v 1.10.50.1 2007/11/06 23:20:30 matt 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 */ \
    100 1:
    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 */ \
    115 1:
    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 */
    175 1:
    176 	ba	extintr
    177 _C_LABEL(extsize) = .-_C_LABEL(extint)
    178 
    179 
    180 #if defined(DDB) || defined(KGDB)
    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 || KGDB */
    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 
    301 realtrap:	/* 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  */
    313 s_trap:
    314 	FRAME_SETUP(tempsave)
    315 /* Now we can recover interrupts again: */
    316 trapagain:
    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
    336 1:
    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 
    349 s_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
    375 1:
    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)
    425 extintr:
    426 	INTRENTER
    427 _C_LABEL(extint_call):
    428 	bl	_C_LABEL(extint_call)	/* to be filled in later */
    429 
    430 intr_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
    485 1:
    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 */
    517 1:
    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
    527 fitint:
    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 */
    540 1:
    541 	INTRENTER
    542 	addi	3,1,8			/* intr frame */
    543 	bl	_C_LABEL(stat_intr)
    544 	b	intr_exit
    545 
    546 #if defined(DDB) || defined(KGDB)
    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/kgdb trap catching code.
    566  */
    567 ddbtrap:
    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
    585 ddbleave:
    586 	FRAME_LEAVE(ddbsave)
    587 	rfi
    588 	ba	.	/* Protect against prefetch */
    589 #endif /* DDB || KGDB */
    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  */
    612 ipkdbtrap:
    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
    630 ipkdbleave:
    631 	FRAME_LEAVE(ipkdbsave)
    632 	rfi
    633 	ba	.	/* Protect against prefetch */
    634 
    635 ipkdbfault:
    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