trap_subr64.S revision 153685
195719Sbenno/* $FreeBSD: head/sys/powerpc/aim/trap_subr.S 153685 2005-12-23 13:05:27Z grehan $ */
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 *
3995719Sbenno *	#include <powerpc/powerpc/trap_subr.S>
4095719Sbenno */
4195719Sbenno
4295719Sbenno/*
43125441Sgrehan * Save/restore segment registers
4495719Sbenno */
45125441Sgrehan#define RESTORE_SRS(pmap,sr)	mtsr    0,sr; \
46125441Sgrehan	lwz	sr,1*4(pmap);	mtsr	1,sr; \
47125441Sgrehan	lwz	sr,2*4(pmap);	mtsr	2,sr; \
48125441Sgrehan	lwz	sr,3*4(pmap);	mtsr	3,sr; \
49125441Sgrehan	lwz	sr,4*4(pmap);	mtsr	4,sr; \
50125441Sgrehan	lwz	sr,5*4(pmap);	mtsr	5,sr; \
51125441Sgrehan	lwz	sr,6*4(pmap);	mtsr	6,sr; \
52125441Sgrehan	lwz	sr,7*4(pmap);	mtsr	7,sr; \
53125441Sgrehan	lwz	sr,8*4(pmap);	mtsr	8,sr; \
54125441Sgrehan	lwz	sr,9*4(pmap);	mtsr	9,sr; \
55125441Sgrehan	lwz	sr,10*4(pmap);	mtsr	10,sr; \
56125441Sgrehan	lwz	sr,11*4(pmap);	mtsr	11,sr; \
57125441Sgrehan	lwz	sr,12*4(pmap);	mtsr	12,sr; \
58125441Sgrehan	lwz	sr,13*4(pmap);	mtsr	13,sr; \
59125441Sgrehan	lwz	sr,14*4(pmap);	mtsr	14,sr; \
60125441Sgrehan	lwz	sr,15*4(pmap);	mtsr	15,sr; isync;
6195719Sbenno
6295719Sbenno/*
63125441Sgrehan * User SRs are loaded through a pointer to the current pmap.
6495719Sbenno */
65125441Sgrehan#define RESTORE_USER_SRS(pmap,sr) \
66125441Sgrehan	GET_CPUINFO(pmap); \
67125441Sgrehan	lwz	pmap,PC_CURPMAP(pmap); \
68125441Sgrehan	lwzu	sr,PM_SR(pmap); \
69125441Sgrehan	RESTORE_SRS(pmap,sr)
7095719Sbenno
7195719Sbenno/*
72125441Sgrehan * Kernel SRs are loaded directly from kernel_pmap_
7395719Sbenno */
74125441Sgrehan#define RESTORE_KERN_SRS(pmap,sr) \
75125441Sgrehan	lis	pmap,CNAME(kernel_pmap_store)@ha; \
76125441Sgrehan	lwzu	sr,CNAME(kernel_pmap_store)+PM_SR@l(pmap); \
77125441Sgrehan	RESTORE_SRS(pmap,sr)
7895719Sbenno
79125441Sgrehan/*
80125441Sgrehan * FRAME_SETUP assumes:
81125441Sgrehan *	SPRG1		SP (1)
82125441Sgrehan *	savearea	r28-r31,DAR,DSISR   (DAR & DSISR only for DSI traps)
83125441Sgrehan *	r28		LR
84125441Sgrehan *	r29		CR
85125441Sgrehan *	r30		scratch
86125441Sgrehan *	r31		scratch
87125441Sgrehan *	r1		kernel stack
88125441Sgrehan *	LR		trap type (from calling address, mask with 0xff00)
89125441Sgrehan *	SRR0/1		as at start of trap
90125441Sgrehan */
91125441Sgrehan#define	FRAME_SETUP(savearea)						\
92125441Sgrehan/* Have to enable translation to allow access of kernel stack: */	\
93125441Sgrehan	GET_CPUINFO(%r31);						\
94125441Sgrehan	mfsrr0	%r30;							\
95125441Sgrehan	stw	%r30,(savearea+CPUSAVE_SRR0)(%r31);	/* save SRR0 */	\
96125441Sgrehan	mfsrr1	%r30;							\
97125441Sgrehan	stw	%r30,(savearea+CPUSAVE_SRR1)(%r31);	/* save SRR1 */	\
98125441Sgrehan	mfmsr	%r30;							\
99125441Sgrehan	ori	%r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */	\
100125441Sgrehan	mtmsr	%r30;			/* stack can now be accessed */	\
101125441Sgrehan	isync;								\
102125441Sgrehan	mfsprg1	%r31;			/* get saved SP */		\
103125441Sgrehan	stwu	%r31,-FRAMELEN(%r1);	/* save it in the callframe */	\
104125441Sgrehan	stw	%r0, FRAME_0+8(%r1);	/* save r0 in the trapframe */	\
105125441Sgrehan	stw	%r31,FRAME_1+8(%r1);	/* save SP   "      "       */	\
106125441Sgrehan	stw	%r2, FRAME_2+8(%r1);	/* save r2   "      "       */	\
107125441Sgrehan	stw	%r28,FRAME_LR+8(%r1);	/* save LR   "      "       */	\
108125441Sgrehan	stw	%r29,FRAME_CR+8(%r1);	/* save CR   "      "       */	\
109125441Sgrehan	GET_CPUINFO(%r2);						\
110125441Sgrehan	lwz	%r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */	\
111125441Sgrehan	lwz	%r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */	\
112125441Sgrehan	lwz	%r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */	\
113125441Sgrehan	lwz	%r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */	\
114125441Sgrehan	stw	%r3,  FRAME_3+8(%r1);	/* save r3-r31 */		\
115125441Sgrehan	stw	%r4,  FRAME_4+8(%r1);					\
116125441Sgrehan	stw	%r5,  FRAME_5+8(%r1);					\
117125441Sgrehan	stw	%r6,  FRAME_6+8(%r1);					\
118125441Sgrehan	stw	%r7,  FRAME_7+8(%r1);					\
119125441Sgrehan	stw	%r8,  FRAME_8+8(%r1);					\
120125441Sgrehan	stw	%r9,  FRAME_9+8(%r1);					\
121125441Sgrehan	stw	%r10, FRAME_10+8(%r1);					\
122125441Sgrehan	stw	%r11, FRAME_11+8(%r1);					\
123125441Sgrehan	stw	%r12, FRAME_12+8(%r1);					\
124125441Sgrehan	stw	%r13, FRAME_13+8(%r1);					\
125125441Sgrehan	stw	%r14, FRAME_14+8(%r1);					\
126125441Sgrehan	stw	%r15, FRAME_15+8(%r1);					\
127125441Sgrehan	stw	%r16, FRAME_16+8(%r1);					\
128125441Sgrehan	stw	%r17, FRAME_17+8(%r1);					\
129125441Sgrehan	stw	%r18, FRAME_18+8(%r1);					\
130125441Sgrehan	stw	%r19, FRAME_19+8(%r1);					\
131125441Sgrehan	stw	%r20, FRAME_20+8(%r1);					\
132125441Sgrehan	stw	%r21, FRAME_21+8(%r1);					\
133125441Sgrehan	stw	%r22, FRAME_22+8(%r1);					\
134125441Sgrehan	stw	%r23, FRAME_23+8(%r1);					\
135125441Sgrehan	stw	%r24, FRAME_24+8(%r1);					\
136125441Sgrehan	stw	%r25, FRAME_25+8(%r1);					\
137125441Sgrehan	stw	%r26, FRAME_26+8(%r1);					\
138125441Sgrehan	stw	%r27, FRAME_27+8(%r1);					\
139125441Sgrehan	stw	%r28, FRAME_28+8(%r1);					\
140125441Sgrehan	stw	%r29, FRAME_29+8(%r1);					\
141125441Sgrehan	stw	%r30, FRAME_30+8(%r1);					\
142125441Sgrehan	stw	%r31, FRAME_31+8(%r1);					\
143125441Sgrehan	lwz	%r28,(savearea+CPUSAVE_DAR)(%r2);  /* saved DAR */	\
144125441Sgrehan	lwz	%r29,(savearea+CPUSAVE_DSISR)(%r2);/* saved DSISR */	\
145125441Sgrehan	lwz	%r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */	\
146125441Sgrehan	lwz	%r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */	\
147125441Sgrehan	mfxer	%r3;							\
148125441Sgrehan	mfctr	%r4;							\
149125441Sgrehan	mflr	%r5;							\
150125441Sgrehan	andi.	%r5,%r5,0xff00;		/* convert LR to exc # */	\
151125441Sgrehan	stw	%r3, FRAME_XER+8(1);	/* save xer/ctr/exc */		\
152125441Sgrehan	stw	%r4, FRAME_CTR+8(1);					\
153125441Sgrehan	stw	%r5, FRAME_EXC+8(1);					\
154125441Sgrehan	stw	%r28,FRAME_DAR+8(1);					\
155125441Sgrehan	stw	%r29,FRAME_DSISR+8(1);	/* save dsisr/srr0/srr1 */	\
156125441Sgrehan	stw	%r30,FRAME_SRR0+8(1);					\
157125441Sgrehan	stw	%r31,FRAME_SRR1+8(1)
15895719Sbenno
159125441Sgrehan#define	FRAME_LEAVE(savearea)						\
160125441Sgrehan/* Now restore regs: */							\
161125441Sgrehan	lwz	%r2,FRAME_SRR0+8(%r1);					\
162125441Sgrehan	lwz	%r3,FRAME_SRR1+8(%r1);					\
163125441Sgrehan	lwz	%r4,FRAME_CTR+8(%r1);					\
164125441Sgrehan	lwz	%r5,FRAME_XER+8(%r1);					\
165125441Sgrehan	lwz	%r6,FRAME_LR+8(%r1);					\
166125441Sgrehan	GET_CPUINFO(%r7);						\
167125441Sgrehan	stw	%r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */	\
168125441Sgrehan	stw	%r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */	\
169125441Sgrehan	lwz	%r7,FRAME_CR+8(%r1);					\
170125441Sgrehan	mtctr	%r4;							\
171125441Sgrehan	mtxer	%r5;							\
172125441Sgrehan	mtlr	%r6;							\
173125441Sgrehan	mtsprg1	%r7;			/* save cr */			\
174125441Sgrehan	lwz	%r31,FRAME_31+8(%r1);   /* restore r0-31 */		\
175125441Sgrehan	lwz	%r30,FRAME_30+8(%r1);					\
176125441Sgrehan	lwz	%r29,FRAME_29+8(%r1);					\
177125441Sgrehan	lwz	%r28,FRAME_28+8(%r1);					\
178125441Sgrehan	lwz	%r27,FRAME_27+8(%r1);					\
179125441Sgrehan	lwz	%r26,FRAME_26+8(%r1);					\
180125441Sgrehan	lwz	%r25,FRAME_25+8(%r1);					\
181125441Sgrehan	lwz	%r24,FRAME_24+8(%r1);					\
182125441Sgrehan	lwz	%r23,FRAME_23+8(%r1);					\
183125441Sgrehan	lwz	%r22,FRAME_22+8(%r1);					\
184125441Sgrehan	lwz	%r21,FRAME_21+8(%r1);					\
185125441Sgrehan	lwz	%r20,FRAME_20+8(%r1);					\
186125441Sgrehan	lwz	%r19,FRAME_19+8(%r1);					\
187125441Sgrehan	lwz	%r18,FRAME_18+8(%r1);					\
188125441Sgrehan	lwz	%r17,FRAME_17+8(%r1);					\
189125441Sgrehan	lwz	%r16,FRAME_16+8(%r1);					\
190125441Sgrehan	lwz	%r15,FRAME_15+8(%r1);					\
191125441Sgrehan	lwz	%r14,FRAME_14+8(%r1);					\
192125441Sgrehan	lwz	%r13,FRAME_13+8(%r1);					\
193125441Sgrehan	lwz	%r12,FRAME_12+8(%r1);					\
194125441Sgrehan	lwz	%r11,FRAME_11+8(%r1);					\
195125441Sgrehan	lwz	%r10,FRAME_10+8(%r1);					\
196125441Sgrehan	lwz	%r9, FRAME_9+8(%r1);					\
197125441Sgrehan	lwz	%r8, FRAME_8+8(%r1);					\
198125441Sgrehan	lwz	%r7, FRAME_7+8(%r1);					\
199125441Sgrehan	lwz	%r6, FRAME_6+8(%r1);					\
200125441Sgrehan	lwz	%r5, FRAME_5+8(%r1);					\
201125441Sgrehan	lwz	%r4, FRAME_4+8(%r1);					\
202125441Sgrehan	lwz	%r3, FRAME_3+8(%r1);					\
203125441Sgrehan	lwz	%r2, FRAME_2+8(%r1);					\
204125441Sgrehan	lwz	%r0, FRAME_0+8(%r1);					\
205125441Sgrehan	lwz	%r1, FRAME_1+8(%r1);					\
206125441Sgrehan/* Can't touch %r1 from here on */					\
207125441Sgrehan	mtsprg2	%r2;			/* save r2 & r3 */		\
208125441Sgrehan	mtsprg3	%r3;							\
209125441Sgrehan/* Disable translation, machine check and recoverability: */		\
210125441Sgrehan	mfmsr	%r2;							\
211125441Sgrehan	andi.	%r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l;	\
212125441Sgrehan	mtmsr	%r2;							\
213125441Sgrehan	isync;								\
214125441Sgrehan/* Decide whether we return to user mode: */				\
215125441Sgrehan	GET_CPUINFO(%r2);						\
216125441Sgrehan	lwz	%r3,(savearea+CPUSAVE_SRR1)(%r2);			\
217125441Sgrehan	mtcr	%r3;							\
218125441Sgrehan	bf	17,1f;			/* branch if PSL_PR is false */	\
219125441Sgrehan/* Restore user SRs */							\
220125441Sgrehan	RESTORE_USER_SRS(%r2,%r3);					\
221125441Sgrehan1:	mfsprg1	%r2;			/* restore cr */		\
222125441Sgrehan	mtcr	%r2;							\
223125441Sgrehan	GET_CPUINFO(%r2);						\
224125441Sgrehan	lwz	%r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */	\
225125441Sgrehan	mtsrr0	%r3;							\
226125441Sgrehan	lwz	%r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */	\
227125441Sgrehan	mtsrr1	%r3;							\
228125441Sgrehan	mfsprg2	%r2;			/* restore r2 & r3 */		\
229125441Sgrehan	mfsprg3	%r3
23095719Sbenno
231132571Sgrehan#ifdef KDB
23295719Sbenno/*
233132571Sgrehan * Define the kdb debugger stack
234132571Sgrehan */
235132571Sgrehan	.data
236132571SgrehanGLOBAL(dbstk)
237132571Sgrehan	.space INTSTK+8			/* kdb stack */
238132571Sgrehan#endif
239132571Sgrehan
240132571Sgrehan/*
24195719Sbenno * This code gets copied to all the trap vectors
242125441Sgrehan * (except ISI/DSI, ALI, and the interrupts)
24395719Sbenno */
24495719Sbenno	.text
24596773Sbenno	.globl	CNAME(trapcode),CNAME(trapsize)
24696773SbennoCNAME(trapcode):
247125441Sgrehan	mtsprg1	%r1			/* save SP */
248125441Sgrehan	GET_CPUINFO(%r1)
249125441Sgrehan	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)	/* free r28-r31 */
250125441Sgrehan	stw	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
251125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
252125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
253125441Sgrehan	mfsprg1	%r1			/* restore SP, in case of branch */
254125441Sgrehan	mflr	%r28			/* save LR */
255125441Sgrehan	mfcr	%r29			/* save CR */
25695719Sbenno/* Test whether we already had PR set */
257125441Sgrehan	mfsrr1	%r31
258125441Sgrehan	mtcr	%r31
259125441Sgrehan	bla	s_trap			/* LR & 0xff00 is exception # */
26096773SbennoCNAME(trapsize) = .-CNAME(trapcode)
26195719Sbenno
26295719Sbenno/*
26395719Sbenno * For ALI: has to save DSISR and DAR
26495719Sbenno */
26596773Sbenno	.globl	CNAME(alitrap),CNAME(alisize)
26696773SbennoCNAME(alitrap):
267125441Sgrehan	mtsprg1	%r1			/* save SP */
268125441Sgrehan	GET_CPUINFO(%r1)
269125441Sgrehan	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)	/* free r28-r31 */
270125441Sgrehan	stw	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
271125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
272125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
273125441Sgrehan	mfdar	%r30
274125441Sgrehan	mfdsisr	%r31
275125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1)
276125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1)
277125441Sgrehan	mfsprg1	%r1			/* restore SP, in case of branch */
278125441Sgrehan	mflr	%r28			/* save LR */
279125441Sgrehan	mfcr	%r29			/* save CR */
28095719Sbenno/* Test whether we already had PR set */
281125441Sgrehan	mfsrr1	%r31
282125441Sgrehan	mtcr	%r31
283125441Sgrehan	bla	s_trap			/* LR & 0xff00 is exception # */
28496773SbennoCNAME(alisize) = .-CNAME(alitrap)
28595719Sbenno
28695719Sbenno/*
28795719Sbenno * Similar to the above for DSI
28895719Sbenno * Has to handle BAT spills
28995719Sbenno * and standard pagetable spills
29095719Sbenno */
29196773Sbenno	.globl	CNAME(dsitrap),CNAME(dsisize)
29296773SbennoCNAME(dsitrap):
293125441Sgrehan	mtsprg1	%r1			/* save SP */
294125441Sgrehan	GET_CPUINFO(%r1)
295125441Sgrehan	stw	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)	/* free r28-r31 */
296125441Sgrehan	stw	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
297125441Sgrehan	stw	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
298125441Sgrehan	stw	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
299125441Sgrehan	mfsprg1	%r1			/* restore SP */
300125441Sgrehan	mfcr	%r29			/* save CR */
301125441Sgrehan	mfxer	%r30			/* save XER */
302125441Sgrehan	mtsprg2	%r30			/* in SPRG2 */
303125441Sgrehan	mfsrr1	%r31			/* test kernel mode */
304125441Sgrehan	mtcr	%r31
305125441Sgrehan	bt	17,1f			/* branch if PSL_PR is set */
306125441Sgrehan	mfdar	%r31			/* get fault address */
307125441Sgrehan	rlwinm	%r31,%r31,7,25,28	/* get segment * 8 */
30895719Sbenno
30995719Sbenno	/* get batu */
310125441Sgrehan	addis	%r31,%r31,CNAME(battable)@ha
311125441Sgrehan	lwz	%r30,CNAME(battable)@l(31)
312125441Sgrehan	mtcr	%r30
313125441Sgrehan	bf	30,1f			/* branch if supervisor valid is
31495719Sbenno					   false */
31595719Sbenno	/* get batl */
316125441Sgrehan	lwz	%r31,CNAME(battable)+4@l(31)
31795719Sbenno/* We randomly use the highest two bat registers here */
318125441Sgrehan	mftb	%r28
319125441Sgrehan	andi.	%r28,%r28,1
32095719Sbenno	bne	2f
321125441Sgrehan	mtdbatu	2,%r30
322125441Sgrehan	mtdbatl	2,%r31
32395719Sbenno	b	3f
32495719Sbenno2:
325125441Sgrehan	mtdbatu	3,%r30
326125441Sgrehan	mtdbatl	3,%r31
32795719Sbenno3:
328125441Sgrehan	mfsprg2	%r30			/* restore XER */
329125441Sgrehan	mtxer	%r30
330125441Sgrehan	mtcr	%r29			/* restore CR */
331125441Sgrehan	mtsprg1	%r1
332125441Sgrehan	GET_CPUINFO(%r1)
333125441Sgrehan	lwz	%r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)	/* restore r28-r31 */
334125441Sgrehan	lwz	%r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
335125441Sgrehan	lwz	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
336125441Sgrehan	lwz	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
337125441Sgrehan	mfsprg1	%r1
33895719Sbenno	rfi				/* return to trapped code */
33995719Sbenno1:
340125441Sgrehan	mflr	%r28			/* save LR (SP already saved) */
341125441Sgrehan	bla	disitrap
34296773SbennoCNAME(dsisize) = .-CNAME(dsitrap)
34395719Sbenno
34495719Sbenno/*
34595719Sbenno * Preamble code for DSI/ISI traps
34695719Sbenno */
34795719Sbennodisitrap:
348125441Sgrehan	GET_CPUINFO(%r1)
349125441Sgrehan	lwz	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
350125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
351125441Sgrehan	lwz	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
352125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
353125441Sgrehan	lwz	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
354125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
355125441Sgrehan	lwz	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
356125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
357125441Sgrehan	mfdar	%r30
358125441Sgrehan	mfdsisr	%r31
359125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1)
360125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1)
361125441Sgrehan
362132571Sgrehan#ifdef KDB
363132571Sgrehan	/* Try and detect a kernel stack overflow */
364132571Sgrehan	mfsrr1	%r31
365132571Sgrehan	mtcr	%r31
366132571Sgrehan	bt	17,realtrap		/* branch is user mode */
367132571Sgrehan	mfsprg1	%r31			/* get old SP */
368132571Sgrehan	sub.	%r30,%r31,%r30		/* SP - DAR */
369132571Sgrehan	bge	1f
370132571Sgrehan	neg	%r30,%r30		/* modulo value */
371132571Sgrehan1:	cmplwi	%cr0,%r30,4096		/* is DAR within a page of SP? */
372132571Sgrehan	bge	%cr0,realtrap		/* no, too far away. */
373132571Sgrehan
374132571Sgrehan	/* Now convert this DSI into a DDB trap.  */
375132571Sgrehan	GET_CPUINFO(%r1)
376132683Sgrehan	lwz	%r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) /* get DAR */
377132683Sgrehan	stw	%r30,(PC_DBSAVE  +CPUSAVE_DAR)(%r1) /* save DAR */
378132683Sgrehan	lwz	%r30,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) /* get DSISR */
379132683Sgrehan	lwz	%r30,(PC_DBSAVE  +CPUSAVE_DSISR)(%r1) /* save DSISR */
380132571Sgrehan	lwz	%r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get  r28 */
381132571Sgrehan	stw	%r30,(PC_DBSAVE  +CPUSAVE_R28)(%r1) /* save r28 */
382132571Sgrehan	lwz	%r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get  r29 */
383132571Sgrehan	stw	%r31,(PC_DBSAVE  +CPUSAVE_R29)(%r1) /* save r29 */
384132571Sgrehan	lwz	%r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get  r30 */
385132571Sgrehan	stw	%r30,(PC_DBSAVE  +CPUSAVE_R30)(%r1) /* save r30 */
386132571Sgrehan	lwz	%r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get  r31 */
387132571Sgrehan	stw	%r31,(PC_DBSAVE  +CPUSAVE_R31)(%r1) /* save r31 */
388132571Sgrehan	lis	%r1,dbstk+INTSTK@ha	/* get new SP */
389132571Sgrehan	addi	%r1,%r1,dbstk+INTSTK@l
390132571Sgrehan	b	dbtrap
391132571Sgrehan#endif
392132571Sgrehan
393125441Sgrehan	/* XXX need stack probe here */
39495719Sbennorealtrap:
39595719Sbenno/* Test whether we already had PR set */
396125441Sgrehan	mfsrr1	%r1
397125441Sgrehan	mtcr	%r1
398125441Sgrehan	mfsprg1	%r1			/* restore SP (might have been
39995719Sbenno					   overwritten) */
400125441Sgrehans_trap:
401125441Sgrehan	bf	17,k_trap		/* branch if PSL_PR is false */
402125441Sgrehan	GET_CPUINFO(%r1)
403125441Sgrehanu_trap:
404125441Sgrehan	lwz	%r1,PC_CURPCB(%r1)
405125441Sgrehan	RESTORE_KERN_SRS(%r30,%r31)	/* enable kernel mapping */
40695719Sbenno
40795719Sbenno/*
40895719Sbenno * Now the common trap catching code.
40995719Sbenno */
410125441Sgrehank_trap:
411125441Sgrehan	FRAME_SETUP(PC_TEMPSAVE)
41299032Sbenno/* Call C interrupt dispatcher: */
41395719Sbennotrapagain:
414125441Sgrehan	addi	%r3,%r1,8
41599032Sbenno	bl	CNAME(powerpc_interrupt)
416132075Sgrehan	.globl	CNAME(trapexit)		/* backtrace code sentinel */
41796773SbennoCNAME(trapexit):
41899032Sbenno
41995719Sbenno/* Disable interrupts: */
420125441Sgrehan	mfmsr	%r3
421125441Sgrehan	andi.	%r3,%r3,~PSL_EE@l
422125441Sgrehan	mtmsr	%r3
42395719Sbenno/* Test AST pending: */
424125441Sgrehan	lwz	%r5,FRAME_SRR1+8(%r1)
425125441Sgrehan	mtcr	%r5
426125441Sgrehan	bf	17,1f			/* branch if PSL_PR is false */
42799032Sbenno
428125441Sgrehan	GET_CPUINFO(%r3)		/* get per-CPU pointer */
429125441Sgrehan	lwz	%r4, PC_CURTHREAD(%r3)	/* deref to get curthread */
430125441Sgrehan	lwz	%r4, TD_FLAGS(%r4)	/* get thread flags value */
431125441Sgrehan	lis	%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
432125441Sgrehan	ori	%r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
433125441Sgrehan	and.	%r4,%r4,%r5
43495719Sbenno	beq	1f
435125441Sgrehan	mfmsr	%r3			/* re-enable interrupts */
436125441Sgrehan	ori	%r3,%r3,PSL_EE@l
437125441Sgrehan	mtmsr	%r3
43899032Sbenno	isync
439125441Sgrehan	addi	%r3,%r1,8
440103608Sgrehan	bl	CNAME(ast)
441153685Sgrehan	.globl	CNAME(asttrapexit)	/* backtrace code sentinel #2 */
442153685SgrehanCNAME(asttrapexit):
44399032Sbenno	b	trapexit		/* test ast ret value ? */
44495719Sbenno1:
445125441Sgrehan	FRAME_LEAVE(PC_TEMPSAVE)
44695719Sbenno	rfi
44795719Sbenno
448148568Sgrehan/*
449148568Sgrehan *     Temporary: vector-unavailable traps are directed to vector-assist traps
450148568Sgrehan */
451148568Sgrehan	.globl  CNAME(vectrap),CNAME(vectrapsize)
452148568SgrehanCNAME(vectrap):
453148568Sgrehan	ba	EXC_VECAST
454148568SgrehanCNAME(vectrapsize) = .-CNAME(vectrap)
455148568Sgrehan
456132075Sgrehan#if defined(KDB)
45795719Sbenno/*
458132075Sgrehan * Deliberate entry to dbtrap
45995719Sbenno */
460132075Sgrehan	.globl	CNAME(ppc_db_trap)
461132075SgrehanCNAME(ppc_db_trap):
462125441Sgrehan	mtsprg1	%r1
463125441Sgrehan	mfmsr	%r3
464125441Sgrehan	mtsrr1	%r3
465125441Sgrehan	andi.	%r3,%r3,~(PSL_EE|PSL_ME)@l
466125441Sgrehan	mtmsr	%r3			/* disable interrupts */
46795719Sbenno	isync
468125441Sgrehan	GET_CPUINFO(%r3)
469132075Sgrehan	stw	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
470132075Sgrehan	stw	%r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
471132075Sgrehan	stw	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
472132075Sgrehan	stw	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
473125441Sgrehan	mflr	%r28
474125441Sgrehan	li	%r29,EXC_BPT
475125441Sgrehan	mtlr	%r29
476125441Sgrehan	mfcr	%r29
477125441Sgrehan	mtsrr0	%r28
47895719Sbenno
47995719Sbenno/*
480132075Sgrehan * Now the kdb trap catching code.
48195719Sbenno */
482132075Sgrehandbtrap:
483132075Sgrehan	FRAME_SETUP(PC_DBSAVE)
48495719Sbenno/* Call C trap code: */
485125441Sgrehan	addi	%r3,%r1,8
486132075Sgrehan	bl	CNAME(db_trap_glue)
487125441Sgrehan	or.	%r3,%r3,%r3
488132075Sgrehan	bne	dbleave
489132075Sgrehan/* This wasn't for KDB, so switch to real trap: */
490125441Sgrehan	lwz	%r3,FRAME_EXC+8(%r1)	/* save exception */
491125441Sgrehan	GET_CPUINFO(%r4)
492132075Sgrehan	stw	%r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
493132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
494125441Sgrehan	mtsprg1	%r1			/* prepare for entrance to realtrap */
495125441Sgrehan	GET_CPUINFO(%r1)
496125441Sgrehan	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
497125441Sgrehan	stw	%r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
498125441Sgrehan	stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
499125441Sgrehan	stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
500125441Sgrehan	mflr	%r28
501125441Sgrehan	mfcr	%r29
502132075Sgrehan	lwz	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
503125441Sgrehan	mtlr	%r31
504125441Sgrehan	mfsprg1	%r1
50595719Sbenno	b	realtrap
506132075Sgrehandbleave:
507132075Sgrehan	FRAME_LEAVE(PC_DBSAVE)
50895719Sbenno	rfi
50995719Sbenno
51095719Sbenno/*
511132075Sgrehan * In case of KDB we want a separate trap catcher for it
51295719Sbenno */
513132075Sgrehan	.globl	CNAME(dblow),CNAME(dbsize)
514132075SgrehanCNAME(dblow):
515125441Sgrehan	mtsprg1	%r1			/* save SP */
516125441Sgrehan	mtsprg2	%r29			/* save r29 */
517125441Sgrehan	mfcr	%r29			/* save CR in r29 */
518125441Sgrehan	mfsrr1	%r1
519125441Sgrehan	mtcr	%r1
520125441Sgrehan	GET_CPUINFO(%r1)
521125441Sgrehan	bf	17,1f			/* branch if privileged */
522125441Sgrehan	stw	%r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
523125441Sgrehan        mfsprg2	%r28				/* r29 holds cr ... */
524125441Sgrehan        stw	%r28,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
525125441Sgrehan        stw	%r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
526125441Sgrehan        stw	%r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
527125441Sgrehan        mflr	%r28					/* save LR */
528125441Sgrehan        bla     u_trap
529125441Sgrehan1:
530132075Sgrehan	stw	%r28,(PC_DBSAVE+CPUSAVE_R28)(%r1)	/* free r28 */
531125441Sgrehan        mfsprg2	%r28				/* r29 holds cr...  */
532132075Sgrehan        stw	%r28,(PC_DBSAVE+CPUSAVE_R29)(%r1)	/* free r29 */
533132075Sgrehan        stw	%r30,(PC_DBSAVE+CPUSAVE_R30)(%r1)	/* free r30 */
534132075Sgrehan        stw	%r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)	/* free r31 */
535125441Sgrehan        mflr	%r28					/* save LR */
536132075Sgrehan	lis	%r1,dbstk+INTSTK@ha	/* get new SP */
537132075Sgrehan	addi	%r1,%r1,dbstk+INTSTK@l
538132075Sgrehan	bla	dbtrap
539132075SgrehanCNAME(dbsize) = .-CNAME(dblow)
540132075Sgrehan#endif /* KDB */
541