195719Sbenno/* $FreeBSD$ */
295719Sbenno/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $	*/
395719Sbenno
4139825Simp/*-
595719Sbenno * Copyright (C) 1995, 1996 Wolfgang Solfrank.
695719Sbenno * Copyright (C) 1995, 1996 TooLs GmbH.
795719Sbenno * All rights reserved.
895719Sbenno *
995719Sbenno * Redistribution and use in source and binary forms, with or without
1095719Sbenno * modification, are permitted provided that the following conditions
1195719Sbenno * are met:
1295719Sbenno * 1. Redistributions of source code must retain the above copyright
1395719Sbenno *    notice, this list of conditions and the following disclaimer.
1495719Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1595719Sbenno *    notice, this list of conditions and the following disclaimer in the
1695719Sbenno *    documentation and/or other materials provided with the distribution.
1795719Sbenno * 3. All advertising materials mentioning features or use of this software
1895719Sbenno *    must display the following acknowledgement:
1995719Sbenno *	This product includes software developed by TooLs GmbH.
2095719Sbenno * 4. The name of TooLs GmbH may not be used to endorse or promote products
2195719Sbenno *    derived from this software without specific prior written permission.
2295719Sbenno *
2395719Sbenno * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2495719Sbenno * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2595719Sbenno * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2695719Sbenno * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2795719Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2895719Sbenno * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2995719Sbenno * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3095719Sbenno * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3195719Sbenno * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3295719Sbenno * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3395719Sbenno */
3495719Sbenno
3595719Sbenno/*
3695719Sbenno * NOTICE: This is not a standalone file.  to use it, #include it in
3795719Sbenno * your port's locore.S, like so:
3895719Sbenno *
39174599Smarcel *	#include <powerpc/aim/trap_subr.S>
4095719Sbenno */
4195719Sbenno
42293641Snwhitehorn/* Locate the per-CPU data structure */
43293641Snwhitehorn#define GET_CPUINFO(r)  \
44293641Snwhitehorn        mfsprg0  r
45293641Snwhitehorn#define GET_TOCBASE(r)  \
46293641Snwhitehorn	li	r,TRAP_TOCBASE;	/* Magic address for TOC */ \
47293641Snwhitehorn	ld	r,0(r)
4895719Sbenno
4995719Sbenno/*
50209975Snwhitehorn * Restore SRs for a pmap
51209975Snwhitehorn *
52209975Snwhitehorn * Requires that r28-r31 be scratch, with r28 initialized to the SLB cache
53209975Snwhitehorn */
54209975Snwhitehorn
55212722Snwhitehorn/*
56212722Snwhitehorn * User SRs are loaded through a pointer to the current pmap.
57212722Snwhitehorn */
58212722Snwhitehornrestore_usersrs:
59222620Snwhitehorn	GET_CPUINFO(%r28)
60222620Snwhitehorn	ld	%r28,PC_USERSLB(%r28)
61209975Snwhitehorn	li	%r29, 0			/* Set the counter to zero */
62209975Snwhitehorn
63209975Snwhitehorn	slbia
64209975Snwhitehorn	slbmfee	%r31,%r29
65209975Snwhitehorn	clrrdi	%r31,%r31,28
66209975Snwhitehorn	slbie	%r31
67222620Snwhitehorn1:	ld	%r31, 0(%r28)		/* Load SLB entry pointer */
68279751Snwhitehorn	cmpdi	%r31, 0			/* If NULL, stop */
69222620Snwhitehorn	beqlr
70209975Snwhitehorn
71212722Snwhitehorn	ld	%r30, 0(%r31)		/* Load SLBV */
72212722Snwhitehorn	ld	%r31, 8(%r31)		/* Load SLBE */
73212722Snwhitehorn	or	%r31, %r31, %r29	/*  Set SLBE slot */
74222620Snwhitehorn	slbmte	%r30, %r31		/* Install SLB entry */
75209975Snwhitehorn
76222620Snwhitehorn	addi	%r28, %r28, 8		/* Advance pointer */
77222620Snwhitehorn	addi	%r29, %r29, 1
78222620Snwhitehorn	b	1b			/* Repeat */
79209975Snwhitehorn
80209975Snwhitehorn/*
81212722Snwhitehorn * Kernel SRs are loaded directly from the PCPU fields
8295719Sbenno */
83212722Snwhitehornrestore_kernsrs:
84222620Snwhitehorn	GET_CPUINFO(%r28)
85222620Snwhitehorn	addi	%r28,%r28,PC_KERNSLB
86212722Snwhitehorn	li	%r29, 0			/* Set the counter to zero */
8795719Sbenno
88212722Snwhitehorn	slbia
89212722Snwhitehorn	slbmfee	%r31,%r29
90212722Snwhitehorn	clrrdi	%r31,%r31,28
91212722Snwhitehorn	slbie	%r31
92279751Snwhitehorn1:	cmpdi	%r29, USER_SLB_SLOT	/* Skip the user slot */
93222620Snwhitehorn	beq-	2f
9495719Sbenno
95222620Snwhitehorn	ld	%r31, 8(%r28)		/* Load SLBE */
96279751Snwhitehorn	cmpdi	%r31, 0			/* If SLBE is not valid, stop */
97222620Snwhitehorn	beqlr
98212722Snwhitehorn	ld	%r30, 0(%r28)		/* Load SLBV  */
99222620Snwhitehorn	slbmte	%r30, %r31		/* Install SLB entry */
100212722Snwhitehorn
101222620Snwhitehorn2:	addi	%r28, %r28, 16		/* Advance pointer */
102222620Snwhitehorn	addi	%r29, %r29, 1
103279751Snwhitehorn	cmpdi	%r29, 64		/* Repeat if we are not at the end */
104222620Snwhitehorn	blt	1b
105222620Snwhitehorn	blr
106212722Snwhitehorn
107125441Sgrehan/*
108125441Sgrehan * FRAME_SETUP assumes:
109125441Sgrehan *	SPRG1		SP (1)
110188860Snwhitehorn * 	SPRG3		trap type
111209975Snwhitehorn *	savearea	r27-r31,DAR,DSISR   (DAR & DSISR only for DSI traps)
112125441Sgrehan *	r28		LR
113125441Sgrehan *	r29		CR
114125441Sgrehan *	r30		scratch
115125441Sgrehan *	r31		scratch
116125441Sgrehan *	r1		kernel stack
117125441Sgrehan *	SRR0/1		as at start of trap
118230123Snwhitehorn *
119230123Snwhitehorn * NOTE: SPRG1 is never used while the MMU is on, making it safe to reuse
120230123Snwhitehorn * in any real-mode fault handler, including those handling double faults.
121125441Sgrehan */
122125441Sgrehan#define	FRAME_SETUP(savearea)						\
123125441Sgrehan/* Have to enable translation to allow access of kernel stack: */	\
124125441Sgrehan	GET_CPUINFO(%r31);						\
125125441Sgrehan	mfsrr0	%r30;							\
126209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_SRR0)(%r31);	/* save SRR0 */	\
127125441Sgrehan	mfsrr1	%r30;							\
128209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_SRR1)(%r31);	/* save SRR1 */	\
129230123Snwhitehorn	mfsprg1	%r31;			/* get saved SP (clears SPRG1) */ \
130125441Sgrehan	mfmsr	%r30;							\
131125441Sgrehan	ori	%r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */	\
132125441Sgrehan	mtmsr	%r30;			/* stack can now be accessed */	\
133125441Sgrehan	isync;								\
134209975Snwhitehorn	stdu	%r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \
135209975Snwhitehorn	std	%r0, FRAME_0+48(%r1);	/* save r0 in the trapframe */	\
136209975Snwhitehorn	std	%r31,FRAME_1+48(%r1);	/* save SP   "      "       */	\
137209975Snwhitehorn	std	%r2, FRAME_2+48(%r1);	/* save r2   "      "       */	\
138209975Snwhitehorn	std	%r28,FRAME_LR+48(%r1);	/* save LR   "      "       */	\
139209975Snwhitehorn	std	%r29,FRAME_CR+48(%r1);	/* save CR   "      "       */	\
140125441Sgrehan	GET_CPUINFO(%r2);						\
141209975Snwhitehorn	ld	%r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */	\
142209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */	\
143209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */	\
144209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
145209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
146209975Snwhitehorn	std	%r3,  FRAME_3+48(%r1);	/* save r3-r31 */		\
147209975Snwhitehorn	std	%r4,  FRAME_4+48(%r1);					\
148209975Snwhitehorn	std	%r5,  FRAME_5+48(%r1);					\
149209975Snwhitehorn	std	%r6,  FRAME_6+48(%r1);					\
150209975Snwhitehorn	std	%r7,  FRAME_7+48(%r1);					\
151209975Snwhitehorn	std	%r8,  FRAME_8+48(%r1);					\
152209975Snwhitehorn	std	%r9,  FRAME_9+48(%r1);					\
153209975Snwhitehorn	std	%r10, FRAME_10+48(%r1);					\
154209975Snwhitehorn	std	%r11, FRAME_11+48(%r1);					\
155209975Snwhitehorn	std	%r12, FRAME_12+48(%r1);					\
156209975Snwhitehorn	std	%r13, FRAME_13+48(%r1);					\
157209975Snwhitehorn	std	%r14, FRAME_14+48(%r1);					\
158209975Snwhitehorn	std	%r15, FRAME_15+48(%r1);					\
159209975Snwhitehorn	std	%r16, FRAME_16+48(%r1);					\
160209975Snwhitehorn	std	%r17, FRAME_17+48(%r1);					\
161209975Snwhitehorn	std	%r18, FRAME_18+48(%r1);					\
162209975Snwhitehorn	std	%r19, FRAME_19+48(%r1);					\
163209975Snwhitehorn	std	%r20, FRAME_20+48(%r1);					\
164209975Snwhitehorn	std	%r21, FRAME_21+48(%r1);					\
165209975Snwhitehorn	std	%r22, FRAME_22+48(%r1);					\
166209975Snwhitehorn	std	%r23, FRAME_23+48(%r1);					\
167209975Snwhitehorn	std	%r24, FRAME_24+48(%r1);					\
168209975Snwhitehorn	std	%r25, FRAME_25+48(%r1);					\
169209975Snwhitehorn	std	%r26, FRAME_26+48(%r1);					\
170209975Snwhitehorn	std	%r27, FRAME_27+48(%r1);					\
171209975Snwhitehorn	std	%r28, FRAME_28+48(%r1);					\
172209975Snwhitehorn	std	%r29, FRAME_29+48(%r1);					\
173209975Snwhitehorn	std	%r30, FRAME_30+48(%r1);					\
174209975Snwhitehorn	std	%r31, FRAME_31+48(%r1);					\
175209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_AIM_DAR)(%r2);  /* saved DAR */	\
176209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
177209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */	\
178209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */	\
179125441Sgrehan	mfxer	%r3;							\
180125441Sgrehan	mfctr	%r4;							\
181188860Snwhitehorn	mfsprg3	%r5;							\
182209975Snwhitehorn	std	%r3, FRAME_XER+48(1);	/* save xer/ctr/exc */		\
183209975Snwhitehorn	std	%r4, FRAME_CTR+48(1);					\
184209975Snwhitehorn	std	%r5, FRAME_EXC+48(1);					\
185209975Snwhitehorn	std	%r28,FRAME_AIM_DAR+48(1);				\
186209975Snwhitehorn	std	%r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */	\
187209975Snwhitehorn	std	%r30,FRAME_SRR0+48(1);					\
188223485Snwhitehorn	std	%r31,FRAME_SRR1+48(1);					\
189223485Snwhitehorn	ld	%r13,PC_CURTHREAD(%r2)	/* set kernel curthread */
19095719Sbenno
191125441Sgrehan#define	FRAME_LEAVE(savearea)						\
192223485Snwhitehorn/* Disable exceptions: */						\
193223485Snwhitehorn	mfmsr	%r2;							\
194223485Snwhitehorn	andi.	%r2,%r2,~PSL_EE@l;					\
195223485Snwhitehorn	mtmsr	%r2;							\
196223485Snwhitehorn	isync;								\
197125441Sgrehan/* Now restore regs: */							\
198209975Snwhitehorn	ld	%r2,FRAME_SRR0+48(%r1);					\
199209975Snwhitehorn	ld	%r3,FRAME_SRR1+48(%r1);					\
200209975Snwhitehorn	ld	%r4,FRAME_CTR+48(%r1);					\
201209975Snwhitehorn	ld	%r5,FRAME_XER+48(%r1);					\
202209975Snwhitehorn	ld	%r6,FRAME_LR+48(%r1);					\
203125441Sgrehan	GET_CPUINFO(%r7);						\
204209975Snwhitehorn	std	%r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */	\
205209975Snwhitehorn	std	%r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */	\
206209975Snwhitehorn	ld	%r7,FRAME_CR+48(%r1);					\
207125441Sgrehan	mtctr	%r4;							\
208125441Sgrehan	mtxer	%r5;							\
209125441Sgrehan	mtlr	%r6;							\
210230123Snwhitehorn	mtsprg2	%r7;			/* save cr */			\
211209975Snwhitehorn	ld	%r31,FRAME_31+48(%r1);   /* restore r0-31 */		\
212209975Snwhitehorn	ld	%r30,FRAME_30+48(%r1);					\
213209975Snwhitehorn	ld	%r29,FRAME_29+48(%r1);					\
214209975Snwhitehorn	ld	%r28,FRAME_28+48(%r1);					\
215209975Snwhitehorn	ld	%r27,FRAME_27+48(%r1);					\
216209975Snwhitehorn	ld	%r26,FRAME_26+48(%r1);					\
217209975Snwhitehorn	ld	%r25,FRAME_25+48(%r1);					\
218209975Snwhitehorn	ld	%r24,FRAME_24+48(%r1);					\
219209975Snwhitehorn	ld	%r23,FRAME_23+48(%r1);					\
220209975Snwhitehorn	ld	%r22,FRAME_22+48(%r1);					\
221209975Snwhitehorn	ld	%r21,FRAME_21+48(%r1);					\
222209975Snwhitehorn	ld	%r20,FRAME_20+48(%r1);					\
223209975Snwhitehorn	ld	%r19,FRAME_19+48(%r1);					\
224209975Snwhitehorn	ld	%r18,FRAME_18+48(%r1);					\
225209975Snwhitehorn	ld	%r17,FRAME_17+48(%r1);					\
226209975Snwhitehorn	ld	%r16,FRAME_16+48(%r1);					\
227209975Snwhitehorn	ld	%r15,FRAME_15+48(%r1);					\
228209975Snwhitehorn	ld	%r14,FRAME_14+48(%r1);					\
229209975Snwhitehorn	ld	%r13,FRAME_13+48(%r1);					\
230209975Snwhitehorn	ld	%r12,FRAME_12+48(%r1);					\
231209975Snwhitehorn	ld	%r11,FRAME_11+48(%r1);					\
232209975Snwhitehorn	ld	%r10,FRAME_10+48(%r1);					\
233209975Snwhitehorn	ld	%r9, FRAME_9+48(%r1);					\
234209975Snwhitehorn	ld	%r8, FRAME_8+48(%r1);					\
235209975Snwhitehorn	ld	%r7, FRAME_7+48(%r1);					\
236209975Snwhitehorn	ld	%r6, FRAME_6+48(%r1);					\
237209975Snwhitehorn	ld	%r5, FRAME_5+48(%r1);					\
238209975Snwhitehorn	ld	%r4, FRAME_4+48(%r1);					\
239209975Snwhitehorn	ld	%r3, FRAME_3+48(%r1);					\
240209975Snwhitehorn	ld	%r2, FRAME_2+48(%r1);					\
241209975Snwhitehorn	ld	%r0, FRAME_0+48(%r1);					\
242209975Snwhitehorn	ld	%r1, FRAME_1+48(%r1);					\
243125441Sgrehan/* Can't touch %r1 from here on */					\
244230123Snwhitehorn	mtsprg3	%r3;			/* save r3 */			\
245125441Sgrehan/* Disable translation, machine check and recoverability: */		\
246230123Snwhitehorn	mfmsr	%r3;							\
247230123Snwhitehorn	andi.	%r3,%r3,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;		\
248230123Snwhitehorn	mtmsr	%r3;							\
249125441Sgrehan	isync;								\
250125441Sgrehan/* Decide whether we return to user mode: */				\
251230123Snwhitehorn	GET_CPUINFO(%r3);						\
252230123Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR1)(%r3);			\
253125441Sgrehan	mtcr	%r3;							\
254125441Sgrehan	bf	17,1f;			/* branch if PSL_PR is false */	\
255125441Sgrehan/* Restore user SRs */							\
256209975Snwhitehorn	GET_CPUINFO(%r3);						\
257209975Snwhitehorn	std	%r27,(savearea+CPUSAVE_R27)(%r3);			\
258209975Snwhitehorn	std	%r28,(savearea+CPUSAVE_R28)(%r3);			\
259209975Snwhitehorn	std	%r29,(savearea+CPUSAVE_R29)(%r3);			\
260209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_R30)(%r3);			\
261209975Snwhitehorn	std	%r31,(savearea+CPUSAVE_R31)(%r3);			\
262209975Snwhitehorn	mflr	%r27;			/* preserve LR */		\
263212722Snwhitehorn	bl	restore_usersrs;	/* uses r28-r31 */		\
264209975Snwhitehorn	mtlr	%r27;							\
265209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_R31)(%r3);			\
266209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_R30)(%r3);			\
267209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_R29)(%r3);			\
268209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_R28)(%r3);			\
269209975Snwhitehorn	ld	%r27,(savearea+CPUSAVE_R27)(%r3);			\
270230123Snwhitehorn1:	mfsprg2	%r3;			/* restore cr */		\
271230123Snwhitehorn	mtcr	%r3;							\
272230123Snwhitehorn	GET_CPUINFO(%r3);						\
273230123Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR0)(%r3); /* restore srr0 */	\
274125441Sgrehan	mtsrr0	%r3;							\
275230123Snwhitehorn	GET_CPUINFO(%r3);						\
276230123Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR1)(%r3); /* restore srr1 */	\
277125441Sgrehan	mtsrr1	%r3;							\
278230123Snwhitehorn	mfsprg3	%r3			/* restore r3 */
27995719Sbenno
280242723Sjhibbits#ifdef KDTRACE_HOOKS
281242723Sjhibbits	.data
282242723Sjhibbits	.globl	dtrace_invop_calltrap_addr
283242723Sjhibbits	.align	8
284242723Sjhibbits	.type	dtrace_invop_calltrap_addr, @object
285242723Sjhibbits        .size	dtrace_invop_calltrap_addr, 8
286242723Sjhibbitsdtrace_invop_calltrap_addr:
287242723Sjhibbits	.word	0
288242723Sjhibbits	.word	0
289242723Sjhibbits
290242723Sjhibbits	.text
291242723Sjhibbits#endif
292242723Sjhibbits
29395719Sbenno/*
294178628Smarcel * Processor reset exception handler. These are typically
295178628Smarcel * the first instructions the processor executes after a
296198400Snwhitehorn * software reset. We do this in two bits so that we are
297198400Snwhitehorn * not still hanging around in the trap handling region
298198400Snwhitehorn * once the MMU is turned on.
299132571Sgrehan */
300277561Snwhitehorn	.globl	CNAME(rstcode), CNAME(rstcodeend)
301178628SmarcelCNAME(rstcode):
302209975Snwhitehorn	/* Explicitly set MSR[SF] */
303209975Snwhitehorn	mfmsr	%r9
304209975Snwhitehorn	li	%r8,1
305209975Snwhitehorn	insrdi	%r9,%r8,1,0
306209975Snwhitehorn	mtmsrd	%r9
307209975Snwhitehorn	isync
308277498Snwhitehorn	bl	1f
309277498Snwhitehorn	.llong	cpu_reset
310277498Snwhitehorn1:	mflr	%r9
311277498Snwhitehorn	ld	%r9,0(%r9)
312277498Snwhitehorn	mtlr	%r9
313209975Snwhitehorn
314277498Snwhitehorn	blr
315277561SnwhitehornCNAME(rstcodeend):
316198400Snwhitehorn
317198400Snwhitehorncpu_reset:
318277335Snwhitehorn	GET_TOCBASE(%r2)
319178628Smarcel
320277335Snwhitehorn	ld	%r1,TOC_REF(tmpstk)(%r2)	/* get new SP */
321277335Snwhitehorn	addi	%r1,%r1,(TMPSTKSZ-48)
322277335Snwhitehorn
323218824Snwhitehorn	bl	CNAME(cpudep_ap_early_bootstrap) /* Set PCPU */
324209975Snwhitehorn	nop
325227386Snwhitehorn	lis	%r3,1@l
326218824Snwhitehorn	bl	CNAME(pmap_cpu_bootstrap)	/* Turn on virtual memory */
327209975Snwhitehorn	nop
328218824Snwhitehorn	bl	CNAME(cpudep_ap_bootstrap)	/* Set up PCPU and stack */
329209975Snwhitehorn	nop
330209975Snwhitehorn	mr	%r1,%r3				/* Use new stack */
331261309Sjhibbits	bl	CNAME(cpudep_ap_setup)
332261309Sjhibbits	nop
333261309Sjhibbits	GET_CPUINFO(%r5)
334261309Sjhibbits	ld	%r3,(PC_RESTORE)(%r5)
335261309Sjhibbits	cmpldi	%cr0,%r3,0
336261309Sjhibbits	beq	%cr0,2f
337261309Sjhibbits	nop
338261309Sjhibbits	li	%r4,1
339261309Sjhibbits	b	CNAME(longjmp)
340261309Sjhibbits	nop
341261309Sjhibbits2:
342261309Sjhibbits#ifdef SMP
343218824Snwhitehorn	bl	CNAME(machdep_ap_bootstrap)	/* And away! */
344209975Snwhitehorn	nop
345261309Sjhibbits#endif
346178628Smarcel
347178628Smarcel	/* Should not be reached */
348178628Smarcel9:
349178628Smarcel	b	9b
350132571Sgrehan
351132571Sgrehan/*
35295719Sbenno * This code gets copied to all the trap vectors
353277498Snwhitehorn * (except ISI/DSI, ALI, and the interrupts). Has to fit in 8 instructions!
35495719Sbenno */
355178628Smarcel
356277561Snwhitehorn	.globl	CNAME(trapcode),CNAME(trapcodeend)
357277498Snwhitehorn	.p2align 3
35896773SbennoCNAME(trapcode):
359125441Sgrehan	mtsprg1	%r1			/* save SP */
360188860Snwhitehorn	mflr	%r1			/* Save the old LR in r1 */
361188860Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
362279751Snwhitehorn	ld	%r1,TRAP_GENTRAP(0)
363277498Snwhitehorn	mtlr	%r1
364279189Snwhitehorn	li	%r1, 0xe0		/* How to get the vector from LR */
365277498Snwhitehorn	blrl				/* Branch to generictrap */
366277561SnwhitehornCNAME(trapcodeend):
36795719Sbenno
36895719Sbenno/*
369230123Snwhitehorn * For SLB misses: do special things for the kernel
370230123Snwhitehorn *
371230123Snwhitehorn * Note: SPRG1 is always safe to overwrite any time the MMU is on, which is
372230123Snwhitehorn * the only time this can be called.
373230123Snwhitehorn */
374277561Snwhitehorn	.globl	CNAME(slbtrap),CNAME(slbtrapend)
375277498Snwhitehorn	.p2align 3
376230123SnwhitehornCNAME(slbtrap):
377230123Snwhitehorn	mtsprg1	%r1			/* save SP */
378230123Snwhitehorn	GET_CPUINFO(%r1)
379230123Snwhitehorn	std	%r2,(PC_SLBSAVE+16)(%r1)
380230123Snwhitehorn	mfcr	%r2			/* save CR */
381230123Snwhitehorn	std	%r2,(PC_SLBSAVE+104)(%r1)
382230123Snwhitehorn	mfsrr1	%r2			/* test kernel mode */
383230123Snwhitehorn	mtcr	%r2
384277498Snwhitehorn	bf	17,2f			/* branch if PSL_PR is false */
385230123Snwhitehorn	/* User mode */
386230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */
387230123Snwhitehorn	mtcr	%r2
388230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+16)(%r1) /* Restore R2 */
389230123Snwhitehorn	mflr	%r1			/* Save the old LR in r1 */
390230123Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
391277498Snwhitehorn					/* 52 bytes so far */
392277498Snwhitehorn	bl	1f
393277498Snwhitehorn	.llong	generictrap
394277498Snwhitehorn1:	mflr	%r1
395277498Snwhitehorn	ld	%r1,0(%r1)
396277498Snwhitehorn	mtlr	%r1
397230123Snwhitehorn	li	%r1, 0x80		/* How to get the vector from LR */
398277498Snwhitehorn	blrl				/* Branch to generictrap */
399277498Snwhitehorn					/* 84 bytes */
400277498Snwhitehorn2:	mflr	%r2			/* Save the old LR in r2 */
401277498Snwhitehorn	nop
402277498Snwhitehorn	bl	3f			/* Begin dance to jump to kern_slbtrap*/
403277498Snwhitehorn	.llong	kern_slbtrap
404277498Snwhitehorn3:	mflr	%r1
405277498Snwhitehorn	ld	%r1,0(%r1)
406277498Snwhitehorn	mtlr	%r1
407277498Snwhitehorn	GET_CPUINFO(%r1)
408277498Snwhitehorn	blrl				/* 124 bytes -- 4 to spare */
409277561SnwhitehornCNAME(slbtrapend):
410230123Snwhitehorn
411230123Snwhitehornkern_slbtrap:
412230123Snwhitehorn	std	%r2,(PC_SLBSAVE+136)(%r1) /* old LR */
413230123Snwhitehorn	std	%r3,(PC_SLBSAVE+24)(%r1) /* save R3 */
414230123Snwhitehorn
415230123Snwhitehorn	/* Check if this needs to be handled as a regular trap (userseg miss) */
416230123Snwhitehorn	mflr	%r2
417230123Snwhitehorn	andi.	%r2,%r2,0xff80
418230123Snwhitehorn	cmpwi	%r2,0x380
419230123Snwhitehorn	bne	1f
420230123Snwhitehorn	mfdar	%r2
421230123Snwhitehorn	b	2f
422230123Snwhitehorn1:	mfsrr0	%r2
423230123Snwhitehorn2:	/* r2 now contains the fault address */
424230123Snwhitehorn	lis	%r3,SEGMENT_MASK@highesta
425230123Snwhitehorn	ori	%r3,%r3,SEGMENT_MASK@highera
426230123Snwhitehorn	sldi	%r3,%r3,32
427230123Snwhitehorn	oris	%r3,%r3,SEGMENT_MASK@ha
428230123Snwhitehorn	ori	%r3,%r3,SEGMENT_MASK@l
429230123Snwhitehorn	and	%r2,%r2,%r3	/* R2 = segment base address */
430230123Snwhitehorn	lis	%r3,USER_ADDR@highesta
431230123Snwhitehorn	ori	%r3,%r3,USER_ADDR@highera
432230123Snwhitehorn	sldi	%r3,%r3,32
433230123Snwhitehorn	oris	%r3,%r3,USER_ADDR@ha
434230123Snwhitehorn	ori	%r3,%r3,USER_ADDR@l
435230123Snwhitehorn	cmpd	%r2,%r3		/* Compare fault base to USER_ADDR */
436230123Snwhitehorn	bne	3f
437230123Snwhitehorn
438230123Snwhitehorn	/* User seg miss, handle as a regular trap */
439230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */
440230123Snwhitehorn	mtcr	%r2
441230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+16)(%r1) /* Restore R2,R3 */
442230123Snwhitehorn	ld	%r3,(PC_SLBSAVE+24)(%r1)
443230123Snwhitehorn	ld	%r1,(PC_SLBSAVE+136)(%r1) /* Save the old LR in r1 */
444230123Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
445230123Snwhitehorn	li	%r1, 0x80		/* How to get the vector from LR */
446230123Snwhitehorn	b	generictrap		/* Retain old LR using b */
447230123Snwhitehorn
448230123Snwhitehorn3:	/* Real kernel SLB miss */
449230123Snwhitehorn	std	%r0,(PC_SLBSAVE+0)(%r1)	/* free all volatile regs */
450230123Snwhitehorn	mfsprg1	%r2			/* Old R1 */
451230123Snwhitehorn	std	%r2,(PC_SLBSAVE+8)(%r1)
452230123Snwhitehorn	/* R2,R3 already saved */
453230123Snwhitehorn	std	%r4,(PC_SLBSAVE+32)(%r1)
454230123Snwhitehorn	std	%r5,(PC_SLBSAVE+40)(%r1)
455230123Snwhitehorn	std	%r6,(PC_SLBSAVE+48)(%r1)
456230123Snwhitehorn	std	%r7,(PC_SLBSAVE+56)(%r1)
457230123Snwhitehorn	std	%r8,(PC_SLBSAVE+64)(%r1)
458230123Snwhitehorn	std	%r9,(PC_SLBSAVE+72)(%r1)
459230123Snwhitehorn	std	%r10,(PC_SLBSAVE+80)(%r1)
460230123Snwhitehorn	std	%r11,(PC_SLBSAVE+88)(%r1)
461230123Snwhitehorn	std	%r12,(PC_SLBSAVE+96)(%r1)
462230123Snwhitehorn	/* CR already saved */
463230123Snwhitehorn	mfxer	%r2			/* save XER */
464230123Snwhitehorn	std	%r2,(PC_SLBSAVE+112)(%r1)
465230123Snwhitehorn	mflr	%r2			/* save LR (SP already saved) */
466230123Snwhitehorn	std	%r2,(PC_SLBSAVE+120)(%r1)
467230123Snwhitehorn	mfctr	%r2			/* save CTR */
468230123Snwhitehorn	std	%r2,(PC_SLBSAVE+128)(%r1)
469230123Snwhitehorn
470230123Snwhitehorn	/* Call handler */
471230123Snwhitehorn	addi	%r1,%r1,PC_SLBSTACK-48+1024
472230123Snwhitehorn	li	%r2,~15
473230123Snwhitehorn	and	%r1,%r1,%r2
474277334Snwhitehorn	GET_TOCBASE(%r2)
475230123Snwhitehorn	mflr	%r3
476230123Snwhitehorn	andi.	%r3,%r3,0xff80
477230123Snwhitehorn	mfdar	%r4
478230123Snwhitehorn	mfsrr0	%r5
479230123Snwhitehorn	bl	handle_kernel_slb_spill
480230123Snwhitehorn	nop
481230123Snwhitehorn
482230123Snwhitehorn	/* Save r28-31, restore r4-r12 */
483230123Snwhitehorn	GET_CPUINFO(%r1)
484230123Snwhitehorn	ld	%r4,(PC_SLBSAVE+32)(%r1)
485230123Snwhitehorn	ld	%r5,(PC_SLBSAVE+40)(%r1)
486230123Snwhitehorn	ld	%r6,(PC_SLBSAVE+48)(%r1)
487230123Snwhitehorn	ld	%r7,(PC_SLBSAVE+56)(%r1)
488230123Snwhitehorn	ld	%r8,(PC_SLBSAVE+64)(%r1)
489230123Snwhitehorn	ld	%r9,(PC_SLBSAVE+72)(%r1)
490230123Snwhitehorn	ld	%r10,(PC_SLBSAVE+80)(%r1)
491230123Snwhitehorn	ld	%r11,(PC_SLBSAVE+88)(%r1)
492230123Snwhitehorn	ld	%r12,(PC_SLBSAVE+96)(%r1)
493230123Snwhitehorn	std	%r28,(PC_SLBSAVE+64)(%r1)
494230123Snwhitehorn	std	%r29,(PC_SLBSAVE+72)(%r1)
495230123Snwhitehorn	std	%r30,(PC_SLBSAVE+80)(%r1)
496230123Snwhitehorn	std	%r31,(PC_SLBSAVE+88)(%r1)
497230123Snwhitehorn
498230123Snwhitehorn	/* Restore kernel mapping */
499230123Snwhitehorn	bl	restore_kernsrs
500230123Snwhitehorn
501230123Snwhitehorn	/* Restore remaining registers */
502230123Snwhitehorn	ld	%r28,(PC_SLBSAVE+64)(%r1)
503230123Snwhitehorn	ld	%r29,(PC_SLBSAVE+72)(%r1)
504230123Snwhitehorn	ld	%r30,(PC_SLBSAVE+80)(%r1)
505230123Snwhitehorn	ld	%r31,(PC_SLBSAVE+88)(%r1)
506230123Snwhitehorn
507230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+104)(%r1)
508230123Snwhitehorn	mtcr	%r2
509230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+112)(%r1)
510230123Snwhitehorn	mtxer	%r2
511230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+120)(%r1)
512230123Snwhitehorn	mtlr	%r2
513230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+128)(%r1)
514230123Snwhitehorn	mtctr	%r2
515230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+136)(%r1)
516230123Snwhitehorn	mtlr	%r2
517230123Snwhitehorn
518230123Snwhitehorn	/* Restore r0-r3 */
519230123Snwhitehorn	ld	%r0,(PC_SLBSAVE+0)(%r1)
520230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+16)(%r1)
521230123Snwhitehorn	ld	%r3,(PC_SLBSAVE+24)(%r1)
522230123Snwhitehorn	mfsprg1	%r1
523230123Snwhitehorn
524230123Snwhitehorn	/* Back to whatever we were doing */
525230123Snwhitehorn	rfid
526230123Snwhitehorn
527230123Snwhitehorn/*
52895719Sbenno * For ALI: has to save DSISR and DAR
52995719Sbenno */
530277561Snwhitehorn	.globl	CNAME(alitrap),CNAME(aliend)
53196773SbennoCNAME(alitrap):
532125441Sgrehan	mtsprg1	%r1			/* save SP */
533125441Sgrehan	GET_CPUINFO(%r1)
534209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
535209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
536209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
537209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
538209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
539125441Sgrehan	mfdar	%r30
540125441Sgrehan	mfdsisr	%r31
541209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
542209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
543125441Sgrehan	mfsprg1	%r1			/* restore SP, in case of branch */
544125441Sgrehan	mflr	%r28			/* save LR */
545125441Sgrehan	mfcr	%r29			/* save CR */
546188860Snwhitehorn
547277498Snwhitehorn	/* Begin dance to branch to s_trap in a bit */
548277498Snwhitehorn	b	1f
549277498Snwhitehorn	.p2align 3
550277498Snwhitehorn1:	nop
551277498Snwhitehorn	bl	1f
552277498Snwhitehorn	.llong	s_trap
553277498Snwhitehorn1:	mflr	%r31
554277498Snwhitehorn	ld	%r31,0(%r31)
555277498Snwhitehorn	mtlr	%r31
556277498Snwhitehorn
557188951Snwhitehorn	/* Put our exception vector in SPRG3 */
558188860Snwhitehorn	li	%r31, EXC_ALI
559188860Snwhitehorn	mtsprg3	%r31
560188860Snwhitehorn
561188860Snwhitehorn	/* Test whether we already had PR set */
562125441Sgrehan	mfsrr1	%r31
563125441Sgrehan	mtcr	%r31
564277498Snwhitehorn	blrl
565277561SnwhitehornCNAME(aliend):
56695719Sbenno
56795719Sbenno/*
56895719Sbenno * Similar to the above for DSI
569277498Snwhitehorn * Has to handle standard pagetable spills
57095719Sbenno */
571277561Snwhitehorn	.globl	CNAME(dsitrap),CNAME(dsiend)
57296773SbennoCNAME(dsitrap):
573125441Sgrehan	mtsprg1	%r1			/* save SP */
574125441Sgrehan	GET_CPUINFO(%r1)
575209975Snwhitehorn	std	%r27,(PC_DISISAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
576209975Snwhitehorn	std	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)
577209975Snwhitehorn	std	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
578209975Snwhitehorn	std	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
579209975Snwhitehorn	std	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
580125441Sgrehan	mfcr	%r29			/* save CR */
581125441Sgrehan	mfxer	%r30			/* save XER */
582125441Sgrehan	mtsprg2	%r30			/* in SPRG2 */
583125441Sgrehan	mfsrr1	%r31			/* test kernel mode */
584125441Sgrehan	mtcr	%r31
585125441Sgrehan	mflr	%r28			/* save LR (SP already saved) */
586277498Snwhitehorn	bl	1f			/* Begin branching to disitrap */
587277498Snwhitehorn	.llong	disitrap
588277498Snwhitehorn1:	mflr	%r1
589277498Snwhitehorn	ld	%r1,0(%r1)
590277498Snwhitehorn	mtlr	%r1
591277498Snwhitehorn	blrl				/* Branch to generictrap */
592277561SnwhitehornCNAME(dsiend):
59395719Sbenno
59495719Sbenno/*
59595719Sbenno * Preamble code for DSI/ISI traps
59695719Sbenno */
59795719Sbennodisitrap:
598188951Snwhitehorn	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
599188860Snwhitehorn	mflr	%r1
600188860Snwhitehorn	andi.	%r1,%r1,0xff00
601188860Snwhitehorn	mtsprg3	%r1
602188860Snwhitehorn
603125441Sgrehan	GET_CPUINFO(%r1)
604209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1)
605209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
606209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
607209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
608209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
609209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
610209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
611209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
612209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
613209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
614125441Sgrehan	mfdar	%r30
615125441Sgrehan	mfdsisr	%r31
616209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
617209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
618125441Sgrehan
619132571Sgrehan#ifdef KDB
620258800Snwhitehorn	/* Try to detect a kernel stack overflow */
621132571Sgrehan	mfsrr1	%r31
622132571Sgrehan	mtcr	%r31
623132571Sgrehan	bt	17,realtrap		/* branch is user mode */
624132571Sgrehan	mfsprg1	%r31			/* get old SP */
625266136Sjhibbits	clrrdi	%r31,%r31,12		/* Round SP down to nearest page */
626132571Sgrehan	sub.	%r30,%r31,%r30		/* SP - DAR */
627132571Sgrehan	bge	1f
628132571Sgrehan	neg	%r30,%r30		/* modulo value */
629209975Snwhitehorn1:	cmpldi	%cr0,%r30,4096		/* is DAR within a page of SP? */
630132571Sgrehan	bge	%cr0,realtrap		/* no, too far away. */
631132571Sgrehan
632132571Sgrehan	/* Now convert this DSI into a DDB trap.  */
633132571Sgrehan	GET_CPUINFO(%r1)
634209975Snwhitehorn	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
635209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
636209975Snwhitehorn	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
637209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
638209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get  r27 */
639209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R27)(%r1) /* save r27 */
640209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get  r28 */
641209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_R28)(%r1) /* save r28 */
642209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get  r29 */
643209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R29)(%r1) /* save r29 */
644209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get  r30 */
645209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_R30)(%r1) /* save r30 */
646209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get  r31 */
647209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R31)(%r1) /* save r31 */
648191039Snwhitehorn	b	dbtrap
649132571Sgrehan#endif
650132571Sgrehan
651125441Sgrehan	/* XXX need stack probe here */
65295719Sbennorealtrap:
65395719Sbenno/* Test whether we already had PR set */
654125441Sgrehan	mfsrr1	%r1
655125441Sgrehan	mtcr	%r1
656125441Sgrehan	mfsprg1	%r1			/* restore SP (might have been
65795719Sbenno					   overwritten) */
658188860Snwhitehorn	bf	17,k_trap		/* branch if PSL_PR is false */
659188860Snwhitehorn	GET_CPUINFO(%r1)
660209975Snwhitehorn	ld	%r1,PC_CURPCB(%r1)
661209975Snwhitehorn	mr	%r27,%r28		/* Save LR, r29 */
662209975Snwhitehorn	mtsprg2	%r29
663212722Snwhitehorn	bl	restore_kernsrs		/* enable kernel mapping */
664209975Snwhitehorn	mfsprg2	%r29
665209975Snwhitehorn	mr	%r28,%r27
666277498Snwhitehorn	b	s_trap
667188860Snwhitehorn
668188860Snwhitehorn/*
669188860Snwhitehorn * generictrap does some standard setup for trap handling to minimize
670188860Snwhitehorn * the code that need be installed in the actual vectors. It expects
671188860Snwhitehorn * the following conditions.
672188860Snwhitehorn *
673188860Snwhitehorn * R1 - Trap vector = LR & (0xff00 | R1)
674188860Snwhitehorn * SPRG1 - Original R1 contents
675188860Snwhitehorn * SPRG2 - Original LR
676188860Snwhitehorn */
677188860Snwhitehorn
678279750Snwhitehorn	.globl	CNAME(generictrap)
679188860Snwhitehorngenerictrap:
680188860Snwhitehorn	/* Save R1 for computing the exception vector */
681188860Snwhitehorn	mtsprg3 %r1
682188860Snwhitehorn
683188860Snwhitehorn	/* Save interesting registers */
684188860Snwhitehorn	GET_CPUINFO(%r1)
685209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
686209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
687209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
688209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
689209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
690209975Snwhitehorn	mfdar	%r30
691209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
692188860Snwhitehorn	mfsprg1	%r1			/* restore SP, in case of branch */
693188860Snwhitehorn	mfsprg2	%r28			/* save LR */
694188860Snwhitehorn	mfcr	%r29			/* save CR */
695188860Snwhitehorn
696188860Snwhitehorn	/* Compute the exception vector from the link register */
697188860Snwhitehorn	mfsprg3 %r31
698188860Snwhitehorn	ori	%r31,%r31,0xff00
699188860Snwhitehorn	mflr	%r30
700277498Snwhitehorn	addi	%r30,%r30,-4 /* The branch instruction, not the next */
701188860Snwhitehorn	and	%r30,%r30,%r31
702188860Snwhitehorn	mtsprg3	%r30
703188860Snwhitehorn
704188860Snwhitehorn	/* Test whether we already had PR set */
705188860Snwhitehorn	mfsrr1	%r31
706188860Snwhitehorn	mtcr	%r31
707188860Snwhitehorn
708125441Sgrehans_trap:
709125441Sgrehan	bf	17,k_trap		/* branch if PSL_PR is false */
710125441Sgrehan	GET_CPUINFO(%r1)
711125441Sgrehanu_trap:
712209975Snwhitehorn	ld	%r1,PC_CURPCB(%r1)
713209975Snwhitehorn	mr	%r27,%r28		/* Save LR, r29 */
714209975Snwhitehorn	mtsprg2	%r29
715212722Snwhitehorn	bl	restore_kernsrs		/* enable kernel mapping */
716209975Snwhitehorn	mfsprg2	%r29
717209975Snwhitehorn	mr	%r28,%r27
71895719Sbenno
71995719Sbenno/*
72095719Sbenno * Now the common trap catching code.
72195719Sbenno */
722125441Sgrehank_trap:
723125441Sgrehan	FRAME_SETUP(PC_TEMPSAVE)
72499032Sbenno/* Call C interrupt dispatcher: */
72595719Sbennotrapagain:
726277334Snwhitehorn	GET_TOCBASE(%r2)
727209975Snwhitehorn	addi	%r3,%r1,48
728218824Snwhitehorn	bl	CNAME(powerpc_interrupt)
729209975Snwhitehorn	nop
730209975Snwhitehorn
731209975Snwhitehorn	.globl	CNAME(trapexit)	/* backtrace code sentinel */
73296773SbennoCNAME(trapexit):
73395719Sbenno/* Disable interrupts: */
734125441Sgrehan	mfmsr	%r3
735125441Sgrehan	andi.	%r3,%r3,~PSL_EE@l
736125441Sgrehan	mtmsr	%r3
737222309Snwhitehorn	isync
73895719Sbenno/* Test AST pending: */
739209975Snwhitehorn	ld	%r5,FRAME_SRR1+48(%r1)
740125441Sgrehan	mtcr	%r5
741125441Sgrehan	bf	17,1f			/* branch if PSL_PR is false */
74299032Sbenno
743125441Sgrehan	GET_CPUINFO(%r3)		/* get per-CPU pointer */
744223485Snwhitehorn	lwz	%r4, TD_FLAGS(%r13)	/* get thread flags value */
745125441Sgrehan	lis	%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
746125441Sgrehan	ori	%r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
747125441Sgrehan	and.	%r4,%r4,%r5
74895719Sbenno	beq	1f
749125441Sgrehan	mfmsr	%r3			/* re-enable interrupts */
750125441Sgrehan	ori	%r3,%r3,PSL_EE@l
751125441Sgrehan	mtmsr	%r3
75299032Sbenno	isync
753277334Snwhitehorn	GET_TOCBASE(%r2)
754209975Snwhitehorn	addi	%r3,%r1,48
755218824Snwhitehorn	bl	CNAME(ast)
756209975Snwhitehorn	nop
757153685Sgrehan	.globl	CNAME(asttrapexit)	/* backtrace code sentinel #2 */
758153685SgrehanCNAME(asttrapexit):
75999032Sbenno	b	trapexit		/* test ast ret value ? */
76095719Sbenno1:
761125441Sgrehan	FRAME_LEAVE(PC_TEMPSAVE)
762190681Snwhitehorn	rfid
763190681Snwhitehorn
764132075Sgrehan#if defined(KDB)
76595719Sbenno/*
766132075Sgrehan * Deliberate entry to dbtrap
76795719Sbenno */
768230400SandreastASENTRY_NOPROF(breakpoint)
769125441Sgrehan	mtsprg1	%r1
770125441Sgrehan	mfmsr	%r3
771125441Sgrehan	mtsrr1	%r3
772125441Sgrehan	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
773125441Sgrehan	mtmsr	%r3			/* disable interrupts */
77495719Sbenno	isync
775125441Sgrehan	GET_CPUINFO(%r3)
776209975Snwhitehorn	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r3)
777209975Snwhitehorn	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
778209975Snwhitehorn	std	%r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
779209975Snwhitehorn	std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
780209975Snwhitehorn	std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
781125441Sgrehan	mflr	%r28
782125441Sgrehan	li	%r29,EXC_BPT
783125441Sgrehan	mtlr	%r29
784125441Sgrehan	mfcr	%r29
785125441Sgrehan	mtsrr0	%r28
78695719Sbenno
78795719Sbenno/*
788132075Sgrehan * Now the kdb trap catching code.
78995719Sbenno */
790132075Sgrehandbtrap:
791188951Snwhitehorn	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
792188860Snwhitehorn	mflr	%r1
793188860Snwhitehorn	andi.	%r1,%r1,0xff00
794188860Snwhitehorn	mtsprg3	%r1
795188860Snwhitehorn
796279751Snwhitehorn	ld	%r1,TRAP_TOCBASE(0)		/* get new SP */
797277335Snwhitehorn	ld	%r1,TOC_REF(tmpstk)(%r1)
798277335Snwhitehorn	addi	%r1,%r1,(TMPSTKSZ-48)
799188860Snwhitehorn
800132075Sgrehan	FRAME_SETUP(PC_DBSAVE)
80195719Sbenno/* Call C trap code: */
802277334Snwhitehorn	GET_TOCBASE(%r2)
803209975Snwhitehorn	addi	%r3,%r1,48
804218824Snwhitehorn	bl	CNAME(db_trap_glue)
805209975Snwhitehorn	nop
806125441Sgrehan	or.	%r3,%r3,%r3
807132075Sgrehan	bne	dbleave
808132075Sgrehan/* This wasn't for KDB, so switch to real trap: */
809209975Snwhitehorn	ld	%r3,FRAME_EXC+48(%r1)	/* save exception */
810125441Sgrehan	GET_CPUINFO(%r4)
811209975Snwhitehorn	std	%r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
812132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
813125441Sgrehan	mtsprg1	%r1			/* prepare for entrance to realtrap */
814125441Sgrehan	GET_CPUINFO(%r1)
815209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
816209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
817209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
818209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
819209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
820125441Sgrehan	mflr	%r28
821125441Sgrehan	mfcr	%r29
822209975Snwhitehorn	ld	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
823190946Snwhitehorn	mtsprg3	%r31			/* SPRG3 was clobbered by FRAME_LEAVE */
824125441Sgrehan	mfsprg1	%r1
82595719Sbenno	b	realtrap
826132075Sgrehandbleave:
827132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
828209975Snwhitehorn	rfid
82995719Sbenno
83095719Sbenno/*
831132075Sgrehan * In case of KDB we want a separate trap catcher for it
83295719Sbenno */
833277561Snwhitehorn	.globl	CNAME(dblow),CNAME(dbend)
834132075SgrehanCNAME(dblow):
835125441Sgrehan	mtsprg1	%r1			/* save SP */
836125441Sgrehan	mtsprg2	%r29			/* save r29 */
837125441Sgrehan	mfcr	%r29			/* save CR in r29 */
838125441Sgrehan	mfsrr1	%r1
839125441Sgrehan	mtcr	%r1
840275268Sjhibbits	bf	17,1f			/* branch if privileged */
841188860Snwhitehorn
842188860Snwhitehorn	/* Unprivileged case */
843188860Snwhitehorn	mtcr	%r29			/* put the condition register back */
844188860Snwhitehorn        mfsprg2	%r29			/* ... and r29 */
845188860Snwhitehorn        mflr	%r1			/* save LR */
846188860Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
847277498Snwhitehorn
848285620Sjhibbits	ld	%r1, TRAP_GENTRAP(0)	/* Get branch address */
849277498Snwhitehorn	mtlr	%r1
850188860Snwhitehorn	li	%r1, 0	 		/* How to get the vector from LR */
851277498Snwhitehorn	blrl				/* Branch to generictrap */
852188860Snwhitehorn
853275268Sjhibbits1:
854188860Snwhitehorn	GET_CPUINFO(%r1)
855209975Snwhitehorn	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r1)	/* free r27 */
856209975Snwhitehorn	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
857125441Sgrehan        mfsprg2	%r28				/* r29 holds cr...  */
858209975Snwhitehorn        std	%r28,(PC_DBSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
859209975Snwhitehorn        std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
860209975Snwhitehorn        std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
861125441Sgrehan        mflr	%r28					/* save LR */
862277498Snwhitehorn	bl	9f					/* Begin branch */
863277498Snwhitehorn	.llong	dbtrap
864277498Snwhitehorn9:	mflr	%r1
865277498Snwhitehorn	ld	%r1,0(%r1)
866277498Snwhitehorn	mtlr	%r1
867277498Snwhitehorn	blrl				/* Branch to generictrap */
868277561SnwhitehornCNAME(dbend):
869132075Sgrehan#endif /* KDB */
870