xref: /openbmc/linux/arch/sparc/kernel/wuf.S (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds/* $Id: wuf.S,v 1.39 2000/01/08 16:38:18 anton Exp $
2*1da177e4SLinus Torvalds * wuf.S: Window underflow trap handler for the Sparc.
3*1da177e4SLinus Torvalds *
4*1da177e4SLinus Torvalds * Copyright (C) 1995 David S. Miller
5*1da177e4SLinus Torvalds */
6*1da177e4SLinus Torvalds
7*1da177e4SLinus Torvalds#include <asm/contregs.h>
8*1da177e4SLinus Torvalds#include <asm/page.h>
9*1da177e4SLinus Torvalds#include <asm/ptrace.h>
10*1da177e4SLinus Torvalds#include <asm/psr.h>
11*1da177e4SLinus Torvalds#include <asm/smp.h>
12*1da177e4SLinus Torvalds#include <asm/asi.h>
13*1da177e4SLinus Torvalds#include <asm/winmacro.h>
14*1da177e4SLinus Torvalds#include <asm/asmmacro.h>
15*1da177e4SLinus Torvalds#include <asm/thread_info.h>
16*1da177e4SLinus Torvalds
17*1da177e4SLinus Torvalds/* Just like the overflow handler we define macros for registers
18*1da177e4SLinus Torvalds * with fixed meanings in this routine.
19*1da177e4SLinus Torvalds */
20*1da177e4SLinus Torvalds#define t_psr       l0
21*1da177e4SLinus Torvalds#define t_pc        l1
22*1da177e4SLinus Torvalds#define t_npc       l2
23*1da177e4SLinus Torvalds#define t_wim       l3
24*1da177e4SLinus Torvalds/* Don't touch the above registers or else you die horribly... */
25*1da177e4SLinus Torvalds
26*1da177e4SLinus Torvalds/* Now macros for the available scratch registers in this routine. */
27*1da177e4SLinus Torvalds#define twin_tmp1    l4
28*1da177e4SLinus Torvalds#define twin_tmp2    l5
29*1da177e4SLinus Torvalds
30*1da177e4SLinus Torvalds#define curptr       g6
31*1da177e4SLinus Torvalds
32*1da177e4SLinus Torvalds	.text
33*1da177e4SLinus Torvalds	.align	4
34*1da177e4SLinus Torvalds
35*1da177e4SLinus Torvalds	/* The trap entry point has executed the following:
36*1da177e4SLinus Torvalds	 *
37*1da177e4SLinus Torvalds	 * rd    %psr, %l0
38*1da177e4SLinus Torvalds	 * rd    %wim, %l3
39*1da177e4SLinus Torvalds	 * b     fill_window_entry
40*1da177e4SLinus Torvalds	 * andcc %l0, PSR_PS, %g0
41*1da177e4SLinus Torvalds	 */
42*1da177e4SLinus Torvalds
43*1da177e4SLinus Torvalds	/* Datum current_thread_info->uwinmask contains at all times a bitmask
44*1da177e4SLinus Torvalds	 * where if any user windows are active, at least one bit will
45*1da177e4SLinus Torvalds	 * be set in to mask.  If no user windows are active, the bitmask
46*1da177e4SLinus Torvalds	 * will be all zeroes.
47*1da177e4SLinus Torvalds	 */
48*1da177e4SLinus Torvalds
49*1da177e4SLinus Torvalds	/* To get an idea of what has just happened to cause this
50*1da177e4SLinus Torvalds	 * trap take a look at this diagram:
51*1da177e4SLinus Torvalds	 *
52*1da177e4SLinus Torvalds	 *      1  2  3  4     <--  Window number
53*1da177e4SLinus Torvalds	 *      ----------
54*1da177e4SLinus Torvalds	 *      T  O  W  I     <--  Symbolic name
55*1da177e4SLinus Torvalds	 *
56*1da177e4SLinus Torvalds	 *      O == the window that execution was in when
57*1da177e4SLinus Torvalds	 *           the restore was attempted
58*1da177e4SLinus Torvalds	 *
59*1da177e4SLinus Torvalds	 *      T == the trap itself has save'd us into this
60*1da177e4SLinus Torvalds	 *           window
61*1da177e4SLinus Torvalds	 *
62*1da177e4SLinus Torvalds	 *      W == this window is the one which is now invalid
63*1da177e4SLinus Torvalds	 *           and must be made valid plus loaded from the
64*1da177e4SLinus Torvalds	 *           stack
65*1da177e4SLinus Torvalds	 *
66*1da177e4SLinus Torvalds	 *      I == this window will be the invalid one when we
67*1da177e4SLinus Torvalds	 *           are done and return from trap if successful
68*1da177e4SLinus Torvalds	 */
69*1da177e4SLinus Torvalds
70*1da177e4SLinus Torvalds	/* BEGINNING OF PATCH INSTRUCTIONS */
71*1da177e4SLinus Torvalds
72*1da177e4SLinus Torvalds	/* On 7-window Sparc the boot code patches fnwin_patch1
73*1da177e4SLinus Torvalds	 * with the following instruction.
74*1da177e4SLinus Torvalds	 */
75*1da177e4SLinus Torvalds	.globl	fnwin_patch1_7win, fnwin_patch2_7win
76*1da177e4SLinus Torvaldsfnwin_patch1_7win:	srl	%t_wim, 6, %twin_tmp2
77*1da177e4SLinus Torvaldsfnwin_patch2_7win:	and	%twin_tmp1, 0x7f, %twin_tmp1
78*1da177e4SLinus Torvalds	/* END OF PATCH INSTRUCTIONS */
79*1da177e4SLinus Torvalds
80*1da177e4SLinus Torvalds	.globl	fill_window_entry, fnwin_patch1, fnwin_patch2
81*1da177e4SLinus Torvaldsfill_window_entry:
82*1da177e4SLinus Torvalds	/* LOCATION: Window 'T' */
83*1da177e4SLinus Torvalds
84*1da177e4SLinus Torvalds	/* Compute what the new %wim is going to be if we retrieve
85*1da177e4SLinus Torvalds	 * the proper window off of the stack.
86*1da177e4SLinus Torvalds	 */
87*1da177e4SLinus Torvalds		sll	%t_wim, 1, %twin_tmp1
88*1da177e4SLinus Torvaldsfnwin_patch1:	srl	%t_wim, 7, %twin_tmp2
89*1da177e4SLinus Torvalds		or	%twin_tmp1, %twin_tmp2, %twin_tmp1
90*1da177e4SLinus Torvaldsfnwin_patch2:	and	%twin_tmp1, 0xff, %twin_tmp1
91*1da177e4SLinus Torvalds
92*1da177e4SLinus Torvalds	wr	%twin_tmp1, 0x0, %wim	/* Make window 'I' invalid */
93*1da177e4SLinus Torvalds
94*1da177e4SLinus Torvalds	andcc	%t_psr, PSR_PS, %g0
95*1da177e4SLinus Torvalds	be	fwin_from_user
96*1da177e4SLinus Torvalds	 restore	%g0, %g0, %g0		/* Restore to window 'O' */
97*1da177e4SLinus Torvalds
98*1da177e4SLinus Torvalds	/* Trapped from kernel, we trust that the kernel does not
99*1da177e4SLinus Torvalds	 * 'over restore' sorta speak and just grab the window
100*1da177e4SLinus Torvalds	 * from the stack and return.  Easy enough.
101*1da177e4SLinus Torvalds	 */
102*1da177e4SLinus Torvaldsfwin_from_kernel:
103*1da177e4SLinus Torvalds	/* LOCATION: Window 'O' */
104*1da177e4SLinus Torvalds
105*1da177e4SLinus Torvalds	restore %g0, %g0, %g0
106*1da177e4SLinus Torvalds
107*1da177e4SLinus Torvalds	/* LOCATION: Window 'W' */
108*1da177e4SLinus Torvalds
109*1da177e4SLinus Torvalds	LOAD_WINDOW(sp)	                /* Load it up */
110*1da177e4SLinus Torvalds
111*1da177e4SLinus Torvalds	/* Spin the wheel... */
112*1da177e4SLinus Torvalds	save	%g0, %g0, %g0
113*1da177e4SLinus Torvalds	save	%g0, %g0, %g0
114*1da177e4SLinus Torvalds	/* I'd like to buy a vowel please... */
115*1da177e4SLinus Torvalds
116*1da177e4SLinus Torvalds	/* LOCATION: Window 'T' */
117*1da177e4SLinus Torvalds
118*1da177e4SLinus Torvalds	/* Now preserve the condition codes in %psr, pause, and
119*1da177e4SLinus Torvalds	 * return from trap.  This is the simplest case of all.
120*1da177e4SLinus Torvalds	 */
121*1da177e4SLinus Torvalds	wr	%t_psr, 0x0, %psr
122*1da177e4SLinus Torvalds	WRITE_PAUSE
123*1da177e4SLinus Torvalds
124*1da177e4SLinus Torvalds	jmp	%t_pc
125*1da177e4SLinus Torvalds	rett	%t_npc
126*1da177e4SLinus Torvalds
127*1da177e4SLinus Torvaldsfwin_from_user:
128*1da177e4SLinus Torvalds	/* LOCATION: Window 'O' */
129*1da177e4SLinus Torvalds
130*1da177e4SLinus Torvalds	restore	%g0, %g0, %g0		/* Restore to window 'W' */
131*1da177e4SLinus Torvalds
132*1da177e4SLinus Torvalds	/* LOCATION: Window 'W' */
133*1da177e4SLinus Torvalds
134*1da177e4SLinus Torvalds	/* Branch to the architecture specific stack validation
135*1da177e4SLinus Torvalds	 * routine.  They can be found below...
136*1da177e4SLinus Torvalds	 */
137*1da177e4SLinus Torvalds	.globl	fwin_mmu_patchme
138*1da177e4SLinus Torvaldsfwin_mmu_patchme:	b	sun4c_fwin_stackchk
139*1da177e4SLinus Torvalds				 andcc	%sp, 0x7, %g0
140*1da177e4SLinus Torvalds
141*1da177e4SLinus Torvalds#define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
142*1da177e4SLinus Torvalds
143*1da177e4SLinus Torvaldsfwin_user_stack_is_bolixed:
144*1da177e4SLinus Torvalds	/* LOCATION: Window 'W' */
145*1da177e4SLinus Torvalds
146*1da177e4SLinus Torvalds	/* Place a pt_regs frame on the kernel stack, save back
147*1da177e4SLinus Torvalds	 * to the trap window and call c-code to deal with this.
148*1da177e4SLinus Torvalds	 */
149*1da177e4SLinus Torvalds	LOAD_CURRENT(l4, l5)
150*1da177e4SLinus Torvalds
151*1da177e4SLinus Torvalds	sethi	%hi(STACK_OFFSET), %l5
152*1da177e4SLinus Torvalds	or	%l5, %lo(STACK_OFFSET), %l5
153*1da177e4SLinus Torvalds	add	%l4, %l5, %l5
154*1da177e4SLinus Torvalds
155*1da177e4SLinus Torvalds	/* Store globals into pt_regs frame. */
156*1da177e4SLinus Torvalds	STORE_PT_GLOBALS(l5)
157*1da177e4SLinus Torvalds	STORE_PT_YREG(l5, g3)
158*1da177e4SLinus Torvalds
159*1da177e4SLinus Torvalds	/* Save current in a global while we change windows. */
160*1da177e4SLinus Torvalds	mov	%l4, %curptr
161*1da177e4SLinus Torvalds
162*1da177e4SLinus Torvalds	save	%g0, %g0, %g0
163*1da177e4SLinus Torvalds
164*1da177e4SLinus Torvalds	/* LOCATION: Window 'O' */
165*1da177e4SLinus Torvalds
166*1da177e4SLinus Torvalds	rd	%psr, %g3		/* Read %psr in live user window */
167*1da177e4SLinus Torvalds	mov	%fp, %g4		/* Save bogus frame pointer. */
168*1da177e4SLinus Torvalds
169*1da177e4SLinus Torvalds	save	%g0, %g0, %g0
170*1da177e4SLinus Torvalds
171*1da177e4SLinus Torvalds	/* LOCATION: Window 'T' */
172*1da177e4SLinus Torvalds
173*1da177e4SLinus Torvalds	sethi	%hi(STACK_OFFSET), %l5
174*1da177e4SLinus Torvalds	or	%l5, %lo(STACK_OFFSET), %l5
175*1da177e4SLinus Torvalds	add	%curptr, %l5, %sp
176*1da177e4SLinus Torvalds
177*1da177e4SLinus Torvalds	/* Build rest of pt_regs. */
178*1da177e4SLinus Torvalds	STORE_PT_INS(sp)
179*1da177e4SLinus Torvalds	STORE_PT_PRIV(sp, t_psr, t_pc, t_npc)
180*1da177e4SLinus Torvalds
181*1da177e4SLinus Torvalds	/* re-set trap time %wim value */
182*1da177e4SLinus Torvalds	wr	%t_wim, 0x0, %wim
183*1da177e4SLinus Torvalds
184*1da177e4SLinus Torvalds	/* Fix users window mask and buffer save count. */
185*1da177e4SLinus Torvalds	mov	0x1, %g5
186*1da177e4SLinus Torvalds	sll	%g5, %g3, %g5
187*1da177e4SLinus Torvalds	st	%g5, [%curptr + TI_UWINMASK]		! one live user window still
188*1da177e4SLinus Torvalds	st	%g0, [%curptr + TI_W_SAVED]		! no windows in the buffer
189*1da177e4SLinus Torvalds
190*1da177e4SLinus Torvalds	wr	%t_psr, PSR_ET, %psr			! enable traps
191*1da177e4SLinus Torvalds	nop
192*1da177e4SLinus Torvalds	call	window_underflow_fault
193*1da177e4SLinus Torvalds	 mov	%g4, %o0
194*1da177e4SLinus Torvalds
195*1da177e4SLinus Torvalds	b	ret_trap_entry
196*1da177e4SLinus Torvalds	 clr	%l6
197*1da177e4SLinus Torvalds
198*1da177e4SLinus Torvaldsfwin_user_stack_is_ok:
199*1da177e4SLinus Torvalds	/* LOCATION: Window 'W' */
200*1da177e4SLinus Torvalds
201*1da177e4SLinus Torvalds	/* The users stack area is kosher and mapped, load the
202*1da177e4SLinus Torvalds	 * window and fall through to the finish up routine.
203*1da177e4SLinus Torvalds	 */
204*1da177e4SLinus Torvalds	LOAD_WINDOW(sp)
205*1da177e4SLinus Torvalds
206*1da177e4SLinus Torvalds	/* Round and round she goes... */
207*1da177e4SLinus Torvalds	save	%g0, %g0, %g0		/* Save to window 'O' */
208*1da177e4SLinus Torvalds	save	%g0, %g0, %g0		/* Save to window 'T' */
209*1da177e4SLinus Torvalds	/* Where she'll trap nobody knows... */
210*1da177e4SLinus Torvalds
211*1da177e4SLinus Torvalds	/* LOCATION: Window 'T' */
212*1da177e4SLinus Torvalds
213*1da177e4SLinus Torvaldsfwin_user_finish_up:
214*1da177e4SLinus Torvalds	/* LOCATION: Window 'T' */
215*1da177e4SLinus Torvalds
216*1da177e4SLinus Torvalds	wr	%t_psr, 0x0, %psr
217*1da177e4SLinus Torvalds	WRITE_PAUSE
218*1da177e4SLinus Torvalds
219*1da177e4SLinus Torvalds	jmp	%t_pc
220*1da177e4SLinus Torvalds	rett	%t_npc
221*1da177e4SLinus Torvalds
222*1da177e4SLinus Torvalds	/* Here come the architecture specific checks for stack.
223*1da177e4SLinus Torvalds	 * mappings.  Note that unlike the window overflow handler
224*1da177e4SLinus Torvalds	 * we only need to check whether the user can read from
225*1da177e4SLinus Torvalds	 * the appropriate addresses.  Also note that we are in
226*1da177e4SLinus Torvalds	 * an invalid window which will be loaded, and this means
227*1da177e4SLinus Torvalds	 * that until we actually load the window up we are free
228*1da177e4SLinus Torvalds	 * to use any of the local registers contained within.
229*1da177e4SLinus Torvalds	 *
230*1da177e4SLinus Torvalds	 * On success these routine branch to fwin_user_stack_is_ok
231*1da177e4SLinus Torvalds	 * if the area at %sp is user readable and the window still
232*1da177e4SLinus Torvalds	 * needs to be loaded, else fwin_user_finish_up if the
233*1da177e4SLinus Torvalds	 * routine has done the loading itself.  On failure (bogus
234*1da177e4SLinus Torvalds	 * user stack) the routine shall branch to the label called
235*1da177e4SLinus Torvalds	 * fwin_user_stack_is_bolixed.
236*1da177e4SLinus Torvalds	 *
237*1da177e4SLinus Torvalds	 * Contrary to the arch-specific window overflow stack
238*1da177e4SLinus Torvalds	 * check routines in wof.S, these routines are free to use
239*1da177e4SLinus Torvalds	 * any of the local registers they want to as this window
240*1da177e4SLinus Torvalds	 * does not belong to anyone at this point, however the
241*1da177e4SLinus Torvalds	 * outs and ins are still verboten as they are part of
242*1da177e4SLinus Torvalds	 * 'someone elses' window possibly.
243*1da177e4SLinus Torvalds	 */
244*1da177e4SLinus Torvalds
245*1da177e4SLinus Torvalds	.align	4
246*1da177e4SLinus Torvalds	.globl	sun4c_fwin_stackchk
247*1da177e4SLinus Torvaldssun4c_fwin_stackchk:
248*1da177e4SLinus Torvalds	/* LOCATION: Window 'W' */
249*1da177e4SLinus Torvalds
250*1da177e4SLinus Torvalds	/* Caller did 'andcc %sp, 0x7, %g0' */
251*1da177e4SLinus Torvalds	be	1f
252*1da177e4SLinus Torvalds	 and	%sp, 0xfff, %l0		! delay slot
253*1da177e4SLinus Torvalds
254*1da177e4SLinus Torvalds	b,a	fwin_user_stack_is_bolixed
255*1da177e4SLinus Torvalds
256*1da177e4SLinus Torvalds	/* See if we have to check the sanity of one page or two */
257*1da177e4SLinus Torvalds1:
258*1da177e4SLinus Torvalds	add	%l0, 0x38, %l0
259*1da177e4SLinus Torvalds	sra	%sp, 29, %l5
260*1da177e4SLinus Torvalds	add	%l5, 0x1, %l5
261*1da177e4SLinus Torvalds	andncc	%l5, 0x1, %g0
262*1da177e4SLinus Torvalds	be	1f
263*1da177e4SLinus Torvalds	 andncc	%l0, 0xff8, %g0
264*1da177e4SLinus Torvalds
265*1da177e4SLinus Torvalds	b,a	fwin_user_stack_is_bolixed	/* %sp is in vma hole, yuck */
266*1da177e4SLinus Torvalds
267*1da177e4SLinus Torvalds1:
268*1da177e4SLinus Torvalds	be	sun4c_fwin_onepage	/* Only one page to check */
269*1da177e4SLinus Torvalds	 lda	[%sp] ASI_PTE, %l1
270*1da177e4SLinus Torvaldssun4c_fwin_twopages:
271*1da177e4SLinus Torvalds	add	%sp, 0x38, %l0
272*1da177e4SLinus Torvalds	sra	%l0, 29, %l5
273*1da177e4SLinus Torvalds	add	%l5, 0x1, %l5
274*1da177e4SLinus Torvalds	andncc	%l5, 0x1, %g0
275*1da177e4SLinus Torvalds	be	1f
276*1da177e4SLinus Torvalds	 lda	[%l0] ASI_PTE, %l1
277*1da177e4SLinus Torvalds
278*1da177e4SLinus Torvalds	b,a	fwin_user_stack_is_bolixed	/* Second page in vma hole */
279*1da177e4SLinus Torvalds
280*1da177e4SLinus Torvalds1:
281*1da177e4SLinus Torvalds	srl	%l1, 29, %l1
282*1da177e4SLinus Torvalds	andcc	%l1, 0x4, %g0
283*1da177e4SLinus Torvalds	bne	sun4c_fwin_onepage
284*1da177e4SLinus Torvalds	 lda	[%sp] ASI_PTE, %l1
285*1da177e4SLinus Torvalds
286*1da177e4SLinus Torvalds	b,a	fwin_user_stack_is_bolixed	/* Second page has bad perms */
287*1da177e4SLinus Torvalds
288*1da177e4SLinus Torvaldssun4c_fwin_onepage:
289*1da177e4SLinus Torvalds	srl	%l1, 29, %l1
290*1da177e4SLinus Torvalds	andcc	%l1, 0x4, %g0
291*1da177e4SLinus Torvalds	bne	fwin_user_stack_is_ok
292*1da177e4SLinus Torvalds	 nop
293*1da177e4SLinus Torvalds
294*1da177e4SLinus Torvalds	/* A page had bad page permissions, losing... */
295*1da177e4SLinus Torvalds	b,a	fwin_user_stack_is_bolixed
296*1da177e4SLinus Torvalds
297*1da177e4SLinus Torvalds	.globl	srmmu_fwin_stackchk
298*1da177e4SLinus Torvaldssrmmu_fwin_stackchk:
299*1da177e4SLinus Torvalds	/* LOCATION: Window 'W' */
300*1da177e4SLinus Torvalds
301*1da177e4SLinus Torvalds	/* Caller did 'andcc %sp, 0x7, %g0' */
302*1da177e4SLinus Torvalds	bne	fwin_user_stack_is_bolixed
303*1da177e4SLinus Torvalds	 sethi   %hi(PAGE_OFFSET), %l5
304*1da177e4SLinus Torvalds
305*1da177e4SLinus Torvalds	/* Check if the users stack is in kernel vma, then our
306*1da177e4SLinus Torvalds	 * trial and error technique below would succeed for
307*1da177e4SLinus Torvalds	 * the 'wrong' reason.
308*1da177e4SLinus Torvalds	 */
309*1da177e4SLinus Torvalds	mov	AC_M_SFSR, %l4
310*1da177e4SLinus Torvalds	cmp	%l5, %sp
311*1da177e4SLinus Torvalds	bleu	fwin_user_stack_is_bolixed
312*1da177e4SLinus Torvalds	 lda	[%l4] ASI_M_MMUREGS, %g0	! clear fault status
313*1da177e4SLinus Torvalds
314*1da177e4SLinus Torvalds	/* The technique is, turn off faults on this processor,
315*1da177e4SLinus Torvalds	 * just let the load rip, then check the sfsr to see if
316*1da177e4SLinus Torvalds	 * a fault did occur.  Then we turn on fault traps again
317*1da177e4SLinus Torvalds	 * and branch conditionally based upon what happened.
318*1da177e4SLinus Torvalds	 */
319*1da177e4SLinus Torvalds	lda	[%g0] ASI_M_MMUREGS, %l5	! read mmu-ctrl reg
320*1da177e4SLinus Torvalds	or	%l5, 0x2, %l5			! turn on no-fault bit
321*1da177e4SLinus Torvalds	sta	%l5, [%g0] ASI_M_MMUREGS	! store it
322*1da177e4SLinus Torvalds
323*1da177e4SLinus Torvalds	/* Cross fingers and go for it. */
324*1da177e4SLinus Torvalds	LOAD_WINDOW(sp)
325*1da177e4SLinus Torvalds
326*1da177e4SLinus Torvalds	/* A penny 'saved'... */
327*1da177e4SLinus Torvalds	save	%g0, %g0, %g0
328*1da177e4SLinus Torvalds	save	%g0, %g0, %g0
329*1da177e4SLinus Torvalds	/* Is a BADTRAP earned... */
330*1da177e4SLinus Torvalds
331*1da177e4SLinus Torvalds	/* LOCATION: Window 'T' */
332*1da177e4SLinus Torvalds
333*1da177e4SLinus Torvalds	lda	[%g0] ASI_M_MMUREGS, %twin_tmp1	! load mmu-ctrl again
334*1da177e4SLinus Torvalds	andn	%twin_tmp1, 0x2, %twin_tmp1	! clear no-fault bit
335*1da177e4SLinus Torvalds	sta	%twin_tmp1, [%g0] ASI_M_MMUREGS	! store it
336*1da177e4SLinus Torvalds
337*1da177e4SLinus Torvalds	mov	AC_M_SFAR, %twin_tmp2
338*1da177e4SLinus Torvalds	lda	[%twin_tmp2] ASI_M_MMUREGS, %g0	! read fault address
339*1da177e4SLinus Torvalds
340*1da177e4SLinus Torvalds	mov	AC_M_SFSR, %twin_tmp2
341*1da177e4SLinus Torvalds	lda	[%twin_tmp2] ASI_M_MMUREGS, %twin_tmp2	! read fault status
342*1da177e4SLinus Torvalds	andcc	%twin_tmp2, 0x2, %g0			! did fault occur?
343*1da177e4SLinus Torvalds
344*1da177e4SLinus Torvalds	bne	1f					! yep, cleanup
345*1da177e4SLinus Torvalds	 nop
346*1da177e4SLinus Torvalds
347*1da177e4SLinus Torvalds	wr	%t_psr, 0x0, %psr
348*1da177e4SLinus Torvalds	nop
349*1da177e4SLinus Torvalds	b	fwin_user_finish_up + 0x4
350*1da177e4SLinus Torvalds	 nop
351*1da177e4SLinus Torvalds
352*1da177e4SLinus Torvalds	/* Did I ever tell you about my window lobotomy?
353*1da177e4SLinus Torvalds	 * anyways... fwin_user_stack_is_bolixed expects
354*1da177e4SLinus Torvalds	 * to be in window 'W' so make it happy or else
355*1da177e4SLinus Torvalds	 * we watchdog badly.
356*1da177e4SLinus Torvalds	 */
357*1da177e4SLinus Torvalds1:
358*1da177e4SLinus Torvalds	restore	%g0, %g0, %g0
359*1da177e4SLinus Torvalds	b	fwin_user_stack_is_bolixed	! oh well
360*1da177e4SLinus Torvalds	 restore	%g0, %g0, %g0
361