xref: /onnv-gate/usr/src/uts/sun4u/ml/wbuf.s (revision 5584:4b4402ef936b)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*5584Sjimand * Common Development and Distribution License (the "License").
6*5584Sjimand * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate/*
22*5584Sjimand * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate#include <sys/asm_linkage.h>
290Sstevel@tonic-gate#include <sys/machthread.h>
300Sstevel@tonic-gate#include <sys/privregs.h>
310Sstevel@tonic-gate#include <sys/machasi.h>
320Sstevel@tonic-gate#include <sys/trap.h>
330Sstevel@tonic-gate#include <sys/mmu.h>
340Sstevel@tonic-gate#include <sys/machparam.h>
350Sstevel@tonic-gate#include <sys/machtrap.h>
360Sstevel@tonic-gate#include <sys/traptrace.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate#if !defined(lint)
390Sstevel@tonic-gate#include "assym.h"
400Sstevel@tonic-gate
410Sstevel@tonic-gate	/*
420Sstevel@tonic-gate	 * Spill fault handlers
430Sstevel@tonic-gate	 *   sn0 - spill normal tl 0
440Sstevel@tonic-gate	 *   sn1 - spill normal tl >0
450Sstevel@tonic-gate	 *   so0 - spill other tl 0
460Sstevel@tonic-gate	 *   so1 - spill other tl >0
470Sstevel@tonic-gate	 */
480Sstevel@tonic-gate
490Sstevel@tonic-gate	ENTRY_NP(fault_32bit_sn0)
500Sstevel@tonic-gate	!
510Sstevel@tonic-gate	FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_SN0)
520Sstevel@tonic-gate	!
530Sstevel@tonic-gate	! Spill normal tl0 fault.
540Sstevel@tonic-gate	! This happens when a user tries to spill to an unmapped or
550Sstevel@tonic-gate	! misaligned stack. We handle an unmapped stack by simulating
560Sstevel@tonic-gate	! a pagefault at the trap pc and a misaligned stack by generating
570Sstevel@tonic-gate	! a user alignment trap.
580Sstevel@tonic-gate	!
590Sstevel@tonic-gate	! spill the window into wbuf slot 0
600Sstevel@tonic-gate	! (we know wbuf is empty since we came from user mode)
610Sstevel@tonic-gate	!
620Sstevel@tonic-gate	! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or
630Sstevel@tonic-gate	! sfar (g5 == T_ALIGNMENT)
640Sstevel@tonic-gate	!
650Sstevel@tonic-gate	CPU_ADDR(%g4, %g1)
660Sstevel@tonic-gate	ldn	[%g4 + CPU_MPCB], %g1
670Sstevel@tonic-gate	stn	%sp, [%g1 + MPCB_SPBUF]
680Sstevel@tonic-gate	ldn	[%g1 + MPCB_WBUF], %g2
690Sstevel@tonic-gate	SAVE_V8WINDOW(%g2)
700Sstevel@tonic-gate	mov	1, %g2
710Sstevel@tonic-gate	st	%g2, [%g1 + MPCB_WBCNT]
720Sstevel@tonic-gate	saved
730Sstevel@tonic-gate	!
740Sstevel@tonic-gate	! setup user_trap args
750Sstevel@tonic-gate	!
760Sstevel@tonic-gate	set	sfmmu_tsbmiss_exception, %g1
770Sstevel@tonic-gate	mov	%g6, %g2			! arg2 = tagaccess
780Sstevel@tonic-gate	mov	T_WIN_OVERFLOW, %g3		! arg3 = traptype
790Sstevel@tonic-gate	cmp	%g5, T_ALIGNMENT
800Sstevel@tonic-gate	bne	%icc, 1f
810Sstevel@tonic-gate	nop
820Sstevel@tonic-gate	set	trap, %g1
830Sstevel@tonic-gate	mov	T_ALIGNMENT, %g3
840Sstevel@tonic-gate1:
850Sstevel@tonic-gate	sub	%g0, 1, %g4
860Sstevel@tonic-gate	!
870Sstevel@tonic-gate	! spill traps increment %cwp by 2,
880Sstevel@tonic-gate	! but user_trap wants the trap %cwp
890Sstevel@tonic-gate	!
900Sstevel@tonic-gate	rdpr	%tstate, %g5
910Sstevel@tonic-gate	and	%g5, TSTATE_CWP, %g5
920Sstevel@tonic-gate	ba,pt	%xcc, user_trap
930Sstevel@tonic-gate	wrpr	%g0, %g5, %cwp
940Sstevel@tonic-gate	SET_SIZE(fault_32bit_sn0)
950Sstevel@tonic-gate
960Sstevel@tonic-gate	!
970Sstevel@tonic-gate	! Spill normal tl1 fault.
980Sstevel@tonic-gate	! This happens when sys_trap's save spills to an unmapped stack.
990Sstevel@tonic-gate	! We handle it by spilling the window to the wbuf and trying
1000Sstevel@tonic-gate	! sys_trap again.
1010Sstevel@tonic-gate	!
1020Sstevel@tonic-gate	! spill the window into wbuf slot 0
1030Sstevel@tonic-gate	! (we know wbuf is empty since we came from user mode)
1040Sstevel@tonic-gate	!
1050Sstevel@tonic-gate	ENTRY_NP(fault_32bit_sn1)
1060Sstevel@tonic-gate	FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_SN1)
1070Sstevel@tonic-gate	CPU_ADDR(%g5, %g6)
1080Sstevel@tonic-gate	ldn	[%g5 + CPU_MPCB], %g6
1090Sstevel@tonic-gate	stn	%sp, [%g6 + MPCB_SPBUF]
1100Sstevel@tonic-gate	ldn	[%g6 + MPCB_WBUF], %g5
1110Sstevel@tonic-gate	SAVE_V8WINDOW(%g5)
1120Sstevel@tonic-gate	mov	1, %g5
1130Sstevel@tonic-gate	st	%g5, [%g6 + MPCB_WBCNT]
1140Sstevel@tonic-gate	saved
1150Sstevel@tonic-gate	set	sys_trap, %g5
1160Sstevel@tonic-gate	wrpr	%g5, %tnpc
1170Sstevel@tonic-gate	done
1180Sstevel@tonic-gate	SET_SIZE(fault_32bit_sn1)
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate	ENTRY_NP(fault_32bit_so0)
1210Sstevel@tonic-gate	!
1220Sstevel@tonic-gate	FAULT_WINTRACE(%g5, %g6, %g1, TT_F32_SO0)
1230Sstevel@tonic-gate	!
1240Sstevel@tonic-gate	! Spill other tl0 fault.
1250Sstevel@tonic-gate	! This happens when the kernel spills a user window and that
1260Sstevel@tonic-gate	! user's stack has been unmapped.
1270Sstevel@tonic-gate	! We handle it by spilling the window into the user's wbuf.
1280Sstevel@tonic-gate	!
1290Sstevel@tonic-gate	! find lwp & increment wbcnt
1300Sstevel@tonic-gate	!
1310Sstevel@tonic-gate	CPU_ADDR(%g5, %g6)
1320Sstevel@tonic-gate	ldn	[%g5 + CPU_MPCB], %g1
1330Sstevel@tonic-gate	ld	[%g1 + MPCB_WBCNT], %g2
1340Sstevel@tonic-gate	add	%g2, 1, %g3
1350Sstevel@tonic-gate	st	%g3, [%g1 + MPCB_WBCNT]
1360Sstevel@tonic-gate	!
1370Sstevel@tonic-gate	! use previous wbcnt to spill new spbuf & wbuf
1380Sstevel@tonic-gate	!
1390Sstevel@tonic-gate	sll	%g2, CPTRSHIFT, %g4		! spbuf size is sizeof (caddr_t)
1400Sstevel@tonic-gate	add	%g1, MPCB_SPBUF, %g3
1410Sstevel@tonic-gate	stn	%sp, [%g3 + %g4]
1420Sstevel@tonic-gate	sll	%g2, RWIN32SHIFT, %g4
1430Sstevel@tonic-gate	ldn	[%g1 + MPCB_WBUF], %g3
1440Sstevel@tonic-gate	add	%g3, %g4, %g3
1450Sstevel@tonic-gate	SAVE_V8WINDOW(%g3)
1460Sstevel@tonic-gate	saved
1470Sstevel@tonic-gate	retry
1480Sstevel@tonic-gate	SET_SIZE(fault_32bit_so0)
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate	!
1510Sstevel@tonic-gate	! Spill other tl1 fault.
1520Sstevel@tonic-gate	! This happens when priv_trap spills a user window and that
1530Sstevel@tonic-gate	! user's stack has been unmapped.
1540Sstevel@tonic-gate	! We handle it by spilling the window to the wbuf and retrying
1550Sstevel@tonic-gate	! the save.
1560Sstevel@tonic-gate	!
1570Sstevel@tonic-gate	ENTRY_NP(fault_32bit_so1)
1580Sstevel@tonic-gate	FAULT_WINTRACE(%g5, %g6, %g7, TT_F32_SO1)
1590Sstevel@tonic-gate	CPU_ADDR(%g5, %g6)
1600Sstevel@tonic-gate	!
1610Sstevel@tonic-gate	! find lwp & increment wbcnt
1620Sstevel@tonic-gate	!
1630Sstevel@tonic-gate	ldn	[%g5 + CPU_MPCB], %g6
1640Sstevel@tonic-gate	ld	[%g6 + MPCB_WBCNT], %g5
1650Sstevel@tonic-gate	add	%g5, 1, %g7
1660Sstevel@tonic-gate	st	%g7, [%g6 + MPCB_WBCNT]
1670Sstevel@tonic-gate	!
1680Sstevel@tonic-gate	! use previous wbcnt to spill new spbuf & wbuf
1690Sstevel@tonic-gate	!
1700Sstevel@tonic-gate	sll	%g5, CPTRSHIFT, %g7		! spbuf size is sizeof (caddr_t)
1710Sstevel@tonic-gate	add	%g6, %g7, %g7
1720Sstevel@tonic-gate	stn	%sp, [%g7 + MPCB_SPBUF]
1730Sstevel@tonic-gate	sll	%g5, RWIN32SHIFT, %g7
1740Sstevel@tonic-gate	ldn	[%g6 + MPCB_WBUF], %g5
1750Sstevel@tonic-gate	add	%g5, %g7, %g7
1760Sstevel@tonic-gate	SAVE_V8WINDOW(%g7)
1770Sstevel@tonic-gate	saved
1780Sstevel@tonic-gate	set	sys_trap, %g5
1790Sstevel@tonic-gate	wrpr	%g5, %tnpc
1800Sstevel@tonic-gate	done
1810Sstevel@tonic-gate	SET_SIZE(fault_32bit_so1)
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate	ENTRY_NP(fault_64bit_sn0)
1840Sstevel@tonic-gate	!
1850Sstevel@tonic-gate	FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_SN0)
1860Sstevel@tonic-gate	!
1870Sstevel@tonic-gate	! Spill normal tl0 fault.
1880Sstevel@tonic-gate	! This happens when a user tries to spill to an unmapped or
1890Sstevel@tonic-gate	! misaligned stack. We handle an unmapped stack by simulating
1900Sstevel@tonic-gate	! a pagefault at the trap pc and a misaligned stack by generating
1910Sstevel@tonic-gate	! a user alignment trap.
1920Sstevel@tonic-gate	!
1930Sstevel@tonic-gate	! spill the window into wbuf slot 0
1940Sstevel@tonic-gate	! (we know wbuf is empty since we came from user mode)
1950Sstevel@tonic-gate	!
1960Sstevel@tonic-gate	! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or
1970Sstevel@tonic-gate	! sfar (g5 == T_ALIGNMENT)
1980Sstevel@tonic-gate	!
1990Sstevel@tonic-gate	CPU_ADDR(%g4, %g1)
2000Sstevel@tonic-gate	ldn	[%g4 + CPU_MPCB], %g1
2010Sstevel@tonic-gate	stn	%sp, [%g1 + MPCB_SPBUF]
2020Sstevel@tonic-gate	ldn	[%g1 + MPCB_WBUF], %g2
2030Sstevel@tonic-gate	SAVE_V9WINDOW(%g2)
2040Sstevel@tonic-gate	mov	1, %g2
2050Sstevel@tonic-gate	st	%g2, [%g1 + MPCB_WBCNT]
2060Sstevel@tonic-gate	saved
2070Sstevel@tonic-gate	!
2080Sstevel@tonic-gate	! setup user_trap args
2090Sstevel@tonic-gate	!
2100Sstevel@tonic-gate	set	sfmmu_tsbmiss_exception, %g1
2110Sstevel@tonic-gate	mov	%g6, %g2			! arg2 = tagaccess
2120Sstevel@tonic-gate	mov	%g5, %g3			! arg3 = traptype
2130Sstevel@tonic-gate	cmp	%g5, T_ALIGNMENT
2140Sstevel@tonic-gate	bne	%icc, 1f
2150Sstevel@tonic-gate	nop
2160Sstevel@tonic-gate	set	trap, %g1
2170Sstevel@tonic-gate	mov	T_ALIGNMENT, %g3
2180Sstevel@tonic-gate1:
2190Sstevel@tonic-gate	sub	%g0, 1, %g4
2200Sstevel@tonic-gate	!
2210Sstevel@tonic-gate	! spill traps increment %cwp by 2,
2220Sstevel@tonic-gate	! but user_trap wants the trap %cwp
2230Sstevel@tonic-gate	!
2240Sstevel@tonic-gate	rdpr	%tstate, %g5
2250Sstevel@tonic-gate	and	%g5, TSTATE_CWP, %g5
2260Sstevel@tonic-gate	ba,pt	%xcc, user_trap
2270Sstevel@tonic-gate	  wrpr	%g0, %g5, %cwp
2280Sstevel@tonic-gate	SET_SIZE(fault_64bit_sn0)
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate	!
2310Sstevel@tonic-gate	! Spill normal tl1 fault.
2320Sstevel@tonic-gate	! This happens when sys_trap's save spills to an unmapped stack.
2330Sstevel@tonic-gate	! We handle it by spilling the window to the wbuf and trying
2340Sstevel@tonic-gate	! sys_trap again.
2350Sstevel@tonic-gate	!
2360Sstevel@tonic-gate	! spill the window into wbuf slot 0
2370Sstevel@tonic-gate	! (we know wbuf is empty since we came from user mode)
2380Sstevel@tonic-gate	!
2390Sstevel@tonic-gate	ENTRY_NP(fault_64bit_sn1)
2400Sstevel@tonic-gate	FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_SN1)
2410Sstevel@tonic-gate	CPU_ADDR(%g5, %g6)
2420Sstevel@tonic-gate	ldn	[%g5 + CPU_MPCB], %g6
2430Sstevel@tonic-gate	stn	%sp, [%g6 + MPCB_SPBUF]
2440Sstevel@tonic-gate	ldn	[%g6 + MPCB_WBUF], %g5
2450Sstevel@tonic-gate	SAVE_V9WINDOW(%g5)
2460Sstevel@tonic-gate	mov	1, %g5
2470Sstevel@tonic-gate	st	%g5, [%g6 + MPCB_WBCNT]
2480Sstevel@tonic-gate	saved
2490Sstevel@tonic-gate	set	sys_trap, %g5
2500Sstevel@tonic-gate	wrpr	%g5, %tnpc
2510Sstevel@tonic-gate	done
2520Sstevel@tonic-gate	SET_SIZE(fault_64bit_sn1)
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate	ENTRY_NP(fault_64bit_so0)
2550Sstevel@tonic-gate	!
2560Sstevel@tonic-gate	FAULT_WINTRACE(%g5, %g6, %g1, TT_F64_SO0)
2570Sstevel@tonic-gate	!
2580Sstevel@tonic-gate	! Spill other tl0 fault.
2590Sstevel@tonic-gate	! This happens when the kernel spills a user window and that
2600Sstevel@tonic-gate	! user's stack has been unmapped.
2610Sstevel@tonic-gate	! We handle it by spilling the window into the user's wbuf.
2620Sstevel@tonic-gate	!
2630Sstevel@tonic-gate	! find lwp & increment wbcnt
2640Sstevel@tonic-gate	!
2650Sstevel@tonic-gate	CPU_ADDR(%g5, %g6)
2660Sstevel@tonic-gate	ldn	[%g5 + CPU_MPCB], %g1
2670Sstevel@tonic-gate	ld	[%g1 + MPCB_WBCNT], %g2
2680Sstevel@tonic-gate	add	%g2, 1, %g3
2690Sstevel@tonic-gate	st	%g3, [%g1 + MPCB_WBCNT]
2700Sstevel@tonic-gate	!
2710Sstevel@tonic-gate	! use previous wbcnt to spill new spbuf & wbuf
2720Sstevel@tonic-gate	!
2730Sstevel@tonic-gate	sll	%g2, CPTRSHIFT, %g4		! spbuf size is sizeof (caddr_t)
2740Sstevel@tonic-gate	add	%g1, MPCB_SPBUF, %g3
2750Sstevel@tonic-gate	stn	%sp, [%g3 + %g4]
2760Sstevel@tonic-gate	sll	%g2, RWIN64SHIFT, %g4
2770Sstevel@tonic-gate	ldn	[%g1 + MPCB_WBUF], %g3
2780Sstevel@tonic-gate	add	%g3, %g4, %g3
2790Sstevel@tonic-gate	SAVE_V9WINDOW(%g3)
2800Sstevel@tonic-gate	saved
2810Sstevel@tonic-gate	retry
2820Sstevel@tonic-gate	SET_SIZE(fault_64bit_so0)
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate	!
2850Sstevel@tonic-gate	! Spill other tl1 fault.
2860Sstevel@tonic-gate	! This happens when priv_trap spills a user window and that
2870Sstevel@tonic-gate	! user's stack has been unmapped.
2880Sstevel@tonic-gate	! We handle it by spilling the window to the wbuf and retrying
2890Sstevel@tonic-gate	! the save.
2900Sstevel@tonic-gate	!
2910Sstevel@tonic-gate	ENTRY_NP(fault_64bit_so1)
2920Sstevel@tonic-gate	FAULT_WINTRACE(%g5, %g6, %g7, TT_F64_SO1)
2930Sstevel@tonic-gate	CPU_ADDR(%g5, %g6)
2940Sstevel@tonic-gate	!
2950Sstevel@tonic-gate	! find lwp & increment wbcnt
2960Sstevel@tonic-gate	!
2970Sstevel@tonic-gate	ldn	[%g5 + CPU_MPCB], %g6
2980Sstevel@tonic-gate	ld	[%g6 + MPCB_WBCNT], %g5
2990Sstevel@tonic-gate	add	%g5, 1, %g7
3000Sstevel@tonic-gate	st	%g7, [%g6 + MPCB_WBCNT]
3010Sstevel@tonic-gate	!
3020Sstevel@tonic-gate	! use previous wbcnt to spill new spbuf & wbuf
3030Sstevel@tonic-gate	!
3040Sstevel@tonic-gate	sll	%g5, CPTRSHIFT, %g7		! spbuf size is sizeof (caddr_t)
3050Sstevel@tonic-gate	add	%g6, %g7, %g7
3060Sstevel@tonic-gate	stn	%sp, [%g7 + MPCB_SPBUF]
3070Sstevel@tonic-gate	sll	%g5, RWIN64SHIFT, %g7
3080Sstevel@tonic-gate	ldn	[%g6 + MPCB_WBUF], %g5
3090Sstevel@tonic-gate	add	%g5, %g7, %g7
3100Sstevel@tonic-gate	SAVE_V9WINDOW(%g7)
3110Sstevel@tonic-gate	saved
3120Sstevel@tonic-gate	set	sys_trap, %g5
3130Sstevel@tonic-gate	wrpr	%g5, %tnpc
3140Sstevel@tonic-gate	done
3150Sstevel@tonic-gate	SET_SIZE(fault_64bit_so1)
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate	/*
3180Sstevel@tonic-gate	 * Fill fault handlers
3190Sstevel@tonic-gate	 *   fn0 - fill normal tl 0
3200Sstevel@tonic-gate	 *   fn1 - fill normal tl 1
3210Sstevel@tonic-gate	 */
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate	ENTRY_NP(fault_32bit_fn0)
3240Sstevel@tonic-gate	!
3250Sstevel@tonic-gate	FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_FN0)
3260Sstevel@tonic-gate	!
3270Sstevel@tonic-gate.fault_fn0_common:
3280Sstevel@tonic-gate	!
3290Sstevel@tonic-gate	! Fill normal tl0 fault.
3300Sstevel@tonic-gate	! This happens when a user tries to fill to an unmapped or
3310Sstevel@tonic-gate	! misaligned stack. We handle an unmapped stack by simulating
3320Sstevel@tonic-gate	! a pagefault at the trap pc and a misaligned stack by generating
3330Sstevel@tonic-gate	! a user alignment trap.
3340Sstevel@tonic-gate	!
3350Sstevel@tonic-gate	! setup user_trap args
3360Sstevel@tonic-gate	!
3370Sstevel@tonic-gate	! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or
3380Sstevel@tonic-gate	! sfar (g5 == T_ALIGNMENT)
3390Sstevel@tonic-gate	!
3400Sstevel@tonic-gate	set	sfmmu_tsbmiss_exception, %g1
3410Sstevel@tonic-gate	mov	%g6, %g2			! arg2 = tagaccess
3420Sstevel@tonic-gate	mov	T_WIN_UNDERFLOW, %g3
3430Sstevel@tonic-gate	cmp	%g5, T_ALIGNMENT
3440Sstevel@tonic-gate	bne	%icc, 1f
3450Sstevel@tonic-gate	nop
3460Sstevel@tonic-gate	set	trap, %g1
3470Sstevel@tonic-gate	mov	T_ALIGNMENT, %g3
3480Sstevel@tonic-gate1:
3490Sstevel@tonic-gate	sub	%g0, 1, %g4
3500Sstevel@tonic-gate	!
3510Sstevel@tonic-gate	! sys_trap wants %cwp to be the same as when the trap occured,
3520Sstevel@tonic-gate	! so set it from %tstate
3530Sstevel@tonic-gate	!
3540Sstevel@tonic-gate	rdpr	%tstate, %g5
3550Sstevel@tonic-gate	and	%g5, TSTATE_CWP, %g5
3560Sstevel@tonic-gate	ba,pt	%xcc, user_trap
3570Sstevel@tonic-gate	wrpr	%g0, %g5, %cwp
3580Sstevel@tonic-gate	SET_SIZE(fault_32bit_fn0)
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate	ENTRY_NP(fault_32bit_fn1)
3610Sstevel@tonic-gate	!
3620Sstevel@tonic-gate	FAULT_WINTRACE(%g1, %g2, %g3, TT_F32_FN1)
3630Sstevel@tonic-gate	!
3640Sstevel@tonic-gate.fault_fn1_common:
3650Sstevel@tonic-gate	!
3660Sstevel@tonic-gate	! Fill normal tl1 fault.
3670Sstevel@tonic-gate	! This happens when user_rtt's restore fills from an unmapped or
3680Sstevel@tonic-gate	! misaligned stack. We handle an unmapped stack by simulating
3690Sstevel@tonic-gate	! a pagefault at user_rtt and a misaligned stack by generating
3700Sstevel@tonic-gate	! a RTT alignment trap.
3710Sstevel@tonic-gate	!
3720Sstevel@tonic-gate	! save fault addr & fix %cwp
3730Sstevel@tonic-gate	!
3740Sstevel@tonic-gate	rdpr	%tstate, %g1
3750Sstevel@tonic-gate	and	%g1, TSTATE_CWP, %g1
3760Sstevel@tonic-gate	wrpr	%g0, %g1, %cwp
3770Sstevel@tonic-gate	!
3780Sstevel@tonic-gate	! fake tl1 traps regs so that after pagefault runs, we
3790Sstevel@tonic-gate	! re-execute at user_rtt.
3800Sstevel@tonic-gate	!
3810Sstevel@tonic-gate	wrpr	%g0, 1, %tl
3820Sstevel@tonic-gate	set	TSTATE_KERN | TSTATE_IE, %g1
3830Sstevel@tonic-gate	wrpr	%g0, %g1, %tstate
3840Sstevel@tonic-gate	set	user_rtt, %g1
3850Sstevel@tonic-gate	wrpr	%g0, %g1, %tpc
3860Sstevel@tonic-gate	add	%g1, 4, %g1
3870Sstevel@tonic-gate	wrpr	%g0, %g1, %tnpc
3880Sstevel@tonic-gate	!
3890Sstevel@tonic-gate	! setup sys_trap args
3900Sstevel@tonic-gate	!
3910Sstevel@tonic-gate	! g5 = mmu trap type, g6 = tag access reg (g5 != T_ALIGNMENT) or
3920Sstevel@tonic-gate	! sfar (g5 == T_ALIGNMENT)
3930Sstevel@tonic-gate	!
3940Sstevel@tonic-gate	set	sfmmu_tsbmiss_exception, %g1
3950Sstevel@tonic-gate	mov	%g6, %g2			! arg2 = tagaccess
3960Sstevel@tonic-gate	set	T_USER | T_SYS_RTT_PAGE, %g3	! arg3 = traptype
3970Sstevel@tonic-gate	cmp	%g5, T_ALIGNMENT
3980Sstevel@tonic-gate	bne	%icc, 1f
3990Sstevel@tonic-gate	nop
4000Sstevel@tonic-gate	set	trap, %g1
4010Sstevel@tonic-gate	set	T_USER | T_SYS_RTT_ALIGN, %g3
4020Sstevel@tonic-gate1:
4030Sstevel@tonic-gate	sub	%g0, 1, %g4
4040Sstevel@tonic-gate	!
4050Sstevel@tonic-gate	! setup to run kernel again by setting THREAD_REG, %wstate
4060Sstevel@tonic-gate	! and the mmu to their kernel values.
4070Sstevel@tonic-gate	!
4080Sstevel@tonic-gate	rdpr	%pstate, %l1
4090Sstevel@tonic-gate	wrpr	%l1, PSTATE_AG, %pstate
4100Sstevel@tonic-gate	mov	%l6, THREAD_REG			! %l6 is user_rtt's thread
4110Sstevel@tonic-gate	wrpr	%g0, %l1, %pstate
4120Sstevel@tonic-gate	rdpr	%wstate, %l1
4130Sstevel@tonic-gate	sllx	%l1, WSTATE_SHIFT, %l1
4140Sstevel@tonic-gate	wrpr	%l1, WSTATE_K64, %wstate
4150Sstevel@tonic-gate	sethi   %hi(kcontextreg), %g5           ! mov   KCONTEXT, %g5
4160Sstevel@tonic-gate        ldx     [%g5 + %lo(kcontextreg)], %g5
4170Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g6
418*5584Sjimand	ldxa	[%g6]ASI_MMU_CTX, %g7
419*5584Sjimand	xor	%g5, %g7, %g7
420*5584Sjimand	srlx	%g7, CTXREG_NEXT_SHIFT, %g7
421*5584Sjimand	brz	%g7, 1f				! if N_pgsz0/1 changed, need demap
422*5584Sjimand	  nop
423*5584Sjimand	mov	DEMAP_ALL_TYPE, %g7
424*5584Sjimand	stxa	%g0, [%g7]ASI_DTLB_DEMAP
425*5584Sjimand	stxa	%g0, [%g7]ASI_ITLB_DEMAP
426*5584Sjimand1:
4270Sstevel@tonic-gate	stxa	%g5, [%g6]ASI_MMU_CTX
4280Sstevel@tonic-gate	sethi   %hi(FLUSH_ADDR), %g5
4290Sstevel@tonic-gate	flush   %g5
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate	ba,pt	%xcc, priv_trap
4320Sstevel@tonic-gate	nop
4330Sstevel@tonic-gate	SET_SIZE(fault_32bit_fn1)
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate	ENTRY_NP(fault_64bit_fn0)
4360Sstevel@tonic-gate	FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_FN0)
4370Sstevel@tonic-gate	b	.fault_fn0_common
4380Sstevel@tonic-gate	  nop
4390Sstevel@tonic-gate	SET_SIZE(fault_64bit_fn0)
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate	ENTRY_NP(fault_64bit_fn1)
4420Sstevel@tonic-gate	FAULT_WINTRACE(%g1, %g2, %g3, TT_F64_FN1)
4430Sstevel@tonic-gate	b	.fault_fn1_common
4440Sstevel@tonic-gate	  nop
4450Sstevel@tonic-gate	SET_SIZE(fault_64bit_fn1)
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate	/*
4480Sstevel@tonic-gate	 * Kernel fault handlers
4490Sstevel@tonic-gate	 */
4500Sstevel@tonic-gate	ENTRY_NP(fault_32bit_not)
4510Sstevel@tonic-gate	ENTRY_NP(fault_64bit_not)
4520Sstevel@tonic-gate	ba,pt	%xcc, ptl1_panic
4530Sstevel@tonic-gate	mov	PTL1_BAD_WTRAP, %g1
4540Sstevel@tonic-gate	SET_SIZE(fault_32bit_not)
4550Sstevel@tonic-gate	SET_SIZE(fault_64bit_not)
4560Sstevel@tonic-gate#endif /* !lint */
457