Home | History | Annotate | Line # | Download | only in booke
trap_subr.S revision 1.3
      1  1.3  matt /*	$NetBSD: trap_subr.S,v 1.3 2011/06/05 16:52:24 matt Exp $	*/
      2  1.2  matt /*-
      3  1.2  matt  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
      4  1.2  matt  * All rights reserved.
      5  1.2  matt  *
      6  1.2  matt  * This code is derived from software contributed to The NetBSD Foundation
      7  1.2  matt  * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
      8  1.2  matt  * Agency and which was developed by Matt Thomas of 3am Software Foundry.
      9  1.2  matt  *
     10  1.2  matt  * This material is based upon work supported by the Defense Advanced Research
     11  1.2  matt  * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
     12  1.2  matt  * Contract No. N66001-09-C-2073.
     13  1.2  matt  * Approved for Public Release, Distribution Unlimited
     14  1.2  matt  *
     15  1.2  matt  * Redistribution and use in source and binary forms, with or without
     16  1.2  matt  * modification, are permitted provided that the following conditions
     17  1.2  matt  * are met:
     18  1.2  matt  * 1. Redistributions of source code must retain the above copyright
     19  1.2  matt  *    notice, this list of conditions and the following disclaimer.
     20  1.2  matt  * 2. Redistributions in binary form must reproduce the above copyright
     21  1.2  matt  *    notice, this list of conditions and the following disclaimer in the
     22  1.2  matt  *    documentation and/or other materials provided with the distribution.
     23  1.2  matt  *
     24  1.2  matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     25  1.2  matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26  1.2  matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     27  1.2  matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     28  1.2  matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     29  1.2  matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     30  1.2  matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     31  1.2  matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     32  1.2  matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     33  1.2  matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     34  1.2  matt  * POSSIBILITY OF SUCH DAMAGE.
     35  1.2  matt  */
     36  1.2  matt 
     37  1.3  matt RCSID("$NetBSD: trap_subr.S,v 1.3 2011/06/05 16:52:24 matt Exp $")
     38  1.2  matt 
     39  1.2  matt 	.globl	_C_LABEL(critintr_call)
     40  1.2  matt 	.globl	_C_LABEL(extintr_call)
     41  1.2  matt 	.globl	_C_LABEL(decrintr_call)
     42  1.2  matt 	.globl	_C_LABEL(fitintr_call)
     43  1.2  matt 	.globl	_C_LABEL(wdogintr_call)
     44  1.2  matt 
     45  1.2  matt 	.globl	_C_LABEL(sctrapexit), _C_LABEL(trapexit), _C_LABEL(intrcall)
     46  1.2  matt 
     47  1.2  matt 	/*
     48  1.2  matt 	 * We have a problem with critical (MSR[CE] or machine check (MSR[ME])
     49  1.2  matt 	 * or debug (MSR[DE]) interrupts/exception in that they could happen
     50  1.2  matt 	 * inbewtween the mtsprg1 %r2 and mfsprg1 %r2.  If that happens, %r2
     51  1.2  matt 	 * will be lost.  Even if we moved to a different sprg, subsequent
     52  1.2  matt 	 * expceptions would use SPRG1 and its value would be lost.  The only
     53  1.2  matt 	 * way to be safe for CE/ME/DE faults to save and restore SPRG1.
     54  1.2  matt 	 *
     55  1.2  matt 	 * Since CE/ME/DE faults may happen anytime, we need r1 to always
     56  1.2  matt 	 * contain a valid kernel stack pointer.  Therefore we use r2 as
     57  1.2  matt 	 * our temporary register.
     58  1.2  matt 	 *
     59  1.2  matt 	 * To prevent %r2 being overwritten, each "level" (normal, critical,
     60  1.2  matt 	 * mchk) uses a unique sprg to save %r2 (sprg1, sprg4, sprg5).
     61  1.2  matt 	 *
     62  1.2  matt 	 * Since we can't control how many nested exceptions we might get,
     63  1.2  matt 	 * we don't use a dedicated save area.  Instead we have a upwards
     64  1.2  matt 	 * growing "stack" of them; the pointer to which is kept in sprg3.
     65  1.2  matt 	 *
     66  1.2  matt 	 * To allocate from the stack, one fetches sprg3, adds the amount
     67  1.2  matt 	 * needed, saves sprg3, and then refers to the save using a
     68  1.2  matt 	 * displacement of -amount.
     69  1.2  matt 	 */
     70  1.2  matt #define	FRAME_EXC_PROLOGUE(start, sprg, srr)				\
     71  1.2  matt 	mt##sprg %r2;			/* save r2 */			\
     72  1.2  matt 	mfsprg3	%r2;			/* get save_area pointer */	\
     73  1.2  matt 	addi	%r2,%r2,4*(32-start);					\
     74  1.2  matt 					/* allocate save area */	\
     75  1.2  matt 	mtsprg3	%r2;			/* save updated pointer */	\
     76  1.2  matt 	stmw	%r##start,-4*(32-start)(%r2);				\
     77  1.2  matt 					/* free r24-r31 for use */	\
     78  1.2  matt 	mf##sprg %r26;			/* get saved r2 */		\
     79  1.2  matt 	mfcr	%r27;			/* get Condition Register */	\
     80  1.2  matt 	mfxer	%r28;			/* get XER */			\
     81  1.2  matt 	mfspr	%r30, SPR_##srr##0;	/* get SRR0 */			\
     82  1.2  matt 	mfspr	%r31, SPR_##srr##1	/* get SRR1 */
     83  1.2  matt 
     84  1.2  matt #define	PROLOGUE_GET_DEAR	mfspr	%r24, SPR_DEAR
     85  1.2  matt #define	PROLOGUE_GET_ESR	mfspr	%r25, SPR_ESR
     86  1.2  matt #define	PROLOGUE_GET_SRRS	mfsrr0	%r24; \
     87  1.2  matt 				mfsrr1	%r25
     88  1.2  matt #define	PROLOGUE_GET_SPRG1	mfsprg1	%r29
     89  1.2  matt #define	PROLOGUE_GET_DBSR	mfspr	%r25, SPR_DBSR
     90  1.2  matt #define	SAVE_ESR		stw	%r25, FRAME_ESR(%r1)
     91  1.2  matt #define	SAVE_DEAR		stw	%r24, FRAME_DEAR(%r1)
     92  1.2  matt #define	SAVE_DEAR_ESR		SAVE_ESR; SAVE_DEAR
     93  1.2  matt #define	SAVE_SRRS		SAVE_DEAR_ESR
     94  1.2  matt #define	SAVE_SPRG1		stw	%r29, FRAME_SPRG1(%r1)
     95  1.2  matt #define	SAVE_DBSR		stw	%r25, FRAME_DBSR(%r1)
     96  1.2  matt #define	SAVE_NOTHING		/* nothing */
     97  1.2  matt #define	RESTORE_SPRG1(r)	lwz	r, FRAME_SPRG1(%r1); \
     98  1.2  matt 				mtsprg1 r
     99  1.2  matt #define	RESTORE_SRR0(r)		lwz	r, FRAME_DEAR(%r1); \
    100  1.2  matt 				mtsrr0	r
    101  1.2  matt #define	RESTORE_SRR1(r)		lwz	r, FRAME_ESR(%r1); \
    102  1.2  matt 				mtsrr1	r
    103  1.2  matt 
    104  1.2  matt #define	FRAME_PROLOGUE		\
    105  1.2  matt 	FRAME_EXC_PROLOGUE(26, sprg1, SRR)
    106  1.2  matt 
    107  1.2  matt #define	FRAME_PROLOGUE_DEAR_ESR	\
    108  1.2  matt 	FRAME_EXC_PROLOGUE(24, sprg1, SRR); \
    109  1.2  matt 	PROLOGUE_GET_ESR; \
    110  1.2  matt 	PROLOGUE_GET_DEAR
    111  1.2  matt 
    112  1.2  matt #define	FRAME_PROLOGUE_ESR	\
    113  1.2  matt 	FRAME_EXC_PROLOGUE(25, sprg1, SRR); \
    114  1.2  matt 	PROLOGUE_GET_ESR
    115  1.2  matt 
    116  1.2  matt #define	FRAME_TLBPROLOGUE	\
    117  1.2  matt 	FRAME_EXC_PROLOGUE(20, sprg1, SRR); \
    118  1.2  matt 	PROLOGUE_GET_ESR; \
    119  1.2  matt 	PROLOGUE_GET_DEAR
    120  1.2  matt 
    121  1.2  matt #define	FRAME_INTR_PROLOGUE	\
    122  1.2  matt 	FRAME_EXC_PROLOGUE(26, sprg1, SRR)
    123  1.2  matt 
    124  1.2  matt /*
    125  1.2  matt  * These need to save SRR0/SRR1 as well their SRR0/SRR1 in case normal
    126  1.2  matt  * exceptions happened during their execution.
    127  1.2  matt  */
    128  1.2  matt #define	FRAME_CRIT_PROLOGUE	\
    129  1.2  matt 	FRAME_EXC_PROLOGUE(24, sprg4, CSRR); \
    130  1.2  matt 	PROLOGUE_GET_SPRG1; \
    131  1.2  matt 	PROLOGUE_GET_SRRS
    132  1.2  matt 
    133  1.2  matt #define	FRAME_MCHK_PROLOGUE	\
    134  1.2  matt 	FRAME_EXC_PROLOGUE(24, sprg5, MCSRR); \
    135  1.2  matt 	PROLOGUE_GET_SPRG1; \
    136  1.2  matt 	PROLOGUE_GET_SRRS
    137  1.2  matt 
    138  1.2  matt #define	FRAME_DEBUG_PROLOGUE	\
    139  1.2  matt 	FRAME_EXC_PROLOGUE(24, sprg4, CSRR); \
    140  1.2  matt 	PROLOGUE_GET_SPRG1; \
    141  1.2  matt 	PROLOGUE_GET_SRRS
    142  1.2  matt 
    143  1.2  matt /*
    144  1.2  matt  * DDB expects to fetch the LR from the previous frame.  But it also
    145  1.2  matt  * expects to be pointing at the instruction after the branch link.  Since
    146  1.2  matt  * we didn't branch, we need to advance it by to fake out DDB.
    147  1.2  matt  */
    148  1.2  matt #ifdef DDB
    149  1.2  matt #define FRAME_SAVE_SRR0_FOR_DDB						\
    150  1.2  matt 	addi	%r30, %r30, 4;		/* ddb thinks its the next insn */ \
    151  1.2  matt 	stw	%r30, FRAMELEN+SZREG(%r1); /* appease ddb stacktrace */
    152  1.2  matt #else
    153  1.2  matt #define FRAME_SAVE_SRR0_FOR_DDB
    154  1.2  matt #endif
    155  1.2  matt 
    156  1.2  matt #ifdef PPC_HAVE_SPE
    157  1.2  matt #define	FRAME_SAVE_SPEFSCR						\
    158  1.2  matt 	mfspefscr %r0;			/* get spefscr */		\
    159  1.2  matt 	stw	%r0, FRAME_SPEFSCR(%r1) /* save into trapframe */
    160  1.2  matt #define	FRAME_RESTORE_SPEFSCR						\
    161  1.2  matt 	lwz	%r0, FRAME_SPEFSCR(%r1); /* fetch from trapframe */	\
    162  1.2  matt 	mtspefscr %r0			/* save spefscr */
    163  1.2  matt #else
    164  1.2  matt #define	FRAME_SAVE_SPEFSCR
    165  1.2  matt #define	FRAME_RESTORE_SPEFSCR
    166  1.2  matt #endif
    167  1.2  matt /*
    168  1.2  matt  * Before the first memory refernence, we must have our state inside registers
    169  1.2  matt  * since the first memory access might cause an exception which would cause
    170  1.2  matt  * SRR0/SRR1 and DEAR/ESR to become unrecoverable.  CR and XER also need to be
    171  1.2  matt  * saved early since they will modified by instrction flow.  The saved stack
    172  1.2  matt  * pointer is also critical but LR and CTR can be deferred being saved until
    173  1.2  matt  * we are actually filling a trapframe.
    174  1.2  matt  */
    175  1.2  matt #define	FRAME_EXC_ENTER(exc, tf, start, save_prologue)			\
    176  1.2  matt 	mtcr	%r31;			/* user mode exception? */	\
    177  1.2  matt 	mr	%r31, %r1;		/* save SP (SRR1 is safe in CR) */ \
    178  1.2  matt 	bf	MSR_PR, 1f;		/*   nope, sp is good */	\
    179  1.2  matt 	mfsprg2	%r2;			/* get curlwp */		\
    180  1.2  matt 	lwz	%r2, L_PCB(%r2);	/* get uarea of curlwp */	\
    181  1.2  matt 	addi	%r1, %r2, USPACE-CALLFRAMELEN;				\
    182  1.2  matt 					/* start stack at top of it */	\
    183  1.2  matt 1:									\
    184  1.2  matt 	stw	%r30, CFRAME_LR(%r1);	/* save in previous callframe */ \
    185  1.2  matt 	stwu	%r31, -FRAMELEN(%r1);	/* get space for trapframe */	\
    186  1.2  matt 	stw	%r0, FRAME_0(%r1);	/* save r0 */			\
    187  1.2  matt 	stw	%r31, FRAME_1(%r1);	/* save (saved) r1 */		\
    188  1.2  matt 	stw	%r26, FRAME_2(%r1);	/* save (saved) r2 */		\
    189  1.2  matt 	save_prologue;			/* save SPRG1/ESR/DEAR */	\
    190  1.2  matt 	/* At this point, r26, r29, and r31 have been saved so we */	\
    191  1.2  matt 	/* can use them for LR, CTR, and SRR1.			  */	\
    192  1.2  matt 	mflr	%r26;			/* get Link Register */		\
    193  1.2  matt 	mfctr	%r29;			/* get CTR */			\
    194  1.2  matt 	mfcr	%r31;			/* get SRR1 */			\
    195  1.2  matt 	stmw	%r26, FRAME_LR(%r1);	/* save LR CR XER CTR SRR0/1 */	\
    196  1.2  matt 	FRAME_SAVE_SRR0_FOR_DDB;					\
    197  1.2  matt 	mr	%r0, %r31;		/* save SRR1 for a bit */	\
    198  1.2  matt 	mfsprg3	%r2;			/* get save_area pointer */	\
    199  1.2  matt 	addi	%r2,%r2,-4*(32-start);	/* find our save area */	\
    200  1.2  matt 	lmw	%r##start,0(%r2);	/* get start-r31 */		\
    201  1.2  matt 	mtsprg3	%r2;			/* save updated pointer */	\
    202  1.2  matt 	stmw	%r3, FRAME_3(%r1);	/* save r2-r31 */		\
    203  1.2  matt 	/* Now everything has been saved */				\
    204  1.2  matt 	mr	%r31, %r0;		/* move SRR1 back to r31 */	\
    205  1.3  matt 	mfsprg2	%r13;			/* put curlwp in r13 */		\
    206  1.2  matt 	FRAME_SAVE_SPEFSCR;						\
    207  1.2  matt 	li	%r7, exc;		/* load EXC_* */		\
    208  1.2  matt 	stw	%r7, FRAME_EXC(%r1);	/* save into trapframe */	\
    209  1.2  matt 	addi	tf, %r1, FRAME_TF	/* get address of trap frame */
    210  1.2  matt 
    211  1.2  matt #define FRAME_EXC_EXIT(rfi, srr)					\
    212  1.2  matt 	lmw	%r26, FRAME_LR(%r1);	/* get LR CR XER CTR SRR0/1 */	\
    213  1.2  matt 	oris	%r31,%r31,PSL_CE@h;					\
    214  1.2  matt 	mtspr	SPR_##srr##1, %r31;	/* restore SRR1 */		\
    215  1.2  matt 	mtspr	SPR_##srr##0, %r30;	/* restore SRR0 */		\
    216  1.2  matt 	FRAME_RESTORE_SPEFSCR;						\
    217  1.2  matt 	mtctr	%r29;			/* restore CTR */		\
    218  1.2  matt 	mtxer	%r28;			/* restore XER */		\
    219  1.2  matt 	mtcr	%r27;			/* restore CR */		\
    220  1.2  matt 	mtlr	%r26;			/* restore LR */		\
    221  1.2  matt 	lmw	%r2, FRAME_2(%r1);	/* restore r2-r31 */		\
    222  1.2  matt 	lwz	%r0, FRAME_0(%r1);	/* restore r0 */		\
    223  1.2  matt 	lwz	%r1, FRAME_1(%r1);	/* restore r1 */		\
    224  1.2  matt 	rfi				/* return from interrupt */
    225  1.2  matt 
    226  1.2  matt 
    227  1.2  matt #define	FRAME_ENTER(exc, tf)		\
    228  1.2  matt 	FRAME_EXC_ENTER(exc, tf, 26, SAVE_NOTHING)
    229  1.2  matt 
    230  1.2  matt #define	FRAME_ENTER_ESR(exc, tf)	\
    231  1.2  matt 	FRAME_EXC_ENTER(exc, tf, 25, SAVE_ESR)
    232  1.2  matt 
    233  1.2  matt #define	FRAME_ENTER_DEAR_ESR(exc, tf)	\
    234  1.2  matt 	FRAME_EXC_ENTER(exc, tf, 24, SAVE_DEAR_ESR)
    235  1.2  matt 
    236  1.2  matt #define	FRAME_EXIT		FRAME_EXC_EXIT(rfi, SRR)
    237  1.2  matt 
    238  1.2  matt #define	FRAME_TLBENTER(exc)	\
    239  1.2  matt 	FRAME_EXC_ENTER(exc, %r4, 20, SAVE_DEAR_ESR)
    240  1.2  matt #define	FRAME_TLBEXIT		FRAME_EXC_EXIT(rfi, SRR)
    241  1.2  matt 
    242  1.2  matt #define	FRAME_MCHK_ENTER(exc)	\
    243  1.2  matt 	FRAME_EXC_ENTER(exc, %r3, 26, SAVE_SPRG1; SAVE_SRRS)
    244  1.2  matt #define	FRAME_MCHK_EXIT		\
    245  1.2  matt 	RESTORE_SRR0(%r28);	\
    246  1.2  matt 	RESTORE_SRR1(%r27);	\
    247  1.2  matt 	RESTORE_SPRG1(%r26);	\
    248  1.2  matt 	FRAME_EXC_EXIT(rfmci, MCSRR)
    249  1.2  matt 
    250  1.2  matt #define	FRAME_DEBUG_ENTER(exc)	\
    251  1.2  matt 	FRAME_EXC_ENTER(exc, %r4, 26, SAVE_SPRG1; SAVE_SRRS)
    252  1.2  matt #define	FRAME_DEBUG_EXIT	\
    253  1.2  matt 	RESTORE_SPRG1(%r26); FRAME_EXC_EXIT(rfci, CSRR)
    254  1.2  matt 
    255  1.2  matt #define	FRAME_INTR_SP							\
    256  1.2  matt 	bf	MSR_PR, 1f;		/*    nope, sp is good */	\
    257  1.2  matt 	mfsprg2	%r2;			/* get curlwp */		\
    258  1.2  matt 	lwz	%r2, L_PCB(%r2);	/* get uarea of curlwp */	\
    259  1.2  matt 	addi	%r1, %r2, USPACE-CALLFRAMELEN;				\
    260  1.2  matt 					/* start stack at top of it */	\
    261  1.2  matt 1:
    262  1.2  matt 
    263  1.2  matt #define	FRAME_INTR_SP_NEW(sym)						\
    264  1.2  matt 	lis	%r2,(sym)@ha;						\
    265  1.2  matt 	addi	%r1,%r2,(sym)@l
    266  1.2  matt 
    267  1.2  matt #define	FRAME_INTR_XENTER(exc, start, get_intr_sp, save_prologue)	\
    268  1.2  matt 	mtcr	%r31;			/* user mode exception? */	\
    269  1.2  matt 	mr	%r31, %r1;		/* save SP (SRR1 is safe in CR) */ \
    270  1.2  matt 	get_intr_sp;			/* get kernel stack pointer */	\
    271  1.2  matt 	stw	%r30, CFRAME_LR(%r1);	/* save in .. */		\
    272  1.2  matt 	stwu	%r31, -FRAMELEN(%r1);	/* get space for trapframe */	\
    273  1.2  matt 	stw	%r0, FRAME_0(%r1);	/* save r0 */			\
    274  1.2  matt 	stw	%r31, FRAME_1(%r1);	/* save (saved) r1 */		\
    275  1.2  matt 	stw	%r26, FRAME_2(%r1);	/* save (saved) r2 */		\
    276  1.2  matt 	save_prologue;			/* save SPRG1 (maybe) */	\
    277  1.2  matt 	mflr	%r26;			/* get LR */			\
    278  1.2  matt 	mfctr	%r29;			/* get CTR */			\
    279  1.2  matt 	mfcr	%r31;			/* get SRR1 */			\
    280  1.2  matt 	stmw	%r26, FRAME_LR(%r1);	/* save LR CR XER CTR SRR0/1 */	\
    281  1.2  matt 	FRAME_SAVE_SRR0_FOR_DDB;					\
    282  1.2  matt 	stw	%r3, FRAME_3(%r1);	/* save r3 */			\
    283  1.2  matt 	stw	%r4, FRAME_4(%r1);	/* save r4 */			\
    284  1.2  matt 	stw	%r5, FRAME_5(%r1);	/* save r5 */			\
    285  1.2  matt 	stw	%r6, FRAME_6(%r1);	/* save r6 */			\
    286  1.2  matt 	stw	%r7, FRAME_7(%r1);	/* save r7 */			\
    287  1.2  matt 	stw	%r8, FRAME_8(%r1);	/* save r8 */			\
    288  1.2  matt 	stw	%r9, FRAME_9(%r1);	/* save r9 */			\
    289  1.2  matt 	stw	%r10, FRAME_10(%r1);	/* save r10 */			\
    290  1.2  matt 	stw	%r11, FRAME_11(%r1);	/* save r11 */			\
    291  1.2  matt 	stw	%r12, FRAME_12(%r1);	/* save r12 */			\
    292  1.2  matt 	stw	%r13, FRAME_13(%r1);	/* save r13 */			\
    293  1.2  matt 	mfsprg3	%r2;			/* get save_area pointer */	\
    294  1.2  matt 	addi	%r2,%r2,-4*(32-start);	/* find our save area */	\
    295  1.2  matt 	lmw	%r##start,0(%r2);	/* get start-r31 */		\
    296  1.2  matt 	mtsprg3	%r2;			/* save updated pointer */	\
    297  1.3  matt 	mfsprg2	%r13;			/* put curlwp into r13 */	\
    298  1.2  matt 	li	%r7, exc;		/* load EXC_* */		\
    299  1.2  matt 	stw	%r7, FRAME_EXC(%r1);	/* save into trapframe */	\
    300  1.2  matt 	addi	%r3, %r1, FRAME_TF	/* only argument is trapframe */
    301  1.2  matt 
    302  1.2  matt #define FRAME_INTR_XEXIT(rfi, srr)					\
    303  1.2  matt 	lwz	%r8, FRAME_LR(%r1);	/* get LR */			\
    304  1.2  matt 	lwz	%r9, FRAME_CR(%r1);	/* get CR */			\
    305  1.2  matt 	lwz	%r10, FRAME_XER(%r1);	/* get XER */			\
    306  1.2  matt 	lwz	%r11, FRAME_CTR(%r1);	/* get CTR */			\
    307  1.2  matt 	lwz	%r12, FRAME_SRR0(%r1);	/* get SRR0 */			\
    308  1.2  matt 	lwz	%r13, FRAME_SRR1(%r1);	/* get SRR1 */			\
    309  1.2  matt 	mtspr	SPR_##srr##1, %r13;	/* restore SRR1 */		\
    310  1.2  matt 	mtspr	SPR_##srr##0, %r12;	/* restore SRR0 */		\
    311  1.2  matt 	mtctr	%r11;			/* restore CTR */		\
    312  1.2  matt 	mtxer	%r10;			/* restore XER */		\
    313  1.2  matt 	mtcr	%r9;			/* restore CR */		\
    314  1.2  matt 	mtlr	%r8;			/* restore LR */		\
    315  1.2  matt 	lwz	%r13, FRAME_13(%r1);	/* restore r13 */		\
    316  1.2  matt 	lwz	%r12, FRAME_12(%r1);	/* restore r12 */		\
    317  1.2  matt 	lwz	%r11, FRAME_11(%r1);	/* restore r11 */		\
    318  1.2  matt 	lwz	%r10, FRAME_10(%r1);	/* restore r10 */		\
    319  1.2  matt 	lwz	%r9, FRAME_9(%r1);	/* restore r9 */		\
    320  1.2  matt 	lwz	%r8, FRAME_8(%r1);	/* restore r8 */		\
    321  1.2  matt 	lwz	%r7, FRAME_7(%r1);	/* restore r7 */		\
    322  1.2  matt 	lwz	%r6, FRAME_6(%r1);	/* restore r6 */		\
    323  1.2  matt 	lwz	%r5, FRAME_5(%r1);	/* restore r5 */		\
    324  1.2  matt 	lwz	%r4, FRAME_4(%r1);	/* restore r4 */		\
    325  1.2  matt 	lwz	%r3, FRAME_3(%r1);	/* restore r3 */		\
    326  1.2  matt 	lwz	%r2, FRAME_2(%r1);	/* restore r2 */		\
    327  1.2  matt 	lwz	%r0, FRAME_0(%r1);	/* restore r0 */		\
    328  1.2  matt 	lwz	%r1, FRAME_1(%r1);	/* restore r1 */		\
    329  1.2  matt 	rfi				/* return from interrupt */
    330  1.2  matt 
    331  1.2  matt #define	FRAME_INTR_ENTER(exc)	\
    332  1.2  matt 	FRAME_INTR_XENTER(exc, 26, FRAME_INTR_SP, SAVE_NOTHING)
    333  1.2  matt #define	FRAME_INTR_EXIT		\
    334  1.2  matt 	FRAME_INTR_XEXIT(rfi, SRR)
    335  1.2  matt #define	FRAME_CRIT_ENTER(exc)	\
    336  1.2  matt 	FRAME_INTR_XENTER(exc, 24, FRAME_INTR_SP, SAVE_SPRG1)
    337  1.2  matt #define	FRAME_WDOG_ENTER(exc, sym)	\
    338  1.2  matt 	FRAME_INTR_XENTER(exc, 24, FRAME_INTR_SP_NEW(sym), SAVE_SPRG1)
    339  1.2  matt #define	FRAME_CRIT_EXIT		\
    340  1.2  matt 	RESTORE_SRR0(%r4);	\
    341  1.2  matt 	RESTORE_SRR1(%r5);	\
    342  1.2  matt 	RESTORE_SPRG1(%r6);	\
    343  1.2  matt 	FRAME_INTR_XEXIT(rfci, CSRR)
    344  1.2  matt 
    345  1.2  matt 	.text
    346  1.2  matt 	.p2align 4
    347  1.2  matt _C_LABEL(critical_input_vector):
    348  1.2  matt 	/* MSR[ME] is unchanged, all others cleared */
    349  1.2  matt 	FRAME_CRIT_PROLOGUE			/* save SP r26-31 CR LR XER */
    350  1.2  matt 	FRAME_CRIT_ENTER(EXC_CII)
    351  1.2  matt _C_LABEL(critintr_call):
    352  1.2  matt 	bl	_C_LABEL(critintr_call)		/* critintr(tf) */
    353  1.2  matt 	FRAME_CRIT_EXIT
    354  1.2  matt 
    355  1.2  matt 	.p2align 4
    356  1.2  matt _C_LABEL(machine_check_vector):
    357  1.2  matt 	/* all MSR bits are cleared */
    358  1.2  matt 	FRAME_MCHK_PROLOGUE			/* save SP r25-31 CR LR XER */
    359  1.2  matt 	FRAME_MCHK_ENTER(EXC_MCHK)
    360  1.2  matt 	/*
    361  1.2  matt 	 * MCAR/MCSR don't need to be saved early since MSR[ME] is cleared
    362  1.2  matt 	 * on entry.
    363  1.2  matt 	 */
    364  1.2  matt 	mfspr	%r7, SPR_MCAR
    365  1.2  matt 	mfspr	%r6, SPR_MCSR
    366  1.2  matt 	stw	%r6, FRAME_MCSR(%r1)
    367  1.2  matt 	stw	%r7, FRAME_MCAR(%r1)
    368  1.2  matt 	li	%r3, T_MACHINE_CHECK
    369  1.2  matt 	bl	_C_LABEL(trap)			/* trap(T_MACHINE_CHECK, tf) */
    370  1.2  matt 	FRAME_MCHK_EXIT
    371  1.2  matt 
    372  1.2  matt 	.p2align 4
    373  1.2  matt _C_LABEL(data_storage_vector):
    374  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    375  1.2  matt 	FRAME_PROLOGUE_DEAR_ESR		/* save r2 DEAR ESR r24-31 CR XER SRR */
    376  1.2  matt 	FRAME_ENTER_DEAR_ESR(EXC_DSI, %r4)
    377  1.2  matt 	li	%r3, T_DSI
    378  1.2  matt 	/* FRAME_ENTER leaves SRR1 in %r31 */
    379  1.2  matt trapenter:
    380  1.2  matt trapagain:
    381  1.2  matt 	wrtee	%r31				/* restore MSR[EE] */
    382  1.2  matt 
    383  1.2  matt 	bl	_C_LABEL(trap)			/* trap(trapcode, tf) */
    384  1.2  matt _C_LABEL(trapexit):
    385  1.2  matt 	wrteei	0				/* disable interrupts */
    386  1.2  matt #	andis.	%r0, %r31, PSL_CE@h
    387  1.2  matt #	tweqi	%r0, 0
    388  1.2  matt 	andi.	%r4, %r31, PSL_PR		/* lets look at PSL_PR */
    389  1.2  matt 	beq	trapdone			/* if clear, skip to exit  */
    390  1.3  matt 	lwz	%r4, L_MD_ASTPENDING(%r13)	/* get ast pending */
    391  1.2  matt 	cmplwi	%r4, 0				/* is there an ast pending */
    392  1.2  matt 	beq+	trapdone			/*    nope, proceed to exit */
    393  1.2  matt 	li	%r6, EXC_AST			/* yes. */
    394  1.2  matt 	stw	%r6, FRAME_EXC(%r1)		/* pretend this is an AST */
    395  1.2  matt 	addi	%r4, %r1, FRAME_TF		/* get address of trap frame */
    396  1.2  matt 	li	%r3, T_AST
    397  1.2  matt 	b	trapagain			/* and deal with it */
    398  1.2  matt trapdone:
    399  1.2  matt 	FRAME_EXIT
    400  1.2  matt 
    401  1.2  matt 	.p2align 4
    402  1.2  matt _C_LABEL(instruction_storage_vector):
    403  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    404  1.2  matt 	FRAME_PROLOGUE_ESR		/* save ESR r2 r25-31 CR XER SRR0/1 */
    405  1.2  matt 	FRAME_ENTER_ESR(EXC_ISI, %r4)
    406  1.2  matt 	li	%r3, T_ISI
    407  1.2  matt 	b	trapenter
    408  1.2  matt 
    409  1.2  matt 	.p2align 4
    410  1.2  matt _ENTRY(external_input_vector)
    411  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    412  1.2  matt 	FRAME_INTR_PROLOGUE			/* save SP r25-31 CR LR XER */
    413  1.2  matt 	FRAME_INTR_ENTER(EXC_EXI)
    414  1.2  matt 
    415  1.2  matt _C_LABEL(extintr_call):
    416  1.2  matt 	bl	_C_LABEL(extintr_call)
    417  1.2  matt _C_LABEL(intrcall):
    418  1.2  matt 	GET_CPUINFO(%r6)			/* get curcpu() */
    419  1.2  matt 	lwz	%r5, FRAME_SRR1(%r1)		/* get saved SRR1 */
    420  1.2  matt #	andis.	%r0, %r5, PSL_CE@h
    421  1.2  matt #	tweqi	%r0, 0
    422  1.2  matt 	andi.	%r4, %r5, PSL_PR		/* lets look at PSL_PR */
    423  1.2  matt 	beq	intrexit			/* if clear, skip to exit  */
    424  1.3  matt 	lwz	%r4, L_MD_ASTPENDING(%r13)	/* get ast pending */
    425  1.2  matt 	cmplwi	%r4, 0				/* is there an ast pending */
    426  1.2  matt 	beq+	intrexit			/*    nope, proceed to exit */
    427  1.2  matt 	stmw	%r14, FRAME_14(%r1)		/* save rest of registers */
    428  1.2  matt 	FRAME_SAVE_SPEFSCR
    429  1.2  matt 	mr	%r31, %r5			/* needed for trapagain */
    430  1.2  matt 	li	%r4, EXC_AST			/* */
    431  1.2  matt 	stw	%r4, FRAME_EXC(%r1)		/* pretend this is an AST */
    432  1.2  matt 	addi	%r4, %r1, FRAME_TF		/* get address of trap frame */
    433  1.2  matt 	li	%r3, T_AST
    434  1.2  matt 	b	trapagain			/* and deal with it */
    435  1.2  matt intrexit:
    436  1.2  matt 	FRAME_INTR_EXIT
    437  1.2  matt 
    438  1.2  matt 	.p2align 4
    439  1.2  matt _C_LABEL(alignment_vector):
    440  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    441  1.2  matt 	FRAME_PROLOGUE_DEAR_ESR			/* save SP r25-31 CR LR XER */
    442  1.2  matt 	FRAME_ENTER_DEAR_ESR(EXC_ALI, %r4)
    443  1.2  matt 	li	%r3, T_ALIGNMENT
    444  1.2  matt 	b	trapenter
    445  1.2  matt 
    446  1.2  matt 	.p2align 4
    447  1.2  matt _C_LABEL(program_vector):
    448  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    449  1.2  matt 	FRAME_PROLOGUE_ESR			/* save SP r25-31 CR LR XER */
    450  1.2  matt 	FRAME_ENTER_ESR(EXC_PGM, %r4)
    451  1.2  matt 	li	%r3, T_PROGRAM
    452  1.2  matt 	b	trapenter
    453  1.2  matt 
    454  1.2  matt #ifdef SPR_IVOR7
    455  1.2  matt 	.p2align 4
    456  1.2  matt _C_LABEL(fp_unavailable_vector):
    457  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    458  1.2  matt 	FRAME_PROLOGUE_ESR			/* save SP r25-31 CR LR XER */
    459  1.2  matt 	FRAME_ENTER_ESR(EXC_FPU, %r4)
    460  1.2  matt 	li	%r3, T_FP_UNAVAILABLE
    461  1.2  matt 	b	trapenter
    462  1.2  matt #endif
    463  1.2  matt 
    464  1.2  matt 	.p2align 4
    465  1.2  matt _C_LABEL(system_call_vector):
    466  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    467  1.2  matt 	FRAME_PROLOGUE				/* save SP r26-31 CR LR XER */
    468  1.2  matt 	FRAME_ENTER(EXC_SC, %r3)
    469  1.2  matt 
    470  1.2  matt 	wrteei	1				/* enable interrupts */
    471  1.3  matt 	lwz	%r7, L_PROC(%r13)		/* get proc for lwp */
    472  1.2  matt 	lwz	%r8, P_MD_SYSCALL(%r7)		/* get syscall */
    473  1.3  matt 	mtlr	%r8				/* need to call indirect */
    474  1.3  matt 	blrl					/* syscall(tf) */
    475  1.2  matt _C_LABEL(sctrapexit):
    476  1.2  matt 	wrteei	0				/* disable interrupts */
    477  1.3  matt 	mfsprg2	%r3				/* get curlwp */
    478  1.3  matt 	lwz	%r4, L_MD_ASTPENDING(%r13)	/* get ast pending */
    479  1.2  matt 	cmplwi	%r4, 0				/* is there an ast pending */
    480  1.2  matt 	beq+	trapdone			/*    nope, proceed to exit */
    481  1.2  matt 	li	%r0, EXC_AST			/* yes. */
    482  1.2  matt 	stw	%r0, FRAME_EXC(%r1)		/* pretend this is an AST */
    483  1.2  matt 	addi	%r4, %r1, FRAME_TF		/* get address of trap frame */
    484  1.2  matt 	li	%r3, T_AST
    485  1.2  matt 	b	trapenter			/* and deal with it */
    486  1.2  matt 
    487  1.2  matt #ifdef SPR_IVOR9
    488  1.2  matt 	.p2align 4
    489  1.2  matt _C_LABEL(ap_unavailable_vector):
    490  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    491  1.2  matt 	FRAME_PROLOGUE				/* save SP r25-31 CR LR XER */
    492  1.2  matt 	FRAME_ENTER(EXC_PGM, %r4)
    493  1.2  matt 	li	%r3, T_AP_UNAVAILABLE
    494  1.2  matt 	b	trapenter
    495  1.2  matt #endif
    496  1.2  matt 
    497  1.2  matt 	.p2align 4
    498  1.2  matt _C_LABEL(decrementer_vector):
    499  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    500  1.2  matt 	FRAME_INTR_PROLOGUE			/* save SP r25-31 CR LR XER */
    501  1.2  matt 	FRAME_INTR_ENTER(EXC_DECR)
    502  1.2  matt 
    503  1.2  matt _C_LABEL(decrintr_call):
    504  1.2  matt 	bl	_C_LABEL(decrintr_call)
    505  1.2  matt 	b	intrexit
    506  1.2  matt 
    507  1.2  matt 	.p2align 4
    508  1.2  matt _C_LABEL(fixed_interval_timer_vector):
    509  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    510  1.2  matt 	FRAME_PROLOGUE				/* save SP r25-31 CR LR XER */
    511  1.2  matt 	FRAME_INTR_ENTER(EXC_FIT)
    512  1.2  matt 
    513  1.2  matt _C_LABEL(fitintr_call):
    514  1.2  matt 	bl	_C_LABEL(fitintr_call)
    515  1.2  matt 	b	intrexit
    516  1.2  matt 
    517  1.2  matt 	.data
    518  1.2  matt 	.lcomm wdogstk,4096
    519  1.2  matt 	.text
    520  1.2  matt 	.p2align 4
    521  1.2  matt _C_LABEL(watchdog_timer_vector):
    522  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    523  1.2  matt 	FRAME_CRIT_PROLOGUE			/* save SP r25-31 CR LR XER */
    524  1.2  matt 	FRAME_WDOG_ENTER(EXC_WDOG, wdogstk+4096-CALLFRAMELEN)
    525  1.2  matt #if 0
    526  1.2  matt 	lis	%r11,0xe0004641@ha
    527  1.2  matt 	addi	%r11,%r11,0xe0004641@l
    528  1.2  matt 	stb	%r11,-65(%r11)
    529  1.2  matt #endif
    530  1.2  matt 
    531  1.2  matt _C_LABEL(wdogintr_call):
    532  1.2  matt 	bl	_C_LABEL(wdogintr_call)
    533  1.2  matt 	FRAME_CRIT_EXIT
    534  1.2  matt 
    535  1.2  matt 	.p2align 4
    536  1.2  matt _C_LABEL(data_tlb_error_vector):
    537  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    538  1.2  matt 	FRAME_TLBPROLOGUE
    539  1.2  matt 	/*
    540  1.2  matt 	 * Registers as this point:
    541  1.2  matt 	 *
    542  1.2  matt 	 * r2  = cpu_info
    543  1.2  matt 	 * r20 = scratch
    544  1.2  matt 	 * r21 = scratch
    545  1.2  matt 	 * r22 = scratch
    546  1.2  matt 	 * r23 = scratch
    547  1.2  matt 	 * r24 = DEAR
    548  1.2  matt 	 * r25 = ESR
    549  1.2  matt 	 * r26 = saved r2
    550  1.2  matt 	 * r27 = CR
    551  1.2  matt 	 * r28 = XER
    552  1.2  matt 	 * r29 = scratch
    553  1.2  matt 	 * r30 = SRR0
    554  1.2  matt 	 * r31 = SRR1
    555  1.2  matt 	 *
    556  1.2  matt 	 * Except for r29, these values must be retained.  However we must
    557  1.2  matt 	 * be cognizant of nesting.  There are two cases here, both related.
    558  1.2  matt 	 *
    559  1.2  matt 	 * We get a critical input or machine check exception and the kernel
    560  1.2  matt 	 * stack doesn't have a TLB entry so we take an exception.  The other
    561  1.2  matt 	 * nesting path is some page used by the exception handler will cause
    562  1.2  matt 	 * a TLB data error.
    563  1.2  matt 	 *
    564  1.2  matt 	 * The second case (more probable) is that the PTE loading will fail
    565  1.2  matt 	 * so we will have to do a hard trap to resolve it.  But in doing so
    566  1.2  matt 	 * we need to save a trapframe which could result in another DTLB
    567  1.2  matt 	 * fault.
    568  1.2  matt 	 *
    569  1.2  matt 	 * In all cases, the save area stack shall protect us.
    570  1.2  matt 	 */
    571  1.2  matt 	/*
    572  1.2  matt 	 * Attempt to update the TLB from the page table.
    573  1.2  matt 	 */
    574  1.2  matt 	mflr	%r29				/* save LR */
    575  1.2  matt 	mr	%r23, %r24			/* address of exception */
    576  1.2  matt 	rlwinm	%r22, %r31,			/* index into ci_pmap_segtab */\
    577  1.2  matt 		MSR_DS+PTR_SCALESHIFT+1, \
    578  1.2  matt 		31-PTR_SCALESHIFT, \
    579  1.2  matt 		31-PTR_SCALESHIFT		/* move PSL_DS[27] to bit 29 */
    580  1.2  matt 	bl	pte_load
    581  1.2  matt 	mtlr	%r29				/* restore LR */
    582  1.2  matt 	/*
    583  1.2  matt 	 * If we returned, pte load failed so let trap deal with it but
    584  1.2  matt 	 * has kept the contents of r24-r31 (expect r29) intact.
    585  1.2  matt 	 */
    586  1.2  matt 	FRAME_TLBENTER(EXC_DSI)
    587  1.2  matt 	li	%r3, T_DATA_TLB_ERROR
    588  1.2  matt 	b	trapenter
    589  1.2  matt 
    590  1.2  matt 	.p2align 4
    591  1.2  matt _C_LABEL(instruction_tlb_error_vector):
    592  1.2  matt 	/* MSR[CE], MSR[ME], MSR[DE] are unchanged, all others cleared */
    593  1.2  matt 	FRAME_TLBPROLOGUE
    594  1.2  matt 	/*
    595  1.2  matt 	 * Attempt to update the TLB from the page table.
    596  1.2  matt 	 */
    597  1.2  matt 	mflr	%r29				/* save LR */
    598  1.2  matt 	mr	%r23, %r30			/* PC of exception */
    599  1.2  matt 	rlwinm	%r22, %r31,			/* index into ci_pmap_segtab */\
    600  1.2  matt 		MSR_IS+PTR_SCALESHIFT+1, \
    601  1.2  matt 		31-PTR_SCALESHIFT, \
    602  1.2  matt 		31-PTR_SCALESHIFT		/* move PSL_IS[26] to bit 29 */
    603  1.2  matt 	bl	pte_load
    604  1.2  matt 	mtlr	%r29				/* restore LR */
    605  1.2  matt 	/*
    606  1.2  matt 	 * If we returned, pte load failed so let trap deal with it but
    607  1.2  matt 	 * has kept the contents of r24-r31 (expect r29) intact.
    608  1.2  matt 	 */
    609  1.2  matt 	FRAME_TLBENTER(EXC_ISI)
    610  1.2  matt 	li	%r3, T_INSTRUCTION_TLB_ERROR
    611  1.2  matt 	b	trapenter
    612  1.2  matt 
    613  1.2  matt 	.p2align 4
    614  1.2  matt _C_LABEL(debug_vector):
    615  1.2  matt 	FRAME_CRIT_PROLOGUE			/* save SP r25-31 CR LR XER */
    616  1.2  matt 	FRAME_CRIT_ENTER(EXC_DEBUG)
    617  1.2  matt 	mfspr	%r6, SPR_DBSR
    618  1.2  matt 	stw	%r6, FRAME_ESR(%r1)
    619  1.2  matt 	li	%r3, T_DEBUG
    620  1.2  matt 	bl	_C_LABEL(trap)
    621  1.2  matt 	FRAME_CRIT_EXIT
    622  1.2  matt 
    623  1.2  matt 	.p2align 4
    624  1.2  matt _C_LABEL(spv_unavailable_vector):
    625  1.2  matt 	FRAME_PROLOGUE_ESR			/* save SP r25-31 CR LR XER */
    626  1.2  matt 	FRAME_ENTER_ESR(EXC_VEC, %r4)
    627  1.2  matt 	li	%r3, T_SPE_UNAVAILABLE
    628  1.2  matt 	b	trapenter
    629  1.2  matt 
    630  1.2  matt 	.p2align 4
    631  1.2  matt _C_LABEL(fpdata_vector):
    632  1.2  matt 	FRAME_PROLOGUE_ESR			/* save SP r25-31 CR LR XER */
    633  1.2  matt 	FRAME_ENTER_ESR(EXC_FPA, %r4)
    634  1.2  matt 	li	%r3, T_EMBEDDED_FP_DATA
    635  1.2  matt 	b	trapenter
    636  1.2  matt 
    637  1.2  matt 	.p2align 4
    638  1.2  matt _C_LABEL(fpround_vector):
    639  1.2  matt 	FRAME_PROLOGUE_ESR			/* save SP r25-31 CR LR XER */
    640  1.2  matt 	FRAME_ENTER_ESR(EXC_FPA, %r4)
    641  1.2  matt 	li	%r3, T_EMBEDDED_FP_ROUND
    642  1.2  matt 	b	trapenter
    643  1.2  matt 
    644  1.2  matt 	.p2align 4
    645  1.2  matt _C_LABEL(perfmon_vector):
    646  1.2  matt 	FRAME_PROLOGUE_ESR			/* save SP r25-31 CR LR XER */
    647  1.2  matt 	FRAME_ENTER_ESR(EXC_PERF, %r4)
    648  1.2  matt 	li	%r3, T_EMBEDDED_PERF_MONITOR
    649  1.2  matt 	b	trapenter
    650  1.2  matt 
    651  1.2  matt 	.p2align 4
    652  1.2  matt pte_load:
    653  1.2  matt 	/*
    654  1.2  matt 	 * r2 = scratch
    655  1.2  matt 	 * r20 = scratch
    656  1.2  matt 	 * r21 = scratch
    657  1.2  matt 	 * r22 = index into ci_pmap_{kern,user}_segtab
    658  1.2  matt 	 * r23 = faulting address
    659  1.2  matt 	 * The rest are for reference and aren't modifiable.  If the load
    660  1.2  matt 	 * fails, they will be used by FRAME_TLBENTER to create the trapframe.
    661  1.2  matt 	 * r24 = DEAR
    662  1.2  matt 	 * r25 = ESR
    663  1.2  matt 	 * r26 = saved r2
    664  1.2  matt 	 * r27 = CR
    665  1.2  matt 	 * r28 = XER
    666  1.2  matt 	 * r29 = LR
    667  1.2  matt 	 * r30 = SRR0
    668  1.2  matt 	 * r31 = SRR1
    669  1.2  matt 	 */
    670  1.2  matt 	cmplwi	%cr2, %r22, 0		/* remember address space */
    671  1.2  matt 	GET_CPUINFO(%r2)
    672  1.2  matt 	addi	%r22, %r22, CI_PMAP_SEGTAB /* index into segtab(s) */
    673  1.2  matt 	lwzx	%r20, %r22, %r2		/* load kern/user L1 PT addr */
    674  1.2  matt 	cmplwi	%r20, 0			/* is segtab null? */
    675  1.2  matt 	beqlr	%cr0			/* yes, return to fallback to trap */
    676  1.2  matt 
    677  1.2  matt 	rlwinm	%r22, %r23, NSEGPG_SCALESHIFT + PTR_SCALESHIFT, \
    678  1.2  matt 		31-(NSEGPG_SCALESHIFT + PTR_SCALESHIFT - 1), \
    679  1.2  matt 		31-PTR_SCALESHIFT	/* extract addr bits [0:9] to [20:29] */
    680  1.2  matt 	lwzx	%r20, %r22, %r20	/* load address of page table page */
    681  1.2  matt 	cmplwi	%r20, 0			/* is page null? */
    682  1.2  matt 	beqlr	%cr0			/* yes, return to fallback to trap */
    683  1.2  matt 
    684  1.2  matt 	rlwinm	%r22, %r23, \
    685  1.2  matt 		NSEGPG_SCALESHIFT + NPTEPG_SCALESHIFT + PTE_SCALESHIFT, \
    686  1.2  matt 		31-(NPTEPG_SCALESHIFT + PTE_SCALESHIFT - 1), \
    687  1.2  matt 		31-PTE_SCALESHIFT	/* extract addr bits [10:19] to [20:29] */
    688  1.2  matt 	lwzx	%r20, %r22, %r20	/* load PTE from page table page */
    689  1.2  matt 	cmplwi	%r20, 0			/* is there a valid PTE? */
    690  1.2  matt 	beqlr	%cr0			/* no, return to fallback to trap */
    691  1.2  matt 
    692  1.2  matt #if (PTE_UNSYNCED << 1) != PTE_xX
    693  1.2  matt #error PTE_UNSYNCED definition error
    694  1.2  matt #endif
    695  1.2  matt #if (PTE_UNMODIFIED << 1) != PTE_xW
    696  1.2  matt #error PTE_UNMODIFIED definition error
    697  1.2  matt #endif
    698  1.2  matt 	andi.	%r22, %r20, (PTE_UNSYNCED|PTE_UNMODIFIED)
    699  1.2  matt 					/* Does the PTE need to be changed? */
    700  1.2  matt 	rotlwi	%r22, %r22, 1		/* if so, clear the right PTE bits */
    701  1.2  matt 	andc	%r20, %r20, %r22	/* pte &= ~((pte & (PTE_UNSYNCED|PTE_UNMODIFIED)) << 1)*/
    702  1.2  matt 
    703  1.2  matt 	/*
    704  1.2  matt 	 * r24-r32 = (no touch)
    705  1.2  matt 	 * r23 = scratch (was fault addr)
    706  1.2  matt 	 * r22 = scratch
    707  1.2  matt 	 * r21 = scratch
    708  1.2  matt 	 * r20 = pte
    709  1.2  matt 	 * cr2 = AS 0=eq/!0=ne
    710  1.2  matt 	 */
    711  1.2  matt 
    712  1.2  matt 	/*
    713  1.2  matt 	 * This is all E500 specific.  We should have a patchable branch
    714  1.2  matt 	 * to support other BookE (440) implementations.
    715  1.2  matt 	 */
    716  1.2  matt e500_pte_load:
    717  1.2  matt 	bne+	%cr2, 1f		/* user access? MAS1 is ok. */
    718  1.2  matt 	mfspr	%r22, SPR_MAS1		/* get MAS1 */
    719  1.2  matt 	lis	%r21, MAS1_TID@h	/* get TID mask */
    720  1.2  matt 	andc	%r22, %r22, %r21	/* clear TID */
    721  1.2  matt 	mtspr	SPR_MAS1, %r22		/* save MAS1 */
    722  1.2  matt 1:
    723  1.2  matt 	andi.	%r21, %r20, PTE_WIMGE_MASK /* extract WIMGE from PTE */
    724  1.2  matt 	cmplwi	%r21, PTE_M		/* if just PTE_M is set, */
    725  1.2  matt 	beq+	%cr0, 2f		/*    skip munging mas2 */
    726  1.2  matt 	mfspr	%r22, SPR_MAS2		/* get MAS2 (updated by error) */
    727  1.2  matt 	clrrwi	%r22, %r22, PTE_RWX_SHIFT /* clear WIMGE bits */
    728  1.2  matt 	or	%r22, %r22, %r21	/* combine with MAS2 contents */
    729  1.2  matt 	mtspr	SPR_MAS2, %r22 		/* put back into MAS2 */
    730  1.2  matt 2:
    731  1.2  matt 	/*
    732  1.2  matt 	 * r23 = fault addr
    733  1.2  matt 	 * r22 = scratch
    734  1.2  matt 	 * r21 = scratch
    735  1.2  matt 	 * r20 = pte
    736  1.2  matt 	 */
    737  1.2  matt 
    738  1.2  matt 	/*
    739  1.2  matt 	 * In MAS3, the protection bits are in the low 6 bits:
    740  1.2  matt 	 *    UX SX UW SW UR SR
    741  1.2  matt 	 * The User bits are 1 bit left of their Supervisor counterparts.
    742  1.2  matt 	 * Rotate the PTE protection bits left until they wrap around to become
    743  1.2  matt 	 * the least significant bits, where the Supervisor protection bits
    744  1.2  matt 	 * are located.  Increase the rotate amount by 1 to place them where
    745  1.2  matt 	 * the User protection bits are located.  We get that 1 by extracting
    746  1.2  matt 	 * the MAS1[TS] (set for User access) and moving it to bit 31 (LSB).
    747  1.2  matt 	 */
    748  1.2  matt 	mfspr	%r21, SPR_MAS1		/* get MAS1 which has TS bit */
    749  1.2  matt 	extrwi	%r21, %r21, 1, 31-MAS1_TS_SHIFT
    750  1.2  matt 					/* extract MAS1_TS to LSB */
    751  1.2  matt 	clrrwi	%r23, %r20, PAGE_SHIFT	/* clear non-RPN bits from PTE */
    752  1.2  matt 	andi.	%r20, %r20, PTE_RWX_MASK /* isolate protection bits */
    753  1.2  matt 	rotrwi	%r20, %r20, PTE_RWX_SHIFT
    754  1.2  matt 	andi.	%r22, %r20, (MAS3_SW|MAS3_SR) /* user pages need to be R/W by kernel */
    755  1.2  matt 	rotlw	%r20, %r20, %r21	/* rotate protection to correct loc */
    756  1.2  matt 	or	%r20, %r20, %r22	/* combine system protection bits */
    757  1.2  matt 	or	%r23, %r23, %r20	/* combine RPN and protection bits */
    758  1.2  matt 	mtspr	SPR_MAS3, %r23		/* put into MAS3 */
    759  1.2  matt 	isync				/* because ECORE500RM tells us too */
    760  1.2  matt 	tlbwe				/* write the TLB entry */
    761  1.2  matt 	/*
    762  1.2  matt 	 * Increment a counter to show how many tlb misses we've handled here.
    763  1.2  matt 	 */
    764  1.2  matt 	lmw	%r30, CI_EV_TLBMISS_SOFT(%r2)
    765  1.2  matt 	addic	%r31, %r31, 1
    766  1.2  matt 	addze	%r30, %r30
    767  1.2  matt 	stmw	%r30, CI_EV_TLBMISS_SOFT(%r2)
    768  1.2  matt 	/*
    769  1.2  matt 	 * Cleanup and leave.  We know any higher priority exception will
    770  1.2  matt 	 * save and restore SPRG1 and %r2 thereby preserving their values.
    771  1.2  matt 	 *
    772  1.2  matt 	 * r24 = DEAR (don't care)
    773  1.2  matt 	 * r25 = ESR (don't care)
    774  1.2  matt 	 * r26 = saved r2
    775  1.2  matt 	 * r27 = CR
    776  1.2  matt 	 * r28 = XER
    777  1.2  matt 	 * r29 = LR
    778  1.2  matt 	 * r30 = LSW of counter
    779  1.2  matt 	 * r31 = MSW of counter
    780  1.2  matt 	 */
    781  1.2  matt 	mtlr	%r29			/* restore Link Register */
    782  1.2  matt 	mtxer	%r28			/* restore XER */
    783  1.2  matt 	mtcr	%r27			/* restore Condition Register */
    784  1.2  matt 	mtsprg1 %r26			/* save saved r2 across load multiple */
    785  1.2  matt 	mfsprg3 %r2			/* get end of save area */
    786  1.2  matt 	addi	%r2,%r2,-4*(32-20)	/* adjust save area down */
    787  1.2  matt 	lmw	%r20,0(%r2)		/* restore r20-r31 */
    788  1.2  matt 	mtsprg3 %r2			/* save new end of save area */
    789  1.2  matt 	mfsprg1	%r2			/* restore r2 */
    790  1.2  matt 	rfi
    791  1.2  matt 
    792  1.2  matt 	.p2align 4
    793  1.2  matt 	.globl _C_LABEL(exception_init)
    794  1.2  matt _C_LABEL(exception_init):
    795  1.2  matt 	lis	%r6,_C_LABEL(critical_input_vector)@h
    796  1.2  matt 	mtspr	SPR_IVPR, %r6
    797  1.2  matt 
    798  1.2  matt 	ori	%r5,%r6,_C_LABEL(critical_input_vector)@l
    799  1.2  matt 	mtspr	SPR_IVOR0, %r5
    800  1.2  matt 
    801  1.2  matt 	ori	%r5,%r6,_C_LABEL(machine_check_vector)@l
    802  1.2  matt 	mtspr	SPR_IVOR1, %r5
    803  1.2  matt 
    804  1.2  matt 	ori	%r5,%r6,_C_LABEL(data_storage_vector)@l
    805  1.2  matt 	mtspr	SPR_IVOR2, %r5
    806  1.2  matt 
    807  1.2  matt 	ori	%r5,%r6,_C_LABEL(instruction_storage_vector)@l
    808  1.2  matt 	mtspr	SPR_IVOR3, %r5
    809  1.2  matt 
    810  1.2  matt 	ori	%r5,%r6,_C_LABEL(external_input_vector)@l
    811  1.2  matt 	mtspr	SPR_IVOR4, %r5
    812  1.2  matt 
    813  1.2  matt 	ori	%r5,%r6,_C_LABEL(alignment_vector)@l
    814  1.2  matt 	mtspr	SPR_IVOR5, %r5
    815  1.2  matt 
    816  1.2  matt 	ori	%r5,%r6,_C_LABEL(program_vector)@l
    817  1.2  matt 	mtspr	SPR_IVOR6, %r5
    818  1.2  matt 
    819  1.2  matt #ifdef SPR_IVOR7
    820  1.2  matt 	ori	%r5,%r6,_C_LABEL(fp_unavailable_vector)@l
    821  1.2  matt 	mtspr	SPR_IVOR7, %r5
    822  1.2  matt #endif
    823  1.2  matt 
    824  1.2  matt 	ori	%r5,%r6,_C_LABEL(system_call_vector)@l
    825  1.2  matt 	mtspr	SPR_IVOR8, %r5
    826  1.2  matt 
    827  1.2  matt #ifdef SPR_IVOR9
    828  1.2  matt 	ori	%r5,%r6,_C_LABEL(ap_unavailable_vector)@l
    829  1.2  matt 	mtspr	SPR_IVOR9, %r5
    830  1.2  matt #endif
    831  1.2  matt 
    832  1.2  matt 	ori	%r5,%r6,_C_LABEL(decrementer_vector)@l
    833  1.2  matt 	mtspr	SPR_IVOR10, %r5
    834  1.2  matt 
    835  1.2  matt 	ori	%r5,%r6,_C_LABEL(fixed_interval_timer_vector)@l
    836  1.2  matt 	mtspr	SPR_IVOR11, %r5
    837  1.2  matt 
    838  1.2  matt 	ori	%r5,%r6,_C_LABEL(watchdog_timer_vector)@l
    839  1.2  matt 	mtspr	SPR_IVOR12, %r5
    840  1.2  matt 
    841  1.2  matt 	ori	%r5,%r6,_C_LABEL(data_tlb_error_vector)@l
    842  1.2  matt 	mtspr	SPR_IVOR13, %r5
    843  1.2  matt 
    844  1.2  matt 	ori	%r5,%r6,_C_LABEL(instruction_tlb_error_vector)@l
    845  1.2  matt 	mtspr	SPR_IVOR14, %r5
    846  1.2  matt 
    847  1.2  matt 	ori	%r5,%r6,_C_LABEL(debug_vector)@l
    848  1.2  matt 	mtspr	SPR_IVOR15, %r5
    849  1.2  matt 
    850  1.2  matt 	ori	%r5,%r6,_C_LABEL(spv_unavailable_vector)@l
    851  1.2  matt 	mtspr	SPR_IVOR32, %r5
    852  1.2  matt 
    853  1.2  matt 	ori	%r5,%r6,_C_LABEL(fpdata_vector)@l
    854  1.2  matt 	mtspr	SPR_IVOR33, %r5
    855  1.2  matt 
    856  1.2  matt 	ori	%r5,%r6,_C_LABEL(fpround_vector)@l
    857  1.2  matt 	mtspr	SPR_IVOR34, %r5
    858  1.2  matt 
    859  1.2  matt 	ori	%r5,%r6,_C_LABEL(perfmon_vector)@l
    860  1.2  matt 	mtspr	SPR_IVOR35, %r5
    861  1.2  matt 
    862  1.3  matt 	mfpir	%r5		/* get Process ID register */
    863  1.3  matt 	cmplwi	%r5,0
    864  1.3  matt 	bnelr			/* return if non-0 (non-primary) */
    865  1.3  matt 
    866  1.2  matt 	lis	%r5,_C_LABEL(critintr_call)@ha
    867  1.2  matt 	lwzu	%r6,_C_LABEL(critintr_call)@l(%r5)
    868  1.2  matt 	lwz	%r7,INTRSW_CRITINTR(%r3)
    869  1.2  matt 	sub	%r8,%r7,%r5
    870  1.2  matt 	add	%r0,%r8,%r6
    871  1.2  matt 	stw	%r0,0(%r5)
    872  1.2  matt 	dcbf	0,%r5
    873  1.2  matt 	icbi	0,%r5
    874  1.2  matt 
    875  1.2  matt 	lis	%r5,_C_LABEL(decrintr_call)@ha
    876  1.2  matt 	lwzu	%r6,_C_LABEL(decrintr_call)@l(%r5)
    877  1.2  matt 	lwz	%r7,INTRSW_DECRINTR(%r3)
    878  1.2  matt 	sub	%r8,%r7,%r5
    879  1.2  matt 	add	%r0,%r8,%r6
    880  1.2  matt 	stw	%r0,0(%r5)
    881  1.2  matt 	dcbf	0,%r5
    882  1.2  matt 	icbi	0,%r5
    883  1.2  matt 
    884  1.2  matt 	lis	%r5,_C_LABEL(fitintr_call)@ha
    885  1.2  matt 	lwzu	%r6,_C_LABEL(fitintr_call)@l(%r5)
    886  1.2  matt 	lwz	%r7,INTRSW_FITINTR(%r3)
    887  1.2  matt 	sub	%r8,%r7,%r5
    888  1.2  matt 	add	%r0,%r8,%r6
    889  1.2  matt 	stw	%r0,0(%r5)
    890  1.2  matt 	dcbf	0,%r5
    891  1.2  matt 	icbi	0,%r5
    892  1.2  matt 
    893  1.2  matt 	lis	%r5,_C_LABEL(wdogintr_call)@ha
    894  1.2  matt 	lwzu	%r6,_C_LABEL(wdogintr_call)@l(%r5)
    895  1.2  matt 	lwz	%r7,INTRSW_WDOGINTR(%r3)
    896  1.2  matt 	sub	%r8,%r7,%r5
    897  1.2  matt 	add	%r0,%r8,%r6
    898  1.2  matt 	stw	%r0,0(%r5)
    899  1.2  matt 	dcbf	0,%r5
    900  1.2  matt 	icbi	0,%r5
    901  1.2  matt 
    902  1.2  matt 	lis	%r5,_C_LABEL(extintr_call)@ha
    903  1.2  matt 	lwzu	%r6,_C_LABEL(extintr_call)@l(%r5)
    904  1.2  matt 	lwz	%r7,INTRSW_EXTINTR(%r3)
    905  1.2  matt 	sub	%r8,%r7,%r5
    906  1.2  matt 	add	%r0,%r8,%r6
    907  1.2  matt 	stw	%r0,0(%r5)
    908  1.2  matt 	dcbf	0,%r5
    909  1.2  matt 	icbi	0,%r5
    910  1.2  matt 
    911  1.2  matt 	lis	%r5,_C_LABEL(powerpc_intrsw)@ha
    912  1.2  matt 	stw	%r3,_C_LABEL(powerpc_intrsw)@l(%r5)
    913  1.2  matt 
    914  1.2  matt 	blr
    915  1.2  matt 
    916  1.2  matt #ifdef notyet
    917  1.2  matt 	.data
    918  1.2  matt 	.lcomm	ddbstk,4096
    919  1.2  matt 	.text
    920  1.2  matt 
    921  1.2  matt _ENTRY(cpu_Debugger)
    922  1.2  matt 	mflr	%r0
    923  1.2  matt 	stw	%r0, CFRAME_LR(%r1)
    924  1.2  matt 
    925  1.2  matt 	mfmsr	%r3
    926  1.2  matt 	wrteei	0
    927  1.2  matt 	mr	%r4,%r1
    928  1.2  matt 	lis	%r10,ddbstk@ha
    929  1.2  matt 	addi	%r10,%r10,ddbstk@l
    930  1.2  matt 	sub	%r5,%r1,%r10
    931  1.2  matt 	cmplwi	%r5,4096
    932  1.2  matt 	blt	%cr0, 1f
    933  1.2  matt 	addi	%r1,%r10,4096-CALLFRAMELEN
    934  1.2  matt 1:
    935  1.2  matt 	stwu	%r4,-FRAMELEN(%r1)
    936  1.2  matt 	stw	%r4,FRAME_1(%r1)
    937  1.2  matt 	stmw	%r13,FRAME_13(%r1)
    938  1.2  matt 	mr	%r26,%r0
    939  1.2  matt 	mfcr	%r27
    940  1.2  matt 	mfxer	%r28
    941  1.2  matt 	mfctr	%r29
    942  1.2  matt 	mr	%r30,%r0
    943  1.2  matt 	mr	%r31,%r3
    944  1.2  matt 	stmw	%r26,FRAME_LR(%r1)
    945  1.2  matt 	mr	%r31,%r1
    946  1.2  matt 	mr	%r1,%r10
    947  1.2  matt 	addi	%r4,%r1,FRAME_TF
    948  1.2  matt 	li	%r3,EXC_PGM
    949  1.2  matt 	stw	%r3,FRAME_EXC(%r1)
    950  1.2  matt 	li	%r3,T_PROGRAM
    951  1.2  matt 	bl	_C_LABEL(trap)
    952  1.2  matt 	lmw	%r26,FRAME_LR(%r1)
    953  1.2  matt 	mtlr	%r26
    954  1.2  matt 	mtcr	%r27
    955  1.2  matt 	mtxer	%r28
    956  1.2  matt 	mtctr	%r29
    957  1.2  matt 	mr	%r0,%r31
    958  1.2  matt 	lmw	%r13,FRAME_13(%r1)
    959  1.2  matt 	lwz	%r1,FRAME_1(%r1)
    960  1.2  matt 	wrtee	%r0
    961  1.2  matt 	blr
    962  1.2  matt #endif /* notyet */
    963