Home | History | Annotate | Line # | Download | only in ibm4xx
trap_subr.S revision 1.2
      1  1.2  simonb /*	$NetBSD: trap_subr.S,v 1.2 2001/06/17 13:38:33 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.2  simonb 	.globl	_C_LABEL(trapexit)
    337  1.2  simonb _C_LABEL(trapexit):
    338  1.1  simonb 	/* Disable interrupts: */
    339  1.1  simonb 	wrteei	0
    340  1.1  simonb 	/* Test AST pending: */
    341  1.1  simonb 	lwz	5,FRAME_SRR1+8(1)
    342  1.1  simonb 	mtcr	5
    343  1.1  simonb 	bc	4,17,1f			/* branch if PSL_PR is false */
    344  1.1  simonb #if defined(MULTIPROCESSOR)
    345  1.1  simonb 	GET_CPUINFO(3)
    346  1.1  simonb 	lwz	4,CI_ASTPENDING(3)
    347  1.1  simonb #else
    348  1.1  simonb 	lis	3,_C_LABEL(astpending)@ha
    349  1.1  simonb 	lwz	4,_C_LABEL(astpending)@l(3)
    350  1.1  simonb #endif
    351  1.1  simonb 	andi.	4,4,1
    352  1.1  simonb 	beq	1f
    353  1.1  simonb 	li	6,EXC_AST
    354  1.1  simonb 	stw	6,FRAME_EXC+8(1)
    355  1.1  simonb 	b	trapagain
    356  1.1  simonb 1:
    357  1.1  simonb 	FRAME_LEAVE(exitsave)
    358  1.1  simonb 	rfi
    359  1.1  simonb 	ba	.	/* Protect against prefetch */
    360  1.1  simonb /*
    361  1.1  simonb  * External interrupt second level handler
    362  1.1  simonb  */
    363  1.1  simonb 
    364  1.1  simonb #define	INTRENTER							\
    365  1.1  simonb /* Save non-volatile registers: */					\
    366  1.1  simonb 	stwu	1,-92(1);		/* temporarily */		\
    367  1.1  simonb 	stw	0,84(1);						\
    368  1.1  simonb 	mfsprg	0,1;			/* get original SP */		\
    369  1.1  simonb 	stw	0,0(1);			/* and store it */		\
    370  1.1  simonb 	stw	3,80(1);						\
    371  1.1  simonb 	stw	4,76(1);						\
    372  1.1  simonb 	stw	5,72(1);						\
    373  1.1  simonb 	stw	6,68(1);						\
    374  1.1  simonb 	stw	7,64(1);						\
    375  1.1  simonb 	stw	8,60(1);						\
    376  1.1  simonb 	stw	9,56(1);						\
    377  1.1  simonb 	stw	10,52(1);						\
    378  1.1  simonb 	stw	11,48(1);						\
    379  1.1  simonb 	stw	12,44(1);						\
    380  1.1  simonb 	stw	28,40(1);		/* saved LR */			\
    381  1.1  simonb 	stw	29,36(1);		/* saved CR */			\
    382  1.1  simonb 	stw	30,32(1);		/* saved XER */			\
    383  1.1  simonb 	lmw	28,tempsave(0);		/* restore r28-r31 */		\
    384  1.1  simonb 	mfctr	6;							\
    385  1.1  simonb 	lis	5,_C_LABEL(intr_depth)@ha;				\
    386  1.1  simonb 	lwz	5,_C_LABEL(intr_depth)@l(5);				\
    387  1.1  simonb 	mfsrr0	4;							\
    388  1.1  simonb 	mfsrr1	3;							\
    389  1.1  simonb 	stw	6,28(1);						\
    390  1.1  simonb 	stw	5,20(1);						\
    391  1.1  simonb 	stw	4,12(1);						\
    392  1.1  simonb 	stw	3,8(1);							\
    393  1.1  simonb 	mfpid	0;			/* get currect PID register */  \
    394  1.1  simonb 	stw	0,88(1)	;						\
    395  1.1  simonb 	li	0, KERNEL_PID;						\
    396  1.1  simonb 	mtpid	0;							\
    397  1.1  simonb /* interrupts are recoverable here, and enable translation */		\
    398  1.1  simonb 	mfmsr	5;							\
    399  1.1  simonb 	ori	5,5,(PSL_IR|PSL_DR);					\
    400  1.1  simonb 	mtmsr	5;							\
    401  1.1  simonb 	isync
    402  1.1  simonb 
    403  1.1  simonb 	.globl	_C_LABEL(extint_call)
    404  1.1  simonb extintr:
    405  1.1  simonb 	INTRENTER
    406  1.1  simonb _C_LABEL(extint_call):
    407  1.1  simonb 	bl	_C_LABEL(extint_call)	/* to be filled in later */
    408  1.1  simonb 
    409  1.1  simonb intr_exit:
    410  1.1  simonb /* Disable interrupts (should already be disabled) and MMU here: */
    411  1.1  simonb 	wrteei	0
    412  1.1  simonb 	isync
    413  1.1  simonb 	lwz	3,88(1)
    414  1.1  simonb 	lwz	4,8(1)			/* Load srr1 */
    415  1.1  simonb 	bl	_C_LABEL(ctx_setup)	/* Get proper ctx */
    416  1.1  simonb 	mfmsr	5
    417  1.1  simonb 	lis	4,(PSL_EE|PSL_DR|PSL_IR)@h
    418  1.1  simonb 	ori	4,4,(PSL_EE|PSL_DR|PSL_IR)@l
    419  1.1  simonb 	andc	5,5,4
    420  1.1  simonb 	mtmsr	5
    421  1.1  simonb 	isync
    422  1.1  simonb 	mtpid	3			/* Load CTX */
    423  1.1  simonb 
    424  1.1  simonb /* restore possibly overwritten registers: */
    425  1.1  simonb 	lwz	12,44(1)
    426  1.1  simonb 	lwz	11,48(1)
    427  1.1  simonb 	lwz	10,52(1)
    428  1.1  simonb 	lwz	9,56(1)
    429  1.1  simonb 	lwz	8,60(1)
    430  1.1  simonb 	lwz	7,64(1)
    431  1.1  simonb 	lwz	6,8(1)
    432  1.1  simonb 	lwz	5,12(1)
    433  1.1  simonb 	lwz	4,28(1)
    434  1.1  simonb 	lwz	3,32(1)
    435  1.1  simonb 	mtsrr1	6
    436  1.1  simonb 	mtsrr0	5
    437  1.1  simonb 	mtctr	4
    438  1.1  simonb 	mtxer	3
    439  1.1  simonb /* Returning to user mode? */
    440  1.1  simonb 	mtcr	6			/* saved SRR1 */
    441  1.1  simonb 	bc	4,17,1f			/* branch if PSL_PR is false */
    442  1.1  simonb 
    443  1.1  simonb #if defined(MULTIPROCESSOR)
    444  1.1  simonb 	lwz	4,CI_ASTPENDING(4)	 /* Test AST pending */
    445  1.1  simonb #else
    446  1.1  simonb 	lis	3,_C_LABEL(astpending)@ha /* Test AST pending */
    447  1.1  simonb 	lwz	4,_C_LABEL(astpending)@l(3)
    448  1.1  simonb #endif
    449  1.1  simonb 	andi.	4,4,1
    450  1.1  simonb 	beq	1f
    451  1.1  simonb /* Setup for entry to realtrap: */
    452  1.1  simonb 	lwz	3,0(1)			/* get saved SP */
    453  1.1  simonb 	mtsprg	1,3
    454  1.1  simonb 	li	6,EXC_AST
    455  1.1  simonb 	stmw	28,tempsave(0)		/* establish tempsave again */
    456  1.1  simonb 	mtlr	6
    457  1.1  simonb 	lwz	28,40(1)		/* saved LR */
    458  1.1  simonb 	lwz	29,36(1)		/* saved CR */
    459  1.1  simonb 	lwz	6,68(1)
    460  1.1  simonb 	lwz	5,72(1)
    461  1.1  simonb 	lwz	4,76(1)
    462  1.1  simonb 	lwz	3,80(1)
    463  1.1  simonb 	lwz	0,84(1)
    464  1.1  simonb 	lis	30,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
    465  1.1  simonb 	lwz	31,_C_LABEL(intr_depth)@l(30)
    466  1.1  simonb 	addi	31,31,-1
    467  1.1  simonb 	stw	31,_C_LABEL(intr_depth)@l(30)
    468  1.1  simonb 	b	realtrap
    469  1.1  simonb 1:
    470  1.1  simonb /* Here is the normal exit of extintr: */
    471  1.1  simonb 	lwz	5,36(1)
    472  1.1  simonb 	lwz	6,40(1)
    473  1.1  simonb 	mtcr	5
    474  1.1  simonb 	mtlr	6
    475  1.1  simonb 	lwz	6,68(1)
    476  1.1  simonb 	lwz	5,72(1)
    477  1.1  simonb 	lis	3,_C_LABEL(intr_depth)@ha /* adjust reentrancy count */
    478  1.1  simonb 	lwz	4,_C_LABEL(intr_depth)@l(3)
    479  1.1  simonb 	addi	4,4,-1
    480  1.1  simonb 	stw	4,_C_LABEL(intr_depth)@l(3)
    481  1.1  simonb 	lwz	4,76(1)
    482  1.1  simonb 	lwz	3,80(1)
    483  1.1  simonb 	lwz	0,84(1)
    484  1.1  simonb 	lwz	1,0(1)
    485  1.1  simonb 	rfi
    486  1.1  simonb 	ba	.	/* Protect against prefetch */
    487  1.1  simonb 
    488  1.1  simonb /*
    489  1.1  simonb  * PIT interrupt handler.
    490  1.1  simonb  */
    491  1.1  simonb 	.align	5
    492  1.1  simonb _C_LABEL(pitint):
    493  1.1  simonb 	mtsprg	1,1			/* save SP */
    494  1.1  simonb 	stmw	28,tempsave(0)		/* free r28-r31 */
    495  1.1  simonb 	mflr	28			/* save LR */
    496  1.1  simonb 	mfcr	29			/* save CR */
    497  1.1  simonb 	mfxer	30			/* save XER */
    498  1.1  simonb 	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
    499  1.1  simonb 	addi	1,1,intstk+INTSTK@l
    500  1.1  simonb 	lwz	31,0(1)			/* were we already running on intstk? */
    501  1.1  simonb 	addic.	31,31,1
    502  1.1  simonb 	stw	31,0(1)
    503  1.1  simonb 	beq	1f
    504  1.1  simonb 	mfsprg	1,1			/* yes, get old SP */
    505  1.1  simonb 1:
    506  1.1  simonb 	INTRENTER
    507  1.1  simonb 	addi	3,1,8			/* intr frame */
    508  1.1  simonb 	bl	_C_LABEL(decr_intr)
    509  1.1  simonb 	b	intr_exit
    510  1.1  simonb 
    511  1.1  simonb /*
    512  1.1  simonb  * FIT interrupt handler.
    513  1.1  simonb  */
    514  1.1  simonb 	.align	5
    515  1.1  simonb fitint:
    516  1.1  simonb 	mtsprg	1,1			/* save SP */
    517  1.1  simonb 	stmw	28,tempsave(0)		/* free r28-r31 */
    518  1.1  simonb 	mflr	28			/* save LR */
    519  1.1  simonb 	mfcr	29			/* save CR */
    520  1.1  simonb 	mfxer	30			/* save XER */
    521  1.1  simonb 	lis	1,intstk+INTSTK@ha	/* get interrupt stack */
    522  1.1  simonb 	addi	1,1,intstk+INTSTK@l
    523  1.1  simonb 	lwz	31,0(1)			/* were we already running on intstk? */
    524  1.1  simonb 	addic.	31,31,1
    525  1.1  simonb 	stw	31,0(1)
    526  1.1  simonb 	beq	1f
    527  1.1  simonb 	mfsprg	1,1			/* yes, get old SP */
    528  1.1  simonb 1:
    529  1.1  simonb 	INTRENTER
    530  1.1  simonb 	addi	3,1,8			/* intr frame */
    531  1.1  simonb 	bl	_C_LABEL(stat_intr)
    532  1.1  simonb 	b	intr_exit
    533  1.1  simonb 
    534  1.1  simonb #ifdef DDB
    535  1.1  simonb /*
    536  1.1  simonb  * Deliberate entry to ddbtrap
    537  1.1  simonb  */
    538  1.1  simonb 	.globl	_C_LABEL(ddb_trap)
    539  1.1  simonb _C_LABEL(ddb_trap):
    540  1.1  simonb 	mtsprg	1,1
    541  1.1  simonb 	mfmsr	3
    542  1.1  simonb 	mtsrr1	3
    543  1.1  simonb 	wrteei	0			/* disable interrupts */
    544  1.1  simonb 	isync
    545  1.1  simonb 	stmw	28,ddbsave(0)
    546  1.1  simonb 	mflr	28
    547  1.1  simonb 	li	29,EXC_BPT
    548  1.1  simonb 	mtlr	29
    549  1.1  simonb 	mfcr	29
    550  1.1  simonb 	mtsrr0	28
    551  1.1  simonb 
    552  1.1  simonb /*
    553  1.1  simonb  * Now the ddb trap catching code.
    554  1.1  simonb  */
    555  1.1  simonb ddbtrap:
    556  1.1  simonb 	FRAME_SETUP(ddbsave)
    557  1.1  simonb /* Call C trap code: */
    558  1.1  simonb 	addi	3,1,8
    559  1.1  simonb 	bl	_C_LABEL(ddb_trap_glue)
    560  1.1  simonb 	or.	3,3,3
    561  1.1  simonb 	bne	ddbleave
    562  1.1  simonb /* This wasn't for DDB, so switch to real trap: */
    563  1.1  simonb 	lwz	3,FRAME_EXC+8(1)	/* save exception */
    564  1.1  simonb 	stw	3,ddbsave+12(0)
    565  1.1  simonb 	FRAME_LEAVE(ddbsave)
    566  1.1  simonb 	mtsprg	1,1			/* prepare for entrance to realtrap */
    567  1.1  simonb 	stmw	28,tempsave(0)
    568  1.1  simonb 	mflr	28
    569  1.1  simonb 	mfcr	29
    570  1.1  simonb 	lwz	31,ddbsave+12(0)
    571  1.1  simonb 	mtlr	31
    572  1.1  simonb 	b	realtrap
    573  1.1  simonb ddbleave:
    574  1.1  simonb 	FRAME_LEAVE(ddbsave)
    575  1.1  simonb 	rfi
    576  1.1  simonb 	ba	.	/* Protect against prefetch */
    577  1.1  simonb #endif /* DDB */
    578  1.1  simonb 
    579  1.1  simonb #ifdef IPKDB
    580  1.1  simonb /*
    581  1.1  simonb  * Deliberate entry to ipkdbtrap
    582  1.1  simonb  */
    583  1.1  simonb 	.globl	_C_LABEL(ipkdb_trap)
    584  1.1  simonb _C_LABEL(ipkdb_trap):
    585  1.1  simonb 	mtsprg	1,1
    586  1.1  simonb 	mfmsr	3
    587  1.1  simonb 	mtsrr1	3
    588  1.1  simonb 	wrteei	0			/* disable interrupts */
    589  1.1  simonb 	isync
    590  1.1  simonb 	stmw	28,ipkdbsave(0)
    591  1.1  simonb 	mflr	28
    592  1.1  simonb 	li	29,EXC_BPT
    593  1.1  simonb 	mtlr	29
    594  1.1  simonb 	mfcr	29
    595  1.1  simonb 	mtsrr0	28
    596  1.1  simonb 
    597  1.1  simonb /*
    598  1.1  simonb  * Now the ipkdb trap catching code.
    599  1.1  simonb  */
    600  1.1  simonb ipkdbtrap:
    601  1.1  simonb 	FRAME_SETUP(ipkdbsave)
    602  1.1  simonb /* Call C trap code: */
    603  1.1  simonb 	addi	3,1,8
    604  1.1  simonb 	bl	_C_LABEL(ipkdb_trap_glue)
    605  1.1  simonb 	or.	3,3,3
    606  1.1  simonb 	bne	ipkdbleave
    607  1.1  simonb /* This wasn't for IPKDB, so switch to real trap: */
    608  1.1  simonb 	lwz	3,FRAME_EXC+8(1)	/* save exception */
    609  1.1  simonb 	stw	3,ipkdbsave+8(0)
    610  1.1  simonb 	FRAME_LEAVE(ipkdbsave)
    611  1.1  simonb 	mtsprg	1,1			/* prepare for entrance to realtrap */
    612  1.1  simonb 	stmw	28,tempsave(0)
    613  1.1  simonb 	mflr	28
    614  1.1  simonb 	mfcr	29
    615  1.1  simonb 	lwz	31,ipkdbsave+8(0)
    616  1.1  simonb 	mtlr	31
    617  1.1  simonb 	b	realtrap
    618  1.1  simonb ipkdbleave:
    619  1.1  simonb 	FRAME_LEAVE(ipkdbsave)
    620  1.1  simonb 	rfi
    621  1.1  simonb 	ba	.	/* Protect against prefetch */
    622  1.1  simonb 
    623  1.1  simonb ipkdbfault:
    624  1.1  simonb 	ba	_ipkdbfault
    625  1.1  simonb _ipkdbfault:
    626  1.1  simonb 	mfsrr0	3
    627  1.1  simonb 	addi	3,3,4
    628  1.1  simonb 	mtsrr0	3
    629  1.1  simonb 	li	3,-1
    630  1.1  simonb 	rfi
    631  1.1  simonb 	ba	.	/* Protect against prefetch */
    632  1.1  simonb 
    633  1.1  simonb /*
    634  1.1  simonb  * int ipkdbfbyte(unsigned char *p)
    635  1.1  simonb  */
    636  1.1  simonb 	.globl	_C_LABEL(ipkdbfbyte)
    637  1.1  simonb _C_LABEL(ipkdbfbyte):
    638  1.1  simonb 	li	9,EXC_DSI		/* establish new fault routine */
    639  1.1  simonb 	lwz	5,0(9)
    640  1.1  simonb 	lis	6,ipkdbfault@ha
    641  1.1  simonb 	lwz	6,ipkdbfault@l(6)
    642  1.1  simonb 	stw	6,0(9)
    643  1.1  simonb #ifdef	IPKDBUSERHACK
    644  1.1  simonb #ifndef PPC_IBM4XX
    645  1.1  simonb 	lis	8,_C_LABEL(ipkdbsr)@ha
    646  1.1  simonb 	lwz	8,_C_LABEL(ipkdbsr)@l(8)
    647  1.1  simonb 	mtsr	USER_SR,8
    648  1.1  simonb 	isync
    649  1.1  simonb #endif
    650  1.1  simonb #endif
    651  1.1  simonb 	dcbst	0,9			/* flush data... */
    652  1.1  simonb 	sync
    653  1.1  simonb 	icbi	0,9			/* and instruction caches */
    654  1.1  simonb 	lbz	3,0(3)			/* fetch data */
    655  1.1  simonb 	stw	5,0(9)			/* restore previous fault handler */
    656  1.1  simonb 	dcbst	0,9			/* and flush data... */
    657  1.1  simonb 	sync
    658  1.1  simonb 	icbi	0,9			/* and instruction caches */
    659  1.1  simonb 	blr
    660  1.1  simonb 
    661  1.1  simonb /*
    662  1.1  simonb  * int ipkdbsbyte(unsigned char *p, int c)
    663  1.1  simonb  */
    664  1.1  simonb 	.globl	_C_LABEL(ipkdbsbyte)
    665  1.1  simonb _C_LABEL(ipkdbsbyte):
    666  1.1  simonb 	li	9,EXC_DSI		/* establish new fault routine */
    667  1.1  simonb 	lwz	5,0(9)
    668  1.1  simonb 	lis	6,ipkdbfault@ha
    669  1.1  simonb 	lwz	6,ipkdbfault@l(6)
    670  1.1  simonb 	stw	6,0(9)
    671  1.1  simonb #ifdef	IPKDBUSERHACK
    672  1.1  simonb #ifndef PPC_IBM4XX
    673  1.1  simonb 	lis	8,_C_LABEL(ipkdbsr)@ha
    674  1.1  simonb 	lwz	8,_C_LABEL(ipkdbsr)@l(8)
    675  1.1  simonb 	mtsr	USER_SR,8
    676  1.1  simonb 	isync
    677  1.1  simonb #endif
    678  1.1  simonb #endif
    679  1.1  simonb 	dcbst	0,9			/* flush data... */
    680  1.1  simonb 	sync
    681  1.1  simonb 	icbi	0,9			/* and instruction caches */
    682  1.1  simonb 	mr	6,3
    683  1.1  simonb 	xor	3,3,3
    684  1.1  simonb 	stb	4,0(6)
    685  1.1  simonb 	dcbst	0,6			/* Now do appropriate flushes
    686  1.1  simonb 					   to data... */
    687  1.1  simonb 	sync
    688  1.1  simonb 	icbi	0,6			/* and instruction caches */
    689  1.1  simonb 	stw	5,0(9)			/* restore previous fault handler */
    690  1.1  simonb 	dcbst	0,9			/* and flush data... */
    691  1.1  simonb 	sync
    692  1.1  simonb 	icbi	0,9			/* and instruction caches */
    693  1.1  simonb 	blr
    694  1.1  simonb #endif	/* IPKDB */
    695