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