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