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