xref: /onnv-gate/usr/src/uts/sun4u/ml/trap_table.s (revision 11172:a792f425ae2e)
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
51640Spetede * Common Development and Distribution License (the "License").
61640Spetede * 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/*
228803SJonathan.Haslam@Sun.COM * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
256127Ssm142603
260Sstevel@tonic-gate#if !defined(lint)
270Sstevel@tonic-gate#include "assym.h"
280Sstevel@tonic-gate#endif /* !lint */
290Sstevel@tonic-gate#include <sys/asm_linkage.h>
300Sstevel@tonic-gate#include <sys/privregs.h>
310Sstevel@tonic-gate#include <sys/sun4asi.h>
321772Sjl139090#include <sys/spitregs.h>
330Sstevel@tonic-gate#include <sys/cheetahregs.h>
340Sstevel@tonic-gate#include <sys/machtrap.h>
350Sstevel@tonic-gate#include <sys/machthread.h>
362712Snn35248#include <sys/machbrand.h>
370Sstevel@tonic-gate#include <sys/pcb.h>
380Sstevel@tonic-gate#include <sys/pte.h>
390Sstevel@tonic-gate#include <sys/mmu.h>
400Sstevel@tonic-gate#include <sys/machpcb.h>
410Sstevel@tonic-gate#include <sys/async.h>
420Sstevel@tonic-gate#include <sys/intreg.h>
430Sstevel@tonic-gate#include <sys/scb.h>
440Sstevel@tonic-gate#include <sys/psr_compat.h>
450Sstevel@tonic-gate#include <sys/syscall.h>
460Sstevel@tonic-gate#include <sys/machparam.h>
470Sstevel@tonic-gate#include <sys/traptrace.h>
480Sstevel@tonic-gate#include <vm/hat_sfmmu.h>
490Sstevel@tonic-gate#include <sys/archsystm.h>
500Sstevel@tonic-gate#include <sys/utrap.h>
510Sstevel@tonic-gate#include <sys/clock.h>
520Sstevel@tonic-gate#include <sys/intr.h>
530Sstevel@tonic-gate#include <sys/fpu/fpu_simulator.h>
540Sstevel@tonic-gate#include <vm/seg_spt.h>
550Sstevel@tonic-gate
560Sstevel@tonic-gate/*
570Sstevel@tonic-gate * WARNING: If you add a fast trap handler which can be invoked by a
580Sstevel@tonic-gate * non-privileged user, you may have to use the FAST_TRAP_DONE macro
590Sstevel@tonic-gate * instead of "done" instruction to return back to the user mode. See
600Sstevel@tonic-gate * comments for the "fast_trap_done" entry point for more information.
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the
630Sstevel@tonic-gate * cases where you always want to process any pending interrupts before
640Sstevel@tonic-gate * returning back to the user mode.
650Sstevel@tonic-gate */
660Sstevel@tonic-gate#define	FAST_TRAP_DONE		\
670Sstevel@tonic-gate	ba,a	fast_trap_done
680Sstevel@tonic-gate
690Sstevel@tonic-gate#define	FAST_TRAP_DONE_CHK_INTR	\
700Sstevel@tonic-gate	ba,a	fast_trap_done_chk_intr
710Sstevel@tonic-gate
720Sstevel@tonic-gate/*
730Sstevel@tonic-gate * SPARC V9 Trap Table
740Sstevel@tonic-gate *
750Sstevel@tonic-gate * Most of the trap handlers are made from common building
760Sstevel@tonic-gate * blocks, and some are instantiated multiple times within
770Sstevel@tonic-gate * the trap table. So, I build a bunch of macros, then
780Sstevel@tonic-gate * populate the table using only the macros.
790Sstevel@tonic-gate *
800Sstevel@tonic-gate * Many macros branch to sys_trap.  Its calling convention is:
810Sstevel@tonic-gate *	%g1		kernel trap handler
820Sstevel@tonic-gate *	%g2, %g3	args for above
830Sstevel@tonic-gate *	%g4		desire %pil
840Sstevel@tonic-gate */
850Sstevel@tonic-gate
860Sstevel@tonic-gate#ifdef	TRAPTRACE
870Sstevel@tonic-gate
880Sstevel@tonic-gate/*
890Sstevel@tonic-gate * Tracing macro. Adds two instructions if TRAPTRACE is defined.
900Sstevel@tonic-gate */
910Sstevel@tonic-gate#define	TT_TRACE(label)		\
920Sstevel@tonic-gate	ba	label		;\
930Sstevel@tonic-gate	rd	%pc, %g7
940Sstevel@tonic-gate#define	TT_TRACE_INS	2
950Sstevel@tonic-gate
960Sstevel@tonic-gate#define	TT_TRACE_L(label)	\
970Sstevel@tonic-gate	ba	label		;\
980Sstevel@tonic-gate	rd	%pc, %l4	;\
990Sstevel@tonic-gate	clr	%l4
1000Sstevel@tonic-gate#define	TT_TRACE_L_INS	3
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate#else
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate#define	TT_TRACE(label)
1050Sstevel@tonic-gate#define	TT_TRACE_INS	0
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate#define	TT_TRACE_L(label)
1080Sstevel@tonic-gate#define	TT_TRACE_L_INS	0
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate#endif
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate/*
1130Sstevel@tonic-gate * This first set are funneled to trap() with %tt as the type.
1140Sstevel@tonic-gate * Trap will then either panic or send the user a signal.
1150Sstevel@tonic-gate */
1160Sstevel@tonic-gate/*
1170Sstevel@tonic-gate * NOT is used for traps that just shouldn't happen.
1180Sstevel@tonic-gate * It comes in both single and quadruple flavors.
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate#if !defined(lint)
1210Sstevel@tonic-gate	.global	trap
1220Sstevel@tonic-gate#endif /* !lint */
1230Sstevel@tonic-gate#define	NOT			\
1240Sstevel@tonic-gate	TT_TRACE(trace_gen)	;\
1250Sstevel@tonic-gate	set	trap, %g1	;\
1260Sstevel@tonic-gate	rdpr	%tt, %g3	;\
1270Sstevel@tonic-gate	ba,pt	%xcc, sys_trap	;\
1280Sstevel@tonic-gate	sub	%g0, 1, %g4	;\
1290Sstevel@tonic-gate	.align	32
1300Sstevel@tonic-gate#define	NOT4	NOT; NOT; NOT; NOT
1310Sstevel@tonic-gate/*
1320Sstevel@tonic-gate * RED is for traps that use the red mode handler.
1330Sstevel@tonic-gate * We should never see these either.
1340Sstevel@tonic-gate */
1350Sstevel@tonic-gate#define	RED	NOT
1360Sstevel@tonic-gate/*
1370Sstevel@tonic-gate * BAD is used for trap vectors we don't have a kernel
1380Sstevel@tonic-gate * handler for.
1390Sstevel@tonic-gate * It also comes in single and quadruple versions.
1400Sstevel@tonic-gate */
1410Sstevel@tonic-gate#define	BAD	NOT
1420Sstevel@tonic-gate#define	BAD4	NOT4
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate#define	DONE			\
1450Sstevel@tonic-gate	done;			\
1460Sstevel@tonic-gate	.align	32
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate/*
1490Sstevel@tonic-gate * TRAP vectors to the trap() function.
1500Sstevel@tonic-gate * It's main use is for user errors.
1510Sstevel@tonic-gate */
1520Sstevel@tonic-gate#if !defined(lint)
1530Sstevel@tonic-gate	.global	trap
1540Sstevel@tonic-gate#endif /* !lint */
1550Sstevel@tonic-gate#define	TRAP(arg)		\
1560Sstevel@tonic-gate	TT_TRACE(trace_gen)	;\
1570Sstevel@tonic-gate	set	trap, %g1	;\
1580Sstevel@tonic-gate	mov	arg, %g3	;\
1590Sstevel@tonic-gate	ba,pt	%xcc, sys_trap	;\
1600Sstevel@tonic-gate	sub	%g0, 1, %g4	;\
1610Sstevel@tonic-gate	.align	32
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate/*
1644141Sedp * SYSCALL is used for unsupported syscall interfaces (with 'which'
1654141Sedp * set to 'nosys') and legacy support of old SunOS 4.x syscalls (with
1664141Sedp * 'which' set to 'syscall_trap32').
1674141Sedp *
1684141Sedp * The SYSCALL_TRAP* macros are used for syscall entry points.
1694141Sedp * SYSCALL_TRAP is used to support LP64 syscalls and SYSCALL_TRAP32
1704141Sedp * is used to support ILP32.  Each macro can only be used once
1714141Sedp * since they each define a symbol.  The symbols are used as hot patch
1724141Sedp * points by the brand infrastructure to dynamically enable and disable
1734141Sedp * brand syscall interposition.  See the comments around BRAND_CALLBACK
1744141Sedp * and brand_plat_interposition_enable() for more information.
1750Sstevel@tonic-gate */
1764127Sedp#define	SYSCALL_NOTT(which)		\
1770Sstevel@tonic-gate	set	(which), %g1		;\
1780Sstevel@tonic-gate	ba,pt	%xcc, sys_trap		;\
1790Sstevel@tonic-gate	sub	%g0, 1, %g4		;\
1800Sstevel@tonic-gate	.align	32
1810Sstevel@tonic-gate
1824141Sedp#define	SYSCALL(which)			\
1834141Sedp	TT_TRACE(trace_gen)		;\
1844141Sedp	SYSCALL_NOTT(which)
1854141Sedp
1864141Sedp#define	SYSCALL_TRAP32				\
1874141Sedp	TT_TRACE(trace_gen)			;\
1884141Sedp	ALTENTRY(syscall_trap32_patch_point)	\
1894141Sedp	SYSCALL_NOTT(syscall_trap32)
1904141Sedp
1914141Sedp#define	SYSCALL_TRAP				\
1924141Sedp	TT_TRACE(trace_gen)			;\
1934141Sedp	ALTENTRY(syscall_trap_patch_point)	\
1944141Sedp	SYSCALL_NOTT(syscall_trap)
1954141Sedp
1965414Smb158278#define	FLUSHW(h_name)			\
1975414Smb158278	.global h_name			;\
1985414Smb158278h_name:					;\
1990Sstevel@tonic-gate	set	trap, %g1		;\
2000Sstevel@tonic-gate	mov	T_FLUSHW, %g3		;\
2010Sstevel@tonic-gate	sub	%g0, 1, %g4		;\
2020Sstevel@tonic-gate	save				;\
2030Sstevel@tonic-gate	flushw				;\
2040Sstevel@tonic-gate	restore				;\
2050Sstevel@tonic-gate	FAST_TRAP_DONE			;\
2060Sstevel@tonic-gate	.align	32
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate/*
2090Sstevel@tonic-gate * GOTO just jumps to a label.
2100Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap.
2110Sstevel@tonic-gate */
2120Sstevel@tonic-gate#define	GOTO(label)		\
2130Sstevel@tonic-gate	.global	label		;\
2140Sstevel@tonic-gate	ba,a	label		;\
2150Sstevel@tonic-gate	.empty			;\
2160Sstevel@tonic-gate	.align	32
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate/*
2190Sstevel@tonic-gate * GOTO_TT just jumps to a label.
2200Sstevel@tonic-gate * correctable ECC error traps at  level 0 and 1 will use this macro.
2210Sstevel@tonic-gate * It's used for things that can be fixed without going thru sys_trap.
2220Sstevel@tonic-gate */
2230Sstevel@tonic-gate#define	GOTO_TT(label, ttlabel)		\
2240Sstevel@tonic-gate	.global	label		;\
2250Sstevel@tonic-gate	TT_TRACE(ttlabel)	;\
2260Sstevel@tonic-gate	ba,a	label		;\
2270Sstevel@tonic-gate	.empty			;\
2280Sstevel@tonic-gate	.align	32
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate/*
2310Sstevel@tonic-gate * Privileged traps
2320Sstevel@tonic-gate * Takes breakpoint if privileged, calls trap() if not.
2330Sstevel@tonic-gate */
2340Sstevel@tonic-gate#define	PRIV(label)			\
2350Sstevel@tonic-gate	rdpr	%tstate, %g1		;\
2360Sstevel@tonic-gate	btst	TSTATE_PRIV, %g1	;\
2370Sstevel@tonic-gate	bnz	label			;\
2380Sstevel@tonic-gate	rdpr	%tt, %g3		;\
2390Sstevel@tonic-gate	set	trap, %g1		;\
2400Sstevel@tonic-gate	ba,pt	%xcc, sys_trap		;\
2410Sstevel@tonic-gate	sub	%g0, 1, %g4		;\
2420Sstevel@tonic-gate	.align	32
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate/*
2460Sstevel@tonic-gate * DTrace traps.
2470Sstevel@tonic-gate */
2480Sstevel@tonic-gate#define	DTRACE_PID			\
2490Sstevel@tonic-gate	.global dtrace_pid_probe				;\
2500Sstevel@tonic-gate	set	dtrace_pid_probe, %g1				;\
2510Sstevel@tonic-gate	ba,pt	%xcc, user_trap					;\
2520Sstevel@tonic-gate	sub	%g0, 1, %g4					;\
2530Sstevel@tonic-gate	.align	32
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate#define	DTRACE_RETURN			\
2560Sstevel@tonic-gate	.global dtrace_return_probe				;\
2570Sstevel@tonic-gate	set	dtrace_return_probe, %g1			;\
2580Sstevel@tonic-gate	ba,pt	%xcc, user_trap					;\
2590Sstevel@tonic-gate	sub	%g0, 1, %g4					;\
2600Sstevel@tonic-gate	.align	32
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate/*
2630Sstevel@tonic-gate * REGISTER WINDOW MANAGEMENT MACROS
2640Sstevel@tonic-gate */
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate/*
2670Sstevel@tonic-gate * various convenient units of padding
2680Sstevel@tonic-gate */
2690Sstevel@tonic-gate#define	SKIP(n)	.skip 4*(n)
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate/*
2720Sstevel@tonic-gate * CLEAN_WINDOW is the simple handler for cleaning a register window.
2730Sstevel@tonic-gate */
2740Sstevel@tonic-gate#define	CLEAN_WINDOW						\
2750Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
2760Sstevel@tonic-gate	rdpr %cleanwin, %l0; inc %l0; wrpr %l0, %cleanwin	;\
2770Sstevel@tonic-gate	clr %l0; clr %l1; clr %l2; clr %l3			;\
2780Sstevel@tonic-gate	clr %l4; clr %l5; clr %l6; clr %l7			;\
2790Sstevel@tonic-gate	clr %o0; clr %o1; clr %o2; clr %o3			;\
2800Sstevel@tonic-gate	clr %o4; clr %o5; clr %o6; clr %o7			;\
2810Sstevel@tonic-gate	retry; .align 128
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate#if !defined(lint)
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate/*
2860Sstevel@tonic-gate * If we get an unresolved tlb miss while in a window handler, the fault
2870Sstevel@tonic-gate * handler will resume execution at the last instruction of the window
2880Sstevel@tonic-gate * hander, instead of delivering the fault to the kernel.  Spill handlers
2890Sstevel@tonic-gate * use this to spill windows into the wbuf.
2900Sstevel@tonic-gate *
2910Sstevel@tonic-gate * The mixed handler works by checking %sp, and branching to the correct
2920Sstevel@tonic-gate * handler.  This is done by branching back to label 1: for 32b frames,
2930Sstevel@tonic-gate * or label 2: for 64b frames; which implies the handler order is: 32b,
2940Sstevel@tonic-gate * 64b, mixed.  The 1: and 2: labels are offset into the routines to
2950Sstevel@tonic-gate * allow the branchs' delay slots to contain useful instructions.
2960Sstevel@tonic-gate */
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate/*
2990Sstevel@tonic-gate * SPILL_32bit spills a 32-bit-wide kernel register window.  It
3000Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the
3010Sstevel@tonic-gate * same.  The stack pointer is required to be eight-byte aligned even
3020Sstevel@tonic-gate * though this code only needs it to be four-byte aligned.
3030Sstevel@tonic-gate */
3040Sstevel@tonic-gate#define	SPILL_32bit(tail)					\
3050Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
3060Sstevel@tonic-gate1:	st	%l0, [%sp + 0]					;\
3070Sstevel@tonic-gate	st	%l1, [%sp + 4]					;\
3080Sstevel@tonic-gate	st	%l2, [%sp + 8]					;\
3090Sstevel@tonic-gate	st	%l3, [%sp + 12]					;\
3100Sstevel@tonic-gate	st	%l4, [%sp + 16]					;\
3110Sstevel@tonic-gate	st	%l5, [%sp + 20]					;\
3120Sstevel@tonic-gate	st	%l6, [%sp + 24]					;\
3130Sstevel@tonic-gate	st	%l7, [%sp + 28]					;\
3140Sstevel@tonic-gate	st	%i0, [%sp + 32]					;\
3150Sstevel@tonic-gate	st	%i1, [%sp + 36]					;\
3160Sstevel@tonic-gate	st	%i2, [%sp + 40]					;\
3170Sstevel@tonic-gate	st	%i3, [%sp + 44]					;\
3180Sstevel@tonic-gate	st	%i4, [%sp + 48]					;\
3190Sstevel@tonic-gate	st	%i5, [%sp + 52]					;\
3200Sstevel@tonic-gate	st	%i6, [%sp + 56]					;\
3210Sstevel@tonic-gate	st	%i7, [%sp + 60]					;\
3220Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
3230Sstevel@tonic-gate	saved							;\
3240Sstevel@tonic-gate	retry							;\
3250Sstevel@tonic-gate	SKIP(31-19-TT_TRACE_L_INS)				;\
3260Sstevel@tonic-gate	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
3270Sstevel@tonic-gate	.empty
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate/*
3300Sstevel@tonic-gate * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit
3310Sstevel@tonic-gate * wide address space via the designated asi.  It is used to spill
3320Sstevel@tonic-gate * non-kernel windows.  The stack pointer is required to be eight-byte
3330Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte
3340Sstevel@tonic-gate * aligned.
3350Sstevel@tonic-gate */
3360Sstevel@tonic-gate#define	SPILL_32bit_asi(asi_num, tail)				\
3370Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
3380Sstevel@tonic-gate1:	sta	%l0, [%sp + %g0]asi_num				;\
3390Sstevel@tonic-gate	mov	4, %g1						;\
3400Sstevel@tonic-gate	sta	%l1, [%sp + %g1]asi_num				;\
3410Sstevel@tonic-gate	mov	8, %g2						;\
3420Sstevel@tonic-gate	sta	%l2, [%sp + %g2]asi_num				;\
3430Sstevel@tonic-gate	mov	12, %g3						;\
3440Sstevel@tonic-gate	sta	%l3, [%sp + %g3]asi_num				;\
3450Sstevel@tonic-gate	add	%sp, 16, %g4					;\
3460Sstevel@tonic-gate	sta	%l4, [%g4 + %g0]asi_num				;\
3470Sstevel@tonic-gate	sta	%l5, [%g4 + %g1]asi_num				;\
3480Sstevel@tonic-gate	sta	%l6, [%g4 + %g2]asi_num				;\
3490Sstevel@tonic-gate	sta	%l7, [%g4 + %g3]asi_num				;\
3500Sstevel@tonic-gate	add	%g4, 16, %g4					;\
3510Sstevel@tonic-gate	sta	%i0, [%g4 + %g0]asi_num				;\
3520Sstevel@tonic-gate	sta	%i1, [%g4 + %g1]asi_num				;\
3530Sstevel@tonic-gate	sta	%i2, [%g4 + %g2]asi_num				;\
3540Sstevel@tonic-gate	sta	%i3, [%g4 + %g3]asi_num				;\
3550Sstevel@tonic-gate	add	%g4, 16, %g4					;\
3560Sstevel@tonic-gate	sta	%i4, [%g4 + %g0]asi_num				;\
3570Sstevel@tonic-gate	sta	%i5, [%g4 + %g1]asi_num				;\
3580Sstevel@tonic-gate	sta	%i6, [%g4 + %g2]asi_num				;\
3590Sstevel@tonic-gate	sta	%i7, [%g4 + %g3]asi_num				;\
3600Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
3610Sstevel@tonic-gate	saved							;\
3620Sstevel@tonic-gate	retry							;\
3630Sstevel@tonic-gate	SKIP(31-25-TT_TRACE_L_INS)				;\
3640Sstevel@tonic-gate	ba,a,pt %xcc, fault_32bit_/**/tail			;\
3650Sstevel@tonic-gate	.empty
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate/*
3680Sstevel@tonic-gate * SPILL_32bit_tt1 spills a 32-bit-wide register window into a 32-bit
3690Sstevel@tonic-gate * wide address space via the designated asi.  It is used to spill
3700Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and
3710Sstevel@tonic-gate * where we don't want to use unnecessary registers.  The stack
3720Sstevel@tonic-gate * pointer is required to be eight-byte aligned even though this code
3730Sstevel@tonic-gate * only needs it to be four-byte aligned.
3740Sstevel@tonic-gate */
3750Sstevel@tonic-gate#define	SPILL_32bit_tt1(asi_num, tail)				\
3760Sstevel@tonic-gate	mov	asi_num, %asi					;\
3770Sstevel@tonic-gate1:	srl	%sp, 0, %sp					;\
3780Sstevel@tonic-gate	sta	%l0, [%sp + 0]%asi				;\
3790Sstevel@tonic-gate	sta	%l1, [%sp + 4]%asi				;\
3800Sstevel@tonic-gate	sta	%l2, [%sp + 8]%asi				;\
3810Sstevel@tonic-gate	sta	%l3, [%sp + 12]%asi				;\
3820Sstevel@tonic-gate	sta	%l4, [%sp + 16]%asi				;\
3830Sstevel@tonic-gate	sta	%l5, [%sp + 20]%asi				;\
3840Sstevel@tonic-gate	sta	%l6, [%sp + 24]%asi				;\
3850Sstevel@tonic-gate	sta	%l7, [%sp + 28]%asi				;\
3860Sstevel@tonic-gate	sta	%i0, [%sp + 32]%asi				;\
3870Sstevel@tonic-gate	sta	%i1, [%sp + 36]%asi				;\
3880Sstevel@tonic-gate	sta	%i2, [%sp + 40]%asi				;\
3890Sstevel@tonic-gate	sta	%i3, [%sp + 44]%asi				;\
3900Sstevel@tonic-gate	sta	%i4, [%sp + 48]%asi				;\
3910Sstevel@tonic-gate	sta	%i5, [%sp + 52]%asi				;\
3920Sstevel@tonic-gate	sta	%i6, [%sp + 56]%asi				;\
3930Sstevel@tonic-gate	sta	%i7, [%sp + 60]%asi				;\
3940Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
3950Sstevel@tonic-gate	saved							;\
3960Sstevel@tonic-gate	retry							;\
3970Sstevel@tonic-gate	SKIP(31-20-TT_TRACE_L_INS)				;\
3980Sstevel@tonic-gate	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
3990Sstevel@tonic-gate	.empty
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate/*
4030Sstevel@tonic-gate * FILL_32bit fills a 32-bit-wide kernel register window.  It assumes
4040Sstevel@tonic-gate * that the kernel context and the nucleus context are the same.  The
4050Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned even though this
4060Sstevel@tonic-gate * code only needs it to be four-byte aligned.
4070Sstevel@tonic-gate */
4080Sstevel@tonic-gate#define	FILL_32bit(tail)					\
4090Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
4100Sstevel@tonic-gate1:	TT_TRACE_L(trace_win)					;\
4110Sstevel@tonic-gate	ld	[%sp + 0], %l0					;\
4120Sstevel@tonic-gate	ld	[%sp + 4], %l1					;\
4130Sstevel@tonic-gate	ld	[%sp + 8], %l2					;\
4140Sstevel@tonic-gate	ld	[%sp + 12], %l3					;\
4150Sstevel@tonic-gate	ld	[%sp + 16], %l4					;\
4160Sstevel@tonic-gate	ld	[%sp + 20], %l5					;\
4170Sstevel@tonic-gate	ld	[%sp + 24], %l6					;\
4180Sstevel@tonic-gate	ld	[%sp + 28], %l7					;\
4190Sstevel@tonic-gate	ld	[%sp + 32], %i0					;\
4200Sstevel@tonic-gate	ld	[%sp + 36], %i1					;\
4210Sstevel@tonic-gate	ld	[%sp + 40], %i2					;\
4220Sstevel@tonic-gate	ld	[%sp + 44], %i3					;\
4230Sstevel@tonic-gate	ld	[%sp + 48], %i4					;\
4240Sstevel@tonic-gate	ld	[%sp + 52], %i5					;\
4250Sstevel@tonic-gate	ld	[%sp + 56], %i6					;\
4260Sstevel@tonic-gate	ld	[%sp + 60], %i7					;\
4270Sstevel@tonic-gate	restored						;\
4280Sstevel@tonic-gate	retry							;\
4290Sstevel@tonic-gate	SKIP(31-19-TT_TRACE_L_INS)				;\
4300Sstevel@tonic-gate	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
4310Sstevel@tonic-gate	.empty
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate/*
4340Sstevel@tonic-gate * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit
4350Sstevel@tonic-gate * wide address space via the designated asi.  It is used to fill
4360Sstevel@tonic-gate * non-kernel windows.  The stack pointer is required to be eight-byte
4370Sstevel@tonic-gate * aligned even though this code only needs it to be four-byte
4380Sstevel@tonic-gate * aligned.
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate#define	FILL_32bit_asi(asi_num, tail)				\
4410Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
4420Sstevel@tonic-gate1:	TT_TRACE_L(trace_win)					;\
4430Sstevel@tonic-gate	mov	4, %g1						;\
4440Sstevel@tonic-gate	lda	[%sp + %g0]asi_num, %l0				;\
4450Sstevel@tonic-gate	mov	8, %g2						;\
4460Sstevel@tonic-gate	lda	[%sp + %g1]asi_num, %l1				;\
4470Sstevel@tonic-gate	mov	12, %g3						;\
4480Sstevel@tonic-gate	lda	[%sp + %g2]asi_num, %l2				;\
4490Sstevel@tonic-gate	lda	[%sp + %g3]asi_num, %l3				;\
4500Sstevel@tonic-gate	add	%sp, 16, %g4					;\
4510Sstevel@tonic-gate	lda	[%g4 + %g0]asi_num, %l4				;\
4520Sstevel@tonic-gate	lda	[%g4 + %g1]asi_num, %l5				;\
4530Sstevel@tonic-gate	lda	[%g4 + %g2]asi_num, %l6				;\
4540Sstevel@tonic-gate	lda	[%g4 + %g3]asi_num, %l7				;\
4550Sstevel@tonic-gate	add	%g4, 16, %g4					;\
4560Sstevel@tonic-gate	lda	[%g4 + %g0]asi_num, %i0				;\
4570Sstevel@tonic-gate	lda	[%g4 + %g1]asi_num, %i1				;\
4580Sstevel@tonic-gate	lda	[%g4 + %g2]asi_num, %i2				;\
4590Sstevel@tonic-gate	lda	[%g4 + %g3]asi_num, %i3				;\
4600Sstevel@tonic-gate	add	%g4, 16, %g4					;\
4610Sstevel@tonic-gate	lda	[%g4 + %g0]asi_num, %i4				;\
4620Sstevel@tonic-gate	lda	[%g4 + %g1]asi_num, %i5				;\
4630Sstevel@tonic-gate	lda	[%g4 + %g2]asi_num, %i6				;\
4640Sstevel@tonic-gate	lda	[%g4 + %g3]asi_num, %i7				;\
4650Sstevel@tonic-gate	restored						;\
4660Sstevel@tonic-gate	retry							;\
4670Sstevel@tonic-gate	SKIP(31-25-TT_TRACE_L_INS)				;\
4680Sstevel@tonic-gate	ba,a,pt %xcc, fault_32bit_/**/tail			;\
4690Sstevel@tonic-gate	.empty
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate/*
4720Sstevel@tonic-gate * FILL_32bit_tt1 fills a 32-bit-wide register window from a 32-bit
4730Sstevel@tonic-gate * wide address space via the designated asi.  It is used to fill
4740Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and
4750Sstevel@tonic-gate * where we don't want to use unnecessary registers.  The stack
4760Sstevel@tonic-gate * pointer is required to be eight-byte aligned even though this code
4770Sstevel@tonic-gate * only needs it to be four-byte aligned.
4780Sstevel@tonic-gate */
4790Sstevel@tonic-gate#define	FILL_32bit_tt1(asi_num, tail)				\
4800Sstevel@tonic-gate	mov	asi_num, %asi					;\
4810Sstevel@tonic-gate1:	srl	%sp, 0, %sp					;\
4820Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
4830Sstevel@tonic-gate	lda	[%sp + 0]%asi, %l0				;\
4840Sstevel@tonic-gate	lda	[%sp + 4]%asi, %l1				;\
4850Sstevel@tonic-gate	lda	[%sp + 8]%asi, %l2				;\
4860Sstevel@tonic-gate	lda	[%sp + 12]%asi, %l3				;\
4870Sstevel@tonic-gate	lda	[%sp + 16]%asi, %l4				;\
4880Sstevel@tonic-gate	lda	[%sp + 20]%asi, %l5				;\
4890Sstevel@tonic-gate	lda	[%sp + 24]%asi, %l6				;\
4900Sstevel@tonic-gate	lda	[%sp + 28]%asi, %l7				;\
4910Sstevel@tonic-gate	lda	[%sp + 32]%asi, %i0				;\
4920Sstevel@tonic-gate	lda	[%sp + 36]%asi, %i1				;\
4930Sstevel@tonic-gate	lda	[%sp + 40]%asi, %i2				;\
4940Sstevel@tonic-gate	lda	[%sp + 44]%asi, %i3				;\
4950Sstevel@tonic-gate	lda	[%sp + 48]%asi, %i4				;\
4960Sstevel@tonic-gate	lda	[%sp + 52]%asi, %i5				;\
4970Sstevel@tonic-gate	lda	[%sp + 56]%asi, %i6				;\
4980Sstevel@tonic-gate	lda	[%sp + 60]%asi, %i7				;\
4990Sstevel@tonic-gate	restored						;\
5000Sstevel@tonic-gate	retry							;\
5010Sstevel@tonic-gate	SKIP(31-20-TT_TRACE_L_INS)				;\
5020Sstevel@tonic-gate	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
5030Sstevel@tonic-gate	.empty
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate/*
5070Sstevel@tonic-gate * SPILL_64bit spills a 64-bit-wide kernel register window.  It
5080Sstevel@tonic-gate * assumes that the kernel context and the nucleus context are the
5090Sstevel@tonic-gate * same.  The stack pointer is required to be eight-byte aligned.
5100Sstevel@tonic-gate */
5110Sstevel@tonic-gate#define	SPILL_64bit(tail)					\
5120Sstevel@tonic-gate2:	stx	%l0, [%sp + V9BIAS64 + 0]			;\
5130Sstevel@tonic-gate	stx	%l1, [%sp + V9BIAS64 + 8]			;\
5140Sstevel@tonic-gate	stx	%l2, [%sp + V9BIAS64 + 16]			;\
5150Sstevel@tonic-gate	stx	%l3, [%sp + V9BIAS64 + 24]			;\
5160Sstevel@tonic-gate	stx	%l4, [%sp + V9BIAS64 + 32]			;\
5170Sstevel@tonic-gate	stx	%l5, [%sp + V9BIAS64 + 40]			;\
5180Sstevel@tonic-gate	stx	%l6, [%sp + V9BIAS64 + 48]			;\
5190Sstevel@tonic-gate	stx	%l7, [%sp + V9BIAS64 + 56]			;\
5200Sstevel@tonic-gate	stx	%i0, [%sp + V9BIAS64 + 64]			;\
5210Sstevel@tonic-gate	stx	%i1, [%sp + V9BIAS64 + 72]			;\
5220Sstevel@tonic-gate	stx	%i2, [%sp + V9BIAS64 + 80]			;\
5230Sstevel@tonic-gate	stx	%i3, [%sp + V9BIAS64 + 88]			;\
5240Sstevel@tonic-gate	stx	%i4, [%sp + V9BIAS64 + 96]			;\
5250Sstevel@tonic-gate	stx	%i5, [%sp + V9BIAS64 + 104]			;\
5260Sstevel@tonic-gate	stx	%i6, [%sp + V9BIAS64 + 112]			;\
5270Sstevel@tonic-gate	stx	%i7, [%sp + V9BIAS64 + 120]			;\
5280Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
5290Sstevel@tonic-gate	saved							;\
5300Sstevel@tonic-gate	retry							;\
5310Sstevel@tonic-gate	SKIP(31-18-TT_TRACE_L_INS)				;\
5320Sstevel@tonic-gate	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
5330Sstevel@tonic-gate	.empty
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate/*
5360Sstevel@tonic-gate * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit
5370Sstevel@tonic-gate * wide address space via the designated asi.  It is used to spill
5380Sstevel@tonic-gate * non-kernel windows.  The stack pointer is required to be eight-byte
5390Sstevel@tonic-gate * aligned.
5400Sstevel@tonic-gate */
5410Sstevel@tonic-gate#define	SPILL_64bit_asi(asi_num, tail)				\
5420Sstevel@tonic-gate	mov	0 + V9BIAS64, %g1				;\
5430Sstevel@tonic-gate2:	stxa	%l0, [%sp + %g1]asi_num				;\
5440Sstevel@tonic-gate	mov	8 + V9BIAS64, %g2				;\
5450Sstevel@tonic-gate	stxa	%l1, [%sp + %g2]asi_num				;\
5460Sstevel@tonic-gate	mov	16 + V9BIAS64, %g3				;\
5470Sstevel@tonic-gate	stxa	%l2, [%sp + %g3]asi_num				;\
5480Sstevel@tonic-gate	mov	24 + V9BIAS64, %g4				;\
5490Sstevel@tonic-gate	stxa	%l3, [%sp + %g4]asi_num				;\
5500Sstevel@tonic-gate	add	%sp, 32, %g5					;\
5510Sstevel@tonic-gate	stxa	%l4, [%g5 + %g1]asi_num				;\
5520Sstevel@tonic-gate	stxa	%l5, [%g5 + %g2]asi_num				;\
5530Sstevel@tonic-gate	stxa	%l6, [%g5 + %g3]asi_num				;\
5540Sstevel@tonic-gate	stxa	%l7, [%g5 + %g4]asi_num				;\
5550Sstevel@tonic-gate	add	%g5, 32, %g5					;\
5560Sstevel@tonic-gate	stxa	%i0, [%g5 + %g1]asi_num				;\
5570Sstevel@tonic-gate	stxa	%i1, [%g5 + %g2]asi_num				;\
5580Sstevel@tonic-gate	stxa	%i2, [%g5 + %g3]asi_num				;\
5590Sstevel@tonic-gate	stxa	%i3, [%g5 + %g4]asi_num				;\
5600Sstevel@tonic-gate	add	%g5, 32, %g5					;\
5610Sstevel@tonic-gate	stxa	%i4, [%g5 + %g1]asi_num				;\
5620Sstevel@tonic-gate	stxa	%i5, [%g5 + %g2]asi_num				;\
5630Sstevel@tonic-gate	stxa	%i6, [%g5 + %g3]asi_num				;\
5640Sstevel@tonic-gate	stxa	%i7, [%g5 + %g4]asi_num				;\
5650Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
5660Sstevel@tonic-gate	saved							;\
5670Sstevel@tonic-gate	retry							;\
5680Sstevel@tonic-gate	SKIP(31-25-TT_TRACE_L_INS)				;\
5690Sstevel@tonic-gate	ba,a,pt %xcc, fault_64bit_/**/tail			;\
5700Sstevel@tonic-gate	.empty
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate/*
5730Sstevel@tonic-gate * SPILL_64bit_tt1 spills a 64-bit-wide register window into a 64-bit
5740Sstevel@tonic-gate * wide address space via the designated asi.  It is used to spill
5750Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and
5760Sstevel@tonic-gate * where we don't want to use unnecessary registers.  The stack
5770Sstevel@tonic-gate * pointer is required to be eight-byte aligned.
5780Sstevel@tonic-gate */
5790Sstevel@tonic-gate#define	SPILL_64bit_tt1(asi_num, tail)				\
5800Sstevel@tonic-gate	mov	asi_num, %asi					;\
5810Sstevel@tonic-gate2:	stxa	%l0, [%sp + V9BIAS64 + 0]%asi			;\
5820Sstevel@tonic-gate	stxa	%l1, [%sp + V9BIAS64 + 8]%asi			;\
5830Sstevel@tonic-gate	stxa	%l2, [%sp + V9BIAS64 + 16]%asi			;\
5840Sstevel@tonic-gate	stxa	%l3, [%sp + V9BIAS64 + 24]%asi			;\
5850Sstevel@tonic-gate	stxa	%l4, [%sp + V9BIAS64 + 32]%asi			;\
5860Sstevel@tonic-gate	stxa	%l5, [%sp + V9BIAS64 + 40]%asi			;\
5870Sstevel@tonic-gate	stxa	%l6, [%sp + V9BIAS64 + 48]%asi			;\
5880Sstevel@tonic-gate	stxa	%l7, [%sp + V9BIAS64 + 56]%asi			;\
5890Sstevel@tonic-gate	stxa	%i0, [%sp + V9BIAS64 + 64]%asi			;\
5900Sstevel@tonic-gate	stxa	%i1, [%sp + V9BIAS64 + 72]%asi			;\
5910Sstevel@tonic-gate	stxa	%i2, [%sp + V9BIAS64 + 80]%asi			;\
5920Sstevel@tonic-gate	stxa	%i3, [%sp + V9BIAS64 + 88]%asi			;\
5930Sstevel@tonic-gate	stxa	%i4, [%sp + V9BIAS64 + 96]%asi			;\
5940Sstevel@tonic-gate	stxa	%i5, [%sp + V9BIAS64 + 104]%asi			;\
5950Sstevel@tonic-gate	stxa	%i6, [%sp + V9BIAS64 + 112]%asi			;\
5960Sstevel@tonic-gate	stxa	%i7, [%sp + V9BIAS64 + 120]%asi			;\
5970Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
5980Sstevel@tonic-gate	saved							;\
5990Sstevel@tonic-gate	retry							;\
6000Sstevel@tonic-gate	SKIP(31-19-TT_TRACE_L_INS)				;\
6010Sstevel@tonic-gate	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
6020Sstevel@tonic-gate	.empty
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate/*
6060Sstevel@tonic-gate * FILL_64bit fills a 64-bit-wide kernel register window.  It assumes
6070Sstevel@tonic-gate * that the kernel context and the nucleus context are the same.  The
6080Sstevel@tonic-gate * stack pointer is required to be eight-byte aligned.
6090Sstevel@tonic-gate */
6100Sstevel@tonic-gate#define	FILL_64bit(tail)					\
6110Sstevel@tonic-gate2:	TT_TRACE_L(trace_win)					;\
6120Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 0], %l0			;\
6130Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 8], %l1			;\
6140Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 16], %l2			;\
6150Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 24], %l3			;\
6160Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 32], %l4			;\
6170Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 40], %l5			;\
6180Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 48], %l6			;\
6190Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 56], %l7			;\
6200Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 64], %i0			;\
6210Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 72], %i1			;\
6220Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 80], %i2			;\
6230Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 88], %i3			;\
6240Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 96], %i4			;\
6250Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 104], %i5			;\
6260Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 112], %i6			;\
6270Sstevel@tonic-gate	ldx	[%sp + V9BIAS64 + 120], %i7			;\
6280Sstevel@tonic-gate	restored						;\
6290Sstevel@tonic-gate	retry							;\
6300Sstevel@tonic-gate	SKIP(31-18-TT_TRACE_L_INS)				;\
6310Sstevel@tonic-gate	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
6320Sstevel@tonic-gate	.empty
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate/*
6350Sstevel@tonic-gate * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit
6360Sstevel@tonic-gate * wide address space via the designated asi.  It is used to fill
6370Sstevel@tonic-gate * non-kernel windows.  The stack pointer is required to be eight-byte
6384127Sedp * aligned.
6390Sstevel@tonic-gate */
6400Sstevel@tonic-gate#define	FILL_64bit_asi(asi_num, tail)				\
6410Sstevel@tonic-gate	mov	V9BIAS64 + 0, %g1				;\
6420Sstevel@tonic-gate2:	TT_TRACE_L(trace_win)					;\
6430Sstevel@tonic-gate	ldxa	[%sp + %g1]asi_num, %l0				;\
6440Sstevel@tonic-gate	mov	V9BIAS64 + 8, %g2				;\
6450Sstevel@tonic-gate	ldxa	[%sp + %g2]asi_num, %l1				;\
6460Sstevel@tonic-gate	mov	V9BIAS64 + 16, %g3				;\
6470Sstevel@tonic-gate	ldxa	[%sp + %g3]asi_num, %l2				;\
6480Sstevel@tonic-gate	mov	V9BIAS64 + 24, %g4				;\
6490Sstevel@tonic-gate	ldxa	[%sp + %g4]asi_num, %l3				;\
6500Sstevel@tonic-gate	add	%sp, 32, %g5					;\
6510Sstevel@tonic-gate	ldxa	[%g5 + %g1]asi_num, %l4				;\
6520Sstevel@tonic-gate	ldxa	[%g5 + %g2]asi_num, %l5				;\
6530Sstevel@tonic-gate	ldxa	[%g5 + %g3]asi_num, %l6				;\
6540Sstevel@tonic-gate	ldxa	[%g5 + %g4]asi_num, %l7				;\
6550Sstevel@tonic-gate	add	%g5, 32, %g5					;\
6560Sstevel@tonic-gate	ldxa	[%g5 + %g1]asi_num, %i0				;\
6570Sstevel@tonic-gate	ldxa	[%g5 + %g2]asi_num, %i1				;\
6580Sstevel@tonic-gate	ldxa	[%g5 + %g3]asi_num, %i2				;\
6590Sstevel@tonic-gate	ldxa	[%g5 + %g4]asi_num, %i3				;\
6600Sstevel@tonic-gate	add	%g5, 32, %g5					;\
6610Sstevel@tonic-gate	ldxa	[%g5 + %g1]asi_num, %i4				;\
6620Sstevel@tonic-gate	ldxa	[%g5 + %g2]asi_num, %i5				;\
6630Sstevel@tonic-gate	ldxa	[%g5 + %g3]asi_num, %i6				;\
6640Sstevel@tonic-gate	ldxa	[%g5 + %g4]asi_num, %i7				;\
6650Sstevel@tonic-gate	restored						;\
6660Sstevel@tonic-gate	retry							;\
6670Sstevel@tonic-gate	SKIP(31-25-TT_TRACE_L_INS)				;\
6680Sstevel@tonic-gate	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
6690Sstevel@tonic-gate	.empty
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate/*
6720Sstevel@tonic-gate * FILL_64bit_tt1 fills a 64-bit-wide register window from a 64-bit
6730Sstevel@tonic-gate * wide address space via the designated asi.  It is used to fill
6740Sstevel@tonic-gate * windows at tl>1 where performance isn't the primary concern and
6750Sstevel@tonic-gate * where we don't want to use unnecessary registers.  The stack
6760Sstevel@tonic-gate * pointer is required to be eight-byte aligned.
6770Sstevel@tonic-gate */
6780Sstevel@tonic-gate#define	FILL_64bit_tt1(asi_num, tail)				\
6790Sstevel@tonic-gate	mov	asi_num, %asi					;\
6800Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
6810Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 0]%asi, %l0			;\
6820Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 8]%asi, %l1			;\
6830Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 16]%asi, %l2			;\
6840Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 24]%asi, %l3			;\
6850Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 32]%asi, %l4			;\
6860Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 40]%asi, %l5			;\
6870Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 48]%asi, %l6			;\
6880Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 56]%asi, %l7			;\
6890Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 64]%asi, %i0			;\
6900Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 72]%asi, %i1			;\
6910Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 80]%asi, %i2			;\
6920Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 88]%asi, %i3			;\
6930Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 96]%asi, %i4			;\
6940Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 104]%asi, %i5			;\
6950Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 112]%asi, %i6			;\
6960Sstevel@tonic-gate	ldxa	[%sp + V9BIAS64 + 120]%asi, %i7			;\
6970Sstevel@tonic-gate	restored						;\
6980Sstevel@tonic-gate	retry							;\
6990Sstevel@tonic-gate	SKIP(31-19-TT_TRACE_L_INS)				;\
7000Sstevel@tonic-gate	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
7010Sstevel@tonic-gate	.empty
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate#endif /* !lint */
7040Sstevel@tonic-gate
7050Sstevel@tonic-gate/*
7060Sstevel@tonic-gate * SPILL_mixed spills either size window, depending on
7070Sstevel@tonic-gate * whether %sp is even or odd, to a 32-bit address space.
7080Sstevel@tonic-gate * This may only be used in conjunction with SPILL_32bit/
7090Sstevel@tonic-gate * SPILL_64bit. New versions of SPILL_mixed_{tt1,asi} would be
7100Sstevel@tonic-gate * needed for use with SPILL_{32,64}bit_{tt1,asi}.  Particular
7110Sstevel@tonic-gate * attention should be paid to the instructions that belong
7120Sstevel@tonic-gate * in the delay slots of the branches depending on the type
7130Sstevel@tonic-gate * of spill handler being branched to.
7140Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd.
7150Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel.
7160Sstevel@tonic-gate */
7170Sstevel@tonic-gate#define	SPILL_mixed						\
7180Sstevel@tonic-gate	btst	1, %sp						;\
7190Sstevel@tonic-gate	bz,a,pt	%xcc, 1b					;\
7200Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
7210Sstevel@tonic-gate	ba,pt	%xcc, 2b					;\
7220Sstevel@tonic-gate	nop							;\
7230Sstevel@tonic-gate	.align	128
7240Sstevel@tonic-gate
7250Sstevel@tonic-gate/*
7260Sstevel@tonic-gate * FILL_mixed(ASI) fills either size window, depending on
7270Sstevel@tonic-gate * whether %sp is even or odd, from a 32-bit address space.
7280Sstevel@tonic-gate * This may only be used in conjunction with FILL_32bit/
7290Sstevel@tonic-gate * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be
7300Sstevel@tonic-gate * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular
7310Sstevel@tonic-gate * attention should be paid to the instructions that belong
7320Sstevel@tonic-gate * in the delay slots of the branches depending on the type
7330Sstevel@tonic-gate * of fill handler being branched to.
7340Sstevel@tonic-gate * Clear upper 32 bits of %sp if it is odd.
7350Sstevel@tonic-gate * We won't need to clear them in 64 bit kernel.
7360Sstevel@tonic-gate */
7370Sstevel@tonic-gate#define	FILL_mixed						\
7380Sstevel@tonic-gate	btst	1, %sp						;\
7390Sstevel@tonic-gate	bz,a,pt	%xcc, 1b					;\
7400Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
7410Sstevel@tonic-gate	ba,pt	%xcc, 2b					;\
7420Sstevel@tonic-gate	nop							;\
7430Sstevel@tonic-gate	.align	128
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate
7460Sstevel@tonic-gate/*
7470Sstevel@tonic-gate * SPILL_32clean/SPILL_64clean spill 32-bit and 64-bit register windows,
7480Sstevel@tonic-gate * respectively, into the address space via the designated asi.  The
7490Sstevel@tonic-gate * unbiased stack pointer is required to be eight-byte aligned (even for
7500Sstevel@tonic-gate * the 32-bit case even though this code does not require such strict
7510Sstevel@tonic-gate * alignment).
7520Sstevel@tonic-gate *
7530Sstevel@tonic-gate * With SPARC v9 the spill trap takes precedence over the cleanwin trap
7540Sstevel@tonic-gate * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save
7550Sstevel@tonic-gate * will cause cwp + 2 to be spilled but will not clean cwp + 1.  That
7560Sstevel@tonic-gate * window may contain kernel data so in user_rtt we set wstate to call
7570Sstevel@tonic-gate * these spill handlers on the first user spill trap.  These handler then
7580Sstevel@tonic-gate * spill the appropriate window but also back up a window and clean the
7590Sstevel@tonic-gate * window that didn't get a cleanwin trap.
7600Sstevel@tonic-gate */
7610Sstevel@tonic-gate#define	SPILL_32clean(asi_num, tail)				\
7620Sstevel@tonic-gate	srl	%sp, 0, %sp					;\
7630Sstevel@tonic-gate	sta	%l0, [%sp + %g0]asi_num				;\
7640Sstevel@tonic-gate	mov	4, %g1						;\
7650Sstevel@tonic-gate	sta	%l1, [%sp + %g1]asi_num				;\
7660Sstevel@tonic-gate	mov	8, %g2						;\
7670Sstevel@tonic-gate	sta	%l2, [%sp + %g2]asi_num				;\
7680Sstevel@tonic-gate	mov	12, %g3						;\
7690Sstevel@tonic-gate	sta	%l3, [%sp + %g3]asi_num				;\
7700Sstevel@tonic-gate	add	%sp, 16, %g4					;\
7710Sstevel@tonic-gate	sta	%l4, [%g4 + %g0]asi_num				;\
7720Sstevel@tonic-gate	sta	%l5, [%g4 + %g1]asi_num				;\
7730Sstevel@tonic-gate	sta	%l6, [%g4 + %g2]asi_num				;\
7740Sstevel@tonic-gate	sta	%l7, [%g4 + %g3]asi_num				;\
7750Sstevel@tonic-gate	add	%g4, 16, %g4					;\
7760Sstevel@tonic-gate	sta	%i0, [%g4 + %g0]asi_num				;\
7770Sstevel@tonic-gate	sta	%i1, [%g4 + %g1]asi_num				;\
7780Sstevel@tonic-gate	sta	%i2, [%g4 + %g2]asi_num				;\
7790Sstevel@tonic-gate	sta	%i3, [%g4 + %g3]asi_num				;\
7800Sstevel@tonic-gate	add	%g4, 16, %g4					;\
7810Sstevel@tonic-gate	sta	%i4, [%g4 + %g0]asi_num				;\
7820Sstevel@tonic-gate	sta	%i5, [%g4 + %g1]asi_num				;\
7830Sstevel@tonic-gate	sta	%i6, [%g4 + %g2]asi_num				;\
7840Sstevel@tonic-gate	sta	%i7, [%g4 + %g3]asi_num				;\
7850Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
7860Sstevel@tonic-gate	b	.spill_clean					;\
7870Sstevel@tonic-gate	  mov	WSTATE_USER32, %g7				;\
7880Sstevel@tonic-gate	SKIP(31-25-TT_TRACE_L_INS)				;\
7890Sstevel@tonic-gate	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
7900Sstevel@tonic-gate	.empty
7910Sstevel@tonic-gate
7920Sstevel@tonic-gate#define	SPILL_64clean(asi_num, tail)				\
7930Sstevel@tonic-gate	mov	0 + V9BIAS64, %g1				;\
7940Sstevel@tonic-gate	stxa	%l0, [%sp + %g1]asi_num				;\
7950Sstevel@tonic-gate	mov	8 + V9BIAS64, %g2				;\
7960Sstevel@tonic-gate	stxa	%l1, [%sp + %g2]asi_num				;\
7970Sstevel@tonic-gate	mov	16 + V9BIAS64, %g3				;\
7980Sstevel@tonic-gate	stxa	%l2, [%sp + %g3]asi_num				;\
7990Sstevel@tonic-gate	mov	24 + V9BIAS64, %g4				;\
8000Sstevel@tonic-gate	stxa	%l3, [%sp + %g4]asi_num				;\
8010Sstevel@tonic-gate	add	%sp, 32, %g5					;\
8020Sstevel@tonic-gate	stxa	%l4, [%g5 + %g1]asi_num				;\
8030Sstevel@tonic-gate	stxa	%l5, [%g5 + %g2]asi_num				;\
8040Sstevel@tonic-gate	stxa	%l6, [%g5 + %g3]asi_num				;\
8050Sstevel@tonic-gate	stxa	%l7, [%g5 + %g4]asi_num				;\
8060Sstevel@tonic-gate	add	%g5, 32, %g5					;\
8070Sstevel@tonic-gate	stxa	%i0, [%g5 + %g1]asi_num				;\
8080Sstevel@tonic-gate	stxa	%i1, [%g5 + %g2]asi_num				;\
8090Sstevel@tonic-gate	stxa	%i2, [%g5 + %g3]asi_num				;\
8100Sstevel@tonic-gate	stxa	%i3, [%g5 + %g4]asi_num				;\
8110Sstevel@tonic-gate	add	%g5, 32, %g5					;\
8120Sstevel@tonic-gate	stxa	%i4, [%g5 + %g1]asi_num				;\
8130Sstevel@tonic-gate	stxa	%i5, [%g5 + %g2]asi_num				;\
8140Sstevel@tonic-gate	stxa	%i6, [%g5 + %g3]asi_num				;\
8150Sstevel@tonic-gate	stxa	%i7, [%g5 + %g4]asi_num				;\
8160Sstevel@tonic-gate	TT_TRACE_L(trace_win)					;\
8170Sstevel@tonic-gate	b	.spill_clean					;\
8180Sstevel@tonic-gate	  mov	WSTATE_USER64, %g7				;\
8190Sstevel@tonic-gate	SKIP(31-25-TT_TRACE_L_INS)				;\
8200Sstevel@tonic-gate	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
8210Sstevel@tonic-gate	.empty
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate/*
8250Sstevel@tonic-gate * Floating point disabled.
8260Sstevel@tonic-gate */
8270Sstevel@tonic-gate#define	FP_DISABLED_TRAP		\
8280Sstevel@tonic-gate	TT_TRACE(trace_gen)		;\
8290Sstevel@tonic-gate	ba,pt	%xcc,.fp_disabled	;\
8300Sstevel@tonic-gate	nop				;\
8310Sstevel@tonic-gate	.align	32
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate/*
8340Sstevel@tonic-gate * Floating point exceptions.
8350Sstevel@tonic-gate */
8360Sstevel@tonic-gate#define	FP_IEEE_TRAP			\
8370Sstevel@tonic-gate	TT_TRACE(trace_gen)		;\
8380Sstevel@tonic-gate	ba,pt	%xcc,.fp_ieee_exception	;\
8390Sstevel@tonic-gate	nop				;\
8400Sstevel@tonic-gate	.align	32
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate#define	FP_TRAP				\
8430Sstevel@tonic-gate	TT_TRACE(trace_gen)		;\
8440Sstevel@tonic-gate	ba,pt	%xcc,.fp_exception	;\
8450Sstevel@tonic-gate	nop				;\
8460Sstevel@tonic-gate	.align	32
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate#if !defined(lint)
8490Sstevel@tonic-gate/*
8500Sstevel@tonic-gate * asynchronous traps at level 0 and level 1
8510Sstevel@tonic-gate *
8520Sstevel@tonic-gate * The first instruction must be a membar for UltraSPARC-III
8530Sstevel@tonic-gate * to stop RED state entry if the store queue has many
8540Sstevel@tonic-gate * pending bad stores (PRM, Chapter 11).
8550Sstevel@tonic-gate */
8561772Sjl139090#define ASYNC_TRAP(ttype, ttlabel, table_name)\
8571772Sjl139090	.global	table_name	;\
8581772Sjl139090table_name:			;\
8590Sstevel@tonic-gate	membar	#Sync		;\
8600Sstevel@tonic-gate	TT_TRACE(ttlabel)	;\
8610Sstevel@tonic-gate	ba	async_err	;\
8620Sstevel@tonic-gate	mov	ttype, %g5	;\
8630Sstevel@tonic-gate	.align	32
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate/*
8660Sstevel@tonic-gate * Defaults to BAD entry, but establishes label to be used for
8670Sstevel@tonic-gate * architecture-specific overwrite of trap table entry.
8680Sstevel@tonic-gate */
8690Sstevel@tonic-gate#define	LABELED_BAD(table_name)		\
8700Sstevel@tonic-gate	.global	table_name		;\
8710Sstevel@tonic-gatetable_name:				;\
8720Sstevel@tonic-gate	BAD
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate#endif /* !lint */
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate/*
8770Sstevel@tonic-gate * illegal instruction trap
8780Sstevel@tonic-gate */
8790Sstevel@tonic-gate#define	ILLTRAP_INSTR			  \
8800Sstevel@tonic-gate	membar	#Sync			  ;\
8810Sstevel@tonic-gate	TT_TRACE(trace_gen)		  ;\
8820Sstevel@tonic-gate	or	%g0, P_UTRAP4, %g2	  ;\
8830Sstevel@tonic-gate	or	%g0, T_UNIMP_INSTR, %g3   ;\
8840Sstevel@tonic-gate	sethi	%hi(.check_v9utrap), %g4  ;\
8850Sstevel@tonic-gate	jmp	%g4 + %lo(.check_v9utrap) ;\
8860Sstevel@tonic-gate	nop				  ;\
8870Sstevel@tonic-gate	.align	32
8880Sstevel@tonic-gate
8890Sstevel@tonic-gate/*
8900Sstevel@tonic-gate * tag overflow trap
8910Sstevel@tonic-gate */
8920Sstevel@tonic-gate#define	TAG_OVERFLOW			  \
8930Sstevel@tonic-gate	TT_TRACE(trace_gen)		  ;\
8940Sstevel@tonic-gate	or	%g0, P_UTRAP10, %g2	  ;\
8950Sstevel@tonic-gate	or	%g0, T_TAG_OVERFLOW, %g3  ;\
8960Sstevel@tonic-gate	sethi	%hi(.check_v9utrap), %g4  ;\
8970Sstevel@tonic-gate	jmp	%g4 + %lo(.check_v9utrap) ;\
8980Sstevel@tonic-gate	nop				  ;\
8990Sstevel@tonic-gate	.align	32
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate/*
9020Sstevel@tonic-gate * divide by zero trap
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate#define	DIV_BY_ZERO			  \
9050Sstevel@tonic-gate	TT_TRACE(trace_gen)		  ;\
9060Sstevel@tonic-gate	or	%g0, P_UTRAP11, %g2	  ;\
9070Sstevel@tonic-gate	or	%g0, T_IDIV0, %g3	  ;\
9080Sstevel@tonic-gate	sethi	%hi(.check_v9utrap), %g4  ;\
9090Sstevel@tonic-gate	jmp	%g4 + %lo(.check_v9utrap) ;\
9100Sstevel@tonic-gate	nop				  ;\
9110Sstevel@tonic-gate	.align	32
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate/*
9140Sstevel@tonic-gate * trap instruction for V9 user trap handlers
9150Sstevel@tonic-gate */
9160Sstevel@tonic-gate#define	TRAP_INSTR			  \
9170Sstevel@tonic-gate	TT_TRACE(trace_gen)		  ;\
9180Sstevel@tonic-gate	or	%g0, T_SOFTWARE_TRAP, %g3 ;\
9190Sstevel@tonic-gate	sethi	%hi(.check_v9utrap), %g4  ;\
9200Sstevel@tonic-gate	jmp	%g4 + %lo(.check_v9utrap) ;\
9210Sstevel@tonic-gate	nop				  ;\
9220Sstevel@tonic-gate	.align	32
9230Sstevel@tonic-gate#define	TRP4	TRAP_INSTR; TRAP_INSTR; TRAP_INSTR; TRAP_INSTR
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate/*
9260Sstevel@tonic-gate * LEVEL_INTERRUPT is for level N interrupts.
9270Sstevel@tonic-gate * VECTOR_INTERRUPT is for the vector trap.
9280Sstevel@tonic-gate */
9290Sstevel@tonic-gate#define	LEVEL_INTERRUPT(level)		\
9300Sstevel@tonic-gate	.global	tt_pil/**/level		;\
9310Sstevel@tonic-gatett_pil/**/level:			;\
9320Sstevel@tonic-gate	ba,pt	%xcc, pil_interrupt	;\
9330Sstevel@tonic-gate	mov	level, %g4		;\
9340Sstevel@tonic-gate	.align	32
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate#define	LEVEL14_INTERRUPT			\
9370Sstevel@tonic-gate	ba	pil14_interrupt			;\
9380Sstevel@tonic-gate	mov	PIL_14, %g4			;\
9390Sstevel@tonic-gate	.align	32
9400Sstevel@tonic-gate
9418803SJonathan.Haslam@Sun.COM#define        LEVEL15_INTERRUPT                       \
9428803SJonathan.Haslam@Sun.COM       ba      pil15_interrupt                 ;\
9438803SJonathan.Haslam@Sun.COM       mov     PIL_15, %g4                     ;\
9448803SJonathan.Haslam@Sun.COM       .align  32
9458803SJonathan.Haslam@Sun.COM
9460Sstevel@tonic-gate#define	VECTOR_INTERRUPT				\
9470Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_RECEIVE_STATUS, %g1	;\
9480Sstevel@tonic-gate	btst	IRSR_BUSY, %g1				;\
9490Sstevel@tonic-gate	bnz,pt	%xcc, vec_interrupt			;\
9500Sstevel@tonic-gate	nop						;\
9510Sstevel@tonic-gate	ba,a,pt	%xcc, vec_intr_spurious			;\
9520Sstevel@tonic-gate	.empty						;\
9530Sstevel@tonic-gate	.align	32
9540Sstevel@tonic-gate
9550Sstevel@tonic-gate/*
9560Sstevel@tonic-gate * MMU Trap Handlers.
9570Sstevel@tonic-gate */
9580Sstevel@tonic-gate#define	SWITCH_GLOBALS	/* mmu->alt, alt->mmu */			\
9590Sstevel@tonic-gate	rdpr	%pstate, %g5						;\
9600Sstevel@tonic-gate	wrpr	%g5, PSTATE_MG | PSTATE_AG, %pstate
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate#define	IMMU_EXCEPTION							\
9630Sstevel@tonic-gate	membar	#Sync							;\
9640Sstevel@tonic-gate	SWITCH_GLOBALS							;\
9650Sstevel@tonic-gate	wr	%g0, ASI_IMMU, %asi					;\
9660Sstevel@tonic-gate	rdpr	%tpc, %g2						;\
9670Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g3					;\
9680Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_end				;\
9690Sstevel@tonic-gate	mov	T_INSTR_EXCEPTION, %g1					;\
9700Sstevel@tonic-gate	.align	32
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate#define	DMMU_EXCEPTION							\
9730Sstevel@tonic-gate	SWITCH_GLOBALS							;\
9740Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi					;\
9750Sstevel@tonic-gate	ldxa	[MMU_TAG_ACCESS]%asi, %g2				;\
9760Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g3					;\
9770Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_end				;\
9780Sstevel@tonic-gate	mov	T_DATA_EXCEPTION, %g1					;\
9790Sstevel@tonic-gate	.align	32
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate#define	DMMU_EXC_AG_PRIV						\
9820Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi					;\
9830Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g2					;\
9840Sstevel@tonic-gate	ba,pt	%xcc, .mmu_priv_exception				;\
9850Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g3					;\
9860Sstevel@tonic-gate	.align	32
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate#define	DMMU_EXC_AG_NOT_ALIGNED						\
9890Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi					;\
9900Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g2					;\
9910Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_not_aligned			;\
9920Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g3					;\
9930Sstevel@tonic-gate	.align	32
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate/*
9960Sstevel@tonic-gate * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2)
9970Sstevel@tonic-gate */
9980Sstevel@tonic-gate#define	DMMU_EXC_LDDF_NOT_ALIGNED					\
9990Sstevel@tonic-gate	btst	1, %sp							;\
10000Sstevel@tonic-gate	bnz,pt	%xcc, .lddf_exception_not_aligned			;\
10010Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi					;\
10020Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g2					;\
10030Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_not_aligned			;\
10040Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g3					;\
10050Sstevel@tonic-gate	.align	32
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate#define	DMMU_EXC_STDF_NOT_ALIGNED					\
10080Sstevel@tonic-gate	btst	1, %sp							;\
10090Sstevel@tonic-gate	bnz,pt	%xcc, .stdf_exception_not_aligned			;\
10100Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi					;\
10110Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g2					;\
10120Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_not_aligned			;\
10130Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g3					;\
10140Sstevel@tonic-gate	.align	32
10150Sstevel@tonic-gate
10160Sstevel@tonic-gate/*
10170Sstevel@tonic-gate * Flush the TLB using either the primary, secondary, or nucleus flush
10180Sstevel@tonic-gate * operation based on whether the ctx from the tag access register matches
10190Sstevel@tonic-gate * the primary or secondary context (flush the nucleus if neither matches).
10200Sstevel@tonic-gate *
10210Sstevel@tonic-gate * Requires a membar #Sync before next ld/st.
10220Sstevel@tonic-gate * exits with:
10230Sstevel@tonic-gate * g2 = tag access register
10240Sstevel@tonic-gate * g3 = ctx number
10250Sstevel@tonic-gate */
10260Sstevel@tonic-gate#if TAGACC_CTX_MASK != CTXREG_CTX_MASK
10270Sstevel@tonic-gate#error "TAGACC_CTX_MASK != CTXREG_CTX_MASK"
10280Sstevel@tonic-gate#endif
10290Sstevel@tonic-gate#define	DTLB_DEMAP_ENTRY						\
10300Sstevel@tonic-gate	mov	MMU_TAG_ACCESS, %g1					;\
10310Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g5					;\
10320Sstevel@tonic-gate	ldxa	[%g1]ASI_DMMU, %g2					;\
10330Sstevel@tonic-gate	sethi	%hi(TAGACC_CTX_MASK), %g4				;\
10340Sstevel@tonic-gate	or	%g4, %lo(TAGACC_CTX_MASK), %g4				;\
10350Sstevel@tonic-gate	and	%g2, %g4, %g3			/* g3 = ctx */		;\
10360Sstevel@tonic-gate	ldxa	[%g5]ASI_DMMU, %g6		/* g6 = primary ctx */	;\
10370Sstevel@tonic-gate	and	%g6, %g4, %g6			/* &= CTXREG_CTX_MASK */ ;\
10380Sstevel@tonic-gate	cmp	%g3, %g6						;\
10390Sstevel@tonic-gate	be,pt	%xcc, 1f						;\
10400Sstevel@tonic-gate	andn	%g2, %g4, %g1			/* ctx = primary */	;\
10410Sstevel@tonic-gate	mov	MMU_SCONTEXT, %g5					;\
10420Sstevel@tonic-gate	ldxa	[%g5]ASI_DMMU, %g6		/* g6 = secondary ctx */ ;\
10430Sstevel@tonic-gate	and	%g6, %g4, %g6			/* &= CTXREG_CTX_MASK */ ;\
10440Sstevel@tonic-gate	cmp	%g3, %g6						;\
10450Sstevel@tonic-gate	be,a,pt	%xcc, 1f						;\
10460Sstevel@tonic-gate	  or	%g1, DEMAP_SECOND, %g1					;\
10470Sstevel@tonic-gate	or	%g1, DEMAP_NUCLEUS, %g1					;\
10480Sstevel@tonic-gate1:	stxa	%g0, [%g1]ASI_DTLB_DEMAP	/* MMU_DEMAP_PAGE */	;\
10490Sstevel@tonic-gate	membar	#Sync
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate#if defined(cscope)
10520Sstevel@tonic-gate/*
10530Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that
10540Sstevel@tonic-gate * are generated by macro expansion of DTLB_MISS().
10550Sstevel@tonic-gate */
10560Sstevel@tonic-gate	.global	tt0_dtlbmiss
10570Sstevel@tonic-gatett0_dtlbmiss:
10580Sstevel@tonic-gate	.global	tt1_dtlbmiss
10590Sstevel@tonic-gatett1_dtlbmiss:
10600Sstevel@tonic-gate	nop
10610Sstevel@tonic-gate#endif
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate/*
10640Sstevel@tonic-gate * Needs to be exactly 32 instructions
10650Sstevel@tonic-gate *
10660Sstevel@tonic-gate * UTLB NOTE: If we don't hit on the 8k pointer then we branch
10670Sstevel@tonic-gate * to a special 4M tsb handler. It would be nice if that handler
10680Sstevel@tonic-gate * could live in this file but currently it seems better to allow
10690Sstevel@tonic-gate * it to fall thru to sfmmu_tsb_miss.
10700Sstevel@tonic-gate */
10711772Sjl139090#ifdef UTSB_PHYS
10721772Sjl139090#define	DTLB_MISS(table_name)						;\
10731772Sjl139090	.global	table_name/**/_dtlbmiss					;\
10741772Sjl139090table_name/**/_dtlbmiss:						;\
10751772Sjl139090	mov	MMU_TAG_ACCESS, %g6		/* select tag acc */	;\
10761772Sjl139090	ldxa	[%g0]ASI_DMMU_TSB_8K, %g1	/* g1 = tsbe ptr */	;\
10771772Sjl139090	ldxa	[%g6]ASI_DMMU, %g2		/* g2 = tag access */	;\
10781772Sjl139090	sllx	%g2, TAGACC_CTX_LSHIFT, %g3				;\
10791772Sjl139090	srlx	%g3, TAGACC_CTX_LSHIFT, %g3	/* g3 = ctx */		;\
10801772Sjl139090	cmp	%g3, INVALID_CONTEXT					;\
10811772Sjl139090	ble,pn	%xcc, sfmmu_kdtlb_miss					;\
10826127Ssm142603	  srax	%g2, PREDISM_BASESHIFT, %g6  /* g6 > 0 ISM predicted */ ;\
10836127Ssm142603	brgz,pn %g6, sfmmu_udtlb_slowpath_ismpred			;\
10841772Sjl139090	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
10851772Sjl139090	ldda	[%g1]ASI_QUAD_LDD_PHYS, %g4	/* g4 = tag, %g5 data */;\
10861772Sjl139090	cmp	%g4, %g7						;\
10876127Ssm142603	bne,pn %xcc, sfmmu_udtlb_slowpath_noismpred			;\
10886127Ssm142603	  nop								;\
10891772Sjl139090	TT_TRACE(trace_tsbhit)		/* 2 instr ifdef TRAPTRACE */	;\
10901772Sjl139090	stxa	%g5, [%g0]ASI_DTLB_IN	/* trapstat expects TTE */	;\
10911772Sjl139090	retry				/* in %g5 */			;\
10921772Sjl139090	unimp	0							;\
10931772Sjl139090	unimp	0							;\
10941772Sjl139090	unimp	0							;\
10951772Sjl139090	unimp	0							;\
10961772Sjl139090	unimp	0							;\
10971772Sjl139090	unimp	0							;\
10981772Sjl139090	unimp	0							;\
10991772Sjl139090	unimp	0							;\
11001772Sjl139090	unimp	0							;\
11016127Ssm142603	unimp	0							;\
11026127Ssm142603	unimp	0							;\
11036127Ssm142603	unimp	0							;\
11046127Ssm142603	unimp	0							;\
11056127Ssm142603	unimp	0							;\
11061772Sjl139090	.align 128
11076127Ssm142603
11081772Sjl139090#else /* UTSB_PHYS */
11090Sstevel@tonic-gate#define	DTLB_MISS(table_name)						;\
11100Sstevel@tonic-gate	.global	table_name/**/_dtlbmiss					;\
11110Sstevel@tonic-gatetable_name/**/_dtlbmiss:						;\
11120Sstevel@tonic-gate	mov	MMU_TAG_ACCESS, %g6		/* select tag acc */	;\
11130Sstevel@tonic-gate	ldxa	[%g0]ASI_DMMU_TSB_8K, %g1	/* g1 = tsbe ptr */	;\
11140Sstevel@tonic-gate	ldxa	[%g6]ASI_DMMU, %g2		/* g2 = tag access */	;\
11150Sstevel@tonic-gate	sllx	%g2, TAGACC_CTX_LSHIFT, %g3				;\
11160Sstevel@tonic-gate	srlx	%g3, TAGACC_CTX_LSHIFT, %g3	/* g3 = ctx */		;\
11170Sstevel@tonic-gate	cmp	%g3, INVALID_CONTEXT					;\
11180Sstevel@tonic-gate	ble,pn	%xcc, sfmmu_kdtlb_miss					;\
11190Sstevel@tonic-gate	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
11200Sstevel@tonic-gate	brlz,pn %g1, sfmmu_udtlb_slowpath				;\
11210Sstevel@tonic-gate	  nop								;\
11220Sstevel@tonic-gate	ldda	[%g1]ASI_NQUAD_LD, %g4	/* g4 = tag, %g5 data */	;\
11230Sstevel@tonic-gate	cmp	%g4, %g7						;\
11240Sstevel@tonic-gate	bne,pn	%xcc, sfmmu_tsb_miss_tt		/* no 4M TSB, miss */	;\
11254528Spaulsan	  mov	-1, %g3		/* set 4M tsbe ptr to -1 */		;\
11260Sstevel@tonic-gate	TT_TRACE(trace_tsbhit)		/* 2 instr ifdef TRAPTRACE */	;\
11270Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_DTLB_IN	/* trapstat expects TTE */	;\
11280Sstevel@tonic-gate	retry				/* in %g5 */			;\
11290Sstevel@tonic-gate	unimp	0							;\
11300Sstevel@tonic-gate	unimp	0							;\
11310Sstevel@tonic-gate	unimp	0							;\
11320Sstevel@tonic-gate	unimp	0							;\
11330Sstevel@tonic-gate	unimp	0							;\
11344528Spaulsan        unimp   0                                                       ;\
11354528Spaulsan        unimp   0                                                       ;\
11364528Spaulsan        unimp   0                                                       ;\
11374528Spaulsan        unimp   0                                                       ;\
11384528Spaulsan        unimp   0                                                       ;\
11394528Spaulsan        unimp   0                                                       ;\
11404528Spaulsan        unimp   0                                                       ;\
11414528Spaulsan        unimp   0                                                       ;\
11424528Spaulsan        unimp   0                                                       ;\
11430Sstevel@tonic-gate	.align 128
11441772Sjl139090#endif /* UTSB_PHYS */
11450Sstevel@tonic-gate
11460Sstevel@tonic-gate#if defined(cscope)
11470Sstevel@tonic-gate/*
11480Sstevel@tonic-gate * Define labels to direct cscope quickly to labels that
11490Sstevel@tonic-gate * are generated by macro expansion of ITLB_MISS().
11500Sstevel@tonic-gate */
11510Sstevel@tonic-gate	.global	tt0_itlbmiss
11520Sstevel@tonic-gatett0_itlbmiss:
11530Sstevel@tonic-gate	.global	tt1_itlbmiss
11540Sstevel@tonic-gatett1_itlbmiss:
11550Sstevel@tonic-gate	nop
11560Sstevel@tonic-gate#endif
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate/*
11590Sstevel@tonic-gate * Instruction miss handler.
11600Sstevel@tonic-gate * ldda instructions will have their ASI patched
11610Sstevel@tonic-gate * by sfmmu_patch_ktsb at runtime.
11620Sstevel@tonic-gate * MUST be EXACTLY 32 instructions or we'll break.
11630Sstevel@tonic-gate */
11641772Sjl139090#ifdef UTSB_PHYS
11656127Ssm142603#define ITLB_MISS(table_name)                                            \
11666127Ssm142603        .global table_name/**/_itlbmiss                                 ;\
11676127Ssm142603table_name/**/_itlbmiss:                                                ;\
11686127Ssm142603        mov     MMU_TAG_ACCESS, %g6             /* select tag acc */    ;\
11696127Ssm142603        ldxa    [%g0]ASI_IMMU_TSB_8K, %g1       /* g1 = tsbe ptr */     ;\
11706127Ssm142603        ldxa    [%g6]ASI_IMMU, %g2              /* g2 = tag access */   ;\
11716127Ssm142603        sllx    %g2, TAGACC_CTX_LSHIFT, %g3                             ;\
11726127Ssm142603        srlx    %g3, TAGACC_CTX_LSHIFT, %g3     /* g3 = ctx */          ;\
11736127Ssm142603        cmp     %g3, INVALID_CONTEXT                                    ;\
11746127Ssm142603        ble,pn  %xcc, sfmmu_kitlb_miss                                  ;\
11756127Ssm142603          srlx  %g2, TAG_VALO_SHIFT, %g7        /* g7 = tsb tag */      ;\
11766127Ssm142603        ldda    [%g1]ASI_QUAD_LDD_PHYS, %g4 /* g4 = tag, g5 = data */   ;\
11776127Ssm142603        cmp     %g4, %g7                                                ;\
11786127Ssm142603        bne,pn  %xcc, sfmmu_uitlb_slowpath                              ;\
11796127Ssm142603          andcc %g5, TTE_EXECPRM_INT, %g0 /* check execute bit */       ;\
11806127Ssm142603        bz,pn   %icc, exec_fault                                        ;\
11816127Ssm142603          nop                                                           ;\
11826127Ssm142603        TT_TRACE(trace_tsbhit)          /* 2 instr ifdef TRAPTRACE */   ;\
11836127Ssm142603        stxa    %g5, [%g0]ASI_ITLB_IN   /* trapstat expects %g5 */      ;\
11846127Ssm142603        retry                                                           ;\
11854528Spaulsan        unimp   0                                                       ;\
11864528Spaulsan        unimp   0                                                       ;\
11874528Spaulsan        unimp   0                                                       ;\
11886127Ssm142603        unimp   0                                                       ;\
11896127Ssm142603        unimp   0                                                       ;\
11906127Ssm142603        unimp   0                                                       ;\
11916127Ssm142603        unimp   0                                                       ;\
11926127Ssm142603        unimp   0                                                       ;\
11936127Ssm142603        unimp   0                                                       ;\
11946127Ssm142603        unimp   0                                                       ;\
11956127Ssm142603        unimp   0                                                       ;\
11966127Ssm142603        unimp   0                                                       ;\
11976127Ssm142603        unimp   0                                                       ;\
11986127Ssm142603        unimp   0                                                       ;\
11996127Ssm142603        .align 128
12006127Ssm142603
12011772Sjl139090#else /* UTSB_PHYS */
12020Sstevel@tonic-gate#define	ITLB_MISS(table_name)						 \
12030Sstevel@tonic-gate	.global	table_name/**/_itlbmiss					;\
12040Sstevel@tonic-gatetable_name/**/_itlbmiss:						;\
12050Sstevel@tonic-gate	mov	MMU_TAG_ACCESS, %g6		/* select tag acc */	;\
12060Sstevel@tonic-gate	ldxa	[%g0]ASI_IMMU_TSB_8K, %g1	/* g1 = tsbe ptr */	;\
12070Sstevel@tonic-gate	ldxa	[%g6]ASI_IMMU, %g2		/* g2 = tag access */	;\
12080Sstevel@tonic-gate	sllx	%g2, TAGACC_CTX_LSHIFT, %g3				;\
12090Sstevel@tonic-gate	srlx	%g3, TAGACC_CTX_LSHIFT, %g3	/* g3 = ctx */		;\
12100Sstevel@tonic-gate	cmp	%g3, INVALID_CONTEXT					;\
12110Sstevel@tonic-gate	ble,pn	%xcc, sfmmu_kitlb_miss					;\
12120Sstevel@tonic-gate	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
12130Sstevel@tonic-gate	brlz,pn	%g1, sfmmu_uitlb_slowpath	/* if >1 TSB branch */	;\
12140Sstevel@tonic-gate	  nop								;\
12150Sstevel@tonic-gate	ldda	[%g1]ASI_NQUAD_LD, %g4	/* g4 = tag, g5 = data */	;\
12160Sstevel@tonic-gate	cmp	%g4, %g7						;\
12170Sstevel@tonic-gate	bne,pn	%xcc, sfmmu_tsb_miss_tt	/* br if 8k ptr miss */		;\
12184528Spaulsan	  mov	-1, %g3		/* set 4M TSB ptr to -1 */		;\
12190Sstevel@tonic-gate	andcc	%g5, TTE_EXECPRM_INT, %g0 /* check execute bit */	;\
12200Sstevel@tonic-gate	bz,pn	%icc, exec_fault					;\
12210Sstevel@tonic-gate	  nop								;\
12220Sstevel@tonic-gate	TT_TRACE(trace_tsbhit)		/* 2 instr ifdef TRAPTRACE */	;\
12230Sstevel@tonic-gate	stxa	%g5, [%g0]ASI_ITLB_IN	/* trapstat expects %g5 */	;\
12240Sstevel@tonic-gate	retry								;\
12250Sstevel@tonic-gate	unimp	0							;\
12260Sstevel@tonic-gate	unimp	0							;\
12270Sstevel@tonic-gate	unimp	0							;\
12280Sstevel@tonic-gate	unimp	0							;\
12290Sstevel@tonic-gate	unimp	0							;\
12304528Spaulsan        unimp   0                                                       ;\
12314528Spaulsan        unimp   0                                                       ;\
12324528Spaulsan        unimp   0                                                       ;\
12334528Spaulsan        unimp   0                                                       ;\
12344528Spaulsan        unimp   0                                                       ;\
12354528Spaulsan        unimp   0                                                       ;\
12360Sstevel@tonic-gate	.align 128
12371772Sjl139090#endif /* UTSB_PHYS */
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate/*
12410Sstevel@tonic-gate * This macro is the first level handler for fast protection faults.
12420Sstevel@tonic-gate * It first demaps the tlb entry which generated the fault and then
12430Sstevel@tonic-gate * attempts to set the modify bit on the hash.  It needs to be
12440Sstevel@tonic-gate * exactly 32 instructions.
12450Sstevel@tonic-gate */
12460Sstevel@tonic-gate#define	DTLB_PROT							 \
12470Sstevel@tonic-gate	DTLB_DEMAP_ENTRY		/* 20 instructions */		;\
12480Sstevel@tonic-gate	/*								;\
12490Sstevel@tonic-gate	 * At this point:						;\
12500Sstevel@tonic-gate	 *   g1 = ????							;\
12510Sstevel@tonic-gate	 *   g2 = tag access register					;\
12520Sstevel@tonic-gate	 *   g3 = ctx number						;\
12530Sstevel@tonic-gate	 *   g4 = ????							;\
12540Sstevel@tonic-gate	 */								;\
12550Sstevel@tonic-gate	TT_TRACE(trace_dataprot)	/* 2 instr ifdef TRAPTRACE */	;\
12560Sstevel@tonic-gate					/* clobbers g1 and g6 */	;\
12570Sstevel@tonic-gate	ldxa	[%g0]ASI_DMMU_TSB_8K, %g1	/* g1 = tsbe ptr */	;\
12580Sstevel@tonic-gate	brnz,pt %g3, sfmmu_uprot_trap		/* user trap */		;\
12590Sstevel@tonic-gate	  nop								;\
12600Sstevel@tonic-gate	ba,a,pt	%xcc, sfmmu_kprot_trap		/* kernel trap */	;\
12610Sstevel@tonic-gate	unimp	0							;\
12620Sstevel@tonic-gate	unimp	0							;\
12630Sstevel@tonic-gate	unimp	0							;\
12640Sstevel@tonic-gate	unimp	0							;\
12650Sstevel@tonic-gate	unimp	0							;\
12660Sstevel@tonic-gate	unimp	0							;\
12670Sstevel@tonic-gate	.align 128
12680Sstevel@tonic-gate
12690Sstevel@tonic-gate#define	DMMU_EXCEPTION_TL1						;\
12700Sstevel@tonic-gate	SWITCH_GLOBALS							;\
12710Sstevel@tonic-gate	ba,a,pt	%xcc, mmu_trap_tl1					;\
12720Sstevel@tonic-gate	  nop								;\
12730Sstevel@tonic-gate	.align 32
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate#define	MISALIGN_ADDR_TL1						;\
12760Sstevel@tonic-gate	ba,a,pt	%xcc, mmu_trap_tl1					;\
12770Sstevel@tonic-gate	  nop								;\
12780Sstevel@tonic-gate	.align 32
12790Sstevel@tonic-gate
12800Sstevel@tonic-gate/*
12810Sstevel@tonic-gate * Trace a tsb hit
12820Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered)
12830Sstevel@tonic-gate * g2 = tag access register (in)
12840Sstevel@tonic-gate * g3 - g4 = scratch (clobbered)
12850Sstevel@tonic-gate * g5 = tsbe data (in)
12860Sstevel@tonic-gate * g6 = scratch (clobbered)
12870Sstevel@tonic-gate * g7 = pc we jumped here from (in)
12880Sstevel@tonic-gate * ttextra = value to OR in to trap type (%tt) (in)
12890Sstevel@tonic-gate */
12900Sstevel@tonic-gate#ifdef TRAPTRACE
12910Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra)						 \
12920Sstevel@tonic-gate	membar	#Sync							;\
12930Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g6					;\
12940Sstevel@tonic-gate	flush	%g6							;\
12950Sstevel@tonic-gate	TRACE_PTR(%g3, %g6)						;\
1296*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g4)					;\
12970Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi				;\
12980Sstevel@tonic-gate	stxa	%g2, [%g3 + TRAP_ENT_SP]%asi	/* tag access */	;\
12990Sstevel@tonic-gate	stxa	%g5, [%g3 + TRAP_ENT_F1]%asi	/* tsb data */		;\
13000Sstevel@tonic-gate	rdpr	%tnpc, %g6						;\
13010Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_F2]%asi				;\
13020Sstevel@tonic-gate	stxa	%g1, [%g3 + TRAP_ENT_F3]%asi	/* tsb pointer */	;\
13030Sstevel@tonic-gate	stxa	%g0, [%g3 + TRAP_ENT_F4]%asi				;\
13040Sstevel@tonic-gate	rdpr	%tpc, %g6						;\
13050Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TPC]%asi				;\
13060Sstevel@tonic-gate	rdpr	%tl, %g6						;\
13070Sstevel@tonic-gate	stha	%g6, [%g3 + TRAP_ENT_TL]%asi				;\
13080Sstevel@tonic-gate	rdpr	%tt, %g6						;\
13090Sstevel@tonic-gate	or	%g6, (ttextra), %g6					;\
13100Sstevel@tonic-gate	stha	%g6, [%g3 + TRAP_ENT_TT]%asi				;\
13110Sstevel@tonic-gate	ldxa	[%g0]ASI_IMMU, %g1		/* tag target */	;\
13120Sstevel@tonic-gate	ldxa	[%g0]ASI_DMMU, %g4					;\
13130Sstevel@tonic-gate	cmp	%g6, FAST_IMMU_MISS_TT					;\
13140Sstevel@tonic-gate	movne	%icc, %g4, %g1						;\
13150Sstevel@tonic-gate	stxa	%g1, [%g3 + TRAP_ENT_TSTATE]%asi /* tsb tag */		;\
13160Sstevel@tonic-gate	stxa	%g0, [%g3 + TRAP_ENT_TR]%asi				;\
13170Sstevel@tonic-gate	TRACE_NEXT(%g3, %g4, %g6)
13180Sstevel@tonic-gate#else
13190Sstevel@tonic-gate#define TRACE_TSBHIT(ttextra)
13200Sstevel@tonic-gate#endif
13210Sstevel@tonic-gate
13220Sstevel@tonic-gate#if defined(lint)
13230Sstevel@tonic-gate
13240Sstevel@tonic-gatestruct scb	trap_table;
13250Sstevel@tonic-gatestruct scb	scb;		/* trap_table/scb are the same object */
13260Sstevel@tonic-gate
13270Sstevel@tonic-gate#else /* lint */
13280Sstevel@tonic-gate
13290Sstevel@tonic-gate/*
13300Sstevel@tonic-gate * =======================================================================
13310Sstevel@tonic-gate *		SPARC V9 TRAP TABLE
13320Sstevel@tonic-gate *
13330Sstevel@tonic-gate * The trap table is divided into two halves: the first half is used when
13340Sstevel@tonic-gate * taking traps when TL=0; the second half is used when taking traps from
13350Sstevel@tonic-gate * TL>0. Note that handlers in the second half of the table might not be able
13360Sstevel@tonic-gate * to make the same assumptions as handlers in the first half of the table.
13370Sstevel@tonic-gate *
13380Sstevel@tonic-gate * Worst case trap nesting so far:
13390Sstevel@tonic-gate *
13400Sstevel@tonic-gate *	at TL=0 client issues software trap requesting service
13410Sstevel@tonic-gate *	at TL=1 nucleus wants a register window
13420Sstevel@tonic-gate *	at TL=2 register window clean/spill/fill takes a TLB miss
13430Sstevel@tonic-gate *	at TL=3 processing TLB miss
13440Sstevel@tonic-gate *	at TL=4 handle asynchronous error
13450Sstevel@tonic-gate *
13460Sstevel@tonic-gate * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode".
13470Sstevel@tonic-gate *
13480Sstevel@tonic-gate * =======================================================================
13490Sstevel@tonic-gate */
13500Sstevel@tonic-gate	.section ".text"
13510Sstevel@tonic-gate	.align	4
13520Sstevel@tonic-gate	.global trap_table, scb, trap_table0, trap_table1, etrap_table
13531640Spetede	.type	trap_table, #object
13541640Spetede	.type	scb, #object
13550Sstevel@tonic-gatetrap_table:
13560Sstevel@tonic-gatescb:
13570Sstevel@tonic-gatetrap_table0:
13580Sstevel@tonic-gate	/* hardware traps */
13590Sstevel@tonic-gate	NOT;				/* 000	reserved */
13600Sstevel@tonic-gate	RED;				/* 001	power on reset */
13610Sstevel@tonic-gate	RED;				/* 002	watchdog reset */
13620Sstevel@tonic-gate	RED;				/* 003	externally initiated reset */
13630Sstevel@tonic-gate	RED;				/* 004	software initiated reset */
13640Sstevel@tonic-gate	RED;				/* 005	red mode exception */
13650Sstevel@tonic-gate	NOT; NOT;			/* 006 - 007 reserved */
13660Sstevel@tonic-gate	IMMU_EXCEPTION;			/* 008	instruction access exception */
13670Sstevel@tonic-gate	NOT;				/* 009	instruction access MMU miss */
13681772Sjl139090	ASYNC_TRAP(T_INSTR_ERROR, trace_gen, tt0_iae);
13690Sstevel@tonic-gate					/* 00A	instruction access error */
13700Sstevel@tonic-gate	NOT; NOT4;			/* 00B - 00F reserved */
13710Sstevel@tonic-gate	ILLTRAP_INSTR;			/* 010	illegal instruction */
13720Sstevel@tonic-gate	TRAP(T_PRIV_INSTR);		/* 011	privileged opcode */
13730Sstevel@tonic-gate	NOT;				/* 012	unimplemented LDD */
13740Sstevel@tonic-gate	NOT;				/* 013	unimplemented STD */
13750Sstevel@tonic-gate	NOT4; NOT4; NOT4;		/* 014 - 01F reserved */
13760Sstevel@tonic-gate	FP_DISABLED_TRAP;		/* 020	fp disabled */
13770Sstevel@tonic-gate	FP_IEEE_TRAP;			/* 021	fp exception ieee 754 */
13780Sstevel@tonic-gate	FP_TRAP;			/* 022	fp exception other */
13790Sstevel@tonic-gate	TAG_OVERFLOW;			/* 023	tag overflow */
13800Sstevel@tonic-gate	CLEAN_WINDOW;			/* 024 - 027 clean window */
13810Sstevel@tonic-gate	DIV_BY_ZERO;			/* 028	division by zero */
13820Sstevel@tonic-gate	NOT;				/* 029	internal processor error */
13830Sstevel@tonic-gate	NOT; NOT; NOT4;			/* 02A - 02F reserved */
13840Sstevel@tonic-gate	DMMU_EXCEPTION;			/* 030	data access exception */
13850Sstevel@tonic-gate	NOT;				/* 031	data access MMU miss */
13861772Sjl139090	ASYNC_TRAP(T_DATA_ERROR, trace_gen, tt0_dae);
13870Sstevel@tonic-gate					/* 032	data access error */
13880Sstevel@tonic-gate	NOT;				/* 033	data access protection */
13890Sstevel@tonic-gate	DMMU_EXC_AG_NOT_ALIGNED;	/* 034	mem address not aligned */
13900Sstevel@tonic-gate	DMMU_EXC_LDDF_NOT_ALIGNED;	/* 035	LDDF mem address not aligned */
13910Sstevel@tonic-gate	DMMU_EXC_STDF_NOT_ALIGNED;	/* 036	STDF mem address not aligned */
13920Sstevel@tonic-gate	DMMU_EXC_AG_PRIV;		/* 037	privileged action */
13930Sstevel@tonic-gate	NOT;				/* 038	LDQF mem address not aligned */
13940Sstevel@tonic-gate	NOT;				/* 039	STQF mem address not aligned */
13950Sstevel@tonic-gate	NOT; NOT; NOT4;			/* 03A - 03F reserved */
13961772Sjl139090	LABELED_BAD(tt0_asdat);		/* 040	async data error */
13970Sstevel@tonic-gate	LEVEL_INTERRUPT(1);		/* 041	interrupt level 1 */
13980Sstevel@tonic-gate	LEVEL_INTERRUPT(2);		/* 042	interrupt level 2 */
13990Sstevel@tonic-gate	LEVEL_INTERRUPT(3);		/* 043	interrupt level 3 */
14000Sstevel@tonic-gate	LEVEL_INTERRUPT(4);		/* 044	interrupt level 4 */
14010Sstevel@tonic-gate	LEVEL_INTERRUPT(5);		/* 045	interrupt level 5 */
14020Sstevel@tonic-gate	LEVEL_INTERRUPT(6);		/* 046	interrupt level 6 */
14030Sstevel@tonic-gate	LEVEL_INTERRUPT(7);		/* 047	interrupt level 7 */
14040Sstevel@tonic-gate	LEVEL_INTERRUPT(8);		/* 048	interrupt level 8 */
14050Sstevel@tonic-gate	LEVEL_INTERRUPT(9);		/* 049	interrupt level 9 */
14060Sstevel@tonic-gate	LEVEL_INTERRUPT(10);		/* 04A	interrupt level 10 */
14070Sstevel@tonic-gate	LEVEL_INTERRUPT(11);		/* 04B	interrupt level 11 */
14080Sstevel@tonic-gate	LEVEL_INTERRUPT(12);		/* 04C	interrupt level 12 */
14090Sstevel@tonic-gate	LEVEL_INTERRUPT(13);		/* 04D	interrupt level 13 */
14100Sstevel@tonic-gate	LEVEL14_INTERRUPT;		/* 04E	interrupt level 14 */
14118803SJonathan.Haslam@Sun.COM	LEVEL15_INTERRUPT;		/* 04F	interrupt level 15 */
14120Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 050 - 05F reserved */
14130Sstevel@tonic-gate	VECTOR_INTERRUPT;		/* 060	interrupt vector */
14140Sstevel@tonic-gate	GOTO(kmdb_trap);		/* 061	PA watchpoint */
14150Sstevel@tonic-gate	GOTO(kmdb_trap);		/* 062	VA watchpoint */
14160Sstevel@tonic-gate	GOTO_TT(ce_err, trace_gen);	/* 063	corrected ECC error */
14170Sstevel@tonic-gate	ITLB_MISS(tt0);			/* 064	instruction access MMU miss */
14180Sstevel@tonic-gate	DTLB_MISS(tt0);			/* 068	data access MMU miss */
14190Sstevel@tonic-gate	DTLB_PROT;			/* 06C	data access protection */
14200Sstevel@tonic-gate	LABELED_BAD(tt0_fecc);		/* 070  fast ecache ECC error */
14210Sstevel@tonic-gate	LABELED_BAD(tt0_dperr);		/* 071  Cheetah+ dcache parity error */
14220Sstevel@tonic-gate	LABELED_BAD(tt0_iperr);		/* 072  Cheetah+ icache parity error */
14230Sstevel@tonic-gate	NOT;				/* 073  reserved */
14240Sstevel@tonic-gate	NOT4; NOT4; NOT4;		/* 074 - 07F reserved */
14250Sstevel@tonic-gate	NOT4;				/* 080	spill 0 normal */
14260Sstevel@tonic-gate	SPILL_32bit_asi(ASI_AIUP,sn0);	/* 084	spill 1 normal */
14270Sstevel@tonic-gate	SPILL_64bit_asi(ASI_AIUP,sn0);	/* 088	spill 2 normal */
14280Sstevel@tonic-gate	SPILL_32clean(ASI_AIUP,sn0);	/* 08C	spill 3 normal */
14290Sstevel@tonic-gate	SPILL_64clean(ASI_AIUP,sn0);	/* 090	spill 4 normal */
14300Sstevel@tonic-gate	SPILL_32bit(not);		/* 094	spill 5 normal */
14310Sstevel@tonic-gate	SPILL_64bit(not);		/* 098	spill 6 normal */
14320Sstevel@tonic-gate	SPILL_mixed;			/* 09C	spill 7 normal */
14330Sstevel@tonic-gate	NOT4;				/* 0A0	spill 0 other */
14340Sstevel@tonic-gate	SPILL_32bit_asi(ASI_AIUS,so0);	/* 0A4	spill 1 other */
14350Sstevel@tonic-gate	SPILL_64bit_asi(ASI_AIUS,so0);	/* 0A8	spill 2 other */
14360Sstevel@tonic-gate	SPILL_32bit_asi(ASI_AIUS,so0);	/* 0AC	spill 3 other */
14370Sstevel@tonic-gate	SPILL_64bit_asi(ASI_AIUS,so0);	/* 0B0	spill 4 other */
14380Sstevel@tonic-gate	NOT4;				/* 0B4	spill 5 other */
14390Sstevel@tonic-gate	NOT4;				/* 0B8	spill 6 other */
14400Sstevel@tonic-gate	NOT4;				/* 0BC	spill 7 other */
14410Sstevel@tonic-gate	NOT4;				/* 0C0	fill 0 normal */
14420Sstevel@tonic-gate	FILL_32bit_asi(ASI_AIUP,fn0);	/* 0C4	fill 1 normal */
14430Sstevel@tonic-gate	FILL_64bit_asi(ASI_AIUP,fn0);	/* 0C8	fill 2 normal */
14440Sstevel@tonic-gate	FILL_32bit_asi(ASI_AIUP,fn0);	/* 0CC	fill 3 normal */
14450Sstevel@tonic-gate	FILL_64bit_asi(ASI_AIUP,fn0);	/* 0D0	fill 4 normal */
14460Sstevel@tonic-gate	FILL_32bit(not);		/* 0D4	fill 5 normal */
14470Sstevel@tonic-gate	FILL_64bit(not);		/* 0D8	fill 6 normal */
14480Sstevel@tonic-gate	FILL_mixed;			/* 0DC	fill 7 normal */
14490Sstevel@tonic-gate	NOT4;				/* 0E0	fill 0 other */
14500Sstevel@tonic-gate	NOT4;				/* 0E4	fill 1 other */
14510Sstevel@tonic-gate	NOT4;				/* 0E8	fill 2 other */
14520Sstevel@tonic-gate	NOT4;				/* 0EC	fill 3 other */
14530Sstevel@tonic-gate	NOT4;				/* 0F0	fill 4 other */
14540Sstevel@tonic-gate	NOT4;				/* 0F4	fill 5 other */
14550Sstevel@tonic-gate	NOT4;				/* 0F8	fill 6 other */
14560Sstevel@tonic-gate	NOT4;				/* 0FC	fill 7 other */
14570Sstevel@tonic-gate	/* user traps */
14580Sstevel@tonic-gate	GOTO(syscall_trap_4x);		/* 100	old system call */
14590Sstevel@tonic-gate	TRAP(T_BREAKPOINT);		/* 101	user breakpoint */
14600Sstevel@tonic-gate	TRAP(T_DIV0);			/* 102	user divide by zero */
14615414Smb158278	FLUSHW(tt0_flushw);		/* 103	flush windows */
14620Sstevel@tonic-gate	GOTO(.clean_windows);		/* 104	clean windows */
14630Sstevel@tonic-gate	BAD;				/* 105	range check ?? */
14640Sstevel@tonic-gate	GOTO(.fix_alignment);		/* 106	do unaligned references */
14650Sstevel@tonic-gate	BAD;				/* 107	unused */
14664141Sedp	SYSCALL_TRAP32;			/* 108	ILP32 system call on LP64 */
14670Sstevel@tonic-gate	GOTO(set_trap0_addr);		/* 109	set trap0 address */
14680Sstevel@tonic-gate	BAD; BAD; BAD4;			/* 10A - 10F unused */
14690Sstevel@tonic-gate	TRP4; TRP4; TRP4; TRP4;		/* 110 - 11F V9 user trap handlers */
14700Sstevel@tonic-gate	GOTO(.getcc);			/* 120	get condition codes */
14710Sstevel@tonic-gate	GOTO(.setcc);			/* 121	set condition codes */
14720Sstevel@tonic-gate	GOTO(.getpsr);			/* 122	get psr */
14730Sstevel@tonic-gate	GOTO(.setpsr);			/* 123	set psr (some fields) */
14740Sstevel@tonic-gate	GOTO(get_timestamp);		/* 124	get timestamp */
14750Sstevel@tonic-gate	GOTO(get_virtime);		/* 125	get lwp virtual time */
14760Sstevel@tonic-gate	PRIV(self_xcall);		/* 126	self xcall */
14770Sstevel@tonic-gate	GOTO(get_hrestime);		/* 127	get hrestime */
14780Sstevel@tonic-gate	BAD;				/* 128	ST_SETV9STACK */
14790Sstevel@tonic-gate	GOTO(.getlgrp);			/* 129  get lgrpid */
14800Sstevel@tonic-gate	BAD; BAD; BAD4;			/* 12A - 12F unused */
14810Sstevel@tonic-gate	BAD4; BAD4; 			/* 130 - 137 unused */
14820Sstevel@tonic-gate	DTRACE_PID;			/* 138  dtrace pid tracing provider */
14832179Sahl	BAD;				/* 139  unused */
14840Sstevel@tonic-gate	DTRACE_RETURN;			/* 13A	dtrace pid return probe */
14850Sstevel@tonic-gate	BAD; BAD4;			/* 13B - 13F unused */
14864141Sedp	SYSCALL_TRAP;			/* 140  LP64 system call */
14871321Srscott	SYSCALL(nosys);			/* 141  unused system call trap */
14880Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL
14890Sstevel@tonic-gate	GOTO(.traptrace_freeze);	/* 142  freeze traptrace */
14900Sstevel@tonic-gate	GOTO(.traptrace_unfreeze);	/* 143  unfreeze traptrace */
14910Sstevel@tonic-gate#else
14921321Srscott	SYSCALL(nosys);			/* 142  unused system call trap */
14931321Srscott	SYSCALL(nosys);			/* 143  unused system call trap */
14940Sstevel@tonic-gate#endif
14950Sstevel@tonic-gate	BAD4; BAD4; BAD4;		/* 144 - 14F unused */
14960Sstevel@tonic-gate	BAD4; BAD4; BAD4; BAD4;		/* 150 - 15F unused */
14970Sstevel@tonic-gate	BAD4; BAD4; BAD4; BAD4;		/* 160 - 16F unused */
14980Sstevel@tonic-gate	BAD;				/* 170 - unused */
14990Sstevel@tonic-gate	BAD;				/* 171 - unused */
15000Sstevel@tonic-gate	BAD; BAD;			/* 172 - 173 unused */
15010Sstevel@tonic-gate	BAD4; BAD4;			/* 174 - 17B unused */
15020Sstevel@tonic-gate#ifdef	PTL1_PANIC_DEBUG
15030Sstevel@tonic-gate	mov PTL1_BAD_DEBUG, %g1; GOTO(ptl1_panic);
15040Sstevel@tonic-gate					/* 17C	test ptl1_panic */
15050Sstevel@tonic-gate#else
15060Sstevel@tonic-gate	BAD;				/* 17C  unused */
15070Sstevel@tonic-gate#endif	/* PTL1_PANIC_DEBUG */
15080Sstevel@tonic-gate	PRIV(kmdb_trap);		/* 17D	kmdb enter (L1-A) */
15090Sstevel@tonic-gate	PRIV(kmdb_trap);		/* 17E	kmdb breakpoint */
15100Sstevel@tonic-gate	PRIV(kctx_obp_bpt);		/* 17F	obp breakpoint */
15110Sstevel@tonic-gate	/* reserved */
15120Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 180 - 18F reserved */
15130Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 190 - 19F reserved */
15140Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 1A0 - 1AF reserved */
15150Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 1B0 - 1BF reserved */
15160Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 1C0 - 1CF reserved */
15170Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 1D0 - 1DF reserved */
15180Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 1E0 - 1EF reserved */
15190Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 1F0 - 1FF reserved */
15200Sstevel@tonic-gatetrap_table1:
15210Sstevel@tonic-gate	NOT4; NOT4; NOT; NOT;		/* 000 - 009 unused */
15221772Sjl139090	ASYNC_TRAP(T_INSTR_ERROR + T_TL1, trace_gen, tt1_iae);
15230Sstevel@tonic-gate					/* 00A	instruction access error */
15240Sstevel@tonic-gate	NOT; NOT4;			/* 00B - 00F unused */
15250Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 010 - 01F unused */
15260Sstevel@tonic-gate	NOT4;				/* 020 - 023 unused */
15270Sstevel@tonic-gate	CLEAN_WINDOW;			/* 024 - 027 clean window */
15280Sstevel@tonic-gate	NOT4; NOT4;			/* 028 - 02F unused */
15290Sstevel@tonic-gate	DMMU_EXCEPTION_TL1;		/* 030 	data access exception */
15300Sstevel@tonic-gate	NOT;				/* 031 unused */
15311772Sjl139090	ASYNC_TRAP(T_DATA_ERROR + T_TL1, trace_gen, tt1_dae);
15320Sstevel@tonic-gate					/* 032	data access error */
15330Sstevel@tonic-gate	NOT;				/* 033	unused */
15340Sstevel@tonic-gate	MISALIGN_ADDR_TL1;		/* 034	mem address not aligned */
15350Sstevel@tonic-gate	NOT; NOT; NOT; NOT4; NOT4	/* 035 - 03F unused */
15361772Sjl139090	LABELED_BAD(tt1_asdat);		/* 040	async data error */
15371772Sjl139090	NOT; NOT; NOT;			/* 041 - 043 unused */
15381772Sjl139090	NOT4; NOT4; NOT4;		/* 044 - 04F unused */
15390Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 050 - 05F unused */
15400Sstevel@tonic-gate	NOT;				/* 060	unused */
15410Sstevel@tonic-gate	GOTO(kmdb_trap_tl1);		/* 061	PA watchpoint */
15420Sstevel@tonic-gate	GOTO(kmdb_trap_tl1);		/* 062	VA watchpoint */
15430Sstevel@tonic-gate	GOTO_TT(ce_err_tl1, trace_gen);	/* 063	corrected ECC error */
15440Sstevel@tonic-gate	ITLB_MISS(tt1);			/* 064	instruction access MMU miss */
15450Sstevel@tonic-gate	DTLB_MISS(tt1);			/* 068	data access MMU miss */
15460Sstevel@tonic-gate	DTLB_PROT;			/* 06C	data access protection */
15470Sstevel@tonic-gate	LABELED_BAD(tt1_fecc);		/* 070  fast ecache ECC error */
15480Sstevel@tonic-gate	LABELED_BAD(tt1_dperr);		/* 071  Cheetah+ dcache parity error */
15490Sstevel@tonic-gate	LABELED_BAD(tt1_iperr);		/* 072  Cheetah+ icache parity error */
15500Sstevel@tonic-gate	NOT;				/* 073  reserved */
15510Sstevel@tonic-gate	NOT4; NOT4; NOT4;		/* 074 - 07F reserved */
15520Sstevel@tonic-gate	NOT4;				/* 080	spill 0 normal */
15530Sstevel@tonic-gate	SPILL_32bit_tt1(ASI_AIUP,sn1);	/* 084	spill 1 normal */
15540Sstevel@tonic-gate	SPILL_64bit_tt1(ASI_AIUP,sn1);	/* 088	spill 2 normal */
15550Sstevel@tonic-gate	SPILL_32bit_tt1(ASI_AIUP,sn1);	/* 08C	spill 3 normal */
15560Sstevel@tonic-gate	SPILL_64bit_tt1(ASI_AIUP,sn1);	/* 090	spill 4 normal */
15570Sstevel@tonic-gate	SPILL_32bit(not);		/* 094	spill 5 normal */
15580Sstevel@tonic-gate	SPILL_64bit(not);		/* 098	spill 6 normal */
15590Sstevel@tonic-gate	SPILL_mixed;			/* 09C	spill 7 normal */
15600Sstevel@tonic-gate	NOT4;				/* 0A0	spill 0 other */
15610Sstevel@tonic-gate	SPILL_32bit_tt1(ASI_AIUS,so1);	/* 0A4	spill 1 other */
15620Sstevel@tonic-gate	SPILL_64bit_tt1(ASI_AIUS,so1);	/* 0A8	spill 2 other */
15630Sstevel@tonic-gate	SPILL_32bit_tt1(ASI_AIUS,so1);	/* 0AC	spill 3 other */
15640Sstevel@tonic-gate	SPILL_64bit_tt1(ASI_AIUS,so1);	/* 0B0  spill 4 other */
15650Sstevel@tonic-gate	NOT4;				/* 0B4  spill 5 other */
15660Sstevel@tonic-gate	NOT4;				/* 0B8  spill 6 other */
15670Sstevel@tonic-gate	NOT4;				/* 0BC  spill 7 other */
15680Sstevel@tonic-gate	NOT4;				/* 0C0	fill 0 normal */
15690Sstevel@tonic-gate	FILL_32bit_tt1(ASI_AIUP,fn1);	/* 0C4	fill 1 normal */
15700Sstevel@tonic-gate	FILL_64bit_tt1(ASI_AIUP,fn1);	/* 0C8	fill 2 normal */
15710Sstevel@tonic-gate	FILL_32bit_tt1(ASI_AIUP,fn1);	/* 0CC	fill 3 normal */
15720Sstevel@tonic-gate	FILL_64bit_tt1(ASI_AIUP,fn1);	/* 0D0	fill 4 normal */
15730Sstevel@tonic-gate	FILL_32bit(not);		/* 0D4	fill 5 normal */
15740Sstevel@tonic-gate	FILL_64bit(not);		/* 0D8	fill 6 normal */
15750Sstevel@tonic-gate	FILL_mixed;			/* 0DC	fill 7 normal */
15760Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 0E0 - 0EF unused */
15770Sstevel@tonic-gate	NOT4; NOT4; NOT4; NOT4;		/* 0F0 - 0FF unused */
15780Sstevel@tonic-gate	LABELED_BAD(tt1_swtrap0);	/* 100  fast ecache ECC error (cont) */
15790Sstevel@tonic-gate	LABELED_BAD(tt1_swtrap1);	/* 101  Ch+ D$ parity error (cont) */
15800Sstevel@tonic-gate	LABELED_BAD(tt1_swtrap2);	/* 102  Ch+ I$ parity error (cont) */
15810Sstevel@tonic-gate	NOT;				/* 103  reserved */
15820Sstevel@tonic-gate/*
15830Sstevel@tonic-gate * We only reserve the above four special case soft traps for code running
15840Sstevel@tonic-gate * at TL>0, so we can truncate the trap table here.
15850Sstevel@tonic-gate */
15860Sstevel@tonic-gateetrap_table:
15870Sstevel@tonic-gate	.size	trap_table, (.-trap_table)
15880Sstevel@tonic-gate	.size	scb, (.-scb)
15890Sstevel@tonic-gate
15900Sstevel@tonic-gate/*
15910Sstevel@tonic-gate * We get to exec_fault in the case of an instruction miss and tte
15920Sstevel@tonic-gate * has no execute bit set.  We go to tl0 to handle it.
15930Sstevel@tonic-gate *
15940Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered)
15950Sstevel@tonic-gate * g2 = tag access register (in)
15960Sstevel@tonic-gate * g3 - g4 = scratch (clobbered)
15970Sstevel@tonic-gate * g5 = tsbe data (in)
15980Sstevel@tonic-gate * g6 = scratch (clobbered)
15990Sstevel@tonic-gate */
16000Sstevel@tonic-gate	ALTENTRY(exec_fault)
16010Sstevel@tonic-gate	TRACE_TSBHIT(0x200)
16020Sstevel@tonic-gate	SWITCH_GLOBALS
16030Sstevel@tonic-gate	mov	MMU_TAG_ACCESS, %g4
16040Sstevel@tonic-gate	ldxa	[%g4]ASI_IMMU, %g2			! arg1 = addr
16050Sstevel@tonic-gate	mov	T_INSTR_MMU_MISS, %g3			! arg2 = traptype
16060Sstevel@tonic-gate	set	trap, %g1
16070Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
16080Sstevel@tonic-gate	  mov	-1, %g4
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate.mmu_exception_not_aligned:
16110Sstevel@tonic-gate	rdpr	%tstate, %g1
16120Sstevel@tonic-gate	btst	TSTATE_PRIV, %g1
16130Sstevel@tonic-gate	bnz,pn	%icc, 2f
16140Sstevel@tonic-gate	nop
16150Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)				! load CPU struct addr
16160Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
16170Sstevel@tonic-gate	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
16180Sstevel@tonic-gate	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
16190Sstevel@tonic-gate	brz,pt	%g5, 2f
16200Sstevel@tonic-gate	nop
16210Sstevel@tonic-gate	ldn	[%g5 + P_UTRAP15], %g5			! unaligned utrap?
16220Sstevel@tonic-gate	brz,pn	%g5, 2f
16230Sstevel@tonic-gate	nop
16240Sstevel@tonic-gate	btst	1, %sp
16250Sstevel@tonic-gate	bz,pt	%xcc, 1f				! 32 bit user program
16260Sstevel@tonic-gate	nop
16270Sstevel@tonic-gate	ba,pt	%xcc, .setup_v9utrap			! 64 bit user program
16280Sstevel@tonic-gate	nop
16290Sstevel@tonic-gate1:
16300Sstevel@tonic-gate	ba,pt	%xcc, .setup_utrap
16310Sstevel@tonic-gate	or	%g2, %g0, %g7
16320Sstevel@tonic-gate2:
16330Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_end
16340Sstevel@tonic-gate	mov	T_ALIGNMENT, %g1
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate.mmu_priv_exception:
16370Sstevel@tonic-gate	rdpr	%tstate, %g1
16380Sstevel@tonic-gate	btst	TSTATE_PRIV, %g1
16390Sstevel@tonic-gate	bnz,pn	%icc, 1f
16400Sstevel@tonic-gate	nop
16410Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)				! load CPU struct addr
16420Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
16430Sstevel@tonic-gate	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
16440Sstevel@tonic-gate	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
16450Sstevel@tonic-gate	brz,pt	%g5, 1f
16460Sstevel@tonic-gate	nop
16470Sstevel@tonic-gate	ldn	[%g5 + P_UTRAP16], %g5
16480Sstevel@tonic-gate	brnz,pt	%g5, .setup_v9utrap
16490Sstevel@tonic-gate	nop
16500Sstevel@tonic-gate1:
16510Sstevel@tonic-gate	mov	T_PRIV_INSTR, %g1
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate.mmu_exception_end:
16540Sstevel@tonic-gate	CPU_INDEX(%g4, %g5)
16550Sstevel@tonic-gate	set	cpu_core, %g5
16560Sstevel@tonic-gate	sllx	%g4, CPU_CORE_SHIFT, %g4
16570Sstevel@tonic-gate	add	%g4, %g5, %g4
16580Sstevel@tonic-gate	lduh	[%g4 + CPUC_DTRACE_FLAGS], %g5
16590Sstevel@tonic-gate	andcc	%g5, CPU_DTRACE_NOFAULT, %g0
16600Sstevel@tonic-gate	bz	%xcc, .mmu_exception_tlb_chk
16610Sstevel@tonic-gate	or	%g5, CPU_DTRACE_BADADDR, %g5
16620Sstevel@tonic-gate	stuh	%g5, [%g4 + CPUC_DTRACE_FLAGS]
16630Sstevel@tonic-gate	done
16640Sstevel@tonic-gate
16650Sstevel@tonic-gate.mmu_exception_tlb_chk:
16660Sstevel@tonic-gate	GET_CPU_IMPL(%g5)			! check SFSR.FT to see if this
16670Sstevel@tonic-gate	cmp	%g5, PANTHER_IMPL		! is a TLB parity error. But
16680Sstevel@tonic-gate	bne	2f				! we only do this check while
16690Sstevel@tonic-gate	mov	1, %g4				! running on Panther CPUs
16700Sstevel@tonic-gate	sllx	%g4, PN_SFSR_PARITY_SHIFT, %g4	! since US-I/II use the same
16710Sstevel@tonic-gate	andcc	%g3, %g4, %g0			! bit for something else which
16720Sstevel@tonic-gate	bz	2f				! will be handled later.
16730Sstevel@tonic-gate	nop
16740Sstevel@tonic-gate.mmu_exception_is_tlb_parity:
16750Sstevel@tonic-gate	.weak itlb_parity_trap
16760Sstevel@tonic-gate	.weak dtlb_parity_trap
16770Sstevel@tonic-gate	set	itlb_parity_trap, %g4
16780Sstevel@tonic-gate	cmp	%g1, T_INSTR_EXCEPTION		! branch to the itlb or
16790Sstevel@tonic-gate	be	3f				! dtlb parity handler
16800Sstevel@tonic-gate	nop					! if this trap is due
16810Sstevel@tonic-gate	set	dtlb_parity_trap, %g4
16820Sstevel@tonic-gate	cmp	%g1, T_DATA_EXCEPTION		! to a IMMU exception
16830Sstevel@tonic-gate	be	3f				! or DMMU exception.
16844127Sedp	nop
16850Sstevel@tonic-gate2:
16860Sstevel@tonic-gate	sllx	%g3, 32, %g3
16870Sstevel@tonic-gate	or	%g3, %g1, %g3
16880Sstevel@tonic-gate	set	trap, %g1
16890Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
16900Sstevel@tonic-gate	sub	%g0, 1, %g4
16910Sstevel@tonic-gate3:
16920Sstevel@tonic-gate	jmp	%g4				! off to the appropriate
16930Sstevel@tonic-gate	nop					! TLB parity handler
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate.fp_disabled:
16960Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)				! load CPU struct addr
16970Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
16980Sstevel@tonic-gate#ifdef SF_ERRATA_30 /* call causes fp-disabled */
16990Sstevel@tonic-gate	brz,a,pn %g1, 2f
17000Sstevel@tonic-gate	  nop
17010Sstevel@tonic-gate#endif
17020Sstevel@tonic-gate	rdpr	%tstate, %g4
17030Sstevel@tonic-gate	btst	TSTATE_PRIV, %g4
17040Sstevel@tonic-gate#ifdef SF_ERRATA_30 /* call causes fp-disabled */
17050Sstevel@tonic-gate	bnz,pn %icc, 2f
17060Sstevel@tonic-gate	  nop
17070Sstevel@tonic-gate#else
17080Sstevel@tonic-gate	bnz,a,pn %icc, ptl1_panic
17090Sstevel@tonic-gate	  mov	PTL1_BAD_FPTRAP, %g1
17100Sstevel@tonic-gate#endif
17110Sstevel@tonic-gate	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
17120Sstevel@tonic-gate	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
17130Sstevel@tonic-gate	brz,a,pt %g5, 2f
17140Sstevel@tonic-gate	  nop
17150Sstevel@tonic-gate	ldn	[%g5 + P_UTRAP7], %g5			! fp_disabled utrap?
17160Sstevel@tonic-gate	brz,a,pn %g5, 2f
17170Sstevel@tonic-gate	  nop
17180Sstevel@tonic-gate	btst	1, %sp
17190Sstevel@tonic-gate	bz,a,pt	%xcc, 1f				! 32 bit user program
17200Sstevel@tonic-gate	  nop
17210Sstevel@tonic-gate	ba,a,pt	%xcc, .setup_v9utrap			! 64 bit user program
17220Sstevel@tonic-gate	  nop
17230Sstevel@tonic-gate1:
17240Sstevel@tonic-gate	ba,pt	%xcc, .setup_utrap
17250Sstevel@tonic-gate	  or	%g0, %g0, %g7
17260Sstevel@tonic-gate2:
17270Sstevel@tonic-gate	set	fp_disabled, %g1
17280Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
17290Sstevel@tonic-gate	  sub	%g0, 1, %g4
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate.fp_ieee_exception:
17320Sstevel@tonic-gate	rdpr	%tstate, %g1
17330Sstevel@tonic-gate	btst	TSTATE_PRIV, %g1
17340Sstevel@tonic-gate	bnz,a,pn %icc, ptl1_panic
17350Sstevel@tonic-gate	  mov	PTL1_BAD_FPTRAP, %g1
17360Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)				! load CPU struct addr
17370Sstevel@tonic-gate	stx	%fsr, [%g1 + CPU_TMP1]
17380Sstevel@tonic-gate	ldx	[%g1 + CPU_TMP1], %g2
17390Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
17400Sstevel@tonic-gate	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
17410Sstevel@tonic-gate	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
17420Sstevel@tonic-gate	brz,a,pt %g5, 1f
17430Sstevel@tonic-gate	  nop
17440Sstevel@tonic-gate	ldn	[%g5 + P_UTRAP8], %g5
17450Sstevel@tonic-gate	brnz,a,pt %g5, .setup_v9utrap
17460Sstevel@tonic-gate	  nop
17470Sstevel@tonic-gate1:
17480Sstevel@tonic-gate	set	_fp_ieee_exception, %g1
17490Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
17500Sstevel@tonic-gate	  sub	%g0, 1, %g4
17510Sstevel@tonic-gate
17520Sstevel@tonic-gate/*
17530Sstevel@tonic-gate * Register Inputs:
17540Sstevel@tonic-gate *	%g5		user trap handler
17550Sstevel@tonic-gate *	%g7		misaligned addr - for alignment traps only
17560Sstevel@tonic-gate */
17570Sstevel@tonic-gate.setup_utrap:
17580Sstevel@tonic-gate	set	trap, %g1			! setup in case we go
17590Sstevel@tonic-gate	mov	T_FLUSH_PCB, %g3		! through sys_trap on
17600Sstevel@tonic-gate	sub	%g0, 1, %g4			! the save instruction below
17610Sstevel@tonic-gate
17620Sstevel@tonic-gate	/*
17630Sstevel@tonic-gate	 * If the DTrace pid provider is single stepping a copied-out
17640Sstevel@tonic-gate	 * instruction, t->t_dtrace_step will be set. In that case we need
17650Sstevel@tonic-gate	 * to abort the single-stepping (since execution of the instruction
17660Sstevel@tonic-gate	 * was interrupted) and use the value of t->t_dtrace_npc as the %npc.
17670Sstevel@tonic-gate	 */
17680Sstevel@tonic-gate	save	%sp, -SA(MINFRAME32), %sp	! window for trap handler
17690Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)			! load CPU struct addr
17700Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1		! load thread pointer
17710Sstevel@tonic-gate	ldub	[%g1 + T_DTRACE_STEP], %g2	! load t->t_dtrace_step
17720Sstevel@tonic-gate	rdpr	%tnpc, %l2			! arg1 == tnpc
17730Sstevel@tonic-gate	brz,pt	%g2, 1f
17740Sstevel@tonic-gate	rdpr	%tpc, %l1			! arg0 == tpc
17750Sstevel@tonic-gate
17760Sstevel@tonic-gate	ldub	[%g1 + T_DTRACE_AST], %g2	! load t->t_dtrace_ast
17770Sstevel@tonic-gate	ldn	[%g1 + T_DTRACE_NPC], %l2	! arg1 = t->t_dtrace_npc (step)
17780Sstevel@tonic-gate	brz,pt	%g2, 1f
17790Sstevel@tonic-gate	st	%g0, [%g1 + T_DTRACE_FT]	! zero all pid provider flags
17800Sstevel@tonic-gate	stub	%g2, [%g1 + T_ASTFLAG]		! aston(t) if t->t_dtrace_ast
17810Sstevel@tonic-gate1:
17820Sstevel@tonic-gate	mov	%g7, %l3			! arg2 == misaligned address
17830Sstevel@tonic-gate
17840Sstevel@tonic-gate	rdpr	%tstate, %g1			! cwp for trap handler
17850Sstevel@tonic-gate	rdpr	%cwp, %g4
17860Sstevel@tonic-gate	bclr	TSTATE_CWP_MASK, %g1
17870Sstevel@tonic-gate	wrpr	%g1, %g4, %tstate
17880Sstevel@tonic-gate	wrpr	%g0, %g5, %tnpc			! trap handler address
17890Sstevel@tonic-gate	FAST_TRAP_DONE
17900Sstevel@tonic-gate	/* NOTREACHED */
17910Sstevel@tonic-gate
17920Sstevel@tonic-gate.check_v9utrap:
17930Sstevel@tonic-gate	rdpr	%tstate, %g1
17940Sstevel@tonic-gate	btst	TSTATE_PRIV, %g1
17950Sstevel@tonic-gate	bnz,a,pn %icc, 3f
17960Sstevel@tonic-gate	  nop
17970Sstevel@tonic-gate	CPU_ADDR(%g4, %g1)				! load CPU struct addr
17980Sstevel@tonic-gate	ldn	[%g4 + CPU_THREAD], %g5			! load thread pointer
17990Sstevel@tonic-gate	ldn	[%g5 + T_PROCP], %g5			! load proc pointer
18000Sstevel@tonic-gate	ldn	[%g5 + P_UTRAPS], %g5			! are there utraps?
18010Sstevel@tonic-gate
18020Sstevel@tonic-gate	cmp	%g3, T_SOFTWARE_TRAP
18030Sstevel@tonic-gate	bne,a,pt %icc, 1f
18040Sstevel@tonic-gate	  nop
18050Sstevel@tonic-gate
18060Sstevel@tonic-gate	brz,pt %g5, 3f			! if p_utraps == NULL goto trap()
18070Sstevel@tonic-gate	  rdpr	%tt, %g3		! delay - get actual hw trap type
18084127Sedp
18090Sstevel@tonic-gate	sub	%g3, 254, %g1		! UT_TRAP_INSTRUCTION_16 = p_utraps[18]
18100Sstevel@tonic-gate	ba,pt	%icc, 2f
18110Sstevel@tonic-gate	  smul	%g1, CPTRSIZE, %g2
18120Sstevel@tonic-gate1:
18130Sstevel@tonic-gate	brz,a,pt %g5, 3f		! if p_utraps == NULL goto trap()
18140Sstevel@tonic-gate	  nop
18150Sstevel@tonic-gate
18160Sstevel@tonic-gate	cmp	%g3, T_UNIMP_INSTR
18170Sstevel@tonic-gate	bne,a,pt %icc, 2f
18180Sstevel@tonic-gate	  nop
18190Sstevel@tonic-gate
18200Sstevel@tonic-gate	mov	1, %g1
18210Sstevel@tonic-gate	st	%g1, [%g4 + CPU_TL1_HDLR] ! set CPU_TL1_HDLR
18224127Sedp	rdpr	%tpc, %g1		! ld trapping instruction using
18230Sstevel@tonic-gate	lduwa	[%g1]ASI_AIUP, %g1	! "AS IF USER" ASI which could fault
18240Sstevel@tonic-gate	st	%g0, [%g4 + CPU_TL1_HDLR] ! clr CPU_TL1_HDLR
18250Sstevel@tonic-gate
18260Sstevel@tonic-gate	sethi	%hi(0xc1c00000), %g4	! setup mask for illtrap instruction
18270Sstevel@tonic-gate	andcc	%g1, %g4, %g4		! and instruction with mask
18280Sstevel@tonic-gate	bnz,a,pt %icc, 3f		! if %g4 == zero, %g1 is an ILLTRAP
18290Sstevel@tonic-gate	  nop				! fall thru to setup
18304127Sedp2:
18310Sstevel@tonic-gate	ldn	[%g5 + %g2], %g5
18320Sstevel@tonic-gate	brnz,a,pt %g5, .setup_v9utrap
18330Sstevel@tonic-gate	  nop
18340Sstevel@tonic-gate3:
18350Sstevel@tonic-gate	set	trap, %g1
18360Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
18370Sstevel@tonic-gate	  sub	%g0, 1, %g4
18380Sstevel@tonic-gate	/* NOTREACHED */
18390Sstevel@tonic-gate
18400Sstevel@tonic-gate/*
18410Sstevel@tonic-gate * Register Inputs:
18420Sstevel@tonic-gate *	%g5		user trap handler
18430Sstevel@tonic-gate */
18440Sstevel@tonic-gate.setup_v9utrap:
18450Sstevel@tonic-gate	set	trap, %g1			! setup in case we go
18460Sstevel@tonic-gate	mov	T_FLUSH_PCB, %g3		! through sys_trap on
18470Sstevel@tonic-gate	sub	%g0, 1, %g4			! the save instruction below
18480Sstevel@tonic-gate
18490Sstevel@tonic-gate	/*
18500Sstevel@tonic-gate	 * If the DTrace pid provider is single stepping a copied-out
18510Sstevel@tonic-gate	 * instruction, t->t_dtrace_step will be set. In that case we need
18520Sstevel@tonic-gate	 * to abort the single-stepping (since execution of the instruction
18530Sstevel@tonic-gate	 * was interrupted) and use the value of t->t_dtrace_npc as the %npc.
18540Sstevel@tonic-gate	 */
18550Sstevel@tonic-gate	save	%sp, -SA(MINFRAME64), %sp	! window for trap handler
18560Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)			! load CPU struct addr
18570Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1		! load thread pointer
18580Sstevel@tonic-gate	ldub	[%g1 + T_DTRACE_STEP], %g2	! load t->t_dtrace_step
18590Sstevel@tonic-gate	rdpr	%tnpc, %l7			! arg1 == tnpc
18600Sstevel@tonic-gate	brz,pt	%g2, 1f
18610Sstevel@tonic-gate	rdpr	%tpc, %l6			! arg0 == tpc
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate	ldub	[%g1 + T_DTRACE_AST], %g2	! load t->t_dtrace_ast
18640Sstevel@tonic-gate	ldn	[%g1 + T_DTRACE_NPC], %l7	! arg1 == t->t_dtrace_npc (step)
18650Sstevel@tonic-gate	brz,pt	%g2, 1f
18660Sstevel@tonic-gate	st	%g0, [%g1 + T_DTRACE_FT]	! zero all pid provider flags
18670Sstevel@tonic-gate	stub	%g2, [%g1 + T_ASTFLAG]		! aston(t) if t->t_dtrace_ast
18680Sstevel@tonic-gate1:
18690Sstevel@tonic-gate	rdpr	%tstate, %g2			! cwp for trap handler
18700Sstevel@tonic-gate	rdpr	%cwp, %g4
18710Sstevel@tonic-gate	bclr	TSTATE_CWP_MASK, %g2
18720Sstevel@tonic-gate	wrpr	%g2, %g4, %tstate
18730Sstevel@tonic-gate
18740Sstevel@tonic-gate	ldn	[%g1 + T_PROCP], %g4		! load proc pointer
18750Sstevel@tonic-gate	ldn	[%g4 + P_AS], %g4		! load as pointer
18760Sstevel@tonic-gate	ldn	[%g4 + A_USERLIMIT], %g4	! load as userlimit
18770Sstevel@tonic-gate	cmp	%l7, %g4			! check for single-step set
18780Sstevel@tonic-gate	bne,pt	%xcc, 4f
18790Sstevel@tonic-gate	  nop
18800Sstevel@tonic-gate	ldn	[%g1 + T_LWP], %g1		! load klwp pointer
18810Sstevel@tonic-gate	ld	[%g1 + PCB_STEP], %g4		! load single-step flag
18820Sstevel@tonic-gate	cmp	%g4, STEP_ACTIVE		! step flags set in pcb?
18830Sstevel@tonic-gate	bne,pt	%icc, 4f
18840Sstevel@tonic-gate	  nop
18850Sstevel@tonic-gate	stn	%g5, [%g1 + PCB_TRACEPC]	! save trap handler addr in pcb
18860Sstevel@tonic-gate	mov	%l7, %g4			! on entry to precise user trap
18870Sstevel@tonic-gate	add	%l6, 4, %l7			! handler, %l6 == pc, %l7 == npc
18880Sstevel@tonic-gate						! at time of trap
18890Sstevel@tonic-gate	wrpr	%g0, %g4, %tnpc			! generate FLTBOUNDS,
18900Sstevel@tonic-gate						! %g4 == userlimit
18910Sstevel@tonic-gate	FAST_TRAP_DONE
18920Sstevel@tonic-gate	/* NOTREACHED */
18930Sstevel@tonic-gate4:
18940Sstevel@tonic-gate	wrpr	%g0, %g5, %tnpc			! trap handler address
18950Sstevel@tonic-gate	FAST_TRAP_DONE_CHK_INTR
18960Sstevel@tonic-gate	/* NOTREACHED */
18970Sstevel@tonic-gate
18980Sstevel@tonic-gate.fp_exception:
18990Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
19000Sstevel@tonic-gate	stx	%fsr, [%g1 + CPU_TMP1]
19010Sstevel@tonic-gate	ldx	[%g1 + CPU_TMP1], %g2
19020Sstevel@tonic-gate
19030Sstevel@tonic-gate	/*
19040Sstevel@tonic-gate	 * Cheetah takes unfinished_FPop trap for certain range of operands
19050Sstevel@tonic-gate	 * to the "fitos" instruction. Instead of going through the slow
19060Sstevel@tonic-gate	 * software emulation path, we try to simulate the "fitos" instruction
19070Sstevel@tonic-gate	 * via "fitod" and "fdtos" provided the following conditions are met:
19080Sstevel@tonic-gate	 *
19090Sstevel@tonic-gate	 *	fpu_exists is set (if DEBUG)
19100Sstevel@tonic-gate	 *	not in privileged mode
19110Sstevel@tonic-gate	 *	ftt is unfinished_FPop
19120Sstevel@tonic-gate	 *	NXM IEEE trap is not enabled
19130Sstevel@tonic-gate	 *	instruction at %tpc is "fitos"
19140Sstevel@tonic-gate	 *
19150Sstevel@tonic-gate	 *  Usage:
19160Sstevel@tonic-gate	 *	%g1	per cpu address
19170Sstevel@tonic-gate	 *	%g2	%fsr
19180Sstevel@tonic-gate	 *	%g6	user instruction
19190Sstevel@tonic-gate	 *
19200Sstevel@tonic-gate	 * Note that we can take a memory access related trap while trying
19210Sstevel@tonic-gate	 * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR
19220Sstevel@tonic-gate	 * flag to catch those traps and let the SFMMU code deal with page
19230Sstevel@tonic-gate	 * fault and data access exception.
19240Sstevel@tonic-gate	 */
19250Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS)
19260Sstevel@tonic-gate	sethi	%hi(fpu_exists), %g7
19270Sstevel@tonic-gate	ld	[%g7 + %lo(fpu_exists)], %g7
19280Sstevel@tonic-gate	brz,pn %g7, .fp_exception_cont
19290Sstevel@tonic-gate	  nop
19300Sstevel@tonic-gate#endif
19310Sstevel@tonic-gate	rdpr	%tstate, %g7			! branch if in privileged mode
19320Sstevel@tonic-gate	btst	TSTATE_PRIV, %g7
19330Sstevel@tonic-gate	bnz,pn	%xcc, .fp_exception_cont
19340Sstevel@tonic-gate	srl	%g2, FSR_FTT_SHIFT, %g7		! extract ftt from %fsr
19350Sstevel@tonic-gate	and	%g7, (FSR_FTT>>FSR_FTT_SHIFT), %g7
19360Sstevel@tonic-gate	cmp	%g7, FTT_UNFIN
19374127Sedp	set	FSR_TEM_NX, %g5
19380Sstevel@tonic-gate	bne,pn	%xcc, .fp_exception_cont	! branch if NOT unfinished_FPop
19390Sstevel@tonic-gate	  andcc	%g2, %g5, %g0
19400Sstevel@tonic-gate	bne,pn	%xcc, .fp_exception_cont	! branch if FSR_TEM_NX enabled
19410Sstevel@tonic-gate	  rdpr	%tpc, %g5			! get faulting PC
19420Sstevel@tonic-gate
19430Sstevel@tonic-gate	or	%g0, 1, %g7
19440Sstevel@tonic-gate	st	%g7, [%g1 + CPU_TL1_HDLR]	! set tl1_hdlr flag
19450Sstevel@tonic-gate	lda	[%g5]ASI_USER, %g6		! get user's instruction
19460Sstevel@tonic-gate	st	%g0, [%g1 + CPU_TL1_HDLR]	! clear tl1_hdlr flag
19470Sstevel@tonic-gate
19480Sstevel@tonic-gate	set	FITOS_INSTR_MASK, %g7
19490Sstevel@tonic-gate	and	%g6, %g7, %g7
19500Sstevel@tonic-gate	set	FITOS_INSTR, %g5
19510Sstevel@tonic-gate	cmp	%g7, %g5
19520Sstevel@tonic-gate	bne,pn	%xcc, .fp_exception_cont	! branch if not FITOS_INSTR
19530Sstevel@tonic-gate	 nop
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate	/*
19560Sstevel@tonic-gate	 * This is unfinished FPops trap for "fitos" instruction. We
19570Sstevel@tonic-gate	 * need to simulate "fitos" via "fitod" and "fdtos" instruction
19580Sstevel@tonic-gate	 * sequence.
19590Sstevel@tonic-gate	 *
19600Sstevel@tonic-gate	 * We need a temporary FP register to do the conversion. Since
19610Sstevel@tonic-gate	 * both source and destination operands for the "fitos" instruction
19620Sstevel@tonic-gate	 * have to be within %f0-%f31, we use an FP register from the upper
19630Sstevel@tonic-gate	 * half to guarantee that it won't collide with the source or the
19640Sstevel@tonic-gate	 * dest operand. However, we do have to save and restore its value.
19650Sstevel@tonic-gate	 *
19660Sstevel@tonic-gate	 * We use %d62 as a temporary FP register for the conversion and
19670Sstevel@tonic-gate	 * branch to appropriate instruction within the conversion tables
19680Sstevel@tonic-gate	 * based upon the rs2 and rd values.
19690Sstevel@tonic-gate	 */
19700Sstevel@tonic-gate
19710Sstevel@tonic-gate	std	%d62, [%g1 + CPU_TMP1]		! save original value
19720Sstevel@tonic-gate
19730Sstevel@tonic-gate	srl	%g6, FITOS_RS2_SHIFT, %g7
19740Sstevel@tonic-gate	and	%g7, FITOS_REG_MASK, %g7
19750Sstevel@tonic-gate	set	_fitos_fitod_table, %g4
19760Sstevel@tonic-gate	sllx	%g7, 2, %g7
19770Sstevel@tonic-gate	jmp	%g4 + %g7
19780Sstevel@tonic-gate	  ba,pt	%xcc, _fitos_fitod_done
19790Sstevel@tonic-gate	.empty
19800Sstevel@tonic-gate
19810Sstevel@tonic-gate_fitos_fitod_table:
19820Sstevel@tonic-gate	  fitod	%f0, %d62
19830Sstevel@tonic-gate	  fitod	%f1, %d62
19840Sstevel@tonic-gate	  fitod	%f2, %d62
19850Sstevel@tonic-gate	  fitod	%f3, %d62
19860Sstevel@tonic-gate	  fitod	%f4, %d62
19870Sstevel@tonic-gate	  fitod	%f5, %d62
19880Sstevel@tonic-gate	  fitod	%f6, %d62
19890Sstevel@tonic-gate	  fitod	%f7, %d62
19900Sstevel@tonic-gate	  fitod	%f8, %d62
19910Sstevel@tonic-gate	  fitod	%f9, %d62
19920Sstevel@tonic-gate	  fitod	%f10, %d62
19930Sstevel@tonic-gate	  fitod	%f11, %d62
19940Sstevel@tonic-gate	  fitod	%f12, %d62
19950Sstevel@tonic-gate	  fitod	%f13, %d62
19960Sstevel@tonic-gate	  fitod	%f14, %d62
19970Sstevel@tonic-gate	  fitod	%f15, %d62
19980Sstevel@tonic-gate	  fitod	%f16, %d62
19990Sstevel@tonic-gate	  fitod	%f17, %d62
20000Sstevel@tonic-gate	  fitod	%f18, %d62
20010Sstevel@tonic-gate	  fitod	%f19, %d62
20020Sstevel@tonic-gate	  fitod	%f20, %d62
20030Sstevel@tonic-gate	  fitod	%f21, %d62
20040Sstevel@tonic-gate	  fitod	%f22, %d62
20050Sstevel@tonic-gate	  fitod	%f23, %d62
20060Sstevel@tonic-gate	  fitod	%f24, %d62
20070Sstevel@tonic-gate	  fitod	%f25, %d62
20080Sstevel@tonic-gate	  fitod	%f26, %d62
20090Sstevel@tonic-gate	  fitod	%f27, %d62
20100Sstevel@tonic-gate	  fitod	%f28, %d62
20110Sstevel@tonic-gate	  fitod	%f29, %d62
20120Sstevel@tonic-gate	  fitod	%f30, %d62
20130Sstevel@tonic-gate	  fitod	%f31, %d62
20140Sstevel@tonic-gate_fitos_fitod_done:
20150Sstevel@tonic-gate
20160Sstevel@tonic-gate	/*
20170Sstevel@tonic-gate	 * Now convert data back into single precision
20180Sstevel@tonic-gate	 */
20190Sstevel@tonic-gate	srl	%g6, FITOS_RD_SHIFT, %g7
20200Sstevel@tonic-gate	and	%g7, FITOS_REG_MASK, %g7
20210Sstevel@tonic-gate	set	_fitos_fdtos_table, %g4
20220Sstevel@tonic-gate	sllx	%g7, 2, %g7
20230Sstevel@tonic-gate	jmp	%g4 + %g7
20240Sstevel@tonic-gate	  ba,pt	%xcc, _fitos_fdtos_done
20250Sstevel@tonic-gate	.empty
20260Sstevel@tonic-gate
20270Sstevel@tonic-gate_fitos_fdtos_table:
20280Sstevel@tonic-gate	  fdtos	%d62, %f0
20290Sstevel@tonic-gate	  fdtos	%d62, %f1
20300Sstevel@tonic-gate	  fdtos	%d62, %f2
20310Sstevel@tonic-gate	  fdtos	%d62, %f3
20320Sstevel@tonic-gate	  fdtos	%d62, %f4
20330Sstevel@tonic-gate	  fdtos	%d62, %f5
20340Sstevel@tonic-gate	  fdtos	%d62, %f6
20350Sstevel@tonic-gate	  fdtos	%d62, %f7
20360Sstevel@tonic-gate	  fdtos	%d62, %f8
20370Sstevel@tonic-gate	  fdtos	%d62, %f9
20380Sstevel@tonic-gate	  fdtos	%d62, %f10
20390Sstevel@tonic-gate	  fdtos	%d62, %f11
20400Sstevel@tonic-gate	  fdtos	%d62, %f12
20410Sstevel@tonic-gate	  fdtos	%d62, %f13
20420Sstevel@tonic-gate	  fdtos	%d62, %f14
20430Sstevel@tonic-gate	  fdtos	%d62, %f15
20440Sstevel@tonic-gate	  fdtos	%d62, %f16
20450Sstevel@tonic-gate	  fdtos	%d62, %f17
20460Sstevel@tonic-gate	  fdtos	%d62, %f18
20470Sstevel@tonic-gate	  fdtos	%d62, %f19
20480Sstevel@tonic-gate	  fdtos	%d62, %f20
20490Sstevel@tonic-gate	  fdtos	%d62, %f21
20500Sstevel@tonic-gate	  fdtos	%d62, %f22
20510Sstevel@tonic-gate	  fdtos	%d62, %f23
20520Sstevel@tonic-gate	  fdtos	%d62, %f24
20530Sstevel@tonic-gate	  fdtos	%d62, %f25
20540Sstevel@tonic-gate	  fdtos	%d62, %f26
20550Sstevel@tonic-gate	  fdtos	%d62, %f27
20560Sstevel@tonic-gate	  fdtos	%d62, %f28
20570Sstevel@tonic-gate	  fdtos	%d62, %f29
20580Sstevel@tonic-gate	  fdtos	%d62, %f30
20590Sstevel@tonic-gate	  fdtos	%d62, %f31
20600Sstevel@tonic-gate_fitos_fdtos_done:
20610Sstevel@tonic-gate
20620Sstevel@tonic-gate	ldd	[%g1 + CPU_TMP1], %d62		! restore %d62
20630Sstevel@tonic-gate
20640Sstevel@tonic-gate#if DEBUG
20650Sstevel@tonic-gate	/*
20660Sstevel@tonic-gate	 * Update FPop_unfinished trap kstat
20670Sstevel@tonic-gate	 */
20680Sstevel@tonic-gate	set	fpustat+FPUSTAT_UNFIN_KSTAT, %g7
20690Sstevel@tonic-gate	ldx	[%g7], %g5
20700Sstevel@tonic-gate1:
20710Sstevel@tonic-gate	add	%g5, 1, %g6
20724127Sedp
20730Sstevel@tonic-gate	casxa	[%g7] ASI_N, %g5, %g6
20740Sstevel@tonic-gate	cmp	%g5, %g6
20750Sstevel@tonic-gate	bne,a,pn %xcc, 1b
20760Sstevel@tonic-gate	  or	%g0, %g6, %g5
20770Sstevel@tonic-gate
20780Sstevel@tonic-gate	/*
20790Sstevel@tonic-gate	 * Update fpu_sim_fitos kstat
20800Sstevel@tonic-gate	 */
20810Sstevel@tonic-gate	set	fpuinfo+FPUINFO_FITOS_KSTAT, %g7
20820Sstevel@tonic-gate	ldx	[%g7], %g5
20830Sstevel@tonic-gate1:
20840Sstevel@tonic-gate	add	%g5, 1, %g6
20850Sstevel@tonic-gate
20860Sstevel@tonic-gate	casxa	[%g7] ASI_N, %g5, %g6
20870Sstevel@tonic-gate	cmp	%g5, %g6
20880Sstevel@tonic-gate	bne,a,pn %xcc, 1b
20890Sstevel@tonic-gate	  or	%g0, %g6, %g5
20900Sstevel@tonic-gate#endif /* DEBUG */
20910Sstevel@tonic-gate
20920Sstevel@tonic-gate	FAST_TRAP_DONE
20930Sstevel@tonic-gate
20940Sstevel@tonic-gate.fp_exception_cont:
20950Sstevel@tonic-gate	/*
20960Sstevel@tonic-gate	 * Let _fp_exception deal with simulating FPop instruction.
20970Sstevel@tonic-gate	 * Note that we need to pass %fsr in %g2 (already read above).
20980Sstevel@tonic-gate	 */
20990Sstevel@tonic-gate
21000Sstevel@tonic-gate	set	_fp_exception, %g1
21010Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
21020Sstevel@tonic-gate	sub	%g0, 1, %g4
21030Sstevel@tonic-gate
21045414Smb158278	.global opl_cleanw_patch
21055414Smb158278opl_cleanw_patch:
21060Sstevel@tonic-gate.clean_windows:
21070Sstevel@tonic-gate	set	trap, %g1
21080Sstevel@tonic-gate	mov	T_FLUSH_PCB, %g3
21090Sstevel@tonic-gate	sub	%g0, 1, %g4
21100Sstevel@tonic-gate	save
21110Sstevel@tonic-gate	flushw
21120Sstevel@tonic-gate	restore
21130Sstevel@tonic-gate	wrpr	%g0, %g0, %cleanwin	! no clean windows
21140Sstevel@tonic-gate
21150Sstevel@tonic-gate	CPU_ADDR(%g4, %g5)
21160Sstevel@tonic-gate	ldn	[%g4 + CPU_MPCB], %g4
21170Sstevel@tonic-gate	brz,a,pn %g4, 1f
21180Sstevel@tonic-gate	  nop
21190Sstevel@tonic-gate	ld	[%g4 + MPCB_WSTATE], %g5
21200Sstevel@tonic-gate	add	%g5, WSTATE_CLEAN_OFFSET, %g5
21210Sstevel@tonic-gate	wrpr	%g0, %g5, %wstate
21220Sstevel@tonic-gate1:	FAST_TRAP_DONE
21230Sstevel@tonic-gate
21240Sstevel@tonic-gate/*
21250Sstevel@tonic-gate * .spill_clean: clean the previous window, restore the wstate, and
21260Sstevel@tonic-gate * "done".
21270Sstevel@tonic-gate *
21280Sstevel@tonic-gate * Entry: %g7 contains new wstate
21290Sstevel@tonic-gate */
21300Sstevel@tonic-gate.spill_clean:
21310Sstevel@tonic-gate	sethi	%hi(nwin_minus_one), %g5
21320Sstevel@tonic-gate	ld	[%g5 + %lo(nwin_minus_one)], %g5 ! %g5 = nwin - 1
21330Sstevel@tonic-gate	rdpr	%cwp, %g6			! %g6 = %cwp
21340Sstevel@tonic-gate	deccc	%g6				! %g6--
21350Sstevel@tonic-gate	movneg	%xcc, %g5, %g6			! if (%g6<0) %g6 = nwin-1
21360Sstevel@tonic-gate	wrpr	%g6, %cwp
21370Sstevel@tonic-gate	TT_TRACE_L(trace_win)
21380Sstevel@tonic-gate	clr	%l0
21390Sstevel@tonic-gate	clr	%l1
21400Sstevel@tonic-gate	clr	%l2
21410Sstevel@tonic-gate	clr	%l3
21420Sstevel@tonic-gate	clr	%l4
21430Sstevel@tonic-gate	clr	%l5
21440Sstevel@tonic-gate	clr	%l6
21450Sstevel@tonic-gate	clr	%l7
21460Sstevel@tonic-gate	wrpr	%g0, %g7, %wstate
21470Sstevel@tonic-gate	saved
21480Sstevel@tonic-gate	retry			! restores correct %cwp
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate.fix_alignment:
21510Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
21520Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g1	! load thread pointer
21530Sstevel@tonic-gate	ldn	[%g1 + T_PROCP], %g1
21540Sstevel@tonic-gate	mov	1, %g2
21550Sstevel@tonic-gate	stb	%g2, [%g1 + P_FIXALIGNMENT]
21560Sstevel@tonic-gate	FAST_TRAP_DONE
21570Sstevel@tonic-gate
21580Sstevel@tonic-gate#define	STDF_REG(REG, ADDR, TMP)		\
21590Sstevel@tonic-gate	sll	REG, 3, REG			;\
21600Sstevel@tonic-gatemark1:	set	start1, TMP			;\
21610Sstevel@tonic-gate	jmp	REG + TMP			;\
21620Sstevel@tonic-gate	  nop					;\
21630Sstevel@tonic-gatestart1:	ba,pt	%xcc, done1			;\
21640Sstevel@tonic-gate	  std	%f0, [ADDR + CPU_TMP1]		;\
21650Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21660Sstevel@tonic-gate	  std	%f32, [ADDR + CPU_TMP1]		;\
21670Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21680Sstevel@tonic-gate	  std	%f2, [ADDR + CPU_TMP1]		;\
21690Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21700Sstevel@tonic-gate	  std	%f34, [ADDR + CPU_TMP1]		;\
21710Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21720Sstevel@tonic-gate	  std	%f4, [ADDR + CPU_TMP1]		;\
21730Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21740Sstevel@tonic-gate	  std	%f36, [ADDR + CPU_TMP1]		;\
21750Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21760Sstevel@tonic-gate	  std	%f6, [ADDR + CPU_TMP1]		;\
21770Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21780Sstevel@tonic-gate	  std	%f38, [ADDR + CPU_TMP1]		;\
21790Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21800Sstevel@tonic-gate	  std	%f8, [ADDR + CPU_TMP1]		;\
21810Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21820Sstevel@tonic-gate	  std	%f40, [ADDR + CPU_TMP1]		;\
21830Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21840Sstevel@tonic-gate	  std	%f10, [ADDR + CPU_TMP1]		;\
21850Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21860Sstevel@tonic-gate	  std	%f42, [ADDR + CPU_TMP1]		;\
21870Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21880Sstevel@tonic-gate	  std	%f12, [ADDR + CPU_TMP1]		;\
21890Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21900Sstevel@tonic-gate	  std	%f44, [ADDR + CPU_TMP1]		;\
21910Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21920Sstevel@tonic-gate	  std	%f14, [ADDR + CPU_TMP1]		;\
21930Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21940Sstevel@tonic-gate	  std	%f46, [ADDR + CPU_TMP1]		;\
21950Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21960Sstevel@tonic-gate	  std	%f16, [ADDR + CPU_TMP1]		;\
21970Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
21980Sstevel@tonic-gate	  std	%f48, [ADDR + CPU_TMP1]		;\
21990Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22000Sstevel@tonic-gate	  std	%f18, [ADDR + CPU_TMP1]		;\
22010Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22020Sstevel@tonic-gate	  std	%f50, [ADDR + CPU_TMP1]		;\
22030Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22040Sstevel@tonic-gate	  std	%f20, [ADDR + CPU_TMP1]		;\
22050Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22060Sstevel@tonic-gate	  std	%f52, [ADDR + CPU_TMP1]		;\
22070Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22080Sstevel@tonic-gate	  std	%f22, [ADDR + CPU_TMP1]		;\
22090Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22100Sstevel@tonic-gate	  std	%f54, [ADDR + CPU_TMP1]		;\
22110Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22120Sstevel@tonic-gate	  std	%f24, [ADDR + CPU_TMP1]		;\
22130Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22140Sstevel@tonic-gate	  std	%f56, [ADDR + CPU_TMP1]		;\
22150Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22160Sstevel@tonic-gate	  std	%f26, [ADDR + CPU_TMP1]		;\
22170Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22180Sstevel@tonic-gate	  std	%f58, [ADDR + CPU_TMP1]		;\
22190Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22200Sstevel@tonic-gate	  std	%f28, [ADDR + CPU_TMP1]		;\
22210Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22220Sstevel@tonic-gate	  std	%f60, [ADDR + CPU_TMP1]		;\
22230Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22240Sstevel@tonic-gate	  std	%f30, [ADDR + CPU_TMP1]		;\
22250Sstevel@tonic-gate	ba,pt	%xcc, done1			;\
22260Sstevel@tonic-gate	  std	%f62, [ADDR + CPU_TMP1]		;\
22270Sstevel@tonic-gatedone1:
22280Sstevel@tonic-gate
22290Sstevel@tonic-gate#define	LDDF_REG(REG, ADDR, TMP)		\
22300Sstevel@tonic-gate	sll	REG, 3, REG			;\
22310Sstevel@tonic-gatemark2:	set	start2, TMP			;\
22320Sstevel@tonic-gate	jmp	REG + TMP			;\
22330Sstevel@tonic-gate	  nop					;\
22340Sstevel@tonic-gatestart2:	ba,pt	%xcc, done2			;\
22350Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f0		;\
22360Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22370Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f32		;\
22380Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22390Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f2		;\
22400Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22410Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f34		;\
22420Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22430Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f4		;\
22440Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22450Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f36		;\
22460Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22470Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f6		;\
22480Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22490Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f38		;\
22500Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22510Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f8		;\
22520Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22530Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f40		;\
22540Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22550Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f10		;\
22560Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22570Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f42		;\
22580Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22590Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f12		;\
22600Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22610Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f44		;\
22620Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22630Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f14		;\
22640Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22650Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f46		;\
22660Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22670Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f16		;\
22680Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22690Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f48		;\
22700Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22710Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f18		;\
22720Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22730Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f50		;\
22740Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22750Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f20		;\
22760Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22770Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f52		;\
22780Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22790Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f22		;\
22800Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22810Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f54		;\
22820Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22830Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f24		;\
22840Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22850Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f56		;\
22860Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22870Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f26		;\
22880Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22890Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f58		;\
22900Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22910Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f28		;\
22920Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22930Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f60		;\
22940Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22950Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f30		;\
22960Sstevel@tonic-gate	ba,pt	%xcc, done2			;\
22970Sstevel@tonic-gate	  ldd	[ADDR + CPU_TMP1], %f62		;\
22980Sstevel@tonic-gatedone2:
22990Sstevel@tonic-gate
23000Sstevel@tonic-gate.lddf_exception_not_aligned:
23010Sstevel@tonic-gate	/*
23020Sstevel@tonic-gate	 * Cheetah overwrites SFAR on a DTLB miss, hence read it now.
23030Sstevel@tonic-gate	 */
23040Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g5	! misaligned vaddr in %g5
23050Sstevel@tonic-gate
23060Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS)
23070Sstevel@tonic-gate	sethi	%hi(fpu_exists), %g2		! check fpu_exists
23080Sstevel@tonic-gate	ld	[%g2 + %lo(fpu_exists)], %g2
23090Sstevel@tonic-gate	brz,a,pn %g2, 4f
23100Sstevel@tonic-gate	  nop
23110Sstevel@tonic-gate#endif
23120Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
23130Sstevel@tonic-gate	or	%g0, 1, %g4
23140Sstevel@tonic-gate	st	%g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
23150Sstevel@tonic-gate
23160Sstevel@tonic-gate	rdpr	%tpc, %g2
23170Sstevel@tonic-gate	lda	[%g2]ASI_AIUP, %g6	! get the user's lddf instruction
23180Sstevel@tonic-gate	srl	%g6, 23, %g1		! using ldda or not?
23190Sstevel@tonic-gate	and	%g1, 1, %g1
23200Sstevel@tonic-gate	brz,a,pt %g1, 2f		! check for ldda instruction
23210Sstevel@tonic-gate	  nop
23220Sstevel@tonic-gate	srl	%g6, 13, %g1		! check immflag
23230Sstevel@tonic-gate	and	%g1, 1, %g1
23240Sstevel@tonic-gate	rdpr	%tstate, %g2		! %tstate in %g2
23250Sstevel@tonic-gate	brnz,a,pn %g1, 1f
23260Sstevel@tonic-gate	  srl	%g2, 31, %g1		! get asi from %tstate
23270Sstevel@tonic-gate	srl	%g6, 5, %g1		! get asi from instruction
23280Sstevel@tonic-gate	and	%g1, 0xFF, %g1		! imm_asi field
23290Sstevel@tonic-gate1:
23300Sstevel@tonic-gate	cmp	%g1, ASI_P		! primary address space
23310Sstevel@tonic-gate	be,a,pt %icc, 2f
23320Sstevel@tonic-gate	  nop
23330Sstevel@tonic-gate	cmp	%g1, ASI_PNF		! primary no fault address space
23340Sstevel@tonic-gate	be,a,pt %icc, 2f
23350Sstevel@tonic-gate	  nop
23360Sstevel@tonic-gate	cmp	%g1, ASI_S		! secondary address space
23370Sstevel@tonic-gate	be,a,pt %icc, 2f
23380Sstevel@tonic-gate	  nop
23390Sstevel@tonic-gate	cmp	%g1, ASI_SNF		! secondary no fault address space
23400Sstevel@tonic-gate	bne,a,pn %icc, 3f
23410Sstevel@tonic-gate	  nop
23420Sstevel@tonic-gate2:
23430Sstevel@tonic-gate	lduwa	[%g5]ASI_USER, %g7	! get first half of misaligned data
23440Sstevel@tonic-gate	add	%g5, 4, %g5		! increment misaligned data address
23450Sstevel@tonic-gate	lduwa	[%g5]ASI_USER, %g5	! get second half of misaligned data
23460Sstevel@tonic-gate
23470Sstevel@tonic-gate	sllx	%g7, 32, %g7
23480Sstevel@tonic-gate	or	%g5, %g7, %g5		! combine data
23490Sstevel@tonic-gate	CPU_ADDR(%g7, %g1)		! save data on a per-cpu basis
23500Sstevel@tonic-gate	stx	%g5, [%g7 + CPU_TMP1]	! save in cpu_tmp1
23510Sstevel@tonic-gate
23520Sstevel@tonic-gate	srl	%g6, 25, %g3		! %g6 has the instruction
23530Sstevel@tonic-gate	and	%g3, 0x1F, %g3		! %g3 has rd
23540Sstevel@tonic-gate	LDDF_REG(%g3, %g7, %g4)
23550Sstevel@tonic-gate
23560Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
23570Sstevel@tonic-gate	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
23580Sstevel@tonic-gate	FAST_TRAP_DONE
23590Sstevel@tonic-gate3:
23600Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
23610Sstevel@tonic-gate	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
23620Sstevel@tonic-gate4:
23630Sstevel@tonic-gate	set	T_USER, %g3		! trap type in %g3
23640Sstevel@tonic-gate	or	%g3, T_LDDF_ALIGN, %g3
23650Sstevel@tonic-gate	mov	%g5, %g2		! misaligned vaddr in %g2
23660Sstevel@tonic-gate	set	fpu_trap, %g1		! goto C for the little and
23670Sstevel@tonic-gate	ba,pt	%xcc, sys_trap		! no fault little asi's
23680Sstevel@tonic-gate	  sub	%g0, 1, %g4
23690Sstevel@tonic-gate
23700Sstevel@tonic-gate.stdf_exception_not_aligned:
23710Sstevel@tonic-gate	/*
23720Sstevel@tonic-gate	 * Cheetah overwrites SFAR on a DTLB miss, hence read it now.
23730Sstevel@tonic-gate	 */
23740Sstevel@tonic-gate	ldxa	[MMU_SFAR]%asi, %g5	! misaligned vaddr in %g5
23750Sstevel@tonic-gate
23760Sstevel@tonic-gate#if defined(DEBUG) || defined(NEED_FPU_EXISTS)
23770Sstevel@tonic-gate	sethi	%hi(fpu_exists), %g7		! check fpu_exists
23780Sstevel@tonic-gate	ld	[%g7 + %lo(fpu_exists)], %g3
23790Sstevel@tonic-gate	brz,a,pn %g3, 4f
23800Sstevel@tonic-gate	  nop
23810Sstevel@tonic-gate#endif
23820Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
23830Sstevel@tonic-gate	or	%g0, 1, %g4
23840Sstevel@tonic-gate	st	%g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
23850Sstevel@tonic-gate
23860Sstevel@tonic-gate	rdpr	%tpc, %g2
23870Sstevel@tonic-gate	lda	[%g2]ASI_AIUP, %g6	! get the user's stdf instruction
23880Sstevel@tonic-gate
23890Sstevel@tonic-gate	srl	%g6, 23, %g1		! using stda or not?
23900Sstevel@tonic-gate	and	%g1, 1, %g1
23910Sstevel@tonic-gate	brz,a,pt %g1, 2f		! check for stda instruction
23920Sstevel@tonic-gate	  nop
23930Sstevel@tonic-gate	srl	%g6, 13, %g1		! check immflag
23940Sstevel@tonic-gate	and	%g1, 1, %g1
23950Sstevel@tonic-gate	rdpr	%tstate, %g2		! %tstate in %g2
23960Sstevel@tonic-gate	brnz,a,pn %g1, 1f
23970Sstevel@tonic-gate	  srl	%g2, 31, %g1		! get asi from %tstate
23980Sstevel@tonic-gate	srl	%g6, 5, %g1		! get asi from instruction
23990Sstevel@tonic-gate	and	%g1, 0xFF, %g1		! imm_asi field
24000Sstevel@tonic-gate1:
24010Sstevel@tonic-gate	cmp	%g1, ASI_P		! primary address space
24020Sstevel@tonic-gate	be,a,pt %icc, 2f
24030Sstevel@tonic-gate	  nop
24040Sstevel@tonic-gate	cmp	%g1, ASI_S		! secondary address space
24050Sstevel@tonic-gate	bne,a,pn %icc, 3f
24060Sstevel@tonic-gate	  nop
24070Sstevel@tonic-gate2:
24080Sstevel@tonic-gate	srl	%g6, 25, %g6
24090Sstevel@tonic-gate	and	%g6, 0x1F, %g6		! %g6 has rd
24100Sstevel@tonic-gate	CPU_ADDR(%g7, %g1)
24110Sstevel@tonic-gate	STDF_REG(%g6, %g7, %g4)		! STDF_REG(REG, ADDR, TMP)
24120Sstevel@tonic-gate
24130Sstevel@tonic-gate	ldx	[%g7 + CPU_TMP1], %g6
24140Sstevel@tonic-gate	srlx	%g6, 32, %g7
24150Sstevel@tonic-gate	stuwa	%g7, [%g5]ASI_USER	! first half
24160Sstevel@tonic-gate	add	%g5, 4, %g5		! increment misaligned data address
24170Sstevel@tonic-gate	stuwa	%g6, [%g5]ASI_USER	! second half
24180Sstevel@tonic-gate
24190Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
24200Sstevel@tonic-gate	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
24210Sstevel@tonic-gate	FAST_TRAP_DONE
24220Sstevel@tonic-gate3:
24230Sstevel@tonic-gate	CPU_ADDR(%g1, %g4)
24240Sstevel@tonic-gate	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
24250Sstevel@tonic-gate4:
24260Sstevel@tonic-gate	set	T_USER, %g3		! trap type in %g3
24270Sstevel@tonic-gate	or	%g3, T_STDF_ALIGN, %g3
24280Sstevel@tonic-gate	mov	%g5, %g2		! misaligned vaddr in %g2
24290Sstevel@tonic-gate	set	fpu_trap, %g1		! goto C for the little and
24300Sstevel@tonic-gate	ba,pt	%xcc, sys_trap		! nofault little asi's
24310Sstevel@tonic-gate	  sub	%g0, 1, %g4
24320Sstevel@tonic-gate
24330Sstevel@tonic-gate#ifdef DEBUG_USER_TRAPTRACECTL
24340Sstevel@tonic-gate
24350Sstevel@tonic-gate.traptrace_freeze:
24360Sstevel@tonic-gate	mov	%l0, %g1 ; mov	%l1, %g2 ; mov	%l2, %g3 ; mov	%l4, %g4
24370Sstevel@tonic-gate	TT_TRACE_L(trace_win)
24380Sstevel@tonic-gate	mov	%g4, %l4 ; mov	%g3, %l2 ; mov	%g2, %l1 ; mov	%g1, %l0
24390Sstevel@tonic-gate	set	trap_freeze, %g1
24400Sstevel@tonic-gate	mov	1, %g2
24410Sstevel@tonic-gate	st	%g2, [%g1]
24420Sstevel@tonic-gate	FAST_TRAP_DONE
24430Sstevel@tonic-gate
24440Sstevel@tonic-gate.traptrace_unfreeze:
24450Sstevel@tonic-gate	set	trap_freeze, %g1
24460Sstevel@tonic-gate	st	%g0, [%g1]
24470Sstevel@tonic-gate	mov	%l0, %g1 ; mov	%l1, %g2 ; mov	%l2, %g3 ; mov	%l4, %g4
24480Sstevel@tonic-gate	TT_TRACE_L(trace_win)
24490Sstevel@tonic-gate	mov	%g4, %l4 ; mov	%g3, %l2 ; mov	%g2, %l1 ; mov	%g1, %l0
24500Sstevel@tonic-gate	FAST_TRAP_DONE
24510Sstevel@tonic-gate
24520Sstevel@tonic-gate#endif /* DEBUG_USER_TRAPTRACECTL */
24530Sstevel@tonic-gate
24540Sstevel@tonic-gate.getcc:
24550Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)
24560Sstevel@tonic-gate	stx	%o0, [%g1 + CPU_TMP1]		! save %o0
24570Sstevel@tonic-gate	stx	%o1, [%g1 + CPU_TMP2]		! save %o1
24580Sstevel@tonic-gate	rdpr	%tstate, %g3			! get tstate
24590Sstevel@tonic-gate	srlx	%g3, PSR_TSTATE_CC_SHIFT, %o0	! shift ccr to V8 psr
24600Sstevel@tonic-gate	set	PSR_ICC, %g2
24610Sstevel@tonic-gate	and	%o0, %g2, %o0			! mask out the rest
24620Sstevel@tonic-gate	srl	%o0, PSR_ICC_SHIFT, %o0		! right justify
24630Sstevel@tonic-gate	rdpr	%pstate, %o1
24640Sstevel@tonic-gate	wrpr	%o1, PSTATE_AG, %pstate		! get into normal globals
24650Sstevel@tonic-gate	mov	%o0, %g1			! move ccr to normal %g1
24660Sstevel@tonic-gate	wrpr	%g0, %o1, %pstate		! back into alternate globals
24670Sstevel@tonic-gate	ldx	[%g1 + CPU_TMP1], %o0		! restore %o0
24680Sstevel@tonic-gate	ldx	[%g1 + CPU_TMP2], %o1		! restore %o1
24690Sstevel@tonic-gate	FAST_TRAP_DONE
24700Sstevel@tonic-gate
24710Sstevel@tonic-gate.setcc:
24720Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)
24730Sstevel@tonic-gate	stx	%o0, [%g1 + CPU_TMP1]		! save %o0
24740Sstevel@tonic-gate	stx	%o1, [%g1 + CPU_TMP2]		! save %o1
24750Sstevel@tonic-gate	rdpr	%pstate, %o0
24760Sstevel@tonic-gate	wrpr	%o0, PSTATE_AG, %pstate		! get into normal globals
24770Sstevel@tonic-gate	mov	%g1, %o1
24780Sstevel@tonic-gate	wrpr	%g0, %o0, %pstate		! back to alternates
24790Sstevel@tonic-gate	sll	%o1, PSR_ICC_SHIFT, %g2
24800Sstevel@tonic-gate	set	PSR_ICC, %g3
24810Sstevel@tonic-gate	and	%g2, %g3, %g2			! mask out rest
24820Sstevel@tonic-gate	sllx	%g2, PSR_TSTATE_CC_SHIFT, %g2
24830Sstevel@tonic-gate	rdpr	%tstate, %g3			! get tstate
24840Sstevel@tonic-gate	srl	%g3, 0, %g3			! clear upper word
24850Sstevel@tonic-gate	or	%g3, %g2, %g3			! or in new bits
24860Sstevel@tonic-gate	wrpr	%g3, %tstate
24870Sstevel@tonic-gate	ldx	[%g1 + CPU_TMP1], %o0		! restore %o0
24880Sstevel@tonic-gate	ldx	[%g1 + CPU_TMP2], %o1		! restore %o1
24890Sstevel@tonic-gate	FAST_TRAP_DONE
24900Sstevel@tonic-gate
24910Sstevel@tonic-gate/*
24920Sstevel@tonic-gate * getpsr(void)
24930Sstevel@tonic-gate * Note that the xcc part of the ccr is not provided.
24940Sstevel@tonic-gate * The V8 code shows why the V9 trap is not faster:
24950Sstevel@tonic-gate * #define GETPSR_TRAP() \
24960Sstevel@tonic-gate *      mov %psr, %i0; jmp %l2; rett %l2+4; nop;
24970Sstevel@tonic-gate */
24980Sstevel@tonic-gate
24990Sstevel@tonic-gate	.type	.getpsr, #function
25000Sstevel@tonic-gate.getpsr:
25010Sstevel@tonic-gate	rdpr	%tstate, %g1			! get tstate
25020Sstevel@tonic-gate	srlx	%g1, PSR_TSTATE_CC_SHIFT, %o0	! shift ccr to V8 psr
25030Sstevel@tonic-gate	set	PSR_ICC, %g2
25040Sstevel@tonic-gate	and	%o0, %g2, %o0			! mask out the rest
25050Sstevel@tonic-gate
25060Sstevel@tonic-gate	rd	%fprs, %g1			! get fprs
25070Sstevel@tonic-gate	and	%g1, FPRS_FEF, %g2		! mask out dirty upper/lower
25080Sstevel@tonic-gate	sllx	%g2, PSR_FPRS_FEF_SHIFT, %g2	! shift fef to V8 psr.ef
25090Sstevel@tonic-gate	or	%o0, %g2, %o0			! or result into psr.ef
25100Sstevel@tonic-gate
25110Sstevel@tonic-gate	set	V9_PSR_IMPLVER, %g2		! SI assigned impl/ver: 0xef
25120Sstevel@tonic-gate	or	%o0, %g2, %o0			! or psr.impl/ver
25130Sstevel@tonic-gate	FAST_TRAP_DONE
25140Sstevel@tonic-gate	SET_SIZE(.getpsr)
25150Sstevel@tonic-gate
25160Sstevel@tonic-gate/*
25170Sstevel@tonic-gate * setpsr(newpsr)
25180Sstevel@tonic-gate * Note that there is no support for ccr.xcc in the V9 code.
25190Sstevel@tonic-gate */
25200Sstevel@tonic-gate
25210Sstevel@tonic-gate	.type	.setpsr, #function
25220Sstevel@tonic-gate.setpsr:
25230Sstevel@tonic-gate	rdpr	%tstate, %g1			! get tstate
25240Sstevel@tonic-gate!	setx	TSTATE_V8_UBITS, %g2
25250Sstevel@tonic-gate	or 	%g0, CCR_ICC, %g3
25260Sstevel@tonic-gate	sllx	%g3, TSTATE_CCR_SHIFT, %g2
25270Sstevel@tonic-gate
25280Sstevel@tonic-gate	andn	%g1, %g2, %g1			! zero current user bits
25290Sstevel@tonic-gate	set	PSR_ICC, %g2
25300Sstevel@tonic-gate	and	%g2, %o0, %g2			! clear all but psr.icc bits
25310Sstevel@tonic-gate	sllx	%g2, PSR_TSTATE_CC_SHIFT, %g3	! shift to tstate.ccr.icc
25320Sstevel@tonic-gate	wrpr	%g1, %g3, %tstate		! write tstate
25330Sstevel@tonic-gate
25340Sstevel@tonic-gate	set	PSR_EF, %g2
25350Sstevel@tonic-gate	and	%g2, %o0, %g2			! clear all but fp enable bit
25360Sstevel@tonic-gate	srlx	%g2, PSR_FPRS_FEF_SHIFT, %g4	! shift ef to V9 fprs.fef
25370Sstevel@tonic-gate	wr	%g0, %g4, %fprs			! write fprs
25380Sstevel@tonic-gate
25390Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)			! load CPU struct addr to %g1
25400Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g2		! load thread pointer
25410Sstevel@tonic-gate	ldn	[%g2 + T_LWP], %g3		! load klwp pointer
25420Sstevel@tonic-gate	ldn	[%g3 + LWP_FPU], %g2		! get lwp_fpu pointer
25430Sstevel@tonic-gate	stuw	%g4, [%g2 + FPU_FPRS]		! write fef value to fpu_fprs
25440Sstevel@tonic-gate	srlx	%g4, 2, %g4			! shift fef value to bit 0
25450Sstevel@tonic-gate	stub	%g4, [%g2 + FPU_EN]		! write fef value to fpu_en
25460Sstevel@tonic-gate	FAST_TRAP_DONE
25470Sstevel@tonic-gate	SET_SIZE(.setpsr)
25480Sstevel@tonic-gate
25490Sstevel@tonic-gate/*
25500Sstevel@tonic-gate * getlgrp
25510Sstevel@tonic-gate * get home lgrpid on which the calling thread is currently executing.
25520Sstevel@tonic-gate */
25530Sstevel@tonic-gate	.type	.getlgrp, #function
25540Sstevel@tonic-gate.getlgrp:
25550Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
25560Sstevel@tonic-gate	ld	[%g1 + CPU_ID], %o0	! load cpu_id
25570Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g2	! load thread pointer
25580Sstevel@tonic-gate	ldn	[%g2 + T_LPL], %g2	! load lpl pointer
25590Sstevel@tonic-gate	ld	[%g2 + LPL_LGRPID], %g1	! load lpl_lgrpid
25600Sstevel@tonic-gate	sra	%g1, 0, %o1
25610Sstevel@tonic-gate	FAST_TRAP_DONE
25620Sstevel@tonic-gate	SET_SIZE(.getlgrp)
25630Sstevel@tonic-gate
25640Sstevel@tonic-gate/*
25650Sstevel@tonic-gate * Entry for old 4.x trap (trap 0).
25660Sstevel@tonic-gate */
25670Sstevel@tonic-gate	ENTRY_NP(syscall_trap_4x)
25680Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
25690Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g2	! load thread pointer
25700Sstevel@tonic-gate	ldn	[%g2 + T_LWP], %g2	! load klwp pointer
25710Sstevel@tonic-gate	ld	[%g2 + PCB_TRAP0], %g2	! lwp->lwp_pcb.pcb_trap0addr
25720Sstevel@tonic-gate	brz,pn	%g2, 1f			! has it been set?
25730Sstevel@tonic-gate	st	%l0, [%g1 + CPU_TMP1]	! delay - save some locals
25740Sstevel@tonic-gate	st	%l1, [%g1 + CPU_TMP2]
25750Sstevel@tonic-gate	rdpr	%tnpc, %l1		! save old tnpc
25760Sstevel@tonic-gate	wrpr	%g0, %g2, %tnpc		! setup tnpc
25770Sstevel@tonic-gate
25780Sstevel@tonic-gate	rdpr	%pstate, %l0
25790Sstevel@tonic-gate	wrpr	%l0, PSTATE_AG, %pstate	! switch to normal globals
25800Sstevel@tonic-gate	mov	%l1, %g6		! pass tnpc to user code in %g6
25810Sstevel@tonic-gate	wrpr	%l0, %g0, %pstate	! switch back to alternate globals
25820Sstevel@tonic-gate
25830Sstevel@tonic-gate	! Note that %g1 still contains CPU struct addr
25840Sstevel@tonic-gate	ld	[%g1 + CPU_TMP2], %l1	! restore locals
25850Sstevel@tonic-gate	ld	[%g1 + CPU_TMP1], %l0
25860Sstevel@tonic-gate	FAST_TRAP_DONE_CHK_INTR
25870Sstevel@tonic-gate1:
25880Sstevel@tonic-gate	mov	%g1, %l0
25890Sstevel@tonic-gate	st	%l1, [%g1 + CPU_TMP2]
25900Sstevel@tonic-gate	rdpr	%pstate, %l1
25910Sstevel@tonic-gate	wrpr	%l1, PSTATE_AG, %pstate
25920Sstevel@tonic-gate	!
25930Sstevel@tonic-gate	! check for old syscall mmap which is the only different one which
25940Sstevel@tonic-gate	! must be the same.  Others are handled in the compatibility library.
25950Sstevel@tonic-gate	!
25960Sstevel@tonic-gate	cmp	%g1, OSYS_mmap	! compare to old 4.x mmap
25970Sstevel@tonic-gate	movz	%icc, SYS_mmap, %g1
25980Sstevel@tonic-gate	wrpr	%g0, %l1, %pstate
25990Sstevel@tonic-gate	ld	[%l0 + CPU_TMP2], %l1	! restore locals
26000Sstevel@tonic-gate	ld	[%l0 + CPU_TMP1], %l0
26010Sstevel@tonic-gate	SYSCALL(syscall_trap32)
26020Sstevel@tonic-gate	SET_SIZE(syscall_trap_4x)
26030Sstevel@tonic-gate
26040Sstevel@tonic-gate/*
26050Sstevel@tonic-gate * Handler for software trap 9.
26060Sstevel@tonic-gate * Set trap0 emulation address for old 4.x system call trap.
26070Sstevel@tonic-gate * XXX - this should be a system call.
26080Sstevel@tonic-gate */
26090Sstevel@tonic-gate	ENTRY_NP(set_trap0_addr)
26100Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
26110Sstevel@tonic-gate	ldn	[%g1 + CPU_THREAD], %g2	! load thread pointer
26120Sstevel@tonic-gate	ldn	[%g2 + T_LWP], %g2	! load klwp pointer
26130Sstevel@tonic-gate	st	%l0, [%g1 + CPU_TMP1]	! save some locals
26140Sstevel@tonic-gate	st	%l1, [%g1 + CPU_TMP2]
26150Sstevel@tonic-gate	rdpr	%pstate, %l0
26160Sstevel@tonic-gate	wrpr	%l0, PSTATE_AG, %pstate
26170Sstevel@tonic-gate	mov	%g1, %l1
26180Sstevel@tonic-gate	wrpr	%g0, %l0, %pstate
26190Sstevel@tonic-gate	andn	%l1, 3, %l1		! force alignment
26200Sstevel@tonic-gate	st	%l1, [%g2 + PCB_TRAP0]	! lwp->lwp_pcb.pcb_trap0addr
26210Sstevel@tonic-gate	ld	[%g1 + CPU_TMP1], %l0	! restore locals
26220Sstevel@tonic-gate	ld	[%g1 + CPU_TMP2], %l1
26230Sstevel@tonic-gate	FAST_TRAP_DONE
26240Sstevel@tonic-gate	SET_SIZE(set_trap0_addr)
26250Sstevel@tonic-gate
26260Sstevel@tonic-gate/*
26270Sstevel@tonic-gate * mmu_trap_tl1
26280Sstevel@tonic-gate * trap handler for unexpected mmu traps.
26290Sstevel@tonic-gate * simply checks if the trap was a user lddf/stdf alignment trap, in which
26300Sstevel@tonic-gate * case we go to fpu_trap or a user trap from the window handler, in which
26310Sstevel@tonic-gate * case we go save the state on the pcb.  Otherwise, we go to ptl1_panic.
26320Sstevel@tonic-gate */
26330Sstevel@tonic-gate	.type	mmu_trap_tl1, #function
26340Sstevel@tonic-gatemmu_trap_tl1:
26350Sstevel@tonic-gate#ifdef	TRAPTRACE
26360Sstevel@tonic-gate	TRACE_PTR(%g5, %g6)
2637*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g7)
26380Sstevel@tonic-gate	stxa	%g6, [%g5 + TRAP_ENT_TICK]%asi
26390Sstevel@tonic-gate	rdpr	%tl, %g6
26400Sstevel@tonic-gate	stha	%g6, [%g5 + TRAP_ENT_TL]%asi
26410Sstevel@tonic-gate	rdpr	%tt, %g6
26420Sstevel@tonic-gate	stha	%g6, [%g5 + TRAP_ENT_TT]%asi
26430Sstevel@tonic-gate	rdpr	%tstate, %g6
26440Sstevel@tonic-gate	stxa	%g6, [%g5 + TRAP_ENT_TSTATE]%asi
26450Sstevel@tonic-gate	stna	%sp, [%g5 + TRAP_ENT_SP]%asi
26460Sstevel@tonic-gate	stna	%g0, [%g5 + TRAP_ENT_TR]%asi
26470Sstevel@tonic-gate	rdpr	%tpc, %g6
26480Sstevel@tonic-gate	stna	%g6, [%g5 + TRAP_ENT_TPC]%asi
26490Sstevel@tonic-gate	set	MMU_SFAR, %g6
26500Sstevel@tonic-gate	ldxa	[%g6]ASI_DMMU, %g6
26510Sstevel@tonic-gate	stxa	%g6, [%g5 + TRAP_ENT_F1]%asi
26520Sstevel@tonic-gate	CPU_PADDR(%g7, %g6);
26530Sstevel@tonic-gate	add	%g7, CPU_TL1_HDLR, %g7
26540Sstevel@tonic-gate	lda	[%g7]ASI_MEM, %g6
26550Sstevel@tonic-gate	stxa	%g6, [%g5 + TRAP_ENT_F2]%asi
26560Sstevel@tonic-gate	set	0xdeadbeef, %g6
26570Sstevel@tonic-gate	stna	%g6, [%g5 + TRAP_ENT_F3]%asi
26580Sstevel@tonic-gate	stna	%g6, [%g5 + TRAP_ENT_F4]%asi
26590Sstevel@tonic-gate	TRACE_NEXT(%g5, %g6, %g7)
26600Sstevel@tonic-gate#endif /* TRAPTRACE */
26610Sstevel@tonic-gate
26620Sstevel@tonic-gate	GET_CPU_IMPL(%g5)
26630Sstevel@tonic-gate	cmp	%g5, PANTHER_IMPL
26640Sstevel@tonic-gate	bne	mmu_trap_tl1_4
26650Sstevel@tonic-gate	  nop
26660Sstevel@tonic-gate	rdpr	%tt, %g5
26670Sstevel@tonic-gate	cmp	%g5, T_DATA_EXCEPTION
26680Sstevel@tonic-gate	bne	mmu_trap_tl1_4
26690Sstevel@tonic-gate	  nop
26700Sstevel@tonic-gate	wr	%g0, ASI_DMMU, %asi
26710Sstevel@tonic-gate	ldxa	[MMU_SFSR]%asi, %g5
26720Sstevel@tonic-gate	mov	1, %g6
26730Sstevel@tonic-gate	sllx	%g6, PN_SFSR_PARITY_SHIFT, %g6
26740Sstevel@tonic-gate	andcc	%g5, %g6, %g0
26750Sstevel@tonic-gate	bz	mmu_trap_tl1_4
26760Sstevel@tonic-gate
26770Sstevel@tonic-gate	/*
26780Sstevel@tonic-gate	 * We are running on a Panther and have hit a DTLB parity error.
26790Sstevel@tonic-gate	 */
26800Sstevel@tonic-gate	ldxa	[MMU_TAG_ACCESS]%asi, %g2
26810Sstevel@tonic-gate	mov	%g5, %g3
26820Sstevel@tonic-gate	ba,pt	%xcc, .mmu_exception_is_tlb_parity
26830Sstevel@tonic-gate	mov	T_DATA_EXCEPTION, %g1
26840Sstevel@tonic-gate
26850Sstevel@tonic-gatemmu_trap_tl1_4:
26860Sstevel@tonic-gate	CPU_PADDR(%g7, %g6);
26870Sstevel@tonic-gate	add     %g7, CPU_TL1_HDLR, %g7		! %g7 = &cpu_m.tl1_hdlr (PA)
26880Sstevel@tonic-gate	/*
26890Sstevel@tonic-gate	 * AM is cleared on trap, so addresses are 64 bit
26900Sstevel@tonic-gate	 */
26910Sstevel@tonic-gate	lda     [%g7]ASI_MEM, %g6
26920Sstevel@tonic-gate	brz,a,pt %g6, 1f
26930Sstevel@tonic-gate	  nop
26940Sstevel@tonic-gate	/*
26950Sstevel@tonic-gate	 * We are going to update cpu_m.tl1_hdlr using physical address.
26960Sstevel@tonic-gate	 * Flush the D$ line, so that stale data won't be accessed later.
26970Sstevel@tonic-gate	 */
26980Sstevel@tonic-gate	CPU_ADDR(%g6, %g5)
26990Sstevel@tonic-gate	add     %g6, CPU_TL1_HDLR, %g6		! %g6 = &cpu_m.tl1_hdlr (VA)
27000Sstevel@tonic-gate	GET_CPU_IMPL(%g5)
27010Sstevel@tonic-gate	cmp	%g5, CHEETAH_IMPL
27021772Sjl139090	bl,pt	%icc, 3f
27031772Sjl139090	 cmp	%g5, SPITFIRE_IMPL
27040Sstevel@tonic-gate	stxa	%g0, [%g7]ASI_DC_INVAL
27050Sstevel@tonic-gate	membar	#Sync
27060Sstevel@tonic-gate	ba,pt	%xcc, 2f
27071772Sjl139090	 nop
27080Sstevel@tonic-gate3:
27091772Sjl139090	bl,pt	%icc, 2f
27101772Sjl139090	 sethi	%hi(dcache_line_mask), %g5
27110Sstevel@tonic-gate	ld	[%g5 + %lo(dcache_line_mask)], %g5
27120Sstevel@tonic-gate	and	%g6, %g5, %g5
27130Sstevel@tonic-gate	stxa	%g0, [%g5]ASI_DC_TAG
27140Sstevel@tonic-gate	membar	#Sync
27150Sstevel@tonic-gate2:
27160Sstevel@tonic-gate	sta     %g0, [%g7]ASI_MEM
27170Sstevel@tonic-gate	SWITCH_GLOBALS				! back to mmu globals
27180Sstevel@tonic-gate	ba,a,pt	%xcc, sfmmu_mmu_trap		! handle page faults
27190Sstevel@tonic-gate1:
27200Sstevel@tonic-gate	rdpr	%tt, %g5
27210Sstevel@tonic-gate	rdpr	%tl, %g7
27220Sstevel@tonic-gate	sub	%g7, 1, %g6
27230Sstevel@tonic-gate	wrpr	%g6, %tl
27240Sstevel@tonic-gate	rdpr	%tt, %g6
27250Sstevel@tonic-gate	wrpr	%g7, %tl
27260Sstevel@tonic-gate	and	%g6, WTRAP_TTMASK, %g6
27270Sstevel@tonic-gate	cmp	%g6, WTRAP_TYPE
27280Sstevel@tonic-gate	bne,a,pn %xcc, ptl1_panic
27290Sstevel@tonic-gate	mov	PTL1_BAD_MMUTRAP, %g1
27300Sstevel@tonic-gate	rdpr	%tpc, %g7
27310Sstevel@tonic-gate	/* tpc should be in the trap table */
27320Sstevel@tonic-gate	set	trap_table, %g6
27330Sstevel@tonic-gate	cmp	%g7, %g6
27340Sstevel@tonic-gate	blt,a,pn %xcc, ptl1_panic
27350Sstevel@tonic-gate	  mov	PTL1_BAD_MMUTRAP, %g1
27360Sstevel@tonic-gate	set	etrap_table, %g6
27370Sstevel@tonic-gate	cmp	%g7, %g6
27380Sstevel@tonic-gate	bge,a,pn %xcc, ptl1_panic
27390Sstevel@tonic-gate	  mov	PTL1_BAD_MMUTRAP, %g1
27400Sstevel@tonic-gate	cmp	%g5, T_ALIGNMENT
27410Sstevel@tonic-gate	move	%icc, MMU_SFAR, %g6
27420Sstevel@tonic-gate	movne	%icc, MMU_TAG_ACCESS, %g6
27430Sstevel@tonic-gate	ldxa	[%g6]ASI_DMMU, %g6
27440Sstevel@tonic-gate	andn	%g7, WTRAP_ALIGN, %g7	/* 128 byte aligned */
27450Sstevel@tonic-gate	add	%g7, WTRAP_FAULTOFF, %g7
27460Sstevel@tonic-gate	wrpr	%g0, %g7, %tnpc
27470Sstevel@tonic-gate	done
27480Sstevel@tonic-gate	SET_SIZE(mmu_trap_tl1)
27490Sstevel@tonic-gate
27500Sstevel@tonic-gate/*
27510Sstevel@tonic-gate * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers.  These
27520Sstevel@tonic-gate * traps are valid only when kmdb is loaded.  When the debugger is active,
27530Sstevel@tonic-gate * the code below is rewritten to transfer control to the appropriate
27540Sstevel@tonic-gate * debugger entry points.
27550Sstevel@tonic-gate */
27560Sstevel@tonic-gate	.global	kmdb_trap
27570Sstevel@tonic-gate	.align	8
27580Sstevel@tonic-gatekmdb_trap:
27590Sstevel@tonic-gate	ba,a	trap_table0
27600Sstevel@tonic-gate	jmp	%g1 + 0
27610Sstevel@tonic-gate	nop
27620Sstevel@tonic-gate
27630Sstevel@tonic-gate	.global	kmdb_trap_tl1
27640Sstevel@tonic-gate	.align	8
27650Sstevel@tonic-gatekmdb_trap_tl1:
27660Sstevel@tonic-gate	ba,a	trap_table0
27670Sstevel@tonic-gate	jmp	%g1 + 0
27680Sstevel@tonic-gate	nop
27690Sstevel@tonic-gate
27700Sstevel@tonic-gate/*
27710Sstevel@tonic-gate * This entry is copied from OBP's trap table during boot.
27720Sstevel@tonic-gate */
27730Sstevel@tonic-gate	.global	obp_bpt
27740Sstevel@tonic-gate	.align	8
27750Sstevel@tonic-gateobp_bpt:
27760Sstevel@tonic-gate	NOT
27770Sstevel@tonic-gate
27780Sstevel@tonic-gate/*
27790Sstevel@tonic-gate * if kernel, set PCONTEXT to 0 for debuggers
27800Sstevel@tonic-gate * if user, clear nucleus page sizes
27810Sstevel@tonic-gate */
27820Sstevel@tonic-gate	.global kctx_obp_bpt
27830Sstevel@tonic-gatekctx_obp_bpt:
27840Sstevel@tonic-gate	set	obp_bpt, %g2
27850Sstevel@tonic-gate1:
27865584Sjimand#ifndef _OPL
27870Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g1
27880Sstevel@tonic-gate	ldxa	[%g1]ASI_DMMU, %g1
27890Sstevel@tonic-gate	srlx	%g1, CTXREG_NEXT_SHIFT, %g3
27900Sstevel@tonic-gate	brz,pt	%g3, 3f			! nucleus pgsz is 0, no problem
27910Sstevel@tonic-gate	  sllx	%g3, CTXREG_NEXT_SHIFT, %g3
27920Sstevel@tonic-gate	set	CTXREG_CTX_MASK, %g4	! check Pcontext
27930Sstevel@tonic-gate	btst	%g4, %g1
27940Sstevel@tonic-gate	bz,a,pt	%xcc, 2f
27950Sstevel@tonic-gate	  clr	%g3			! kernel:  PCONTEXT=0
27960Sstevel@tonic-gate	xor	%g3, %g1, %g3		! user:	clr N_pgsz0/1 bits
27970Sstevel@tonic-gate2:
27980Sstevel@tonic-gate	set	DEMAP_ALL_TYPE, %g1
27990Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_DTLB_DEMAP
28000Sstevel@tonic-gate	stxa	%g0, [%g1]ASI_ITLB_DEMAP
28010Sstevel@tonic-gate	mov	MMU_PCONTEXT, %g1
28020Sstevel@tonic-gate	stxa	%g3, [%g1]ASI_DMMU
28030Sstevel@tonic-gate        membar  #Sync
28040Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g1
28050Sstevel@tonic-gate	flush	%g1			! flush required by immu
28065584Sjimand#endif /* _OPL */
28070Sstevel@tonic-gate3:
28080Sstevel@tonic-gate	jmp	%g2
28090Sstevel@tonic-gate	  nop
28100Sstevel@tonic-gate
28110Sstevel@tonic-gate
28120Sstevel@tonic-gate#ifdef	TRAPTRACE
28130Sstevel@tonic-gate/*
28140Sstevel@tonic-gate * TRAPTRACE support.
28150Sstevel@tonic-gate * labels here are branched to with "rd %pc, %g7" in the delay slot.
28160Sstevel@tonic-gate * Return is done by "jmp %g7 + 4".
28170Sstevel@tonic-gate */
28180Sstevel@tonic-gate
28190Sstevel@tonic-gatetrace_gen:
28200Sstevel@tonic-gate	TRACE_PTR(%g3, %g6)
2821*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g4)
28220Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
28230Sstevel@tonic-gate	rdpr	%tl, %g6
28240Sstevel@tonic-gate	stha	%g6, [%g3 + TRAP_ENT_TL]%asi
28250Sstevel@tonic-gate	rdpr	%tt, %g6
28260Sstevel@tonic-gate	stha	%g6, [%g3 + TRAP_ENT_TT]%asi
28270Sstevel@tonic-gate	rdpr	%tstate, %g6
28280Sstevel@tonic-gate	stxa	%g6, [%g3 + TRAP_ENT_TSTATE]%asi
28290Sstevel@tonic-gate	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
28300Sstevel@tonic-gate	rdpr	%tpc, %g6
28310Sstevel@tonic-gate	stna	%g6, [%g3 + TRAP_ENT_TPC]%asi
28320Sstevel@tonic-gate	TRACE_NEXT(%g3, %g4, %g5)
28330Sstevel@tonic-gate	jmp	%g7 + 4
28340Sstevel@tonic-gate	nop
28350Sstevel@tonic-gate
28360Sstevel@tonic-gatetrace_win:
28370Sstevel@tonic-gate	TRACE_WIN_INFO(0, %l0, %l1, %l2)
28380Sstevel@tonic-gate	! Keep the locals as clean as possible, caller cleans %l4
28390Sstevel@tonic-gate	clr	%l2
28400Sstevel@tonic-gate	clr	%l1
28410Sstevel@tonic-gate	jmp	%l4 + 4
28420Sstevel@tonic-gate	  clr	%l0
28430Sstevel@tonic-gate
28440Sstevel@tonic-gate/*
28450Sstevel@tonic-gate * Trace a tsb hit
28460Sstevel@tonic-gate * g1 = tsbe pointer (in/clobbered)
28470Sstevel@tonic-gate * g2 = tag access register (in)
28480Sstevel@tonic-gate * g3 - g4 = scratch (clobbered)
28490Sstevel@tonic-gate * g5 = tsbe data (in)
28500Sstevel@tonic-gate * g6 = scratch (clobbered)
28510Sstevel@tonic-gate * g7 = pc we jumped here from (in)
28520Sstevel@tonic-gate */
28530Sstevel@tonic-gate
28540Sstevel@tonic-gate	! Do not disturb %g5, it will be used after the trace
28550Sstevel@tonic-gate	ALTENTRY(trace_tsbhit)
28560Sstevel@tonic-gate	TRACE_TSBHIT(0)
28570Sstevel@tonic-gate	jmp	%g7 + 4
28580Sstevel@tonic-gate	nop
28590Sstevel@tonic-gate
28600Sstevel@tonic-gate/*
28610Sstevel@tonic-gate * Trace a TSB miss
28620Sstevel@tonic-gate *
28630Sstevel@tonic-gate * g1 = tsb8k pointer (in)
28640Sstevel@tonic-gate * g2 = tag access register (in)
28650Sstevel@tonic-gate * g3 = tsb4m pointer (in)
28660Sstevel@tonic-gate * g4 = tsbe tag (in/clobbered)
28670Sstevel@tonic-gate * g5 - g6 = scratch (clobbered)
28680Sstevel@tonic-gate * g7 = pc we jumped here from (in)
28690Sstevel@tonic-gate */
28700Sstevel@tonic-gate	.global	trace_tsbmiss
28710Sstevel@tonic-gatetrace_tsbmiss:
28720Sstevel@tonic-gate	membar	#Sync
28730Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g6
28740Sstevel@tonic-gate	flush	%g6
28750Sstevel@tonic-gate	TRACE_PTR(%g5, %g6)
28760Sstevel@tonic-gate	stxa	%g2, [%g5 + TRAP_ENT_SP]%asi		! tag access
28770Sstevel@tonic-gate	stxa	%g4, [%g5 + TRAP_ENT_F1]%asi		! tsb tag
2878*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g4)
2879*11172SHaik.Aftandilian@Sun.COM	stxa	%g6, [%g5 + TRAP_ENT_TICK]%asi
28800Sstevel@tonic-gate	rdpr	%tnpc, %g6
28810Sstevel@tonic-gate	stxa	%g6, [%g5 + TRAP_ENT_F2]%asi
28820Sstevel@tonic-gate	stna	%g1, [%g5 + TRAP_ENT_F3]%asi		! tsb8k pointer
28830Sstevel@tonic-gate	srlx	%g1, 32, %g6
28840Sstevel@tonic-gate	stna	%g6, [%g5 + TRAP_ENT_F4]%asi		! huh?
28850Sstevel@tonic-gate	rdpr	%tpc, %g6
28860Sstevel@tonic-gate	stna	%g6, [%g5 + TRAP_ENT_TPC]%asi
28870Sstevel@tonic-gate	rdpr	%tl, %g6
28880Sstevel@tonic-gate	stha	%g6, [%g5 + TRAP_ENT_TL]%asi
28890Sstevel@tonic-gate	rdpr	%tt, %g6
28900Sstevel@tonic-gate	or	%g6, TT_MMU_MISS, %g4
28910Sstevel@tonic-gate	stha	%g4, [%g5 + TRAP_ENT_TT]%asi
28920Sstevel@tonic-gate	cmp	%g6, FAST_IMMU_MISS_TT
28930Sstevel@tonic-gate	be,a	%icc, 1f
28940Sstevel@tonic-gate	  ldxa	[%g0]ASI_IMMU, %g6
28950Sstevel@tonic-gate	ldxa	[%g0]ASI_DMMU, %g6
28960Sstevel@tonic-gate1:	stxa	%g6, [%g5 + TRAP_ENT_TSTATE]%asi	! tag target
28970Sstevel@tonic-gate	stxa	%g3, [%g5 + TRAP_ENT_TR]%asi		! tsb4m pointer
28980Sstevel@tonic-gate	TRACE_NEXT(%g5, %g4, %g6)
28990Sstevel@tonic-gate	jmp	%g7 + 4
29000Sstevel@tonic-gate	nop
29010Sstevel@tonic-gate
29020Sstevel@tonic-gate/*
29030Sstevel@tonic-gate * g2 = tag access register (in)
29040Sstevel@tonic-gate * g3 = ctx number (in)
29050Sstevel@tonic-gate */
29060Sstevel@tonic-gatetrace_dataprot:
29070Sstevel@tonic-gate	membar	#Sync
29080Sstevel@tonic-gate	sethi	%hi(FLUSH_ADDR), %g6
29090Sstevel@tonic-gate	flush	%g6
29100Sstevel@tonic-gate	TRACE_PTR(%g1, %g6)
2911*11172SHaik.Aftandilian@Sun.COM	GET_TRACE_TICK(%g6, %g5)
29120Sstevel@tonic-gate	stxa	%g6, [%g1 + TRAP_ENT_TICK]%asi
29130Sstevel@tonic-gate	rdpr	%tpc, %g6
29140Sstevel@tonic-gate	stna	%g6, [%g1 + TRAP_ENT_TPC]%asi
29150Sstevel@tonic-gate	rdpr	%tstate, %g6
29160Sstevel@tonic-gate	stxa	%g6, [%g1 + TRAP_ENT_TSTATE]%asi
29170Sstevel@tonic-gate	stxa	%g2, [%g1 + TRAP_ENT_SP]%asi		! tag access reg
29180Sstevel@tonic-gate	stxa	%g0, [%g1 + TRAP_ENT_TR]%asi
29190Sstevel@tonic-gate	stxa	%g0, [%g1 + TRAP_ENT_F1]%asi
29200Sstevel@tonic-gate	stxa	%g0, [%g1 + TRAP_ENT_F2]%asi
29210Sstevel@tonic-gate	stxa	%g0, [%g1 + TRAP_ENT_F3]%asi
29220Sstevel@tonic-gate	stxa	%g0, [%g1 + TRAP_ENT_F4]%asi
29230Sstevel@tonic-gate	rdpr	%tl, %g6
29240Sstevel@tonic-gate	stha	%g6, [%g1 + TRAP_ENT_TL]%asi
29250Sstevel@tonic-gate	rdpr	%tt, %g6
29260Sstevel@tonic-gate	stha	%g6, [%g1 + TRAP_ENT_TT]%asi
29270Sstevel@tonic-gate	TRACE_NEXT(%g1, %g4, %g5)
29280Sstevel@tonic-gate	jmp	%g7 + 4
29290Sstevel@tonic-gate	nop
29300Sstevel@tonic-gate
29310Sstevel@tonic-gate#endif /* TRAPTRACE */
29320Sstevel@tonic-gate
29338803SJonathan.Haslam@Sun.COM       .align  32
29348803SJonathan.Haslam@Sun.COM       .global pil15_epilogue
29358803SJonathan.Haslam@Sun.COMpil15_epilogue:
29368803SJonathan.Haslam@Sun.COM       ba      pil_interrupt_common
29378803SJonathan.Haslam@Sun.COM       nop
29388803SJonathan.Haslam@Sun.COM       .align  32
29398803SJonathan.Haslam@Sun.COM
29400Sstevel@tonic-gate/*
29410Sstevel@tonic-gate * fast_trap_done, fast_trap_done_chk_intr:
29420Sstevel@tonic-gate *
29430Sstevel@tonic-gate * Due to the design of UltraSPARC pipeline, pending interrupts are not
29440Sstevel@tonic-gate * taken immediately after a RETRY or DONE instruction which causes IE to
29450Sstevel@tonic-gate * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed
29460Sstevel@tonic-gate * to execute first before taking any interrupts. If that instruction
29470Sstevel@tonic-gate * results in other traps, and if the corresponding trap handler runs
29480Sstevel@tonic-gate * entirely at TL=1 with interrupts disabled, then pending interrupts
29490Sstevel@tonic-gate * won't be taken until after yet another instruction following the %tpc
29500Sstevel@tonic-gate * or %tnpc.
29510Sstevel@tonic-gate *
29520Sstevel@tonic-gate * A malicious user program can use this feature to block out interrupts
29530Sstevel@tonic-gate * for extended durations, which can result in send_mondo_timeout kernel
29540Sstevel@tonic-gate * panic.
29550Sstevel@tonic-gate *
29560Sstevel@tonic-gate * This problem is addressed by servicing any pending interrupts via
29570Sstevel@tonic-gate * sys_trap before returning back to the user mode from a fast trap
29580Sstevel@tonic-gate * handler. The "done" instruction within a fast trap handler, which
29590Sstevel@tonic-gate * runs entirely at TL=1 with interrupts disabled, is replaced with the
29600Sstevel@tonic-gate * FAST_TRAP_DONE macro, which branches control to this fast_trap_done
29610Sstevel@tonic-gate * entry point.
29620Sstevel@tonic-gate *
29630Sstevel@tonic-gate * We check for any pending interrupts here and force a sys_trap to
29640Sstevel@tonic-gate * service those interrupts, if any. To minimize overhead, pending
29650Sstevel@tonic-gate * interrupts are checked if the %tpc happens to be at 16K boundary,
29660Sstevel@tonic-gate * which allows a malicious program to execute at most 4K consecutive
29670Sstevel@tonic-gate * instructions before we service any pending interrupts. If a worst
29680Sstevel@tonic-gate * case fast trap handler takes about 2 usec, then interrupts will be
29690Sstevel@tonic-gate * blocked for at most 8 msec, less than a clock tick.
29700Sstevel@tonic-gate *
29710Sstevel@tonic-gate * For the cases where we don't know if the %tpc will cross a 16K
29720Sstevel@tonic-gate * boundary, we can't use the above optimization and always process
29730Sstevel@tonic-gate * any pending interrupts via fast_frap_done_chk_intr entry point.
29740Sstevel@tonic-gate *
29750Sstevel@tonic-gate * Entry Conditions:
29760Sstevel@tonic-gate * 	%pstate		am:0 priv:1 ie:0
29770Sstevel@tonic-gate * 			globals are AG (not normal globals)
29780Sstevel@tonic-gate */
29790Sstevel@tonic-gate
29800Sstevel@tonic-gate	.global	fast_trap_done, fast_trap_done_chk_intr
29810Sstevel@tonic-gatefast_trap_done:
29820Sstevel@tonic-gate	rdpr	%tpc, %g5
29830Sstevel@tonic-gate	sethi	%hi(0xffffc000), %g6	! 1's complement of 0x3fff
29840Sstevel@tonic-gate	andncc	%g5, %g6, %g0		! check lower 14 bits of %tpc
29850Sstevel@tonic-gate	bz,a,pn	%icc, 1f		! branch if zero (lower 32 bits only)
29860Sstevel@tonic-gate	  ldxa	[%g0]ASI_INTR_RECEIVE_STATUS, %g5
29870Sstevel@tonic-gate	done
29880Sstevel@tonic-gate
29892712Snn35248	ALTENTRY(fast_trap_done_check_interrupts)
29900Sstevel@tonic-gatefast_trap_done_chk_intr:
29910Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_RECEIVE_STATUS, %g5
29920Sstevel@tonic-gate
29930Sstevel@tonic-gate1:	rd	SOFTINT, %g6
29940Sstevel@tonic-gate	and	%g5, IRSR_BUSY, %g5
29950Sstevel@tonic-gate	orcc	%g5, %g6, %g0
29960Sstevel@tonic-gate	bnz,pn	%xcc, 2f		! branch if any pending intr
29970Sstevel@tonic-gate	nop
29980Sstevel@tonic-gate	done
29990Sstevel@tonic-gate
30000Sstevel@tonic-gate2:
30010Sstevel@tonic-gate	/*
30020Sstevel@tonic-gate	 * We get here if there are any pending interrupts.
30030Sstevel@tonic-gate	 * Adjust %tpc/%tnpc as we'll be resuming via "retry"
30040Sstevel@tonic-gate	 * instruction.
30050Sstevel@tonic-gate	 */
30060Sstevel@tonic-gate	rdpr	%tnpc, %g5
30070Sstevel@tonic-gate	wrpr	%g0, %g5, %tpc
30080Sstevel@tonic-gate	add	%g5, 4, %g5
30090Sstevel@tonic-gate	wrpr	%g0, %g5, %tnpc
30100Sstevel@tonic-gate
30110Sstevel@tonic-gate	/*
30120Sstevel@tonic-gate	 * Force a dummy sys_trap call so that interrupts can be serviced.
30130Sstevel@tonic-gate	 */
30140Sstevel@tonic-gate	set	fast_trap_dummy_call, %g1
30150Sstevel@tonic-gate	ba,pt	%xcc, sys_trap
30160Sstevel@tonic-gate	  mov	-1, %g4
30170Sstevel@tonic-gate
30180Sstevel@tonic-gatefast_trap_dummy_call:
30190Sstevel@tonic-gate	retl
30200Sstevel@tonic-gate	nop
30210Sstevel@tonic-gate
30222712Snn35248/*
30234141Sedp * Currently the brand syscall interposition code is not enabled by
30244141Sedp * default.  Instead, when a branded zone is first booted the brand
30254141Sedp * infrastructure will patch the trap table so that the syscall
30264141Sedp * entry points are redirected to syscall_wrapper32 and syscall_wrapper
30274141Sedp * for ILP32 and LP64 syscalls respectively.  this is done in
30284141Sedp * brand_plat_interposition_enable().  Note that the syscall wrappers
30294141Sedp * below do not collect any trap trace data since the syscall hot patch
30304141Sedp * points are reached after trap trace data has already been collected.
30312712Snn35248 */
30322712Snn35248#define	BRAND_CALLBACK(callback_id)					    \
30334127Sedp	CPU_ADDR(%g2, %g1)		/* load CPU struct addr to %g2	*/ ;\
30344127Sedp	ldn	[%g2 + CPU_THREAD], %g3	/* load thread pointer		*/ ;\
30354127Sedp	ldn	[%g3 + T_PROCP], %g3	/* get proc pointer		*/ ;\
30364127Sedp	ldn	[%g3 + P_BRAND], %g3	/* get brand pointer		*/ ;\
30374127Sedp	brz	%g3, 1f			/* No brand?  No callback. 	*/ ;\
30382712Snn35248	nop 								   ;\
30394127Sedp	ldn	[%g3 + B_MACHOPS], %g3	/* get machops list		*/ ;\
30404127Sedp	ldn	[%g3 + (callback_id << 3)], %g3 			   ;\
30414127Sedp	brz	%g3, 1f							   ;\
30422712Snn35248	/*								    \
30432712Snn35248	 * This isn't pretty.  We want a low-latency way for the callback   \
30442712Snn35248	 * routine to decline to do anything.  We just pass in an address   \
30452712Snn35248	 * the routine can directly jmp back to, pretending that nothing    \
30462712Snn35248	 * has happened.						    \
30474127Sedp	 * 								    \
30484127Sedp	 * %g1: return address (where the brand handler jumps back to)	    \
30494127Sedp	 * %g2: address of CPU structure				    \
30504127Sedp	 * %g3: address of brand handler (where we will jump to)	    \
30512712Snn35248	 */								    \
30522712Snn35248	mov	%pc, %g1						   ;\
30532712Snn35248	add	%g1, 16, %g1						   ;\
30544127Sedp	jmp	%g3							   ;\
30552712Snn35248	nop								   ;\
30562712Snn352481:
30572712Snn35248
30582712Snn35248	ENTRY_NP(syscall_wrapper32)
30592712Snn35248	BRAND_CALLBACK(BRAND_CB_SYSCALL32)
30604127Sedp	SYSCALL_NOTT(syscall_trap32)
30612712Snn35248	SET_SIZE(syscall_wrapper32)
30622712Snn35248
30632712Snn35248	ENTRY_NP(syscall_wrapper)
30642712Snn35248	BRAND_CALLBACK(BRAND_CB_SYSCALL)
30654127Sedp	SYSCALL_NOTT(syscall_trap)
30662712Snn35248	SET_SIZE(syscall_wrapper)
30672712Snn35248
30680Sstevel@tonic-gate#endif	/* lint */
3069