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
4295719Sbenno/*
43125441Sgrehan * Save/restore segment registers
4495719Sbenno */
4595719Sbenno
4695719Sbenno/*
47209975Snwhitehorn * Restore SRs for a pmap
48209975Snwhitehorn *
49209975Snwhitehorn * Requires that r28-r31 be scratch, with r28 initialized to the SLB cache
50209975Snwhitehorn */
51209975Snwhitehorn
52212722Snwhitehorn/*
53212722Snwhitehorn * User SRs are loaded through a pointer to the current pmap.
54212722Snwhitehorn */
55212722Snwhitehornrestore_usersrs:
56222620Snwhitehorn	GET_CPUINFO(%r28)
57222620Snwhitehorn	ld	%r28,PC_USERSLB(%r28)
58209975Snwhitehorn	li	%r29, 0			/* Set the counter to zero */
59209975Snwhitehorn
60209975Snwhitehorn	slbia
61209975Snwhitehorn	slbmfee	%r31,%r29
62209975Snwhitehorn	clrrdi	%r31,%r31,28
63209975Snwhitehorn	slbie	%r31
64222620Snwhitehorn1:	ld	%r31, 0(%r28)		/* Load SLB entry pointer */
65222620Snwhitehorn	cmpli	0, %r31, 0		/* If NULL, stop */
66222620Snwhitehorn	beqlr
67209975Snwhitehorn
68212722Snwhitehorn	ld	%r30, 0(%r31)		/* Load SLBV */
69212722Snwhitehorn	ld	%r31, 8(%r31)		/* Load SLBE */
70212722Snwhitehorn	or	%r31, %r31, %r29	/*  Set SLBE slot */
71222620Snwhitehorn	slbmte	%r30, %r31		/* Install SLB entry */
72209975Snwhitehorn
73222620Snwhitehorn	addi	%r28, %r28, 8		/* Advance pointer */
74222620Snwhitehorn	addi	%r29, %r29, 1
75222620Snwhitehorn	b	1b			/* Repeat */
76209975Snwhitehorn
77209975Snwhitehorn/*
78212722Snwhitehorn * Kernel SRs are loaded directly from the PCPU fields
7995719Sbenno */
80212722Snwhitehornrestore_kernsrs:
81222620Snwhitehorn	GET_CPUINFO(%r28)
82222620Snwhitehorn	addi	%r28,%r28,PC_KERNSLB
83212722Snwhitehorn	li	%r29, 0			/* Set the counter to zero */
8495719Sbenno
85212722Snwhitehorn	slbia
86212722Snwhitehorn	slbmfee	%r31,%r29
87212722Snwhitehorn	clrrdi	%r31,%r31,28
88212722Snwhitehorn	slbie	%r31
89222620Snwhitehorn1:	cmpli	0, %r29, USER_SLB_SLOT	/* Skip the user slot */
90222620Snwhitehorn	beq-	2f
9195719Sbenno
92222620Snwhitehorn	ld	%r31, 8(%r28)		/* Load SLBE */
93222620Snwhitehorn	cmpli	0, %r31, 0		/* If SLBE is not valid, stop */
94222620Snwhitehorn	beqlr
95212722Snwhitehorn	ld	%r30, 0(%r28)		/* Load SLBV  */
96222620Snwhitehorn	slbmte	%r30, %r31		/* Install SLB entry */
97212722Snwhitehorn
98222620Snwhitehorn2:	addi	%r28, %r28, 16		/* Advance pointer */
99222620Snwhitehorn	addi	%r29, %r29, 1
100222620Snwhitehorn	cmpli	0, %r29, 64		/* Repeat if we are not at the end */
101222620Snwhitehorn	blt	1b
102222620Snwhitehorn	blr
103212722Snwhitehorn
104125441Sgrehan/*
105125441Sgrehan * FRAME_SETUP assumes:
106125441Sgrehan *	SPRG1		SP (1)
107188860Snwhitehorn * 	SPRG3		trap type
108209975Snwhitehorn *	savearea	r27-r31,DAR,DSISR   (DAR & DSISR only for DSI traps)
109125441Sgrehan *	r28		LR
110125441Sgrehan *	r29		CR
111125441Sgrehan *	r30		scratch
112125441Sgrehan *	r31		scratch
113125441Sgrehan *	r1		kernel stack
114125441Sgrehan *	SRR0/1		as at start of trap
115230123Snwhitehorn *
116230123Snwhitehorn * NOTE: SPRG1 is never used while the MMU is on, making it safe to reuse
117230123Snwhitehorn * in any real-mode fault handler, including those handling double faults.
118125441Sgrehan */
119125441Sgrehan#define	FRAME_SETUP(savearea)						\
120125441Sgrehan/* Have to enable translation to allow access of kernel stack: */	\
121125441Sgrehan	GET_CPUINFO(%r31);						\
122125441Sgrehan	mfsrr0	%r30;							\
123209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_SRR0)(%r31);	/* save SRR0 */	\
124125441Sgrehan	mfsrr1	%r30;							\
125209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_SRR1)(%r31);	/* save SRR1 */	\
126230123Snwhitehorn	mfsprg1	%r31;			/* get saved SP (clears SPRG1) */ \
127125441Sgrehan	mfmsr	%r30;							\
128125441Sgrehan	ori	%r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */	\
129125441Sgrehan	mtmsr	%r30;			/* stack can now be accessed */	\
130125441Sgrehan	isync;								\
131209975Snwhitehorn	stdu	%r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \
132209975Snwhitehorn	std	%r0, FRAME_0+48(%r1);	/* save r0 in the trapframe */	\
133209975Snwhitehorn	std	%r31,FRAME_1+48(%r1);	/* save SP   "      "       */	\
134209975Snwhitehorn	std	%r2, FRAME_2+48(%r1);	/* save r2   "      "       */	\
135209975Snwhitehorn	std	%r28,FRAME_LR+48(%r1);	/* save LR   "      "       */	\
136209975Snwhitehorn	std	%r29,FRAME_CR+48(%r1);	/* save CR   "      "       */	\
137125441Sgrehan	GET_CPUINFO(%r2);						\
138209975Snwhitehorn	ld	%r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */	\
139209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */	\
140209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */	\
141209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
142209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
143209975Snwhitehorn	std	%r3,  FRAME_3+48(%r1);	/* save r3-r31 */		\
144209975Snwhitehorn	std	%r4,  FRAME_4+48(%r1);					\
145209975Snwhitehorn	std	%r5,  FRAME_5+48(%r1);					\
146209975Snwhitehorn	std	%r6,  FRAME_6+48(%r1);					\
147209975Snwhitehorn	std	%r7,  FRAME_7+48(%r1);					\
148209975Snwhitehorn	std	%r8,  FRAME_8+48(%r1);					\
149209975Snwhitehorn	std	%r9,  FRAME_9+48(%r1);					\
150209975Snwhitehorn	std	%r10, FRAME_10+48(%r1);					\
151209975Snwhitehorn	std	%r11, FRAME_11+48(%r1);					\
152209975Snwhitehorn	std	%r12, FRAME_12+48(%r1);					\
153209975Snwhitehorn	std	%r13, FRAME_13+48(%r1);					\
154209975Snwhitehorn	std	%r14, FRAME_14+48(%r1);					\
155209975Snwhitehorn	std	%r15, FRAME_15+48(%r1);					\
156209975Snwhitehorn	std	%r16, FRAME_16+48(%r1);					\
157209975Snwhitehorn	std	%r17, FRAME_17+48(%r1);					\
158209975Snwhitehorn	std	%r18, FRAME_18+48(%r1);					\
159209975Snwhitehorn	std	%r19, FRAME_19+48(%r1);					\
160209975Snwhitehorn	std	%r20, FRAME_20+48(%r1);					\
161209975Snwhitehorn	std	%r21, FRAME_21+48(%r1);					\
162209975Snwhitehorn	std	%r22, FRAME_22+48(%r1);					\
163209975Snwhitehorn	std	%r23, FRAME_23+48(%r1);					\
164209975Snwhitehorn	std	%r24, FRAME_24+48(%r1);					\
165209975Snwhitehorn	std	%r25, FRAME_25+48(%r1);					\
166209975Snwhitehorn	std	%r26, FRAME_26+48(%r1);					\
167209975Snwhitehorn	std	%r27, FRAME_27+48(%r1);					\
168209975Snwhitehorn	std	%r28, FRAME_28+48(%r1);					\
169209975Snwhitehorn	std	%r29, FRAME_29+48(%r1);					\
170209975Snwhitehorn	std	%r30, FRAME_30+48(%r1);					\
171209975Snwhitehorn	std	%r31, FRAME_31+48(%r1);					\
172209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_AIM_DAR)(%r2);  /* saved DAR */	\
173209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
174209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */	\
175209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */	\
176125441Sgrehan	mfxer	%r3;							\
177125441Sgrehan	mfctr	%r4;							\
178188860Snwhitehorn	mfsprg3	%r5;							\
179209975Snwhitehorn	std	%r3, FRAME_XER+48(1);	/* save xer/ctr/exc */		\
180209975Snwhitehorn	std	%r4, FRAME_CTR+48(1);					\
181209975Snwhitehorn	std	%r5, FRAME_EXC+48(1);					\
182209975Snwhitehorn	std	%r28,FRAME_AIM_DAR+48(1);				\
183209975Snwhitehorn	std	%r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */	\
184209975Snwhitehorn	std	%r30,FRAME_SRR0+48(1);					\
185223485Snwhitehorn	std	%r31,FRAME_SRR1+48(1);					\
186223485Snwhitehorn	ld	%r13,PC_CURTHREAD(%r2)	/* set kernel curthread */
18795719Sbenno
188125441Sgrehan#define	FRAME_LEAVE(savearea)						\
189223485Snwhitehorn/* Disable exceptions: */						\
190223485Snwhitehorn	mfmsr	%r2;							\
191223485Snwhitehorn	andi.	%r2,%r2,~PSL_EE@l;					\
192223485Snwhitehorn	mtmsr	%r2;							\
193223485Snwhitehorn	isync;								\
194125441Sgrehan/* Now restore regs: */							\
195209975Snwhitehorn	ld	%r2,FRAME_SRR0+48(%r1);					\
196209975Snwhitehorn	ld	%r3,FRAME_SRR1+48(%r1);					\
197209975Snwhitehorn	ld	%r4,FRAME_CTR+48(%r1);					\
198209975Snwhitehorn	ld	%r5,FRAME_XER+48(%r1);					\
199209975Snwhitehorn	ld	%r6,FRAME_LR+48(%r1);					\
200125441Sgrehan	GET_CPUINFO(%r7);						\
201209975Snwhitehorn	std	%r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */	\
202209975Snwhitehorn	std	%r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */	\
203209975Snwhitehorn	ld	%r7,FRAME_CR+48(%r1);					\
204125441Sgrehan	mtctr	%r4;							\
205125441Sgrehan	mtxer	%r5;							\
206125441Sgrehan	mtlr	%r6;							\
207230123Snwhitehorn	mtsprg2	%r7;			/* save cr */			\
208209975Snwhitehorn	ld	%r31,FRAME_31+48(%r1);   /* restore r0-31 */		\
209209975Snwhitehorn	ld	%r30,FRAME_30+48(%r1);					\
210209975Snwhitehorn	ld	%r29,FRAME_29+48(%r1);					\
211209975Snwhitehorn	ld	%r28,FRAME_28+48(%r1);					\
212209975Snwhitehorn	ld	%r27,FRAME_27+48(%r1);					\
213209975Snwhitehorn	ld	%r26,FRAME_26+48(%r1);					\
214209975Snwhitehorn	ld	%r25,FRAME_25+48(%r1);					\
215209975Snwhitehorn	ld	%r24,FRAME_24+48(%r1);					\
216209975Snwhitehorn	ld	%r23,FRAME_23+48(%r1);					\
217209975Snwhitehorn	ld	%r22,FRAME_22+48(%r1);					\
218209975Snwhitehorn	ld	%r21,FRAME_21+48(%r1);					\
219209975Snwhitehorn	ld	%r20,FRAME_20+48(%r1);					\
220209975Snwhitehorn	ld	%r19,FRAME_19+48(%r1);					\
221209975Snwhitehorn	ld	%r18,FRAME_18+48(%r1);					\
222209975Snwhitehorn	ld	%r17,FRAME_17+48(%r1);					\
223209975Snwhitehorn	ld	%r16,FRAME_16+48(%r1);					\
224209975Snwhitehorn	ld	%r15,FRAME_15+48(%r1);					\
225209975Snwhitehorn	ld	%r14,FRAME_14+48(%r1);					\
226209975Snwhitehorn	ld	%r13,FRAME_13+48(%r1);					\
227209975Snwhitehorn	ld	%r12,FRAME_12+48(%r1);					\
228209975Snwhitehorn	ld	%r11,FRAME_11+48(%r1);					\
229209975Snwhitehorn	ld	%r10,FRAME_10+48(%r1);					\
230209975Snwhitehorn	ld	%r9, FRAME_9+48(%r1);					\
231209975Snwhitehorn	ld	%r8, FRAME_8+48(%r1);					\
232209975Snwhitehorn	ld	%r7, FRAME_7+48(%r1);					\
233209975Snwhitehorn	ld	%r6, FRAME_6+48(%r1);					\
234209975Snwhitehorn	ld	%r5, FRAME_5+48(%r1);					\
235209975Snwhitehorn	ld	%r4, FRAME_4+48(%r1);					\
236209975Snwhitehorn	ld	%r3, FRAME_3+48(%r1);					\
237209975Snwhitehorn	ld	%r2, FRAME_2+48(%r1);					\
238209975Snwhitehorn	ld	%r0, FRAME_0+48(%r1);					\
239209975Snwhitehorn	ld	%r1, FRAME_1+48(%r1);					\
240125441Sgrehan/* Can't touch %r1 from here on */					\
241230123Snwhitehorn	mtsprg3	%r3;			/* save r3 */			\
242125441Sgrehan/* Disable translation, machine check and recoverability: */		\
243230123Snwhitehorn	mfmsr	%r3;							\
244230123Snwhitehorn	andi.	%r3,%r3,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l;		\
245230123Snwhitehorn	mtmsr	%r3;							\
246125441Sgrehan	isync;								\
247125441Sgrehan/* Decide whether we return to user mode: */				\
248230123Snwhitehorn	GET_CPUINFO(%r3);						\
249230123Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR1)(%r3);			\
250125441Sgrehan	mtcr	%r3;							\
251125441Sgrehan	bf	17,1f;			/* branch if PSL_PR is false */	\
252125441Sgrehan/* Restore user SRs */							\
253209975Snwhitehorn	GET_CPUINFO(%r3);						\
254209975Snwhitehorn	std	%r27,(savearea+CPUSAVE_R27)(%r3);			\
255209975Snwhitehorn	std	%r28,(savearea+CPUSAVE_R28)(%r3);			\
256209975Snwhitehorn	std	%r29,(savearea+CPUSAVE_R29)(%r3);			\
257209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_R30)(%r3);			\
258209975Snwhitehorn	std	%r31,(savearea+CPUSAVE_R31)(%r3);			\
259209975Snwhitehorn	mflr	%r27;			/* preserve LR */		\
260212722Snwhitehorn	bl	restore_usersrs;	/* uses r28-r31 */		\
261209975Snwhitehorn	mtlr	%r27;							\
262209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_R31)(%r3);			\
263209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_R30)(%r3);			\
264209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_R29)(%r3);			\
265209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_R28)(%r3);			\
266209975Snwhitehorn	ld	%r27,(savearea+CPUSAVE_R27)(%r3);			\
267230123Snwhitehorn1:	mfsprg2	%r3;			/* restore cr */		\
268230123Snwhitehorn	mtcr	%r3;							\
269230123Snwhitehorn	GET_CPUINFO(%r3);						\
270230123Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR0)(%r3); /* restore srr0 */	\
271125441Sgrehan	mtsrr0	%r3;							\
272230123Snwhitehorn	GET_CPUINFO(%r3);						\
273230123Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR1)(%r3); /* restore srr1 */	\
274125441Sgrehan	mtsrr1	%r3;							\
275230123Snwhitehorn	mfsprg3	%r3			/* restore r3 */
27695719Sbenno
277242723Sjhibbits#ifdef KDTRACE_HOOKS
278242723Sjhibbits	.data
279242723Sjhibbits	.globl	dtrace_invop_calltrap_addr
280242723Sjhibbits	.align	8
281242723Sjhibbits	.type	dtrace_invop_calltrap_addr, @object
282242723Sjhibbits        .size	dtrace_invop_calltrap_addr, 8
283242723Sjhibbitsdtrace_invop_calltrap_addr:
284242723Sjhibbits	.word	0
285242723Sjhibbits	.word	0
286242723Sjhibbits
287242723Sjhibbits	.text
288242723Sjhibbits#endif
289242723Sjhibbits
290178628Smarcel#ifdef SMP
29195719Sbenno/*
292178628Smarcel * Processor reset exception handler. These are typically
293178628Smarcel * the first instructions the processor executes after a
294198400Snwhitehorn * software reset. We do this in two bits so that we are
295198400Snwhitehorn * not still hanging around in the trap handling region
296198400Snwhitehorn * once the MMU is turned on.
297132571Sgrehan */
298178628Smarcel	.globl	CNAME(rstcode), CNAME(rstsize)
299178628SmarcelCNAME(rstcode):
300209975Snwhitehorn	/* Explicitly set MSR[SF] */
301209975Snwhitehorn	mfmsr	%r9
302209975Snwhitehorn	li	%r8,1
303209975Snwhitehorn	insrdi	%r9,%r8,1,0
304209975Snwhitehorn	mtmsrd	%r9
305209975Snwhitehorn	isync
306209975Snwhitehorn
307198400Snwhitehorn	ba	cpu_reset
308198400SnwhitehornCNAME(rstsize) = . - CNAME(rstcode)
309198400Snwhitehorn
310198400Snwhitehorncpu_reset:
311209975Snwhitehorn	lis	%r1,(tmpstk+TMPSTKSZ-48)@ha	/* get new SP */
312209975Snwhitehorn	addi	%r1,%r1,(tmpstk+TMPSTKSZ-48)@l
313178628Smarcel
314209975Snwhitehorn	lis	%r3,tocbase@ha
315209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
316183060Smarcel	lis	%r3,1@l
317218824Snwhitehorn	bl	CNAME(cpudep_ap_early_bootstrap) /* Set PCPU */
318209975Snwhitehorn	nop
319227386Snwhitehorn	lis	%r3,1@l
320218824Snwhitehorn	bl	CNAME(pmap_cpu_bootstrap)	/* Turn on virtual memory */
321209975Snwhitehorn	nop
322218824Snwhitehorn	bl	CNAME(cpudep_ap_bootstrap)	/* Set up PCPU and stack */
323209975Snwhitehorn	nop
324209975Snwhitehorn	mr	%r1,%r3				/* Use new stack */
325218824Snwhitehorn	bl	CNAME(machdep_ap_bootstrap)	/* And away! */
326209975Snwhitehorn	nop
327178628Smarcel
328178628Smarcel	/* Should not be reached */
329178628Smarcel9:
330178628Smarcel	b	9b
331132571Sgrehan#endif
332132571Sgrehan
333132571Sgrehan/*
33495719Sbenno * This code gets copied to all the trap vectors
335125441Sgrehan * (except ISI/DSI, ALI, and the interrupts)
33695719Sbenno */
337178628Smarcel
33896773Sbenno	.globl	CNAME(trapcode),CNAME(trapsize)
33996773SbennoCNAME(trapcode):
340125441Sgrehan	mtsprg1	%r1			/* save SP */
341188860Snwhitehorn	mflr	%r1			/* Save the old LR in r1 */
342188860Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
343209975Snwhitehorn	li	%r1, 0xA0		/* How to get the vector from LR */
344188860Snwhitehorn	bla	generictrap		/* LR & SPRG3 is exception # */
34596773SbennoCNAME(trapsize) = .-CNAME(trapcode)
34695719Sbenno
34795719Sbenno/*
348230123Snwhitehorn * For SLB misses: do special things for the kernel
349230123Snwhitehorn *
350230123Snwhitehorn * Note: SPRG1 is always safe to overwrite any time the MMU is on, which is
351230123Snwhitehorn * the only time this can be called.
352230123Snwhitehorn */
353230123Snwhitehorn	.globl	CNAME(slbtrap),CNAME(slbtrapsize)
354230123SnwhitehornCNAME(slbtrap):
355230123Snwhitehorn	mtsprg1	%r1			/* save SP */
356230123Snwhitehorn	GET_CPUINFO(%r1)
357230123Snwhitehorn	std	%r2,(PC_SLBSAVE+16)(%r1)
358230123Snwhitehorn	mfcr	%r2			/* save CR */
359230123Snwhitehorn	std	%r2,(PC_SLBSAVE+104)(%r1)
360230123Snwhitehorn	mfsrr1	%r2			/* test kernel mode */
361230123Snwhitehorn	mtcr	%r2
362230123Snwhitehorn	bf	17,1f			/* branch if PSL_PR is false */
363230123Snwhitehorn	/* User mode */
364230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */
365230123Snwhitehorn	mtcr	%r2
366230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+16)(%r1) /* Restore R2 */
367230123Snwhitehorn	mflr	%r1			/* Save the old LR in r1 */
368230123Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
369230123Snwhitehorn	li	%r1, 0x80		/* How to get the vector from LR */
370230123Snwhitehorn	bla	generictrap		/* LR & SPRG3 is exception # */
371230123Snwhitehorn1:	mflr	%r2			/* Save the old LR in r2 */
372230123Snwhitehorn	bla	kern_slbtrap
373230123SnwhitehornCNAME(slbtrapsize) = .-CNAME(slbtrap)
374230123Snwhitehorn
375230123Snwhitehornkern_slbtrap:
376230123Snwhitehorn	std	%r2,(PC_SLBSAVE+136)(%r1) /* old LR */
377230123Snwhitehorn	std	%r3,(PC_SLBSAVE+24)(%r1) /* save R3 */
378230123Snwhitehorn
379230123Snwhitehorn	/* Check if this needs to be handled as a regular trap (userseg miss) */
380230123Snwhitehorn	mflr	%r2
381230123Snwhitehorn	andi.	%r2,%r2,0xff80
382230123Snwhitehorn	cmpwi	%r2,0x380
383230123Snwhitehorn	bne	1f
384230123Snwhitehorn	mfdar	%r2
385230123Snwhitehorn	b	2f
386230123Snwhitehorn1:	mfsrr0	%r2
387230123Snwhitehorn2:	/* r2 now contains the fault address */
388230123Snwhitehorn	lis	%r3,SEGMENT_MASK@highesta
389230123Snwhitehorn	ori	%r3,%r3,SEGMENT_MASK@highera
390230123Snwhitehorn	sldi	%r3,%r3,32
391230123Snwhitehorn	oris	%r3,%r3,SEGMENT_MASK@ha
392230123Snwhitehorn	ori	%r3,%r3,SEGMENT_MASK@l
393230123Snwhitehorn	and	%r2,%r2,%r3	/* R2 = segment base address */
394230123Snwhitehorn	lis	%r3,USER_ADDR@highesta
395230123Snwhitehorn	ori	%r3,%r3,USER_ADDR@highera
396230123Snwhitehorn	sldi	%r3,%r3,32
397230123Snwhitehorn	oris	%r3,%r3,USER_ADDR@ha
398230123Snwhitehorn	ori	%r3,%r3,USER_ADDR@l
399230123Snwhitehorn	cmpd	%r2,%r3		/* Compare fault base to USER_ADDR */
400230123Snwhitehorn	bne	3f
401230123Snwhitehorn
402230123Snwhitehorn	/* User seg miss, handle as a regular trap */
403230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */
404230123Snwhitehorn	mtcr	%r2
405230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+16)(%r1) /* Restore R2,R3 */
406230123Snwhitehorn	ld	%r3,(PC_SLBSAVE+24)(%r1)
407230123Snwhitehorn	ld	%r1,(PC_SLBSAVE+136)(%r1) /* Save the old LR in r1 */
408230123Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
409230123Snwhitehorn	li	%r1, 0x80		/* How to get the vector from LR */
410230123Snwhitehorn	b	generictrap		/* Retain old LR using b */
411230123Snwhitehorn
412230123Snwhitehorn3:	/* Real kernel SLB miss */
413230123Snwhitehorn	std	%r0,(PC_SLBSAVE+0)(%r1)	/* free all volatile regs */
414230123Snwhitehorn	mfsprg1	%r2			/* Old R1 */
415230123Snwhitehorn	std	%r2,(PC_SLBSAVE+8)(%r1)
416230123Snwhitehorn	/* R2,R3 already saved */
417230123Snwhitehorn	std	%r4,(PC_SLBSAVE+32)(%r1)
418230123Snwhitehorn	std	%r5,(PC_SLBSAVE+40)(%r1)
419230123Snwhitehorn	std	%r6,(PC_SLBSAVE+48)(%r1)
420230123Snwhitehorn	std	%r7,(PC_SLBSAVE+56)(%r1)
421230123Snwhitehorn	std	%r8,(PC_SLBSAVE+64)(%r1)
422230123Snwhitehorn	std	%r9,(PC_SLBSAVE+72)(%r1)
423230123Snwhitehorn	std	%r10,(PC_SLBSAVE+80)(%r1)
424230123Snwhitehorn	std	%r11,(PC_SLBSAVE+88)(%r1)
425230123Snwhitehorn	std	%r12,(PC_SLBSAVE+96)(%r1)
426230123Snwhitehorn	/* CR already saved */
427230123Snwhitehorn	mfxer	%r2			/* save XER */
428230123Snwhitehorn	std	%r2,(PC_SLBSAVE+112)(%r1)
429230123Snwhitehorn	mflr	%r2			/* save LR (SP already saved) */
430230123Snwhitehorn	std	%r2,(PC_SLBSAVE+120)(%r1)
431230123Snwhitehorn	mfctr	%r2			/* save CTR */
432230123Snwhitehorn	std	%r2,(PC_SLBSAVE+128)(%r1)
433230123Snwhitehorn
434230123Snwhitehorn	/* Call handler */
435230123Snwhitehorn	addi	%r1,%r1,PC_SLBSTACK-48+1024
436230123Snwhitehorn	li	%r2,~15
437230123Snwhitehorn	and	%r1,%r1,%r2
438230123Snwhitehorn	lis	%r3,tocbase@ha
439230123Snwhitehorn	ld	%r2,tocbase@l(%r3)
440230123Snwhitehorn	mflr	%r3
441230123Snwhitehorn	andi.	%r3,%r3,0xff80
442230123Snwhitehorn	mfdar	%r4
443230123Snwhitehorn	mfsrr0	%r5
444230123Snwhitehorn	bl	handle_kernel_slb_spill
445230123Snwhitehorn	nop
446230123Snwhitehorn
447230123Snwhitehorn	/* Save r28-31, restore r4-r12 */
448230123Snwhitehorn	GET_CPUINFO(%r1)
449230123Snwhitehorn	ld	%r4,(PC_SLBSAVE+32)(%r1)
450230123Snwhitehorn	ld	%r5,(PC_SLBSAVE+40)(%r1)
451230123Snwhitehorn	ld	%r6,(PC_SLBSAVE+48)(%r1)
452230123Snwhitehorn	ld	%r7,(PC_SLBSAVE+56)(%r1)
453230123Snwhitehorn	ld	%r8,(PC_SLBSAVE+64)(%r1)
454230123Snwhitehorn	ld	%r9,(PC_SLBSAVE+72)(%r1)
455230123Snwhitehorn	ld	%r10,(PC_SLBSAVE+80)(%r1)
456230123Snwhitehorn	ld	%r11,(PC_SLBSAVE+88)(%r1)
457230123Snwhitehorn	ld	%r12,(PC_SLBSAVE+96)(%r1)
458230123Snwhitehorn	std	%r28,(PC_SLBSAVE+64)(%r1)
459230123Snwhitehorn	std	%r29,(PC_SLBSAVE+72)(%r1)
460230123Snwhitehorn	std	%r30,(PC_SLBSAVE+80)(%r1)
461230123Snwhitehorn	std	%r31,(PC_SLBSAVE+88)(%r1)
462230123Snwhitehorn
463230123Snwhitehorn	/* Restore kernel mapping */
464230123Snwhitehorn	bl	restore_kernsrs
465230123Snwhitehorn
466230123Snwhitehorn	/* Restore remaining registers */
467230123Snwhitehorn	ld	%r28,(PC_SLBSAVE+64)(%r1)
468230123Snwhitehorn	ld	%r29,(PC_SLBSAVE+72)(%r1)
469230123Snwhitehorn	ld	%r30,(PC_SLBSAVE+80)(%r1)
470230123Snwhitehorn	ld	%r31,(PC_SLBSAVE+88)(%r1)
471230123Snwhitehorn
472230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+104)(%r1)
473230123Snwhitehorn	mtcr	%r2
474230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+112)(%r1)
475230123Snwhitehorn	mtxer	%r2
476230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+120)(%r1)
477230123Snwhitehorn	mtlr	%r2
478230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+128)(%r1)
479230123Snwhitehorn	mtctr	%r2
480230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+136)(%r1)
481230123Snwhitehorn	mtlr	%r2
482230123Snwhitehorn
483230123Snwhitehorn	/* Restore r0-r3 */
484230123Snwhitehorn	ld	%r0,(PC_SLBSAVE+0)(%r1)
485230123Snwhitehorn	ld	%r2,(PC_SLBSAVE+16)(%r1)
486230123Snwhitehorn	ld	%r3,(PC_SLBSAVE+24)(%r1)
487230123Snwhitehorn	mfsprg1	%r1
488230123Snwhitehorn
489230123Snwhitehorn	/* Back to whatever we were doing */
490230123Snwhitehorn	rfid
491230123Snwhitehorn
492230123Snwhitehorn/*
49395719Sbenno * For ALI: has to save DSISR and DAR
49495719Sbenno */
49596773Sbenno	.globl	CNAME(alitrap),CNAME(alisize)
49696773SbennoCNAME(alitrap):
497125441Sgrehan	mtsprg1	%r1			/* save SP */
498125441Sgrehan	GET_CPUINFO(%r1)
499209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
500209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
501209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
502209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
503209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
504125441Sgrehan	mfdar	%r30
505125441Sgrehan	mfdsisr	%r31
506209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
507209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
508125441Sgrehan	mfsprg1	%r1			/* restore SP, in case of branch */
509125441Sgrehan	mflr	%r28			/* save LR */
510125441Sgrehan	mfcr	%r29			/* save CR */
511188860Snwhitehorn
512188951Snwhitehorn	/* Put our exception vector in SPRG3 */
513188860Snwhitehorn	li	%r31, EXC_ALI
514188860Snwhitehorn	mtsprg3	%r31
515188860Snwhitehorn
516188860Snwhitehorn	/* Test whether we already had PR set */
517125441Sgrehan	mfsrr1	%r31
518125441Sgrehan	mtcr	%r31
519188860Snwhitehorn	bla	s_trap
52096773SbennoCNAME(alisize) = .-CNAME(alitrap)
52195719Sbenno
52295719Sbenno/*
52395719Sbenno * Similar to the above for DSI
52495719Sbenno * Has to handle BAT spills
52595719Sbenno * and standard pagetable spills
52695719Sbenno */
52796773Sbenno	.globl	CNAME(dsitrap),CNAME(dsisize)
52896773SbennoCNAME(dsitrap):
529125441Sgrehan	mtsprg1	%r1			/* save SP */
530125441Sgrehan	GET_CPUINFO(%r1)
531209975Snwhitehorn	std	%r27,(PC_DISISAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
532209975Snwhitehorn	std	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)
533209975Snwhitehorn	std	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
534209975Snwhitehorn	std	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
535209975Snwhitehorn	std	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
536125441Sgrehan	mfsprg1	%r1			/* restore SP */
537125441Sgrehan	mfcr	%r29			/* save CR */
538125441Sgrehan	mfxer	%r30			/* save XER */
539125441Sgrehan	mtsprg2	%r30			/* in SPRG2 */
540125441Sgrehan	mfsrr1	%r31			/* test kernel mode */
541125441Sgrehan	mtcr	%r31
542125441Sgrehan	mflr	%r28			/* save LR (SP already saved) */
543125441Sgrehan	bla	disitrap
54496773SbennoCNAME(dsisize) = .-CNAME(dsitrap)
54595719Sbenno
54695719Sbenno/*
54795719Sbenno * Preamble code for DSI/ISI traps
54895719Sbenno */
54995719Sbennodisitrap:
550188951Snwhitehorn	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
551188860Snwhitehorn	mflr	%r1
552188860Snwhitehorn	andi.	%r1,%r1,0xff00
553188860Snwhitehorn	mtsprg3	%r1
554188860Snwhitehorn
555125441Sgrehan	GET_CPUINFO(%r1)
556209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1)
557209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
558209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
559209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
560209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
561209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
562209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
563209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
564209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
565209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
566125441Sgrehan	mfdar	%r30
567125441Sgrehan	mfdsisr	%r31
568209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
569209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
570125441Sgrehan
571132571Sgrehan#ifdef KDB
572132571Sgrehan	/* Try and detect a kernel stack overflow */
573132571Sgrehan	mfsrr1	%r31
574132571Sgrehan	mtcr	%r31
575132571Sgrehan	bt	17,realtrap		/* branch is user mode */
576132571Sgrehan	mfsprg1	%r31			/* get old SP */
577132571Sgrehan	sub.	%r30,%r31,%r30		/* SP - DAR */
578132571Sgrehan	bge	1f
579132571Sgrehan	neg	%r30,%r30		/* modulo value */
580209975Snwhitehorn1:	cmpldi	%cr0,%r30,4096		/* is DAR within a page of SP? */
581132571Sgrehan	bge	%cr0,realtrap		/* no, too far away. */
582132571Sgrehan
583132571Sgrehan	/* Now convert this DSI into a DDB trap.  */
584132571Sgrehan	GET_CPUINFO(%r1)
585209975Snwhitehorn	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
586209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
587209975Snwhitehorn	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
588209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
589209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get  r27 */
590209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R27)(%r1) /* save r27 */
591209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get  r28 */
592209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_R28)(%r1) /* save r28 */
593209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get  r29 */
594209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R29)(%r1) /* save r29 */
595209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get  r30 */
596209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_R30)(%r1) /* save r30 */
597209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get  r31 */
598209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R31)(%r1) /* save r31 */
599191039Snwhitehorn	b	dbtrap
600132571Sgrehan#endif
601132571Sgrehan
602125441Sgrehan	/* XXX need stack probe here */
60395719Sbennorealtrap:
60495719Sbenno/* Test whether we already had PR set */
605125441Sgrehan	mfsrr1	%r1
606125441Sgrehan	mtcr	%r1
607125441Sgrehan	mfsprg1	%r1			/* restore SP (might have been
60895719Sbenno					   overwritten) */
609188860Snwhitehorn	bf	17,k_trap		/* branch if PSL_PR is false */
610188860Snwhitehorn	GET_CPUINFO(%r1)
611209975Snwhitehorn	ld	%r1,PC_CURPCB(%r1)
612209975Snwhitehorn	mr	%r27,%r28		/* Save LR, r29 */
613209975Snwhitehorn	mtsprg2	%r29
614212722Snwhitehorn	bl	restore_kernsrs		/* enable kernel mapping */
615209975Snwhitehorn	mfsprg2	%r29
616209975Snwhitehorn	mr	%r28,%r27
617188860Snwhitehorn	ba s_trap
618188860Snwhitehorn
619188860Snwhitehorn/*
620188860Snwhitehorn * generictrap does some standard setup for trap handling to minimize
621188860Snwhitehorn * the code that need be installed in the actual vectors. It expects
622188860Snwhitehorn * the following conditions.
623188860Snwhitehorn *
624188860Snwhitehorn * R1 - Trap vector = LR & (0xff00 | R1)
625188860Snwhitehorn * SPRG1 - Original R1 contents
626188860Snwhitehorn * SPRG2 - Original LR
627188860Snwhitehorn */
628188860Snwhitehorn
629188860Snwhitehorngenerictrap:
630188860Snwhitehorn	/* Save R1 for computing the exception vector */
631188860Snwhitehorn	mtsprg3 %r1
632188860Snwhitehorn
633188860Snwhitehorn	/* Save interesting registers */
634188860Snwhitehorn	GET_CPUINFO(%r1)
635209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
636209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
637209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
638209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
639209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
640209975Snwhitehorn	mfdar	%r30
641209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
642188860Snwhitehorn	mfsprg1	%r1			/* restore SP, in case of branch */
643188860Snwhitehorn	mfsprg2	%r28			/* save LR */
644188860Snwhitehorn	mfcr	%r29			/* save CR */
645188860Snwhitehorn
646188860Snwhitehorn	/* Compute the exception vector from the link register */
647188860Snwhitehorn	mfsprg3 %r31
648188860Snwhitehorn	ori	%r31,%r31,0xff00
649188860Snwhitehorn	mflr	%r30
650188860Snwhitehorn	and	%r30,%r30,%r31
651188860Snwhitehorn	mtsprg3	%r30
652188860Snwhitehorn
653188860Snwhitehorn	/* Test whether we already had PR set */
654188860Snwhitehorn	mfsrr1	%r31
655188860Snwhitehorn	mtcr	%r31
656188860Snwhitehorn
657125441Sgrehans_trap:
658125441Sgrehan	bf	17,k_trap		/* branch if PSL_PR is false */
659125441Sgrehan	GET_CPUINFO(%r1)
660125441Sgrehanu_trap:
661209975Snwhitehorn	ld	%r1,PC_CURPCB(%r1)
662209975Snwhitehorn	mr	%r27,%r28		/* Save LR, r29 */
663209975Snwhitehorn	mtsprg2	%r29
664212722Snwhitehorn	bl	restore_kernsrs		/* enable kernel mapping */
665209975Snwhitehorn	mfsprg2	%r29
666209975Snwhitehorn	mr	%r28,%r27
66795719Sbenno
66895719Sbenno/*
66995719Sbenno * Now the common trap catching code.
67095719Sbenno */
671125441Sgrehank_trap:
672125441Sgrehan	FRAME_SETUP(PC_TEMPSAVE)
67399032Sbenno/* Call C interrupt dispatcher: */
67495719Sbennotrapagain:
675209975Snwhitehorn	lis	%r3,tocbase@ha
676209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
677209975Snwhitehorn	addi	%r3,%r1,48
678218824Snwhitehorn	bl	CNAME(powerpc_interrupt)
679209975Snwhitehorn	nop
680209975Snwhitehorn
681209975Snwhitehorn	.globl	CNAME(trapexit)	/* backtrace code sentinel */
68296773SbennoCNAME(trapexit):
68395719Sbenno/* Disable interrupts: */
684125441Sgrehan	mfmsr	%r3
685125441Sgrehan	andi.	%r3,%r3,~PSL_EE@l
686125441Sgrehan	mtmsr	%r3
687222309Snwhitehorn	isync
68895719Sbenno/* Test AST pending: */
689209975Snwhitehorn	ld	%r5,FRAME_SRR1+48(%r1)
690125441Sgrehan	mtcr	%r5
691125441Sgrehan	bf	17,1f			/* branch if PSL_PR is false */
69299032Sbenno
693125441Sgrehan	GET_CPUINFO(%r3)		/* get per-CPU pointer */
694223485Snwhitehorn	lwz	%r4, TD_FLAGS(%r13)	/* get thread flags value */
695125441Sgrehan	lis	%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
696125441Sgrehan	ori	%r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
697125441Sgrehan	and.	%r4,%r4,%r5
69895719Sbenno	beq	1f
699125441Sgrehan	mfmsr	%r3			/* re-enable interrupts */
700125441Sgrehan	ori	%r3,%r3,PSL_EE@l
701125441Sgrehan	mtmsr	%r3
70299032Sbenno	isync
703209975Snwhitehorn	lis	%r3,tocbase@ha
704209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
705209975Snwhitehorn	addi	%r3,%r1,48
706218824Snwhitehorn	bl	CNAME(ast)
707209975Snwhitehorn	nop
708153685Sgrehan	.globl	CNAME(asttrapexit)	/* backtrace code sentinel #2 */
709153685SgrehanCNAME(asttrapexit):
71099032Sbenno	b	trapexit		/* test ast ret value ? */
71195719Sbenno1:
712125441Sgrehan	FRAME_LEAVE(PC_TEMPSAVE)
713190681Snwhitehorn	rfid
714190681Snwhitehorn
715132075Sgrehan#if defined(KDB)
71695719Sbenno/*
717132075Sgrehan * Deliberate entry to dbtrap
71895719Sbenno */
719230400SandreastASENTRY_NOPROF(breakpoint)
720125441Sgrehan	mtsprg1	%r1
721125441Sgrehan	mfmsr	%r3
722125441Sgrehan	mtsrr1	%r3
723125441Sgrehan	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
724125441Sgrehan	mtmsr	%r3			/* disable interrupts */
72595719Sbenno	isync
726125441Sgrehan	GET_CPUINFO(%r3)
727209975Snwhitehorn	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r3)
728209975Snwhitehorn	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
729209975Snwhitehorn	std	%r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
730209975Snwhitehorn	std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
731209975Snwhitehorn	std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
732125441Sgrehan	mflr	%r28
733125441Sgrehan	li	%r29,EXC_BPT
734125441Sgrehan	mtlr	%r29
735125441Sgrehan	mfcr	%r29
736125441Sgrehan	mtsrr0	%r28
73795719Sbenno
73895719Sbenno/*
739132075Sgrehan * Now the kdb trap catching code.
74095719Sbenno */
741132075Sgrehandbtrap:
742188951Snwhitehorn	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
743188860Snwhitehorn	mflr	%r1
744188860Snwhitehorn	andi.	%r1,%r1,0xff00
745188860Snwhitehorn	mtsprg3	%r1
746188860Snwhitehorn
747209975Snwhitehorn	lis	%r1,(tmpstk+TMPSTKSZ-48)@ha	/* get new SP */
748209975Snwhitehorn	addi	%r1,%r1,(tmpstk+TMPSTKSZ-48)@l
749188860Snwhitehorn
750132075Sgrehan	FRAME_SETUP(PC_DBSAVE)
75195719Sbenno/* Call C trap code: */
752209975Snwhitehorn	lis	%r3,tocbase@ha
753209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
754209975Snwhitehorn	addi	%r3,%r1,48
755218824Snwhitehorn	bl	CNAME(db_trap_glue)
756209975Snwhitehorn	nop
757125441Sgrehan	or.	%r3,%r3,%r3
758132075Sgrehan	bne	dbleave
759132075Sgrehan/* This wasn't for KDB, so switch to real trap: */
760209975Snwhitehorn	ld	%r3,FRAME_EXC+48(%r1)	/* save exception */
761125441Sgrehan	GET_CPUINFO(%r4)
762209975Snwhitehorn	std	%r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
763132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
764125441Sgrehan	mtsprg1	%r1			/* prepare for entrance to realtrap */
765125441Sgrehan	GET_CPUINFO(%r1)
766209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
767209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
768209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
769209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
770209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
771125441Sgrehan	mflr	%r28
772125441Sgrehan	mfcr	%r29
773209975Snwhitehorn	ld	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
774190946Snwhitehorn	mtsprg3	%r31			/* SPRG3 was clobbered by FRAME_LEAVE */
775125441Sgrehan	mfsprg1	%r1
77695719Sbenno	b	realtrap
777132075Sgrehandbleave:
778132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
779209975Snwhitehorn	rfid
78095719Sbenno
78195719Sbenno/*
782132075Sgrehan * In case of KDB we want a separate trap catcher for it
78395719Sbenno */
784132075Sgrehan	.globl	CNAME(dblow),CNAME(dbsize)
785132075SgrehanCNAME(dblow):
786125441Sgrehan	mtsprg1	%r1			/* save SP */
787125441Sgrehan	mtsprg2	%r29			/* save r29 */
788125441Sgrehan	mfcr	%r29			/* save CR in r29 */
789125441Sgrehan	mfsrr1	%r1
790125441Sgrehan	mtcr	%r1
791125441Sgrehan	bf	17,1f			/* branch if privileged */
792188860Snwhitehorn
793188860Snwhitehorn	/* Unprivileged case */
794188860Snwhitehorn	mtcr	%r29			/* put the condition register back */
795188860Snwhitehorn        mfsprg2	%r29			/* ... and r29 */
796188860Snwhitehorn        mflr	%r1			/* save LR */
797188860Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
798188860Snwhitehorn	li	%r1, 0	 		/* How to get the vector from LR */
799188860Snwhitehorn
800188860Snwhitehorn        bla     generictrap		/* and we look like a generic trap */
801125441Sgrehan1:
802188860Snwhitehorn	/* Privileged, so drop to KDB */
803188860Snwhitehorn	GET_CPUINFO(%r1)
804209975Snwhitehorn	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r1)	/* free r27 */
805209975Snwhitehorn	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
806125441Sgrehan        mfsprg2	%r28				/* r29 holds cr...  */
807209975Snwhitehorn        std	%r28,(PC_DBSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
808209975Snwhitehorn        std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
809209975Snwhitehorn        std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
810125441Sgrehan        mflr	%r28					/* save LR */
811132075Sgrehan	bla	dbtrap
812132075SgrehanCNAME(dbsize) = .-CNAME(dblow)
813132075Sgrehan#endif /* KDB */
814