trap_subr64.S revision 222620
195719Sbenno/* $FreeBSD: head/sys/powerpc/aim/trap_subr64.S 222620 2011-06-02 14:25:52Z nwhitehorn $ */
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
115125441Sgrehan */
116125441Sgrehan#define	FRAME_SETUP(savearea)						\
117125441Sgrehan/* Have to enable translation to allow access of kernel stack: */	\
118125441Sgrehan	GET_CPUINFO(%r31);						\
119125441Sgrehan	mfsrr0	%r30;							\
120209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_SRR0)(%r31);	/* save SRR0 */	\
121125441Sgrehan	mfsrr1	%r30;							\
122209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_SRR1)(%r31);	/* save SRR1 */	\
123125441Sgrehan	mfmsr	%r30;							\
124125441Sgrehan	ori	%r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */	\
125125441Sgrehan	mtmsr	%r30;			/* stack can now be accessed */	\
126125441Sgrehan	isync;								\
127125441Sgrehan	mfsprg1	%r31;			/* get saved SP */		\
128209975Snwhitehorn	stdu	%r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \
129209975Snwhitehorn	std	%r0, FRAME_0+48(%r1);	/* save r0 in the trapframe */	\
130209975Snwhitehorn	std	%r31,FRAME_1+48(%r1);	/* save SP   "      "       */	\
131209975Snwhitehorn	std	%r2, FRAME_2+48(%r1);	/* save r2   "      "       */	\
132209975Snwhitehorn	std	%r28,FRAME_LR+48(%r1);	/* save LR   "      "       */	\
133209975Snwhitehorn	std	%r29,FRAME_CR+48(%r1);	/* save CR   "      "       */	\
134125441Sgrehan	GET_CPUINFO(%r2);						\
135209975Snwhitehorn	ld	%r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */	\
136209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */	\
137209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */	\
138209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
139209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
140209975Snwhitehorn	std	%r3,  FRAME_3+48(%r1);	/* save r3-r31 */		\
141209975Snwhitehorn	std	%r4,  FRAME_4+48(%r1);					\
142209975Snwhitehorn	std	%r5,  FRAME_5+48(%r1);					\
143209975Snwhitehorn	std	%r6,  FRAME_6+48(%r1);					\
144209975Snwhitehorn	std	%r7,  FRAME_7+48(%r1);					\
145209975Snwhitehorn	std	%r8,  FRAME_8+48(%r1);					\
146209975Snwhitehorn	std	%r9,  FRAME_9+48(%r1);					\
147209975Snwhitehorn	std	%r10, FRAME_10+48(%r1);					\
148209975Snwhitehorn	std	%r11, FRAME_11+48(%r1);					\
149209975Snwhitehorn	std	%r12, FRAME_12+48(%r1);					\
150209975Snwhitehorn	std	%r13, FRAME_13+48(%r1);					\
151209975Snwhitehorn	std	%r14, FRAME_14+48(%r1);					\
152209975Snwhitehorn	std	%r15, FRAME_15+48(%r1);					\
153209975Snwhitehorn	std	%r16, FRAME_16+48(%r1);					\
154209975Snwhitehorn	std	%r17, FRAME_17+48(%r1);					\
155209975Snwhitehorn	std	%r18, FRAME_18+48(%r1);					\
156209975Snwhitehorn	std	%r19, FRAME_19+48(%r1);					\
157209975Snwhitehorn	std	%r20, FRAME_20+48(%r1);					\
158209975Snwhitehorn	std	%r21, FRAME_21+48(%r1);					\
159209975Snwhitehorn	std	%r22, FRAME_22+48(%r1);					\
160209975Snwhitehorn	std	%r23, FRAME_23+48(%r1);					\
161209975Snwhitehorn	std	%r24, FRAME_24+48(%r1);					\
162209975Snwhitehorn	std	%r25, FRAME_25+48(%r1);					\
163209975Snwhitehorn	std	%r26, FRAME_26+48(%r1);					\
164209975Snwhitehorn	std	%r27, FRAME_27+48(%r1);					\
165209975Snwhitehorn	std	%r28, FRAME_28+48(%r1);					\
166209975Snwhitehorn	std	%r29, FRAME_29+48(%r1);					\
167209975Snwhitehorn	std	%r30, FRAME_30+48(%r1);					\
168209975Snwhitehorn	std	%r31, FRAME_31+48(%r1);					\
169209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_AIM_DAR)(%r2);  /* saved DAR */	\
170209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
171209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */	\
172209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */	\
173125441Sgrehan	mfxer	%r3;							\
174125441Sgrehan	mfctr	%r4;							\
175188860Snwhitehorn	mfsprg3	%r5;							\
176209975Snwhitehorn	std	%r3, FRAME_XER+48(1);	/* save xer/ctr/exc */		\
177209975Snwhitehorn	std	%r4, FRAME_CTR+48(1);					\
178209975Snwhitehorn	std	%r5, FRAME_EXC+48(1);					\
179209975Snwhitehorn	std	%r28,FRAME_AIM_DAR+48(1);				\
180209975Snwhitehorn	std	%r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */	\
181209975Snwhitehorn	std	%r30,FRAME_SRR0+48(1);					\
182209975Snwhitehorn	std	%r31,FRAME_SRR1+48(1)
18395719Sbenno
184125441Sgrehan#define	FRAME_LEAVE(savearea)						\
185125441Sgrehan/* Now restore regs: */							\
186209975Snwhitehorn	ld	%r2,FRAME_SRR0+48(%r1);					\
187209975Snwhitehorn	ld	%r3,FRAME_SRR1+48(%r1);					\
188209975Snwhitehorn	ld	%r4,FRAME_CTR+48(%r1);					\
189209975Snwhitehorn	ld	%r5,FRAME_XER+48(%r1);					\
190209975Snwhitehorn	ld	%r6,FRAME_LR+48(%r1);					\
191125441Sgrehan	GET_CPUINFO(%r7);						\
192209975Snwhitehorn	std	%r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */	\
193209975Snwhitehorn	std	%r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */	\
194209975Snwhitehorn	ld	%r7,FRAME_CR+48(%r1);					\
195125441Sgrehan	mtctr	%r4;							\
196125441Sgrehan	mtxer	%r5;							\
197125441Sgrehan	mtlr	%r6;							\
198125441Sgrehan	mtsprg1	%r7;			/* save cr */			\
199209975Snwhitehorn	ld	%r31,FRAME_31+48(%r1);   /* restore r0-31 */		\
200209975Snwhitehorn	ld	%r30,FRAME_30+48(%r1);					\
201209975Snwhitehorn	ld	%r29,FRAME_29+48(%r1);					\
202209975Snwhitehorn	ld	%r28,FRAME_28+48(%r1);					\
203209975Snwhitehorn	ld	%r27,FRAME_27+48(%r1);					\
204209975Snwhitehorn	ld	%r26,FRAME_26+48(%r1);					\
205209975Snwhitehorn	ld	%r25,FRAME_25+48(%r1);					\
206209975Snwhitehorn	ld	%r24,FRAME_24+48(%r1);					\
207209975Snwhitehorn	ld	%r23,FRAME_23+48(%r1);					\
208209975Snwhitehorn	ld	%r22,FRAME_22+48(%r1);					\
209209975Snwhitehorn	ld	%r21,FRAME_21+48(%r1);					\
210209975Snwhitehorn	ld	%r20,FRAME_20+48(%r1);					\
211209975Snwhitehorn	ld	%r19,FRAME_19+48(%r1);					\
212209975Snwhitehorn	ld	%r18,FRAME_18+48(%r1);					\
213209975Snwhitehorn	ld	%r17,FRAME_17+48(%r1);					\
214209975Snwhitehorn	ld	%r16,FRAME_16+48(%r1);					\
215209975Snwhitehorn	ld	%r15,FRAME_15+48(%r1);					\
216209975Snwhitehorn	ld	%r14,FRAME_14+48(%r1);					\
217209975Snwhitehorn	ld	%r13,FRAME_13+48(%r1);					\
218209975Snwhitehorn	ld	%r12,FRAME_12+48(%r1);					\
219209975Snwhitehorn	ld	%r11,FRAME_11+48(%r1);					\
220209975Snwhitehorn	ld	%r10,FRAME_10+48(%r1);					\
221209975Snwhitehorn	ld	%r9, FRAME_9+48(%r1);					\
222209975Snwhitehorn	ld	%r8, FRAME_8+48(%r1);					\
223209975Snwhitehorn	ld	%r7, FRAME_7+48(%r1);					\
224209975Snwhitehorn	ld	%r6, FRAME_6+48(%r1);					\
225209975Snwhitehorn	ld	%r5, FRAME_5+48(%r1);					\
226209975Snwhitehorn	ld	%r4, FRAME_4+48(%r1);					\
227209975Snwhitehorn	ld	%r3, FRAME_3+48(%r1);					\
228209975Snwhitehorn	ld	%r2, FRAME_2+48(%r1);					\
229209975Snwhitehorn	ld	%r0, FRAME_0+48(%r1);					\
230209975Snwhitehorn	ld	%r1, FRAME_1+48(%r1);					\
231125441Sgrehan/* Can't touch %r1 from here on */					\
232125441Sgrehan	mtsprg2	%r2;			/* save r2 & r3 */		\
233125441Sgrehan	mtsprg3	%r3;							\
234125441Sgrehan/* Disable translation, machine check and recoverability: */		\
235125441Sgrehan	mfmsr	%r2;							\
236125441Sgrehan	andi.	%r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l;	\
237125441Sgrehan	mtmsr	%r2;							\
238125441Sgrehan	isync;								\
239125441Sgrehan/* Decide whether we return to user mode: */				\
240125441Sgrehan	GET_CPUINFO(%r2);						\
241209975Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR1)(%r2);			\
242125441Sgrehan	mtcr	%r3;							\
243125441Sgrehan	bf	17,1f;			/* branch if PSL_PR is false */	\
244125441Sgrehan/* Restore user SRs */							\
245209975Snwhitehorn	GET_CPUINFO(%r3);						\
246209975Snwhitehorn	std	%r27,(savearea+CPUSAVE_R27)(%r3);			\
247209975Snwhitehorn	std	%r28,(savearea+CPUSAVE_R28)(%r3);			\
248209975Snwhitehorn	std	%r29,(savearea+CPUSAVE_R29)(%r3);			\
249209975Snwhitehorn	std	%r30,(savearea+CPUSAVE_R30)(%r3);			\
250209975Snwhitehorn	std	%r31,(savearea+CPUSAVE_R31)(%r3);			\
251209975Snwhitehorn	mflr	%r27;			/* preserve LR */		\
252212722Snwhitehorn	bl	restore_usersrs;	/* uses r28-r31 */		\
253209975Snwhitehorn	mtlr	%r27;							\
254209975Snwhitehorn	ld	%r31,(savearea+CPUSAVE_R31)(%r3);			\
255209975Snwhitehorn	ld	%r30,(savearea+CPUSAVE_R30)(%r3);			\
256209975Snwhitehorn	ld	%r29,(savearea+CPUSAVE_R29)(%r3);			\
257209975Snwhitehorn	ld	%r28,(savearea+CPUSAVE_R28)(%r3);			\
258209975Snwhitehorn	ld	%r27,(savearea+CPUSAVE_R27)(%r3);			\
259125441Sgrehan1:	mfsprg1	%r2;			/* restore cr */		\
260125441Sgrehan	mtcr	%r2;							\
261125441Sgrehan	GET_CPUINFO(%r2);						\
262209975Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */	\
263125441Sgrehan	mtsrr0	%r3;							\
264209975Snwhitehorn	ld	%r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */	\
265125441Sgrehan	mtsrr1	%r3;							\
266125441Sgrehan	mfsprg2	%r2;			/* restore r2 & r3 */		\
267125441Sgrehan	mfsprg3	%r3
26895719Sbenno
269178628Smarcel#ifdef SMP
27095719Sbenno/*
271178628Smarcel * Processor reset exception handler. These are typically
272178628Smarcel * the first instructions the processor executes after a
273198400Snwhitehorn * software reset. We do this in two bits so that we are
274198400Snwhitehorn * not still hanging around in the trap handling region
275198400Snwhitehorn * once the MMU is turned on.
276132571Sgrehan */
277178628Smarcel	.globl	CNAME(rstcode), CNAME(rstsize)
278178628SmarcelCNAME(rstcode):
279209975Snwhitehorn	/* Explicitly set MSR[SF] */
280209975Snwhitehorn	mfmsr	%r9
281209975Snwhitehorn	li	%r8,1
282209975Snwhitehorn	insrdi	%r9,%r8,1,0
283209975Snwhitehorn	mtmsrd	%r9
284209975Snwhitehorn	isync
285209975Snwhitehorn
286198400Snwhitehorn	ba	cpu_reset
287198400SnwhitehornCNAME(rstsize) = . - CNAME(rstcode)
288198400Snwhitehorn
289198400Snwhitehorncpu_reset:
290209975Snwhitehorn	lis	%r1,(tmpstk+TMPSTKSZ-48)@ha	/* get new SP */
291209975Snwhitehorn	addi	%r1,%r1,(tmpstk+TMPSTKSZ-48)@l
292178628Smarcel
293209975Snwhitehorn	lis	%r3,tocbase@ha
294209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
295183060Smarcel	lis	%r3,1@l
296218824Snwhitehorn	bl	CNAME(cpudep_ap_early_bootstrap) /* Set PCPU */
297209975Snwhitehorn	nop
298218824Snwhitehorn	bl	CNAME(pmap_cpu_bootstrap)	/* Turn on virtual memory */
299209975Snwhitehorn	nop
300218824Snwhitehorn	bl	CNAME(cpudep_ap_bootstrap)	/* Set up PCPU and stack */
301209975Snwhitehorn	nop
302209975Snwhitehorn	mr	%r1,%r3				/* Use new stack */
303218824Snwhitehorn	bl	CNAME(machdep_ap_bootstrap)	/* And away! */
304209975Snwhitehorn	nop
305178628Smarcel
306178628Smarcel	/* Should not be reached */
307178628Smarcel9:
308178628Smarcel	b	9b
309132571Sgrehan#endif
310132571Sgrehan
311132571Sgrehan/*
31295719Sbenno * This code gets copied to all the trap vectors
313125441Sgrehan * (except ISI/DSI, ALI, and the interrupts)
31495719Sbenno */
315178628Smarcel
31696773Sbenno	.globl	CNAME(trapcode),CNAME(trapsize)
31796773SbennoCNAME(trapcode):
318125441Sgrehan	mtsprg1	%r1			/* save SP */
319188860Snwhitehorn	mflr	%r1			/* Save the old LR in r1 */
320188860Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
321209975Snwhitehorn	li	%r1, 0xA0		/* How to get the vector from LR */
322188860Snwhitehorn	bla	generictrap		/* LR & SPRG3 is exception # */
32396773SbennoCNAME(trapsize) = .-CNAME(trapcode)
32495719Sbenno
32595719Sbenno/*
32695719Sbenno * For ALI: has to save DSISR and DAR
32795719Sbenno */
32896773Sbenno	.globl	CNAME(alitrap),CNAME(alisize)
32996773SbennoCNAME(alitrap):
330125441Sgrehan	mtsprg1	%r1			/* save SP */
331125441Sgrehan	GET_CPUINFO(%r1)
332209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
333209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
334209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
335209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
336209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
337125441Sgrehan	mfdar	%r30
338125441Sgrehan	mfdsisr	%r31
339209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
340209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
341125441Sgrehan	mfsprg1	%r1			/* restore SP, in case of branch */
342125441Sgrehan	mflr	%r28			/* save LR */
343125441Sgrehan	mfcr	%r29			/* save CR */
344188860Snwhitehorn
345188951Snwhitehorn	/* Put our exception vector in SPRG3 */
346188860Snwhitehorn	li	%r31, EXC_ALI
347188860Snwhitehorn	mtsprg3	%r31
348188860Snwhitehorn
349188860Snwhitehorn	/* Test whether we already had PR set */
350125441Sgrehan	mfsrr1	%r31
351125441Sgrehan	mtcr	%r31
352188860Snwhitehorn	bla	s_trap
35396773SbennoCNAME(alisize) = .-CNAME(alitrap)
35495719Sbenno
35595719Sbenno/*
35695719Sbenno * Similar to the above for DSI
35795719Sbenno * Has to handle BAT spills
35895719Sbenno * and standard pagetable spills
35995719Sbenno */
36096773Sbenno	.globl	CNAME(dsitrap),CNAME(dsisize)
36196773SbennoCNAME(dsitrap):
362125441Sgrehan	mtsprg1	%r1			/* save SP */
363125441Sgrehan	GET_CPUINFO(%r1)
364209975Snwhitehorn	std	%r27,(PC_DISISAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
365209975Snwhitehorn	std	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)
366209975Snwhitehorn	std	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
367209975Snwhitehorn	std	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
368209975Snwhitehorn	std	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
369125441Sgrehan	mfsprg1	%r1			/* restore SP */
370125441Sgrehan	mfcr	%r29			/* save CR */
371125441Sgrehan	mfxer	%r30			/* save XER */
372125441Sgrehan	mtsprg2	%r30			/* in SPRG2 */
373125441Sgrehan	mfsrr1	%r31			/* test kernel mode */
374125441Sgrehan	mtcr	%r31
375125441Sgrehan	mflr	%r28			/* save LR (SP already saved) */
376125441Sgrehan	bla	disitrap
37796773SbennoCNAME(dsisize) = .-CNAME(dsitrap)
37895719Sbenno
37995719Sbenno/*
38095719Sbenno * Preamble code for DSI/ISI traps
38195719Sbenno */
38295719Sbennodisitrap:
383188951Snwhitehorn	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
384188860Snwhitehorn	mflr	%r1
385188860Snwhitehorn	andi.	%r1,%r1,0xff00
386188860Snwhitehorn	mtsprg3	%r1
387188860Snwhitehorn
388125441Sgrehan	GET_CPUINFO(%r1)
389209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1)
390209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
391209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
392209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
393209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
394209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
395209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
396209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
397209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
398209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
399125441Sgrehan	mfdar	%r30
400125441Sgrehan	mfdsisr	%r31
401209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
402209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
403125441Sgrehan
404132571Sgrehan#ifdef KDB
405132571Sgrehan	/* Try and detect a kernel stack overflow */
406132571Sgrehan	mfsrr1	%r31
407132571Sgrehan	mtcr	%r31
408132571Sgrehan	bt	17,realtrap		/* branch is user mode */
409132571Sgrehan	mfsprg1	%r31			/* get old SP */
410132571Sgrehan	sub.	%r30,%r31,%r30		/* SP - DAR */
411132571Sgrehan	bge	1f
412132571Sgrehan	neg	%r30,%r30		/* modulo value */
413209975Snwhitehorn1:	cmpldi	%cr0,%r30,4096		/* is DAR within a page of SP? */
414132571Sgrehan	bge	%cr0,realtrap		/* no, too far away. */
415132571Sgrehan
416132571Sgrehan	/* Now convert this DSI into a DDB trap.  */
417132571Sgrehan	GET_CPUINFO(%r1)
418209975Snwhitehorn	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
419209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
420209975Snwhitehorn	ld	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
421209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
422209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get  r27 */
423209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R27)(%r1) /* save r27 */
424209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get  r28 */
425209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_R28)(%r1) /* save r28 */
426209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get  r29 */
427209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R29)(%r1) /* save r29 */
428209975Snwhitehorn	ld	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get  r30 */
429209975Snwhitehorn	std	%r30,(PC_DBSAVE  +CPUSAVE_R30)(%r1) /* save r30 */
430209975Snwhitehorn	ld	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get  r31 */
431209975Snwhitehorn	std	%r31,(PC_DBSAVE  +CPUSAVE_R31)(%r1) /* save r31 */
432191039Snwhitehorn	b	dbtrap
433132571Sgrehan#endif
434132571Sgrehan
435125441Sgrehan	/* XXX need stack probe here */
43695719Sbennorealtrap:
43795719Sbenno/* Test whether we already had PR set */
438125441Sgrehan	mfsrr1	%r1
439125441Sgrehan	mtcr	%r1
440125441Sgrehan	mfsprg1	%r1			/* restore SP (might have been
44195719Sbenno					   overwritten) */
442188860Snwhitehorn	bf	17,k_trap		/* branch if PSL_PR is false */
443188860Snwhitehorn	GET_CPUINFO(%r1)
444209975Snwhitehorn	ld	%r1,PC_CURPCB(%r1)
445209975Snwhitehorn	mr	%r27,%r28		/* Save LR, r29 */
446209975Snwhitehorn	mtsprg2	%r29
447212722Snwhitehorn	bl	restore_kernsrs		/* enable kernel mapping */
448209975Snwhitehorn	mfsprg2	%r29
449209975Snwhitehorn	mr	%r28,%r27
450188860Snwhitehorn	ba s_trap
451188860Snwhitehorn
452188860Snwhitehorn/*
453188860Snwhitehorn * generictrap does some standard setup for trap handling to minimize
454188860Snwhitehorn * the code that need be installed in the actual vectors. It expects
455188860Snwhitehorn * the following conditions.
456188860Snwhitehorn *
457188860Snwhitehorn * R1 - Trap vector = LR & (0xff00 | R1)
458188860Snwhitehorn * SPRG1 - Original R1 contents
459188860Snwhitehorn * SPRG2 - Original LR
460188860Snwhitehorn */
461188860Snwhitehorn
462188860Snwhitehorngenerictrap:
463188860Snwhitehorn	/* Save R1 for computing the exception vector */
464188860Snwhitehorn	mtsprg3 %r1
465188860Snwhitehorn
466188860Snwhitehorn	/* Save interesting registers */
467188860Snwhitehorn	GET_CPUINFO(%r1)
468209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)	/* free r27-r31 */
469209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
470209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
471209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
472209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
473209975Snwhitehorn	mfdar	%r30
474209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
475188860Snwhitehorn	mfsprg1	%r1			/* restore SP, in case of branch */
476188860Snwhitehorn	mfsprg2	%r28			/* save LR */
477188860Snwhitehorn	mfcr	%r29			/* save CR */
478188860Snwhitehorn
479188860Snwhitehorn	/* Compute the exception vector from the link register */
480188860Snwhitehorn	mfsprg3 %r31
481188860Snwhitehorn	ori	%r31,%r31,0xff00
482188860Snwhitehorn	mflr	%r30
483188860Snwhitehorn	and	%r30,%r30,%r31
484188860Snwhitehorn	mtsprg3	%r30
485188860Snwhitehorn
486188860Snwhitehorn	/* Test whether we already had PR set */
487188860Snwhitehorn	mfsrr1	%r31
488188860Snwhitehorn	mtcr	%r31
489188860Snwhitehorn
490125441Sgrehans_trap:
491125441Sgrehan	bf	17,k_trap		/* branch if PSL_PR is false */
492125441Sgrehan	GET_CPUINFO(%r1)
493125441Sgrehanu_trap:
494209975Snwhitehorn	ld	%r1,PC_CURPCB(%r1)
495209975Snwhitehorn	mr	%r27,%r28		/* Save LR, r29 */
496209975Snwhitehorn	mtsprg2	%r29
497212722Snwhitehorn	bl	restore_kernsrs		/* enable kernel mapping */
498209975Snwhitehorn	mfsprg2	%r29
499209975Snwhitehorn	mr	%r28,%r27
50095719Sbenno
50195719Sbenno/*
50295719Sbenno * Now the common trap catching code.
50395719Sbenno */
504125441Sgrehank_trap:
505125441Sgrehan	FRAME_SETUP(PC_TEMPSAVE)
50699032Sbenno/* Call C interrupt dispatcher: */
50795719Sbennotrapagain:
508209975Snwhitehorn	lis	%r3,tocbase@ha
509209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
510209975Snwhitehorn	addi	%r3,%r1,48
511218824Snwhitehorn	bl	CNAME(powerpc_interrupt)
512209975Snwhitehorn	nop
513209975Snwhitehorn
514209975Snwhitehorn	.globl	CNAME(trapexit)	/* backtrace code sentinel */
51596773SbennoCNAME(trapexit):
51695719Sbenno/* Disable interrupts: */
517125441Sgrehan	mfmsr	%r3
518125441Sgrehan	andi.	%r3,%r3,~PSL_EE@l
519125441Sgrehan	mtmsr	%r3
520222309Snwhitehorn	isync
52195719Sbenno/* Test AST pending: */
522209975Snwhitehorn	ld	%r5,FRAME_SRR1+48(%r1)
523125441Sgrehan	mtcr	%r5
524125441Sgrehan	bf	17,1f			/* branch if PSL_PR is false */
52599032Sbenno
526125441Sgrehan	GET_CPUINFO(%r3)		/* get per-CPU pointer */
527209975Snwhitehorn	ld	%r4, PC_CURTHREAD(%r3)	/* deref to get curthread */
528125441Sgrehan	lwz	%r4, TD_FLAGS(%r4)	/* get thread flags value */
529125441Sgrehan	lis	%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
530125441Sgrehan	ori	%r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
531125441Sgrehan	and.	%r4,%r4,%r5
53295719Sbenno	beq	1f
533125441Sgrehan	mfmsr	%r3			/* re-enable interrupts */
534125441Sgrehan	ori	%r3,%r3,PSL_EE@l
535125441Sgrehan	mtmsr	%r3
53699032Sbenno	isync
537209975Snwhitehorn	lis	%r3,tocbase@ha
538209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
539209975Snwhitehorn	addi	%r3,%r1,48
540218824Snwhitehorn	bl	CNAME(ast)
541209975Snwhitehorn	nop
542153685Sgrehan	.globl	CNAME(asttrapexit)	/* backtrace code sentinel #2 */
543153685SgrehanCNAME(asttrapexit):
54499032Sbenno	b	trapexit		/* test ast ret value ? */
54595719Sbenno1:
546125441Sgrehan	FRAME_LEAVE(PC_TEMPSAVE)
547190681Snwhitehorn	rfid
548190681Snwhitehorn
549132075Sgrehan#if defined(KDB)
55095719Sbenno/*
551132075Sgrehan * Deliberate entry to dbtrap
55295719Sbenno */
553209975SnwhitehornASENTRY(breakpoint)
554125441Sgrehan	mtsprg1	%r1
555125441Sgrehan	mfmsr	%r3
556125441Sgrehan	mtsrr1	%r3
557125441Sgrehan	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
558125441Sgrehan	mtmsr	%r3			/* disable interrupts */
55995719Sbenno	isync
560125441Sgrehan	GET_CPUINFO(%r3)
561209975Snwhitehorn	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r3)
562209975Snwhitehorn	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
563209975Snwhitehorn	std	%r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
564209975Snwhitehorn	std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
565209975Snwhitehorn	std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
566125441Sgrehan	mflr	%r28
567125441Sgrehan	li	%r29,EXC_BPT
568125441Sgrehan	mtlr	%r29
569125441Sgrehan	mfcr	%r29
570125441Sgrehan	mtsrr0	%r28
57195719Sbenno
57295719Sbenno/*
573132075Sgrehan * Now the kdb trap catching code.
57495719Sbenno */
575132075Sgrehandbtrap:
576188951Snwhitehorn	/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
577188860Snwhitehorn	mflr	%r1
578188860Snwhitehorn	andi.	%r1,%r1,0xff00
579188860Snwhitehorn	mtsprg3	%r1
580188860Snwhitehorn
581209975Snwhitehorn	lis	%r1,(tmpstk+TMPSTKSZ-48)@ha	/* get new SP */
582209975Snwhitehorn	addi	%r1,%r1,(tmpstk+TMPSTKSZ-48)@l
583188860Snwhitehorn
584132075Sgrehan	FRAME_SETUP(PC_DBSAVE)
58595719Sbenno/* Call C trap code: */
586209975Snwhitehorn	lis	%r3,tocbase@ha
587209975Snwhitehorn	ld	%r2,tocbase@l(%r3)
588209975Snwhitehorn	addi	%r3,%r1,48
589218824Snwhitehorn	bl	CNAME(db_trap_glue)
590209975Snwhitehorn	nop
591125441Sgrehan	or.	%r3,%r3,%r3
592132075Sgrehan	bne	dbleave
593132075Sgrehan/* This wasn't for KDB, so switch to real trap: */
594209975Snwhitehorn	ld	%r3,FRAME_EXC+48(%r1)	/* save exception */
595125441Sgrehan	GET_CPUINFO(%r4)
596209975Snwhitehorn	std	%r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
597132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
598125441Sgrehan	mtsprg1	%r1			/* prepare for entrance to realtrap */
599125441Sgrehan	GET_CPUINFO(%r1)
600209975Snwhitehorn	std	%r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
601209975Snwhitehorn	std	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
602209975Snwhitehorn	std	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
603209975Snwhitehorn	std	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
604209975Snwhitehorn	std	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
605125441Sgrehan	mflr	%r28
606125441Sgrehan	mfcr	%r29
607209975Snwhitehorn	ld	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
608190946Snwhitehorn	mtsprg3	%r31			/* SPRG3 was clobbered by FRAME_LEAVE */
609125441Sgrehan	mfsprg1	%r1
61095719Sbenno	b	realtrap
611132075Sgrehandbleave:
612132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
613209975Snwhitehorn	rfid
61495719Sbenno
61595719Sbenno/*
616132075Sgrehan * In case of KDB we want a separate trap catcher for it
61795719Sbenno */
618132075Sgrehan	.globl	CNAME(dblow),CNAME(dbsize)
619132075SgrehanCNAME(dblow):
620125441Sgrehan	mtsprg1	%r1			/* save SP */
621125441Sgrehan	mtsprg2	%r29			/* save r29 */
622125441Sgrehan	mfcr	%r29			/* save CR in r29 */
623125441Sgrehan	mfsrr1	%r1
624125441Sgrehan	mtcr	%r1
625125441Sgrehan	bf	17,1f			/* branch if privileged */
626188860Snwhitehorn
627188860Snwhitehorn	/* Unprivileged case */
628188860Snwhitehorn	mtcr	%r29			/* put the condition register back */
629188860Snwhitehorn        mfsprg2	%r29			/* ... and r29 */
630188860Snwhitehorn        mflr	%r1			/* save LR */
631188860Snwhitehorn	mtsprg2 %r1			/* And then in SPRG2 */
632188860Snwhitehorn	li	%r1, 0	 		/* How to get the vector from LR */
633188860Snwhitehorn
634188860Snwhitehorn        bla     generictrap		/* and we look like a generic trap */
635125441Sgrehan1:
636188860Snwhitehorn	/* Privileged, so drop to KDB */
637188860Snwhitehorn	GET_CPUINFO(%r1)
638209975Snwhitehorn	std	%r27,(PC_DBSAVE+CPUSAVE_R27)(%r1)	/* free r27 */
639209975Snwhitehorn	std	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
640125441Sgrehan        mfsprg2	%r28				/* r29 holds cr...  */
641209975Snwhitehorn        std	%r28,(PC_DBSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
642209975Snwhitehorn        std	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
643209975Snwhitehorn        std	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
644125441Sgrehan        mflr	%r28					/* save LR */
645132075Sgrehan	bla	dbtrap
646132075SgrehanCNAME(dbsize) = .-CNAME(dblow)
647132075Sgrehan#endif /* KDB */
648