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