xref: /titanic_44/usr/src/uts/sun4v/ml/trap_table.s (revision c651b32e568cbf9b715a127805fe1cba321be5b0)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#if !defined(lint)
28#include "assym.h"
29#endif /* !lint */
30#include <sys/asm_linkage.h>
31#include <sys/privregs.h>
32#include <sys/sun4asi.h>
33#include <sys/machasi.h>
34#include <sys/hypervisor_api.h>
35#include <sys/machtrap.h>
36#include <sys/machthread.h>
37#include <sys/machbrand.h>
38#include <sys/pcb.h>
39#include <sys/pte.h>
40#include <sys/mmu.h>
41#include <sys/machpcb.h>
42#include <sys/async.h>
43#include <sys/intreg.h>
44#include <sys/scb.h>
45#include <sys/psr_compat.h>
46#include <sys/syscall.h>
47#include <sys/machparam.h>
48#include <sys/traptrace.h>
49#include <vm/hat_sfmmu.h>
50#include <sys/archsystm.h>
51#include <sys/utrap.h>
52#include <sys/clock.h>
53#include <sys/intr.h>
54#include <sys/fpu/fpu_simulator.h>
55#include <vm/seg_spt.h>
56
57/*
58 * WARNING: If you add a fast trap handler which can be invoked by a
59 * non-privileged user, you may have to use the FAST_TRAP_DONE macro
60 * instead of "done" instruction to return back to the user mode. See
61 * comments for the "fast_trap_done" entry point for more information.
62 *
63 * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the
64 * cases where you always want to process any pending interrupts before
65 * returning back to the user mode.
66 */
67#define	FAST_TRAP_DONE		\
68	ba,a	fast_trap_done
69
70#define	FAST_TRAP_DONE_CHK_INTR	\
71	ba,a	fast_trap_done_chk_intr
72
73/*
74 * SPARC V9 Trap Table
75 *
76 * Most of the trap handlers are made from common building
77 * blocks, and some are instantiated multiple times within
78 * the trap table. So, I build a bunch of macros, then
79 * populate the table using only the macros.
80 *
81 * Many macros branch to sys_trap.  Its calling convention is:
82 *	%g1		kernel trap handler
83 *	%g2, %g3	args for above
84 *	%g4		desire %pil
85 */
86
87#ifdef	TRAPTRACE
88
89/*
90 * Tracing macro. Adds two instructions if TRAPTRACE is defined.
91 */
92#define	TT_TRACE(label)		\
93	ba	label		;\
94	rd	%pc, %g7
95#define	TT_TRACE_INS	2
96
97#define	TT_TRACE_L(label)	\
98	ba	label		;\
99	rd	%pc, %l4	;\
100	clr	%l4
101#define	TT_TRACE_L_INS	3
102
103#else
104
105#define	TT_TRACE(label)
106#define	TT_TRACE_INS	0
107
108#define	TT_TRACE_L(label)
109#define	TT_TRACE_L_INS	0
110
111#endif
112
113/*
114 * This first set are funneled to trap() with %tt as the type.
115 * Trap will then either panic or send the user a signal.
116 */
117/*
118 * NOT is used for traps that just shouldn't happen.
119 * It comes in both single and quadruple flavors.
120 */
121#if !defined(lint)
122	.global	trap
123#endif /* !lint */
124#define	NOT			\
125	TT_TRACE(trace_gen)	;\
126	set	trap, %g1	;\
127	rdpr	%tt, %g3	;\
128	ba,pt	%xcc, sys_trap	;\
129	sub	%g0, 1, %g4	;\
130	.align	32
131#define	NOT4	NOT; NOT; NOT; NOT
132
133#define	NOTP				\
134	TT_TRACE(trace_gen)		;\
135	ba,pt	%xcc, ptl1_panic	;\
136	  mov	PTL1_BAD_TRAP, %g1	;\
137	.align	32
138#define	NOTP4	NOTP; NOTP; NOTP; NOTP
139
140
141/*
142 * BAD is used for trap vectors we don't have a kernel
143 * handler for.
144 * It also comes in single and quadruple versions.
145 */
146#define	BAD	NOT
147#define	BAD4	NOT4
148
149#define	DONE			\
150	done;			\
151	.align	32
152
153/*
154 * TRAP vectors to the trap() function.
155 * It's main use is for user errors.
156 */
157#if !defined(lint)
158	.global	trap
159#endif /* !lint */
160#define	TRAP(arg)		\
161	TT_TRACE(trace_gen)	;\
162	set	trap, %g1	;\
163	mov	arg, %g3	;\
164	ba,pt	%xcc, sys_trap	;\
165	sub	%g0, 1, %g4	;\
166	.align	32
167
168/*
169 * SYSCALL is used for unsupported syscall interfaces (with 'which'
170 * set to 'nosys') and legacy support of old SunOS 4.x syscalls (with
171 * 'which' set to 'syscall_trap32').
172 *
173 * The SYSCALL_TRAP* macros are used for syscall entry points.
174 * SYSCALL_TRAP is used to support LP64 syscalls and SYSCALL_TRAP32
175 * is used to support ILP32.  Each macro can only be used once
176 * since they each define a symbol.  The symbols are used as hot patch
177 * points by the brand infrastructure to dynamically enable and disable
178 * brand syscall interposition.  See the comments around BRAND_CALLBACK
179 * and brand_plat_interposition_enable() for more information.
180 */
181#define	SYSCALL_NOTT(which)		\
182	set	(which), %g1		;\
183	ba,pt	%xcc, user_trap		;\
184	sub	%g0, 1, %g4		;\
185	.align	32
186
187#define	SYSCALL(which)			\
188	TT_TRACE(trace_gen)		;\
189	SYSCALL_NOTT(which)
190
191#define	SYSCALL_TRAP32				\
192	TT_TRACE(trace_gen)			;\
193	ALTENTRY(syscall_trap32_patch_point)	\
194	SYSCALL_NOTT(syscall_trap32)
195
196#define	SYSCALL_TRAP				\
197	TT_TRACE(trace_gen)			;\
198	ALTENTRY(syscall_trap_patch_point)	\
199	SYSCALL_NOTT(syscall_trap)
200
201/*
202 * GOTO just jumps to a label.
203 * It's used for things that can be fixed without going thru sys_trap.
204 */
205#define	GOTO(label)		\
206	.global	label		;\
207	ba,a	label		;\
208	.empty			;\
209	.align	32
210
211/*
212 * GOTO_TT just jumps to a label.
213 * correctable ECC error traps at  level 0 and 1 will use this macro.
214 * It's used for things that can be fixed without going thru sys_trap.
215 */
216#define	GOTO_TT(label, ttlabel)		\
217	.global	label		;\
218	TT_TRACE(ttlabel)	;\
219	ba,a	label		;\
220	.empty			;\
221	.align	32
222
223/*
224 * Privileged traps
225 * Takes breakpoint if privileged, calls trap() if not.
226 */
227#define	PRIV(label)			\
228	rdpr	%tstate, %g1		;\
229	btst	TSTATE_PRIV, %g1	;\
230	bnz	label			;\
231	rdpr	%tt, %g3		;\
232	set	trap, %g1		;\
233	ba,pt	%xcc, sys_trap		;\
234	sub	%g0, 1, %g4		;\
235	.align	32
236
237
238/*
239 * DTrace traps.
240 */
241#define	DTRACE_PID			\
242	.global dtrace_pid_probe				;\
243	set	dtrace_pid_probe, %g1				;\
244	ba,pt	%xcc, user_trap					;\
245	sub	%g0, 1, %g4					;\
246	.align	32
247
248#define	DTRACE_RETURN			\
249	.global dtrace_return_probe				;\
250	set	dtrace_return_probe, %g1			;\
251	ba,pt	%xcc, user_trap					;\
252	sub	%g0, 1, %g4					;\
253	.align	32
254
255/*
256 * REGISTER WINDOW MANAGEMENT MACROS
257 */
258
259/*
260 * various convenient units of padding
261 */
262#define	SKIP(n)	.skip 4*(n)
263
264/*
265 * CLEAN_WINDOW is the simple handler for cleaning a register window.
266 */
267#define	CLEAN_WINDOW						\
268	TT_TRACE_L(trace_win)					;\
269	rdpr %cleanwin, %l0; inc %l0; wrpr %l0, %cleanwin	;\
270	clr %l0; clr %l1; clr %l2; clr %l3			;\
271	clr %l4; clr %l5; clr %l6; clr %l7			;\
272	clr %o0; clr %o1; clr %o2; clr %o3			;\
273	clr %o4; clr %o5; clr %o6; clr %o7			;\
274	retry; .align 128
275
276#if !defined(lint)
277
278/*
279 * If we get an unresolved tlb miss while in a window handler, the fault
280 * handler will resume execution at the last instruction of the window
281 * hander, instead of delivering the fault to the kernel.  Spill handlers
282 * use this to spill windows into the wbuf.
283 *
284 * The mixed handler works by checking %sp, and branching to the correct
285 * handler.  This is done by branching back to label 1: for 32b frames,
286 * or label 2: for 64b frames; which implies the handler order is: 32b,
287 * 64b, mixed.  The 1: and 2: labels are offset into the routines to
288 * allow the branchs' delay slots to contain useful instructions.
289 */
290
291/*
292 * SPILL_32bit spills a 32-bit-wide kernel register window.  It
293 * assumes that the kernel context and the nucleus context are the
294 * same.  The stack pointer is required to be eight-byte aligned even
295 * though this code only needs it to be four-byte aligned.
296 */
297#define	SPILL_32bit(tail)					\
298	srl	%sp, 0, %sp					;\
2991:	st	%l0, [%sp + 0]					;\
300	st	%l1, [%sp + 4]					;\
301	st	%l2, [%sp + 8]					;\
302	st	%l3, [%sp + 12]					;\
303	st	%l4, [%sp + 16]					;\
304	st	%l5, [%sp + 20]					;\
305	st	%l6, [%sp + 24]					;\
306	st	%l7, [%sp + 28]					;\
307	st	%i0, [%sp + 32]					;\
308	st	%i1, [%sp + 36]					;\
309	st	%i2, [%sp + 40]					;\
310	st	%i3, [%sp + 44]					;\
311	st	%i4, [%sp + 48]					;\
312	st	%i5, [%sp + 52]					;\
313	st	%i6, [%sp + 56]					;\
314	st	%i7, [%sp + 60]					;\
315	TT_TRACE_L(trace_win)					;\
316	saved							;\
317	retry							;\
318	SKIP(31-19-TT_TRACE_L_INS)				;\
319	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
320	.empty
321
322/*
323 * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit
324 * wide address space via the designated asi.  It is used to spill
325 * non-kernel windows.  The stack pointer is required to be eight-byte
326 * aligned even though this code only needs it to be four-byte
327 * aligned.
328 */
329#define	SPILL_32bit_asi(asi_num, tail)				\
330	srl	%sp, 0, %sp					;\
3311:	sta	%l0, [%sp + %g0]asi_num				;\
332	mov	4, %g1						;\
333	sta	%l1, [%sp + %g1]asi_num				;\
334	mov	8, %g2						;\
335	sta	%l2, [%sp + %g2]asi_num				;\
336	mov	12, %g3						;\
337	sta	%l3, [%sp + %g3]asi_num				;\
338	add	%sp, 16, %g4					;\
339	sta	%l4, [%g4 + %g0]asi_num				;\
340	sta	%l5, [%g4 + %g1]asi_num				;\
341	sta	%l6, [%g4 + %g2]asi_num				;\
342	sta	%l7, [%g4 + %g3]asi_num				;\
343	add	%g4, 16, %g4					;\
344	sta	%i0, [%g4 + %g0]asi_num				;\
345	sta	%i1, [%g4 + %g1]asi_num				;\
346	sta	%i2, [%g4 + %g2]asi_num				;\
347	sta	%i3, [%g4 + %g3]asi_num				;\
348	add	%g4, 16, %g4					;\
349	sta	%i4, [%g4 + %g0]asi_num				;\
350	sta	%i5, [%g4 + %g1]asi_num				;\
351	sta	%i6, [%g4 + %g2]asi_num				;\
352	sta	%i7, [%g4 + %g3]asi_num				;\
353	TT_TRACE_L(trace_win)					;\
354	saved							;\
355	retry							;\
356	SKIP(31-25-TT_TRACE_L_INS)				;\
357	ba,a,pt %xcc, fault_32bit_/**/tail			;\
358	.empty
359
360#define	SPILL_32bit_tt1(asi_num, tail)				\
361	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
362	.empty							;\
363	.align 128
364
365
366/*
367 * FILL_32bit fills a 32-bit-wide kernel register window.  It assumes
368 * that the kernel context and the nucleus context are the same.  The
369 * stack pointer is required to be eight-byte aligned even though this
370 * code only needs it to be four-byte aligned.
371 */
372#define	FILL_32bit(tail)					\
373	srl	%sp, 0, %sp					;\
3741:	TT_TRACE_L(trace_win)					;\
375	ld	[%sp + 0], %l0					;\
376	ld	[%sp + 4], %l1					;\
377	ld	[%sp + 8], %l2					;\
378	ld	[%sp + 12], %l3					;\
379	ld	[%sp + 16], %l4					;\
380	ld	[%sp + 20], %l5					;\
381	ld	[%sp + 24], %l6					;\
382	ld	[%sp + 28], %l7					;\
383	ld	[%sp + 32], %i0					;\
384	ld	[%sp + 36], %i1					;\
385	ld	[%sp + 40], %i2					;\
386	ld	[%sp + 44], %i3					;\
387	ld	[%sp + 48], %i4					;\
388	ld	[%sp + 52], %i5					;\
389	ld	[%sp + 56], %i6					;\
390	ld	[%sp + 60], %i7					;\
391	restored						;\
392	retry							;\
393	SKIP(31-19-TT_TRACE_L_INS)				;\
394	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
395	.empty
396
397/*
398 * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit
399 * wide address space via the designated asi.  It is used to fill
400 * non-kernel windows.  The stack pointer is required to be eight-byte
401 * aligned even though this code only needs it to be four-byte
402 * aligned.
403 */
404#define	FILL_32bit_asi(asi_num, tail)				\
405	srl	%sp, 0, %sp					;\
4061:	TT_TRACE_L(trace_win)					;\
407	mov	4, %g1						;\
408	lda	[%sp + %g0]asi_num, %l0				;\
409	mov	8, %g2						;\
410	lda	[%sp + %g1]asi_num, %l1				;\
411	mov	12, %g3						;\
412	lda	[%sp + %g2]asi_num, %l2				;\
413	lda	[%sp + %g3]asi_num, %l3				;\
414	add	%sp, 16, %g4					;\
415	lda	[%g4 + %g0]asi_num, %l4				;\
416	lda	[%g4 + %g1]asi_num, %l5				;\
417	lda	[%g4 + %g2]asi_num, %l6				;\
418	lda	[%g4 + %g3]asi_num, %l7				;\
419	add	%g4, 16, %g4					;\
420	lda	[%g4 + %g0]asi_num, %i0				;\
421	lda	[%g4 + %g1]asi_num, %i1				;\
422	lda	[%g4 + %g2]asi_num, %i2				;\
423	lda	[%g4 + %g3]asi_num, %i3				;\
424	add	%g4, 16, %g4					;\
425	lda	[%g4 + %g0]asi_num, %i4				;\
426	lda	[%g4 + %g1]asi_num, %i5				;\
427	lda	[%g4 + %g2]asi_num, %i6				;\
428	lda	[%g4 + %g3]asi_num, %i7				;\
429	restored						;\
430	retry							;\
431	SKIP(31-25-TT_TRACE_L_INS)				;\
432	ba,a,pt %xcc, fault_32bit_/**/tail			;\
433	.empty
434
435
436/*
437 * SPILL_64bit spills a 64-bit-wide kernel register window.  It
438 * assumes that the kernel context and the nucleus context are the
439 * same.  The stack pointer is required to be eight-byte aligned.
440 */
441#define	SPILL_64bit(tail)					\
4422:	stx	%l0, [%sp + V9BIAS64 + 0]			;\
443	stx	%l1, [%sp + V9BIAS64 + 8]			;\
444	stx	%l2, [%sp + V9BIAS64 + 16]			;\
445	stx	%l3, [%sp + V9BIAS64 + 24]			;\
446	stx	%l4, [%sp + V9BIAS64 + 32]			;\
447	stx	%l5, [%sp + V9BIAS64 + 40]			;\
448	stx	%l6, [%sp + V9BIAS64 + 48]			;\
449	stx	%l7, [%sp + V9BIAS64 + 56]			;\
450	stx	%i0, [%sp + V9BIAS64 + 64]			;\
451	stx	%i1, [%sp + V9BIAS64 + 72]			;\
452	stx	%i2, [%sp + V9BIAS64 + 80]			;\
453	stx	%i3, [%sp + V9BIAS64 + 88]			;\
454	stx	%i4, [%sp + V9BIAS64 + 96]			;\
455	stx	%i5, [%sp + V9BIAS64 + 104]			;\
456	stx	%i6, [%sp + V9BIAS64 + 112]			;\
457	stx	%i7, [%sp + V9BIAS64 + 120]			;\
458	TT_TRACE_L(trace_win)					;\
459	saved							;\
460	retry							;\
461	SKIP(31-18-TT_TRACE_L_INS)				;\
462	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
463	.empty
464
465#define	SPILL_64bit_ktt1(tail)				\
466	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
467	.empty							;\
468	.align 128
469
470#define	SPILL_mixed_ktt1(tail)				\
471	btst	1, %sp						;\
472	bz,a,pt	%xcc, fault_32bit_/**/tail			;\
473	srl	%sp, 0, %sp					;\
474	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
475	.empty							;\
476	.align 128
477
478/*
479 * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit
480 * wide address space via the designated asi.  It is used to spill
481 * non-kernel windows.  The stack pointer is required to be eight-byte
482 * aligned.
483 */
484#define	SPILL_64bit_asi(asi_num, tail)				\
485	mov	0 + V9BIAS64, %g1				;\
4862:	stxa	%l0, [%sp + %g1]asi_num				;\
487	mov	8 + V9BIAS64, %g2				;\
488	stxa	%l1, [%sp + %g2]asi_num				;\
489	mov	16 + V9BIAS64, %g3				;\
490	stxa	%l2, [%sp + %g3]asi_num				;\
491	mov	24 + V9BIAS64, %g4				;\
492	stxa	%l3, [%sp + %g4]asi_num				;\
493	add	%sp, 32, %g5					;\
494	stxa	%l4, [%g5 + %g1]asi_num				;\
495	stxa	%l5, [%g5 + %g2]asi_num				;\
496	stxa	%l6, [%g5 + %g3]asi_num				;\
497	stxa	%l7, [%g5 + %g4]asi_num				;\
498	add	%g5, 32, %g5					;\
499	stxa	%i0, [%g5 + %g1]asi_num				;\
500	stxa	%i1, [%g5 + %g2]asi_num				;\
501	stxa	%i2, [%g5 + %g3]asi_num				;\
502	stxa	%i3, [%g5 + %g4]asi_num				;\
503	add	%g5, 32, %g5					;\
504	stxa	%i4, [%g5 + %g1]asi_num				;\
505	stxa	%i5, [%g5 + %g2]asi_num				;\
506	stxa	%i6, [%g5 + %g3]asi_num				;\
507	stxa	%i7, [%g5 + %g4]asi_num				;\
508	TT_TRACE_L(trace_win)					;\
509	saved							;\
510	retry							;\
511	SKIP(31-25-TT_TRACE_L_INS)				;\
512	ba,a,pt %xcc, fault_64bit_/**/tail			;\
513	.empty
514
515#define	SPILL_64bit_tt1(asi_num, tail)				\
516	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
517	.empty							;\
518	.align 128
519
520/*
521 * FILL_64bit fills a 64-bit-wide kernel register window.  It assumes
522 * that the kernel context and the nucleus context are the same.  The
523 * stack pointer is required to be eight-byte aligned.
524 */
525#define	FILL_64bit(tail)					\
5262:	TT_TRACE_L(trace_win)					;\
527	ldx	[%sp + V9BIAS64 + 0], %l0			;\
528	ldx	[%sp + V9BIAS64 + 8], %l1			;\
529	ldx	[%sp + V9BIAS64 + 16], %l2			;\
530	ldx	[%sp + V9BIAS64 + 24], %l3			;\
531	ldx	[%sp + V9BIAS64 + 32], %l4			;\
532	ldx	[%sp + V9BIAS64 + 40], %l5			;\
533	ldx	[%sp + V9BIAS64 + 48], %l6			;\
534	ldx	[%sp + V9BIAS64 + 56], %l7			;\
535	ldx	[%sp + V9BIAS64 + 64], %i0			;\
536	ldx	[%sp + V9BIAS64 + 72], %i1			;\
537	ldx	[%sp + V9BIAS64 + 80], %i2			;\
538	ldx	[%sp + V9BIAS64 + 88], %i3			;\
539	ldx	[%sp + V9BIAS64 + 96], %i4			;\
540	ldx	[%sp + V9BIAS64 + 104], %i5			;\
541	ldx	[%sp + V9BIAS64 + 112], %i6			;\
542	ldx	[%sp + V9BIAS64 + 120], %i7			;\
543	restored						;\
544	retry							;\
545	SKIP(31-18-TT_TRACE_L_INS)				;\
546	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
547	.empty
548
549/*
550 * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit
551 * wide address space via the designated asi.  It is used to fill
552 * non-kernel windows.  The stack pointer is required to be eight-byte
553 * aligned.
554 */
555#define	FILL_64bit_asi(asi_num, tail)				\
556	mov	V9BIAS64 + 0, %g1				;\
5572:	TT_TRACE_L(trace_win)					;\
558	ldxa	[%sp + %g1]asi_num, %l0				;\
559	mov	V9BIAS64 + 8, %g2				;\
560	ldxa	[%sp + %g2]asi_num, %l1				;\
561	mov	V9BIAS64 + 16, %g3				;\
562	ldxa	[%sp + %g3]asi_num, %l2				;\
563	mov	V9BIAS64 + 24, %g4				;\
564	ldxa	[%sp + %g4]asi_num, %l3				;\
565	add	%sp, 32, %g5					;\
566	ldxa	[%g5 + %g1]asi_num, %l4				;\
567	ldxa	[%g5 + %g2]asi_num, %l5				;\
568	ldxa	[%g5 + %g3]asi_num, %l6				;\
569	ldxa	[%g5 + %g4]asi_num, %l7				;\
570	add	%g5, 32, %g5					;\
571	ldxa	[%g5 + %g1]asi_num, %i0				;\
572	ldxa	[%g5 + %g2]asi_num, %i1				;\
573	ldxa	[%g5 + %g3]asi_num, %i2				;\
574	ldxa	[%g5 + %g4]asi_num, %i3				;\
575	add	%g5, 32, %g5					;\
576	ldxa	[%g5 + %g1]asi_num, %i4				;\
577	ldxa	[%g5 + %g2]asi_num, %i5				;\
578	ldxa	[%g5 + %g3]asi_num, %i6				;\
579	ldxa	[%g5 + %g4]asi_num, %i7				;\
580	restored						;\
581	retry							;\
582	SKIP(31-25-TT_TRACE_L_INS)				;\
583	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
584	.empty
585
586
587#endif /* !lint */
588
589/*
590 * SPILL_mixed spills either size window, depending on
591 * whether %sp is even or odd, to a 32-bit address space.
592 * This may only be used in conjunction with SPILL_32bit/
593 * FILL_64bit.
594 * Clear upper 32 bits of %sp if it is odd.
595 * We won't need to clear them in 64 bit kernel.
596 */
597#define	SPILL_mixed						\
598	btst	1, %sp						;\
599	bz,a,pt	%xcc, 1b					;\
600	srl	%sp, 0, %sp					;\
601	ba,pt	%xcc, 2b					;\
602	nop							;\
603	.align	128
604
605/*
606 * FILL_mixed(ASI) fills either size window, depending on
607 * whether %sp is even or odd, from a 32-bit address space.
608 * This may only be used in conjunction with FILL_32bit/
609 * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be
610 * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular
611 * attention should be paid to the instructions that belong
612 * in the delay slots of the branches depending on the type
613 * of fill handler being branched to.
614 * Clear upper 32 bits of %sp if it is odd.
615 * We won't need to clear them in 64 bit kernel.
616 */
617#define	FILL_mixed						\
618	btst	1, %sp						;\
619	bz,a,pt	%xcc, 1b					;\
620	srl	%sp, 0, %sp					;\
621	ba,pt	%xcc, 2b					;\
622	nop							;\
623	.align	128
624
625
626/*
627 * SPILL_32clean/SPILL_64clean spill 32-bit and 64-bit register windows,
628 * respectively, into the address space via the designated asi.  The
629 * unbiased stack pointer is required to be eight-byte aligned (even for
630 * the 32-bit case even though this code does not require such strict
631 * alignment).
632 *
633 * With SPARC v9 the spill trap takes precedence over the cleanwin trap
634 * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save
635 * will cause cwp + 2 to be spilled but will not clean cwp + 1.  That
636 * window may contain kernel data so in user_rtt we set wstate to call
637 * these spill handlers on the first user spill trap.  These handler then
638 * spill the appropriate window but also back up a window and clean the
639 * window that didn't get a cleanwin trap.
640 */
641#define	SPILL_32clean(asi_num, tail)				\
642	srl	%sp, 0, %sp					;\
643	sta	%l0, [%sp + %g0]asi_num				;\
644	mov	4, %g1						;\
645	sta	%l1, [%sp + %g1]asi_num				;\
646	mov	8, %g2						;\
647	sta	%l2, [%sp + %g2]asi_num				;\
648	mov	12, %g3						;\
649	sta	%l3, [%sp + %g3]asi_num				;\
650	add	%sp, 16, %g4					;\
651	sta	%l4, [%g4 + %g0]asi_num				;\
652	sta	%l5, [%g4 + %g1]asi_num				;\
653	sta	%l6, [%g4 + %g2]asi_num				;\
654	sta	%l7, [%g4 + %g3]asi_num				;\
655	add	%g4, 16, %g4					;\
656	sta	%i0, [%g4 + %g0]asi_num				;\
657	sta	%i1, [%g4 + %g1]asi_num				;\
658	sta	%i2, [%g4 + %g2]asi_num				;\
659	sta	%i3, [%g4 + %g3]asi_num				;\
660	add	%g4, 16, %g4					;\
661	sta	%i4, [%g4 + %g0]asi_num				;\
662	sta	%i5, [%g4 + %g1]asi_num				;\
663	sta	%i6, [%g4 + %g2]asi_num				;\
664	sta	%i7, [%g4 + %g3]asi_num				;\
665	TT_TRACE_L(trace_win)					;\
666	b	.spill_clean					;\
667	  mov	WSTATE_USER32, %g7				;\
668	SKIP(31-25-TT_TRACE_L_INS)				;\
669	ba,a,pt	%xcc, fault_32bit_/**/tail			;\
670	.empty
671
672#define	SPILL_64clean(asi_num, tail)				\
673	mov	0 + V9BIAS64, %g1				;\
674	stxa	%l0, [%sp + %g1]asi_num				;\
675	mov	8 + V9BIAS64, %g2				;\
676	stxa	%l1, [%sp + %g2]asi_num				;\
677	mov	16 + V9BIAS64, %g3				;\
678	stxa	%l2, [%sp + %g3]asi_num				;\
679	mov	24 + V9BIAS64, %g4				;\
680	stxa	%l3, [%sp + %g4]asi_num				;\
681	add	%sp, 32, %g5					;\
682	stxa	%l4, [%g5 + %g1]asi_num				;\
683	stxa	%l5, [%g5 + %g2]asi_num				;\
684	stxa	%l6, [%g5 + %g3]asi_num				;\
685	stxa	%l7, [%g5 + %g4]asi_num				;\
686	add	%g5, 32, %g5					;\
687	stxa	%i0, [%g5 + %g1]asi_num				;\
688	stxa	%i1, [%g5 + %g2]asi_num				;\
689	stxa	%i2, [%g5 + %g3]asi_num				;\
690	stxa	%i3, [%g5 + %g4]asi_num				;\
691	add	%g5, 32, %g5					;\
692	stxa	%i4, [%g5 + %g1]asi_num				;\
693	stxa	%i5, [%g5 + %g2]asi_num				;\
694	stxa	%i6, [%g5 + %g3]asi_num				;\
695	stxa	%i7, [%g5 + %g4]asi_num				;\
696	TT_TRACE_L(trace_win)					;\
697	b	.spill_clean					;\
698	  mov	WSTATE_USER64, %g7				;\
699	SKIP(31-25-TT_TRACE_L_INS)				;\
700	ba,a,pt	%xcc, fault_64bit_/**/tail			;\
701	.empty
702
703
704/*
705 * Floating point disabled.
706 */
707#define	FP_DISABLED_TRAP		\
708	TT_TRACE(trace_gen)		;\
709	ba,pt	%xcc,.fp_disabled	;\
710	nop				;\
711	.align	32
712
713/*
714 * Floating point exceptions.
715 */
716#define	FP_IEEE_TRAP			\
717	TT_TRACE(trace_gen)		;\
718	ba,pt	%xcc,.fp_ieee_exception	;\
719	nop				;\
720	.align	32
721
722#define	FP_TRAP				\
723	TT_TRACE(trace_gen)		;\
724	ba,pt	%xcc,.fp_exception	;\
725	nop				;\
726	.align	32
727
728#if !defined(lint)
729
730/*
731 * ECACHE_ECC error traps at level 0 and level 1
732 */
733#define	ECACHE_ECC(table_name)		\
734	.global	table_name		;\
735table_name:				;\
736	membar	#Sync			;\
737	set	trap, %g1		;\
738	rdpr	%tt, %g3		;\
739	ba,pt	%xcc, sys_trap		;\
740	sub	%g0, 1, %g4		;\
741	.align	32
742
743#endif /* !lint */
744
745/*
746 * illegal instruction trap
747 */
748#define	ILLTRAP_INSTR			  \
749	membar	#Sync			  ;\
750	TT_TRACE(trace_gen)		  ;\
751	or	%g0, P_UTRAP4, %g2	  ;\
752	or	%g0, T_UNIMP_INSTR, %g3   ;\
753	sethi	%hi(.check_v9utrap), %g4  ;\
754	jmp	%g4 + %lo(.check_v9utrap) ;\
755	nop				  ;\
756	.align	32
757
758/*
759 * tag overflow trap
760 */
761#define	TAG_OVERFLOW			  \
762	TT_TRACE(trace_gen)		  ;\
763	or	%g0, P_UTRAP10, %g2	  ;\
764	or	%g0, T_TAG_OVERFLOW, %g3  ;\
765	sethi	%hi(.check_v9utrap), %g4  ;\
766	jmp	%g4 + %lo(.check_v9utrap) ;\
767	nop				  ;\
768	.align	32
769
770/*
771 * divide by zero trap
772 */
773#define	DIV_BY_ZERO			  \
774	TT_TRACE(trace_gen)		  ;\
775	or	%g0, P_UTRAP11, %g2	  ;\
776	or	%g0, T_IDIV0, %g3	  ;\
777	sethi	%hi(.check_v9utrap), %g4  ;\
778	jmp	%g4 + %lo(.check_v9utrap) ;\
779	nop				  ;\
780	.align	32
781
782/*
783 * trap instruction for V9 user trap handlers
784 */
785#define	TRAP_INSTR			  \
786	TT_TRACE(trace_gen)		  ;\
787	or	%g0, T_SOFTWARE_TRAP, %g3 ;\
788	sethi	%hi(.check_v9utrap), %g4  ;\
789	jmp	%g4 + %lo(.check_v9utrap) ;\
790	nop				  ;\
791	.align	32
792#define	TRP4	TRAP_INSTR; TRAP_INSTR; TRAP_INSTR; TRAP_INSTR
793
794/*
795 * LEVEL_INTERRUPT is for level N interrupts.
796 * VECTOR_INTERRUPT is for the vector trap.
797 */
798#define	LEVEL_INTERRUPT(level)		\
799	.global	tt_pil/**/level		;\
800tt_pil/**/level:			;\
801	ba,pt	%xcc, pil_interrupt	;\
802	mov	level, %g4		;\
803	.align	32
804
805#define	LEVEL14_INTERRUPT			\
806	ba	pil14_interrupt			;\
807	mov	PIL_14, %g4			;\
808	.align	32
809
810#define CPU_MONDO			\
811	ba,a,pt	%xcc, cpu_mondo		;\
812	.align	32
813
814#define DEV_MONDO			\
815	ba,a,pt	%xcc, dev_mondo		;\
816	.align	32
817
818/*
819 * We take over the rtba after we set our trap table and
820 * fault status area. The watchdog reset trap is now handled by the OS.
821 */
822#define WATCHDOG_RESET			\
823	mov	PTL1_BAD_WATCHDOG, %g1	;\
824	ba,a,pt	%xcc, .watchdog_trap	;\
825	.align	32
826
827/*
828 * RED is for traps that use the red mode handler.
829 * We should never see these either.
830 */
831#define RED			\
832	mov	PTL1_BAD_RED, %g1	;\
833	ba,a,pt	%xcc, .watchdog_trap	;\
834	.align	32
835
836
837/*
838 * MMU Trap Handlers.
839 */
840
841/*
842 * synthesize for trap(): SFSR in %g3
843 */
844#define IMMU_EXCEPTION							\
845	ba,a,pt	%xcc, .immu_exception					;\
846	.align	32
847
848/*
849 * synthesize for trap(): TAG_ACCESS in %g2, SFSR in %g3
850 */
851#define	DMMU_EXCEPTION							\
852	ba,a,pt	%xcc, .dmmu_exception					;\
853	.align	32
854
855/*
856 * synthesize for trap(): SFAR in %g2, SFSR in %g3
857 */
858#define	DMMU_EXC_AG_PRIV						\
859	MMU_FAULT_STATUS_AREA(%g3)					;\
860	ldx	[%g3 + MMFSA_D_ADDR], %g2				;\
861	/* Fault type not available in MMU fault status area */		;\
862	mov	MMFSA_F_PRVACT, %g1					;\
863	ldx	[%g3 + MMFSA_D_CTX], %g3				;\
864	sllx	%g3, SFSR_CTX_SHIFT, %g3				;\
865	ba,pt	%xcc, .mmu_priv_exception				;\
866	or	%g3, %g1, %g3						;\
867	.align	32
868
869/*
870 * synthesize for trap(): SFAR in %g2, SFSR in %g3
871 */
872#define	DMMU_EXC_AG_NOT_ALIGNED						\
873	MMU_FAULT_STATUS_AREA(%g3)					;\
874	ldx	[%g3 + MMFSA_D_ADDR], %g2				;\
875	/* Fault type not available in MMU fault status area */		;\
876	mov	MMFSA_F_UNALIGN, %g1					;\
877	ldx	[%g3 + MMFSA_D_CTX], %g3				;\
878	sllx	%g3, SFSR_CTX_SHIFT, %g3				;\
879	ba,pt	%xcc, .mmu_exception_not_aligned			;\
880	or	%g3, %g1, %g3			/* SFSR */		;\
881	.align	32
882/*
883 * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2)
884 */
885
886/*
887 * synthesize for trap(): SFAR in %g2, SFSR in %g3
888 */
889#define	DMMU_EXC_LDDF_NOT_ALIGNED					\
890	ba,a,pt	%xcc, .dmmu_exc_lddf_not_aligned			;\
891	.align	32
892/*
893 * synthesize for trap(): SFAR in %g2, SFSR in %g3
894 */
895#define	DMMU_EXC_STDF_NOT_ALIGNED					\
896	ba,a,pt	%xcc, .dmmu_exc_stdf_not_aligned			;\
897	.align	32
898
899#if defined(cscope)
900/*
901 * Define labels to direct cscope quickly to labels that
902 * are generated by macro expansion of DTLB_MISS().
903 */
904	.global	tt0_dtlbmiss
905tt0_dtlbmiss:
906	.global	tt1_dtlbmiss
907tt1_dtlbmiss:
908	nop
909#endif
910
911/*
912 * Data miss handler (must be exactly 32 instructions)
913 *
914 * This handler is invoked only if the hypervisor has been instructed
915 * not to do any TSB walk.
916 *
917 * Kernel and invalid context cases are handled by the sfmmu_kdtlb_miss
918 * handler.
919 *
920 * User TLB miss handling depends upon whether a user process has one or
921 * two TSBs. User TSB information (physical base and size code) is kept
922 * in two dedicated scratchpad registers. Absence of a user TSB (primarily
923 * second TSB) is indicated by a negative value (-1) in that register.
924 */
925
926/*
927 * synthesize for miss handler: pseudo-tag access in %g2 (with context "type"
928 * (0=kernel, 1=invalid, or 2=user) rather than context ID)
929 */
930#define	DTLB_MISS(table_name)						;\
931	.global	table_name/**/_dtlbmiss					;\
932table_name/**/_dtlbmiss:						;\
933	GET_MMU_D_PTAGACC_CTXTYPE(%g2, %g3)	/* 8 instr */		;\
934	cmp	%g3, INVALID_CONTEXT					;\
935	ble,pn	%xcc, sfmmu_kdtlb_miss					;\
936	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
937	mov	SCRATCHPAD_UTSBREG2, %g1				;\
938	ldxa	[%g1]ASI_SCRATCHPAD, %g1	/* get 2nd tsbreg */	;\
939	brgez,pn %g1, sfmmu_udtlb_slowpath	/* branch if 2 TSBs */	;\
940	  nop								;\
941	GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5)	/* 11 instr */		;\
942	ba,pt	%xcc, sfmmu_udtlb_fastpath	/* no 4M TSB, miss */	;\
943	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
944	.align 128
945
946
947#if defined(cscope)
948/*
949 * Define labels to direct cscope quickly to labels that
950 * are generated by macro expansion of ITLB_MISS().
951 */
952	.global	tt0_itlbmiss
953tt0_itlbmiss:
954	.global	tt1_itlbmiss
955tt1_itlbmiss:
956	nop
957#endif
958
959/*
960 * Instruction miss handler.
961 *
962 * This handler is invoked only if the hypervisor has been instructed
963 * not to do any TSB walk.
964 *
965 * ldda instructions will have their ASI patched
966 * by sfmmu_patch_ktsb at runtime.
967 * MUST be EXACTLY 32 instructions or we'll break.
968 */
969
970/*
971 * synthesize for miss handler: TAG_ACCESS in %g2 (with context "type"
972 * (0=kernel, 1=invalid, or 2=user) rather than context ID)
973 */
974#define	ITLB_MISS(table_name)						 \
975	.global	table_name/**/_itlbmiss					;\
976table_name/**/_itlbmiss:						;\
977	GET_MMU_I_PTAGACC_CTXTYPE(%g2, %g3)	/* 8 instr */		;\
978	cmp	%g3, INVALID_CONTEXT					;\
979	ble,pn	%xcc, sfmmu_kitlb_miss					;\
980	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
981	mov	SCRATCHPAD_UTSBREG2, %g1				;\
982	ldxa	[%g1]ASI_SCRATCHPAD, %g1	/* get 2nd tsbreg */	;\
983	brgez,pn %g1, sfmmu_uitlb_slowpath	/* branch if 2 TSBs */	;\
984	  nop								;\
985	GET_1ST_TSBE_PTR(%g2, %g1, %g4, %g5)	/* 11 instr */		;\
986	ba,pt	%xcc, sfmmu_uitlb_fastpath	/* no 4M TSB, miss */	;\
987	  srlx	%g2, TAG_VALO_SHIFT, %g7	/* g7 = tsb tag */	;\
988	.align 128
989
990#define	DTSB_MISS \
991	GOTO_TT(sfmmu_slow_dmmu_miss,trace_dmmu)
992
993#define	ITSB_MISS \
994	GOTO_TT(sfmmu_slow_immu_miss,trace_immu)
995
996/*
997 * This macro is the first level handler for fast protection faults.
998 * It first demaps the tlb entry which generated the fault and then
999 * attempts to set the modify bit on the hash.  It needs to be
1000 * exactly 32 instructions.
1001 */
1002/*
1003 * synthesize for miss handler: TAG_ACCESS in %g2 (with context "type"
1004 * (0=kernel, 1=invalid, or 2=user) rather than context ID)
1005 */
1006#define	DTLB_PROT							 \
1007	GET_MMU_D_PTAGACC_CTXTYPE(%g2, %g3)	/* 8 instr */		;\
1008	/*								;\
1009	 *   g2 = pseudo-tag access register (ctx type rather than ctx ID) ;\
1010	 *   g3 = ctx type (0, 1, or 2)					;\
1011	 */								;\
1012	TT_TRACE(trace_dataprot)	/* 2 instr ifdef TRAPTRACE */	;\
1013					/* clobbers g1 and g6 XXXQ? */	;\
1014	brnz,pt %g3, sfmmu_uprot_trap		/* user trap */		;\
1015	  nop								;\
1016	ba,a,pt	%xcc, sfmmu_kprot_trap		/* kernel trap */	;\
1017	.align 128
1018
1019#define	DMMU_EXCEPTION_TL1						;\
1020	ba,a,pt	%xcc, mmu_trap_tl1					;\
1021	.align 32
1022
1023#define	MISALIGN_ADDR_TL1						;\
1024	ba,a,pt	%xcc, mmu_trap_tl1					;\
1025	.align 32
1026
1027/*
1028 * Trace a tsb hit
1029 * g1 = tsbe pointer (in/clobbered)
1030 * g2 = tag access register (in)
1031 * g3 - g4 = scratch (clobbered)
1032 * g5 = tsbe data (in)
1033 * g6 = scratch (clobbered)
1034 * g7 = pc we jumped here from (in)
1035 * ttextra = value to OR in to trap type (%tt) (in)
1036 */
1037#ifdef TRAPTRACE
1038#define TRACE_TSBHIT(ttextra)						 \
1039	membar	#Sync							;\
1040	sethi	%hi(FLUSH_ADDR), %g6					;\
1041	flush	%g6							;\
1042	TRACE_PTR(%g3, %g6)						;\
1043	GET_TRACE_TICK(%g6)						;\
1044	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi				;\
1045	stna	%g2, [%g3 + TRAP_ENT_SP]%asi	/* tag access */	;\
1046	stna	%g5, [%g3 + TRAP_ENT_F1]%asi	/* tsb data */		;\
1047	rdpr	%tnpc, %g6						;\
1048	stna	%g6, [%g3 + TRAP_ENT_F2]%asi				;\
1049	stna	%g1, [%g3 + TRAP_ENT_F3]%asi	/* tsb pointer */	;\
1050	stna	%g0, [%g3 + TRAP_ENT_F4]%asi				;\
1051	rdpr	%tpc, %g6						;\
1052	stna	%g6, [%g3 + TRAP_ENT_TPC]%asi				;\
1053	TRACE_SAVE_TL_GL_REGS(%g3, %g6)					;\
1054	rdpr	%tt, %g6						;\
1055	or	%g6, (ttextra), %g1					;\
1056	stha	%g1, [%g3 + TRAP_ENT_TT]%asi				;\
1057	MMU_FAULT_STATUS_AREA(%g4)					;\
1058	mov	MMFSA_D_ADDR, %g1					;\
1059	cmp	%g6, FAST_IMMU_MISS_TT					;\
1060	move	%xcc, MMFSA_I_ADDR, %g1					;\
1061	cmp	%g6, T_INSTR_MMU_MISS					;\
1062	move	%xcc, MMFSA_I_ADDR, %g1					;\
1063	ldx	[%g4 + %g1], %g1					;\
1064	stxa	%g1, [%g3 + TRAP_ENT_TSTATE]%asi /* fault addr */	;\
1065	mov	MMFSA_D_CTX, %g1					;\
1066	cmp	%g6, FAST_IMMU_MISS_TT					;\
1067	move	%xcc, MMFSA_I_CTX, %g1					;\
1068	cmp	%g6, T_INSTR_MMU_MISS					;\
1069	move	%xcc, MMFSA_I_CTX, %g1					;\
1070	ldx	[%g4 + %g1], %g1					;\
1071	stna	%g1, [%g3 + TRAP_ENT_TR]%asi				;\
1072	TRACE_NEXT(%g3, %g4, %g6)
1073#else
1074#define TRACE_TSBHIT(ttextra)
1075#endif
1076
1077
1078#if defined(lint)
1079
1080struct scb	trap_table;
1081struct scb	scb;		/* trap_table/scb are the same object */
1082
1083#else /* lint */
1084
1085/*
1086 * =======================================================================
1087 *		SPARC V9 TRAP TABLE
1088 *
1089 * The trap table is divided into two halves: the first half is used when
1090 * taking traps when TL=0; the second half is used when taking traps from
1091 * TL>0. Note that handlers in the second half of the table might not be able
1092 * to make the same assumptions as handlers in the first half of the table.
1093 *
1094 * Worst case trap nesting so far:
1095 *
1096 *	at TL=0 client issues software trap requesting service
1097 *	at TL=1 nucleus wants a register window
1098 *	at TL=2 register window clean/spill/fill takes a TLB miss
1099 *	at TL=3 processing TLB miss
1100 *	at TL=4 handle asynchronous error
1101 *
1102 * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode".
1103 *
1104 * =======================================================================
1105 */
1106	.section ".text"
1107	.align	4
1108	.global trap_table, scb, trap_table0, trap_table1, etrap_table
1109	.type	trap_table, #object
1110	.type	trap_table0, #object
1111	.type	trap_table1, #object
1112	.type	scb, #object
1113trap_table:
1114scb:
1115trap_table0:
1116	/* hardware traps */
1117	NOT;				/* 000	reserved */
1118	RED;				/* 001	power on reset */
1119	WATCHDOG_RESET;			/* 002	watchdog reset */
1120	RED;				/* 003	externally initiated reset */
1121	RED;				/* 004	software initiated reset */
1122	RED;				/* 005	red mode exception */
1123	NOT; NOT;			/* 006 - 007 reserved */
1124	IMMU_EXCEPTION;			/* 008	instruction access exception */
1125	ITSB_MISS;			/* 009	instruction access MMU miss */
1126 	NOT;				/* 00A  reserved */
1127	NOT; NOT4;			/* 00B - 00F reserved */
1128	ILLTRAP_INSTR;			/* 010	illegal instruction */
1129	TRAP(T_PRIV_INSTR);		/* 011	privileged opcode */
1130	TRAP(T_UNIMP_LDD);		/* 012	unimplemented LDD */
1131	TRAP(T_UNIMP_STD);		/* 013	unimplemented STD */
1132	NOT4; NOT4; NOT4;		/* 014 - 01F reserved */
1133	FP_DISABLED_TRAP;		/* 020	fp disabled */
1134	FP_IEEE_TRAP;			/* 021	fp exception ieee 754 */
1135	FP_TRAP;			/* 022	fp exception other */
1136	TAG_OVERFLOW;			/* 023	tag overflow */
1137	CLEAN_WINDOW;			/* 024 - 027 clean window */
1138	DIV_BY_ZERO;			/* 028	division by zero */
1139	NOT;				/* 029	internal processor error */
1140	NOT; NOT; NOT4;			/* 02A - 02F reserved */
1141	DMMU_EXCEPTION;			/* 030	data access exception */
1142	DTSB_MISS;			/* 031	data access MMU miss */
1143	NOT;				/* 032  reserved */
1144	NOT;				/* 033	data access protection */
1145	DMMU_EXC_AG_NOT_ALIGNED;	/* 034	mem address not aligned */
1146	DMMU_EXC_LDDF_NOT_ALIGNED;	/* 035	LDDF mem address not aligned */
1147	DMMU_EXC_STDF_NOT_ALIGNED;	/* 036	STDF mem address not aligned */
1148	DMMU_EXC_AG_PRIV;		/* 037	privileged action */
1149	NOT;				/* 038	LDQF mem address not aligned */
1150	NOT;				/* 039	STQF mem address not aligned */
1151	NOT; NOT; NOT4;			/* 03A - 03F reserved */
1152	NOT;				/* 040	async data error */
1153	LEVEL_INTERRUPT(1);		/* 041	interrupt level 1 */
1154	LEVEL_INTERRUPT(2);		/* 042	interrupt level 2 */
1155	LEVEL_INTERRUPT(3);		/* 043	interrupt level 3 */
1156	LEVEL_INTERRUPT(4);		/* 044	interrupt level 4 */
1157	LEVEL_INTERRUPT(5);		/* 045	interrupt level 5 */
1158	LEVEL_INTERRUPT(6);		/* 046	interrupt level 6 */
1159	LEVEL_INTERRUPT(7);		/* 047	interrupt level 7 */
1160	LEVEL_INTERRUPT(8);		/* 048	interrupt level 8 */
1161	LEVEL_INTERRUPT(9);		/* 049	interrupt level 9 */
1162	LEVEL_INTERRUPT(10);		/* 04A	interrupt level 10 */
1163	LEVEL_INTERRUPT(11);		/* 04B	interrupt level 11 */
1164	LEVEL_INTERRUPT(12);		/* 04C	interrupt level 12 */
1165	LEVEL_INTERRUPT(13);		/* 04D	interrupt level 13 */
1166	LEVEL14_INTERRUPT;		/* 04E	interrupt level 14 */
1167	LEVEL_INTERRUPT(15);		/* 04F	interrupt level 15 */
1168	NOT4; NOT4; NOT4; NOT4;		/* 050 - 05F reserved */
1169	NOT;				/* 060	interrupt vector */
1170	GOTO(kmdb_trap);		/* 061	PA watchpoint */
1171	GOTO(kmdb_trap);		/* 062	VA watchpoint */
1172	NOT;				/* 063	reserved */
1173	ITLB_MISS(tt0);			/* 064	instruction access MMU miss */
1174	DTLB_MISS(tt0);			/* 068	data access MMU miss */
1175	DTLB_PROT;			/* 06C	data access protection */
1176	NOT;				/* 070  reserved */
1177	NOT;				/* 071  reserved */
1178	NOT;				/* 072  reserved */
1179	NOT;				/* 073  reserved */
1180	NOT4; NOT4			/* 074 - 07B reserved */
1181	CPU_MONDO;			/* 07C	cpu_mondo */
1182	DEV_MONDO;			/* 07D	dev_mondo */
1183	GOTO_TT(resumable_error, trace_gen);	/* 07E  resumable error */
1184	GOTO_TT(nonresumable_error, trace_gen);	/* 07F  non-reasumable error */
1185	NOT4;				/* 080	spill 0 normal */
1186	SPILL_32bit_asi(ASI_AIUP,sn0);	/* 084	spill 1 normal */
1187	SPILL_64bit_asi(ASI_AIUP,sn0);	/* 088	spill 2 normal */
1188	SPILL_32clean(ASI_AIUP,sn0);	/* 08C	spill 3 normal */
1189	SPILL_64clean(ASI_AIUP,sn0);	/* 090	spill 4 normal */
1190	SPILL_32bit(not);		/* 094	spill 5 normal */
1191	SPILL_64bit(not);		/* 098	spill 6 normal */
1192	SPILL_mixed;			/* 09C	spill 7 normal */
1193	NOT4;				/* 0A0	spill 0 other */
1194	SPILL_32bit_asi(ASI_AIUS,so0);	/* 0A4	spill 1 other */
1195	SPILL_64bit_asi(ASI_AIUS,so0);	/* 0A8	spill 2 other */
1196	SPILL_32bit_asi(ASI_AIUS,so0);	/* 0AC	spill 3 other */
1197	SPILL_64bit_asi(ASI_AIUS,so0);	/* 0B0	spill 4 other */
1198	NOT4;				/* 0B4	spill 5 other */
1199	NOT4;				/* 0B8	spill 6 other */
1200	NOT4;				/* 0BC	spill 7 other */
1201	NOT4;				/* 0C0	fill 0 normal */
1202	FILL_32bit_asi(ASI_AIUP,fn0);	/* 0C4	fill 1 normal */
1203	FILL_64bit_asi(ASI_AIUP,fn0);	/* 0C8	fill 2 normal */
1204	FILL_32bit_asi(ASI_AIUP,fn0);	/* 0CC	fill 3 normal */
1205	FILL_64bit_asi(ASI_AIUP,fn0);	/* 0D0	fill 4 normal */
1206	FILL_32bit(not);		/* 0D4	fill 5 normal */
1207	FILL_64bit(not);		/* 0D8	fill 6 normal */
1208	FILL_mixed;			/* 0DC	fill 7 normal */
1209	NOT4;				/* 0E0	fill 0 other */
1210	NOT4;				/* 0E4	fill 1 other */
1211	NOT4;				/* 0E8	fill 2 other */
1212	NOT4;				/* 0EC	fill 3 other */
1213	NOT4;				/* 0F0	fill 4 other */
1214	NOT4;				/* 0F4	fill 5 other */
1215	NOT4;				/* 0F8	fill 6 other */
1216	NOT4;				/* 0FC	fill 7 other */
1217	/* user traps */
1218	GOTO(syscall_trap_4x);		/* 100	old system call */
1219	TRAP(T_BREAKPOINT);		/* 101	user breakpoint */
1220	TRAP(T_DIV0);			/* 102	user divide by zero */
1221	GOTO(.flushw);			/* 103	flush windows */
1222	GOTO(.clean_windows);		/* 104	clean windows */
1223	BAD;				/* 105	range check ?? */
1224	GOTO(.fix_alignment);		/* 106	do unaligned references */
1225	BAD;				/* 107	unused */
1226	SYSCALL_TRAP32;			/* 108	ILP32 system call on LP64 */
1227	GOTO(set_trap0_addr);		/* 109	set trap0 address */
1228	BAD; BAD; BAD4;			/* 10A - 10F unused */
1229	TRP4; TRP4; TRP4; TRP4;		/* 110 - 11F V9 user trap handlers */
1230	GOTO(.getcc);			/* 120	get condition codes */
1231	GOTO(.setcc);			/* 121	set condition codes */
1232	GOTO(.getpsr);			/* 122	get psr */
1233	GOTO(.setpsr);			/* 123	set psr (some fields) */
1234	GOTO(get_timestamp);		/* 124	get timestamp */
1235	GOTO(get_virtime);		/* 125	get lwp virtual time */
1236	PRIV(self_xcall);		/* 126	self xcall */
1237	GOTO(get_hrestime);		/* 127	get hrestime */
1238	BAD;				/* 128	ST_SETV9STACK */
1239	GOTO(.getlgrp);			/* 129  get lgrpid */
1240	BAD; BAD; BAD4;			/* 12A - 12F unused */
1241	BAD4; BAD4; 			/* 130 - 137 unused */
1242	DTRACE_PID;			/* 138  dtrace pid tracing provider */
1243	BAD;				/* 139  unused */
1244	DTRACE_RETURN;			/* 13A	dtrace pid return probe */
1245	BAD; BAD4;			/* 13B - 13F unused */
1246	SYSCALL_TRAP;			/* 140  LP64 system call */
1247	SYSCALL(nosys);			/* 141  unused system call trap */
1248#ifdef DEBUG_USER_TRAPTRACECTL
1249	GOTO(.traptrace_freeze);	/* 142  freeze traptrace */
1250	GOTO(.traptrace_unfreeze);	/* 143  unfreeze traptrace */
1251#else
1252	SYSCALL(nosys);			/* 142  unused system call trap */
1253	SYSCALL(nosys);			/* 143  unused system call trap */
1254#endif
1255	BAD4; BAD4; BAD4;		/* 144 - 14F unused */
1256	BAD4; BAD4; BAD4; BAD4;		/* 150 - 15F unused */
1257	BAD4; BAD4; BAD4; BAD4;		/* 160 - 16F unused */
1258	BAD;				/* 170 - unused */
1259	BAD;				/* 171 - unused */
1260	BAD; BAD;			/* 172 - 173 unused */
1261	BAD4; BAD4;			/* 174 - 17B unused */
1262#ifdef	PTL1_PANIC_DEBUG
1263	mov PTL1_BAD_DEBUG, %g1; GOTO(ptl1_panic);
1264					/* 17C	test ptl1_panic */
1265#else
1266	BAD;				/* 17C  unused */
1267#endif	/* PTL1_PANIC_DEBUG */
1268	PRIV(kmdb_trap);		/* 17D	kmdb enter (L1-A) */
1269	PRIV(kmdb_trap);		/* 17E	kmdb breakpoint */
1270	PRIV(obp_bpt);			/* 17F	obp breakpoint */
1271	/* reserved */
1272	NOT4; NOT4; NOT4; NOT4;		/* 180 - 18F reserved */
1273	NOT4; NOT4; NOT4; NOT4;		/* 190 - 19F reserved */
1274	NOT4; NOT4; NOT4; NOT4;		/* 1A0 - 1AF reserved */
1275	NOT4; NOT4; NOT4; NOT4;		/* 1B0 - 1BF reserved */
1276	NOT4; NOT4; NOT4; NOT4;		/* 1C0 - 1CF reserved */
1277	NOT4; NOT4; NOT4; NOT4;		/* 1D0 - 1DF reserved */
1278	NOT4; NOT4; NOT4; NOT4;		/* 1E0 - 1EF reserved */
1279	NOT4; NOT4; NOT4; NOT4;		/* 1F0 - 1FF reserved */
1280	.size	trap_table0, (.-trap_table0)
1281trap_table1:
1282	NOT4; NOT4;			/* 000 - 007 unused */
1283	NOT;				/* 008	instruction access exception */
1284	ITSB_MISS;			/* 009	instruction access MMU miss */
1285 	NOT;				/* 00A  reserved */
1286	NOT; NOT4;			/* 00B - 00F unused */
1287	NOT4; NOT4; NOT4; NOT4;		/* 010 - 01F unused */
1288	NOT4;				/* 020 - 023 unused */
1289	CLEAN_WINDOW;			/* 024 - 027 clean window */
1290	NOT4; NOT4;			/* 028 - 02F unused */
1291	DMMU_EXCEPTION_TL1;		/* 030 	data access exception */
1292	DTSB_MISS;			/* 031  data access MMU miss */
1293	NOT;				/* 032  reserved */
1294	NOT;				/* 033	unused */
1295	MISALIGN_ADDR_TL1;		/* 034	mem address not aligned */
1296	NOT; NOT; NOT; NOT4; NOT4	/* 035 - 03F unused */
1297	NOT4; NOT4; NOT4; NOT4;		/* 040 - 04F unused */
1298	NOT4; NOT4; NOT4; NOT4;		/* 050 - 05F unused */
1299	NOT;				/* 060	unused */
1300	GOTO(kmdb_trap_tl1);		/* 061	PA watchpoint */
1301	GOTO(kmdb_trap_tl1);		/* 062	VA watchpoint */
1302	NOT;				/* 063	reserved */
1303	ITLB_MISS(tt1);			/* 064	instruction access MMU miss */
1304	DTLB_MISS(tt1);			/* 068	data access MMU miss */
1305	DTLB_PROT;			/* 06C	data access protection */
1306	NOT;				/* 070  reserved */
1307	NOT;				/* 071  reserved */
1308	NOT;				/* 072  reserved */
1309	NOT;				/* 073  reserved */
1310	NOT4; NOT4;			/* 074 - 07B reserved */
1311	NOT;				/* 07C  reserved */
1312	NOT;				/* 07D  reserved */
1313	NOT;				/* 07E  resumable error */
1314	GOTO_TT(nonresumable_error, trace_gen);	/* 07F  nonresumable error */
1315	NOTP4;				/* 080	spill 0 normal */
1316	SPILL_32bit_tt1(ASI_AIUP,sn1);	/* 084	spill 1 normal */
1317	SPILL_64bit_tt1(ASI_AIUP,sn1);	/* 088	spill 2 normal */
1318	SPILL_32bit_tt1(ASI_AIUP,sn1);	/* 08C	spill 3 normal */
1319	SPILL_64bit_tt1(ASI_AIUP,sn1);	/* 090	spill 4 normal */
1320	NOTP4;				/* 094	spill 5 normal */
1321	SPILL_64bit_ktt1(sk);		/* 098	spill 6 normal */
1322	SPILL_mixed_ktt1(sk);		/* 09C	spill 7 normal */
1323	NOTP4;				/* 0A0	spill 0 other */
1324	SPILL_32bit_tt1(ASI_AIUS,so1);	/* 0A4  spill 1 other */
1325	SPILL_64bit_tt1(ASI_AIUS,so1);	/* 0A8	spill 2 other */
1326	SPILL_32bit_tt1(ASI_AIUS,so1);	/* 0AC	spill 3 other */
1327	SPILL_64bit_tt1(ASI_AIUS,so1);	/* 0B0  spill 4 other */
1328	NOTP4;				/* 0B4  spill 5 other */
1329	NOTP4;				/* 0B8  spill 6 other */
1330	NOTP4;				/* 0BC  spill 7 other */
1331	NOT4;				/* 0C0	fill 0 normal */
1332	NOT4;				/* 0C4	fill 1 normal */
1333	NOT4;				/* 0C8	fill 2 normal */
1334	NOT4;				/* 0CC	fill 3 normal */
1335	NOT4;				/* 0D0	fill 4 normal */
1336	NOT4;				/* 0D4	fill 5 normal */
1337	NOT4;				/* 0D8	fill 6 normal */
1338	NOT4;				/* 0DC	fill 7 normal */
1339	NOT4; NOT4; NOT4; NOT4;		/* 0E0 - 0EF unused */
1340	NOT4; NOT4; NOT4; NOT4;		/* 0F0 - 0FF unused */
1341/*
1342 * Code running at TL>0 does not use soft traps, so
1343 * we can truncate the table here.
1344 * However:
1345 * sun4v uses (hypervisor) ta instructions at TL > 0, so
1346 * provide a safety net for now.
1347 */
1348	/* soft traps */
1349	BAD4; BAD4; BAD4; BAD4;		/* 100 - 10F unused */
1350	BAD4; BAD4; BAD4; BAD4;		/* 110 - 11F unused */
1351	BAD4; BAD4; BAD4; BAD4;		/* 120 - 12F unused */
1352	BAD4; BAD4; BAD4; BAD4;		/* 130 - 13F unused */
1353	BAD4; BAD4; BAD4; BAD4;		/* 140 - 14F unused */
1354	BAD4; BAD4; BAD4; BAD4;		/* 150 - 15F unused */
1355	BAD4; BAD4; BAD4; BAD4;		/* 160 - 16F unused */
1356	BAD4; BAD4; BAD4; BAD4;		/* 170 - 17F unused */
1357	/* reserved */
1358	NOT4; NOT4; NOT4; NOT4;		/* 180 - 18F reserved */
1359	NOT4; NOT4; NOT4; NOT4;		/* 190 - 19F reserved */
1360	NOT4; NOT4; NOT4; NOT4;		/* 1A0 - 1AF reserved */
1361	NOT4; NOT4; NOT4; NOT4;		/* 1B0 - 1BF reserved */
1362	NOT4; NOT4; NOT4; NOT4;		/* 1C0 - 1CF reserved */
1363	NOT4; NOT4; NOT4; NOT4;		/* 1D0 - 1DF reserved */
1364	NOT4; NOT4; NOT4; NOT4;		/* 1E0 - 1EF reserved */
1365	NOT4; NOT4; NOT4; NOT4;		/* 1F0 - 1FF reserved */
1366etrap_table:
1367	.size	trap_table1, (.-trap_table1)
1368	.size	trap_table, (.-trap_table)
1369	.size	scb, (.-scb)
1370
1371/*
1372 * We get to exec_fault in the case of an instruction miss and tte
1373 * has no execute bit set.  We go to tl0 to handle it.
1374 *
1375 * g1 = tsbe pointer (in/clobbered)
1376 * g2 = tag access register (in)
1377 * g3 - g4 = scratch (clobbered)
1378 * g5 = tsbe data (in)
1379 * g6 = scratch (clobbered)
1380 * g7 = pc we jumped here from (in)
1381 */
1382/*
1383 * synthesize for miss handler: TAG_ACCESS in %g2 (with context "type"
1384 * (0=kernel, 1=invalid, or 2=user) rather than context ID)
1385 */
1386	ALTENTRY(exec_fault)
1387	set	icache_is_coherent, %g6		/* check soft exec mode */
1388	ld	[%g6], %g6
1389	brz,pn	%g6, sfmmu_slow_immu_miss
1390	  nop
1391	TRACE_TSBHIT(TT_MMU_EXEC)
1392	MMU_FAULT_STATUS_AREA(%g4)
1393	ldx	[%g4 + MMFSA_I_ADDR], %g2	/* g2 = address */
1394	ldx	[%g4 + MMFSA_I_CTX], %g3	/* g3 = ctx */
1395	srlx	%g2, MMU_PAGESHIFT, %g2		! align address to page boundry
1396	cmp	%g3, USER_CONTEXT_TYPE
1397	sllx	%g2, MMU_PAGESHIFT, %g2
1398	movgu	%icc, USER_CONTEXT_TYPE, %g3
1399	or	%g2, %g3, %g2			/* TAG_ACCESS */
1400	mov	T_INSTR_MMU_MISS, %g3		! arg2 = traptype
1401	set	trap, %g1
1402	ba,pt	%xcc, sys_trap
1403	  mov	-1, %g4
1404
1405.mmu_exception_not_aligned:
1406	/* %g2 = sfar, %g3 = sfsr */
1407	rdpr	%tstate, %g1
1408	btst	TSTATE_PRIV, %g1
1409	bnz,pn	%icc, 2f
1410	nop
1411	CPU_ADDR(%g1, %g4)				! load CPU struct addr
1412	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
1413	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
1414	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
1415	brz,pt	%g5, 2f
1416	nop
1417	ldn	[%g5 + P_UTRAP15], %g5			! unaligned utrap?
1418	brz,pn	%g5, 2f
1419	nop
1420	btst	1, %sp
1421	bz,pt	%xcc, 1f				! 32 bit user program
1422	nop
1423	ba,pt	%xcc, .setup_v9utrap			! 64 bit user program
1424	nop
14251:
1426	ba,pt	%xcc, .setup_utrap
1427	or	%g2, %g0, %g7
14282:
1429	ba,pt	%xcc, .mmu_exception_end
1430	mov	T_ALIGNMENT, %g1
1431
1432.mmu_priv_exception:
1433	rdpr	%tstate, %g1
1434	btst	TSTATE_PRIV, %g1
1435	bnz,pn	%icc, 1f
1436	nop
1437	CPU_ADDR(%g1, %g4)				! load CPU struct addr
1438	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
1439	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
1440	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
1441	brz,pt	%g5, 1f
1442	nop
1443	ldn	[%g5 + P_UTRAP16], %g5
1444	brnz,pt	%g5, .setup_v9utrap
1445	nop
14461:
1447	mov	T_PRIV_INSTR, %g1
1448
1449.mmu_exception_end:
1450	CPU_INDEX(%g4, %g5)
1451	set	cpu_core, %g5
1452	sllx	%g4, CPU_CORE_SHIFT, %g4
1453	add	%g4, %g5, %g4
1454	lduh	[%g4 + CPUC_DTRACE_FLAGS], %g5
1455	andcc	%g5, CPU_DTRACE_NOFAULT, %g0
1456	bz	1f
1457	or	%g5, CPU_DTRACE_BADADDR, %g5
1458	stuh	%g5, [%g4 + CPUC_DTRACE_FLAGS]
1459	done
1460
14611:
1462	sllx	%g3, 32, %g3
1463	or	%g3, %g1, %g3
1464	set	trap, %g1
1465	ba,pt	%xcc, sys_trap
1466	sub	%g0, 1, %g4
1467
1468.fp_disabled:
1469	CPU_ADDR(%g1, %g4)				! load CPU struct addr
1470	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
1471	rdpr	%tstate, %g4
1472	btst	TSTATE_PRIV, %g4
1473	bnz,a,pn %icc, ptl1_panic
1474	  mov	PTL1_BAD_FPTRAP, %g1
1475
1476	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
1477	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
1478	brz,a,pt %g5, 2f
1479	  nop
1480	ldn	[%g5 + P_UTRAP7], %g5			! fp_disabled utrap?
1481	brz,a,pn %g5, 2f
1482	  nop
1483	btst	1, %sp
1484	bz,a,pt	%xcc, 1f				! 32 bit user program
1485	  nop
1486	ba,a,pt	%xcc, .setup_v9utrap			! 64 bit user program
1487	  nop
14881:
1489	ba,pt	%xcc, .setup_utrap
1490	  or	%g0, %g0, %g7
14912:
1492	set	fp_disabled, %g1
1493	ba,pt	%xcc, sys_trap
1494	  sub	%g0, 1, %g4
1495
1496.fp_ieee_exception:
1497	rdpr	%tstate, %g1
1498	btst	TSTATE_PRIV, %g1
1499	bnz,a,pn %icc, ptl1_panic
1500	  mov	PTL1_BAD_FPTRAP, %g1
1501	CPU_ADDR(%g1, %g4)				! load CPU struct addr
1502	stx	%fsr, [%g1 + CPU_TMP1]
1503	ldx	[%g1 + CPU_TMP1], %g2
1504	ldn	[%g1 + CPU_THREAD], %g1			! load thread pointer
1505	ldn	[%g1 + T_PROCP], %g1			! load proc pointer
1506	ldn	[%g1 + P_UTRAPS], %g5			! are there utraps?
1507	brz,a,pt %g5, 1f
1508	  nop
1509	ldn	[%g5 + P_UTRAP8], %g5
1510	brnz,a,pt %g5, .setup_v9utrap
1511	  nop
15121:
1513	set	_fp_ieee_exception, %g1
1514	ba,pt	%xcc, sys_trap
1515	  sub	%g0, 1, %g4
1516
1517/*
1518 * Register Inputs:
1519 *	%g5		user trap handler
1520 *	%g7		misaligned addr - for alignment traps only
1521 */
1522.setup_utrap:
1523	set	trap, %g1			! setup in case we go
1524	mov	T_FLUSH_PCB, %g3		! through sys_trap on
1525	sub	%g0, 1, %g4			! the save instruction below
1526
1527	/*
1528	 * If the DTrace pid provider is single stepping a copied-out
1529	 * instruction, t->t_dtrace_step will be set. In that case we need
1530	 * to abort the single-stepping (since execution of the instruction
1531	 * was interrupted) and use the value of t->t_dtrace_npc as the %npc.
1532	 */
1533	save	%sp, -SA(MINFRAME32), %sp	! window for trap handler
1534	CPU_ADDR(%g1, %g4)			! load CPU struct addr
1535	ldn	[%g1 + CPU_THREAD], %g1		! load thread pointer
1536	ldub	[%g1 + T_DTRACE_STEP], %g2	! load t->t_dtrace_step
1537	rdpr	%tnpc, %l2			! arg1 == tnpc
1538	brz,pt	%g2, 1f
1539	rdpr	%tpc, %l1			! arg0 == tpc
1540
1541	ldub	[%g1 + T_DTRACE_AST], %g2	! load t->t_dtrace_ast
1542	ldn	[%g1 + T_DTRACE_NPC], %l2	! arg1 = t->t_dtrace_npc (step)
1543	brz,pt	%g2, 1f
1544	st	%g0, [%g1 + T_DTRACE_FT]	! zero all pid provider flags
1545	stub	%g2, [%g1 + T_ASTFLAG]		! aston(t) if t->t_dtrace_ast
15461:
1547	mov	%g7, %l3			! arg2 == misaligned address
1548
1549	rdpr	%tstate, %g1			! cwp for trap handler
1550	rdpr	%cwp, %g4
1551	bclr	TSTATE_CWP_MASK, %g1
1552	wrpr	%g1, %g4, %tstate
1553	wrpr	%g0, %g5, %tnpc			! trap handler address
1554	FAST_TRAP_DONE
1555	/* NOTREACHED */
1556
1557.check_v9utrap:
1558	rdpr	%tstate, %g1
1559	btst	TSTATE_PRIV, %g1
1560	bnz,a,pn %icc, 3f
1561	  nop
1562	CPU_ADDR(%g4, %g1)				! load CPU struct addr
1563	ldn	[%g4 + CPU_THREAD], %g5			! load thread pointer
1564	ldn	[%g5 + T_PROCP], %g5			! load proc pointer
1565	ldn	[%g5 + P_UTRAPS], %g5			! are there utraps?
1566
1567	cmp	%g3, T_SOFTWARE_TRAP
1568	bne,a,pt %icc, 1f
1569	  nop
1570
1571	brz,pt %g5, 3f			! if p_utraps == NULL goto trap()
1572	  rdpr	%tt, %g3		! delay - get actual hw trap type
1573
1574	sub	%g3, 254, %g1		! UT_TRAP_INSTRUCTION_16 = p_utraps[18]
1575	ba,pt	%icc, 2f
1576	  smul	%g1, CPTRSIZE, %g2
15771:
1578	brz,a,pt %g5, 3f		! if p_utraps == NULL goto trap()
1579	  nop
1580
1581	cmp	%g3, T_UNIMP_INSTR
1582	bne,a,pt %icc, 2f
1583	  nop
1584
1585	mov	1, %g1
1586	st	%g1, [%g4 + CPU_TL1_HDLR] ! set CPU_TL1_HDLR
1587	rdpr	%tpc, %g1		! ld trapping instruction using
1588	lduwa	[%g1]ASI_AIUP, %g1	! "AS IF USER" ASI which could fault
1589	st	%g0, [%g4 + CPU_TL1_HDLR] ! clr CPU_TL1_HDLR
1590
1591	sethi	%hi(0xc1c00000), %g4	! setup mask for illtrap instruction
1592	andcc	%g1, %g4, %g4		! and instruction with mask
1593	bnz,a,pt %icc, 3f		! if %g4 == zero, %g1 is an ILLTRAP
1594	  nop				! fall thru to setup
15952:
1596	ldn	[%g5 + %g2], %g5
1597	brnz,a,pt %g5, .setup_v9utrap
1598	  nop
15993:
1600	set	trap, %g1
1601	ba,pt	%xcc, sys_trap
1602	  sub	%g0, 1, %g4
1603	/* NOTREACHED */
1604
1605/*
1606 * Register Inputs:
1607 *	%g5		user trap handler
1608 */
1609.setup_v9utrap:
1610	set	trap, %g1			! setup in case we go
1611	mov	T_FLUSH_PCB, %g3		! through sys_trap on
1612	sub	%g0, 1, %g4			! the save instruction below
1613
1614	/*
1615	 * If the DTrace pid provider is single stepping a copied-out
1616	 * instruction, t->t_dtrace_step will be set. In that case we need
1617	 * to abort the single-stepping (since execution of the instruction
1618	 * was interrupted) and use the value of t->t_dtrace_npc as the %npc.
1619	 */
1620	save	%sp, -SA(MINFRAME64), %sp	! window for trap handler
1621	CPU_ADDR(%g1, %g4)			! load CPU struct addr
1622	ldn	[%g1 + CPU_THREAD], %g1		! load thread pointer
1623	ldub	[%g1 + T_DTRACE_STEP], %g2	! load t->t_dtrace_step
1624	rdpr	%tnpc, %l7			! arg1 == tnpc
1625	brz,pt	%g2, 1f
1626	rdpr	%tpc, %l6			! arg0 == tpc
1627
1628	ldub	[%g1 + T_DTRACE_AST], %g2	! load t->t_dtrace_ast
1629	ldn	[%g1 + T_DTRACE_NPC], %l7	! arg1 == t->t_dtrace_npc (step)
1630	brz,pt	%g2, 1f
1631	st	%g0, [%g1 + T_DTRACE_FT]	! zero all pid provider flags
1632	stub	%g2, [%g1 + T_ASTFLAG]		! aston(t) if t->t_dtrace_ast
16331:
1634	rdpr	%tstate, %g2			! cwp for trap handler
1635	rdpr	%cwp, %g4
1636	bclr	TSTATE_CWP_MASK, %g2
1637	wrpr	%g2, %g4, %tstate
1638
1639	ldn	[%g1 + T_PROCP], %g4		! load proc pointer
1640	ldn	[%g4 + P_AS], %g4		! load as pointer
1641	ldn	[%g4 + A_USERLIMIT], %g4	! load as userlimit
1642	cmp	%l7, %g4			! check for single-step set
1643	bne,pt	%xcc, 4f
1644	  nop
1645	ldn	[%g1 + T_LWP], %g1		! load klwp pointer
1646	ld	[%g1 + PCB_STEP], %g4		! load single-step flag
1647	cmp	%g4, STEP_ACTIVE		! step flags set in pcb?
1648	bne,pt	%icc, 4f
1649	  nop
1650	stn	%g5, [%g1 + PCB_TRACEPC]	! save trap handler addr in pcb
1651	mov	%l7, %g4			! on entry to precise user trap
1652	add	%l6, 4, %l7			! handler, %l6 == pc, %l7 == npc
1653						! at time of trap
1654	wrpr	%g0, %g4, %tnpc			! generate FLTBOUNDS,
1655						! %g4 == userlimit
1656	FAST_TRAP_DONE
1657	/* NOTREACHED */
16584:
1659	wrpr	%g0, %g5, %tnpc			! trap handler address
1660	FAST_TRAP_DONE_CHK_INTR
1661	/* NOTREACHED */
1662
1663.fp_exception:
1664	CPU_ADDR(%g1, %g4)
1665	stx	%fsr, [%g1 + CPU_TMP1]
1666	ldx	[%g1 + CPU_TMP1], %g2
1667
1668	/*
1669	 * Cheetah takes unfinished_FPop trap for certain range of operands
1670	 * to the "fitos" instruction. Instead of going through the slow
1671	 * software emulation path, we try to simulate the "fitos" instruction
1672	 * via "fitod" and "fdtos" provided the following conditions are met:
1673	 *
1674	 *	fpu_exists is set (if DEBUG)
1675	 *	not in privileged mode
1676	 *	ftt is unfinished_FPop
1677	 *	NXM IEEE trap is not enabled
1678	 *	instruction at %tpc is "fitos"
1679	 *
1680	 *  Usage:
1681	 *	%g1	per cpu address
1682	 *	%g2	%fsr
1683	 *	%g6	user instruction
1684	 *
1685	 * Note that we can take a memory access related trap while trying
1686	 * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR
1687	 * flag to catch those traps and let the SFMMU code deal with page
1688	 * fault and data access exception.
1689	 */
1690#if defined(DEBUG) || defined(NEED_FPU_EXISTS)
1691	sethi	%hi(fpu_exists), %g7
1692	ld	[%g7 + %lo(fpu_exists)], %g7
1693	brz,pn %g7, .fp_exception_cont
1694	  nop
1695#endif
1696	rdpr	%tstate, %g7			! branch if in privileged mode
1697	btst	TSTATE_PRIV, %g7
1698	bnz,pn	%xcc, .fp_exception_cont
1699	srl	%g2, FSR_FTT_SHIFT, %g7		! extract ftt from %fsr
1700	and	%g7, (FSR_FTT>>FSR_FTT_SHIFT), %g7
1701	cmp	%g7, FTT_UNFIN
1702	set	FSR_TEM_NX, %g5
1703	bne,pn	%xcc, .fp_exception_cont	! branch if NOT unfinished_FPop
1704	  andcc	%g2, %g5, %g0
1705	bne,pn	%xcc, .fp_exception_cont	! branch if FSR_TEM_NX enabled
1706	  rdpr	%tpc, %g5			! get faulting PC
1707
1708	or	%g0, 1, %g7
1709	st	%g7, [%g1 + CPU_TL1_HDLR]	! set tl1_hdlr flag
1710	lda	[%g5]ASI_USER, %g6		! get user's instruction
1711	st	%g0, [%g1 + CPU_TL1_HDLR]	! clear tl1_hdlr flag
1712
1713	set	FITOS_INSTR_MASK, %g7
1714	and	%g6, %g7, %g7
1715	set	FITOS_INSTR, %g5
1716	cmp	%g7, %g5
1717	bne,pn	%xcc, .fp_exception_cont	! branch if not FITOS_INSTR
1718	 nop
1719
1720	/*
1721	 * This is unfinished FPops trap for "fitos" instruction. We
1722	 * need to simulate "fitos" via "fitod" and "fdtos" instruction
1723	 * sequence.
1724	 *
1725	 * We need a temporary FP register to do the conversion. Since
1726	 * both source and destination operands for the "fitos" instruction
1727	 * have to be within %f0-%f31, we use an FP register from the upper
1728	 * half to guarantee that it won't collide with the source or the
1729	 * dest operand. However, we do have to save and restore its value.
1730	 *
1731	 * We use %d62 as a temporary FP register for the conversion and
1732	 * branch to appropriate instruction within the conversion tables
1733	 * based upon the rs2 and rd values.
1734	 */
1735
1736	std	%d62, [%g1 + CPU_TMP1]		! save original value
1737
1738	srl	%g6, FITOS_RS2_SHIFT, %g7
1739	and	%g7, FITOS_REG_MASK, %g7
1740	set	_fitos_fitod_table, %g4
1741	sllx	%g7, 2, %g7
1742	jmp	%g4 + %g7
1743	  ba,pt	%xcc, _fitos_fitod_done
1744	.empty
1745
1746_fitos_fitod_table:
1747	  fitod	%f0, %d62
1748	  fitod	%f1, %d62
1749	  fitod	%f2, %d62
1750	  fitod	%f3, %d62
1751	  fitod	%f4, %d62
1752	  fitod	%f5, %d62
1753	  fitod	%f6, %d62
1754	  fitod	%f7, %d62
1755	  fitod	%f8, %d62
1756	  fitod	%f9, %d62
1757	  fitod	%f10, %d62
1758	  fitod	%f11, %d62
1759	  fitod	%f12, %d62
1760	  fitod	%f13, %d62
1761	  fitod	%f14, %d62
1762	  fitod	%f15, %d62
1763	  fitod	%f16, %d62
1764	  fitod	%f17, %d62
1765	  fitod	%f18, %d62
1766	  fitod	%f19, %d62
1767	  fitod	%f20, %d62
1768	  fitod	%f21, %d62
1769	  fitod	%f22, %d62
1770	  fitod	%f23, %d62
1771	  fitod	%f24, %d62
1772	  fitod	%f25, %d62
1773	  fitod	%f26, %d62
1774	  fitod	%f27, %d62
1775	  fitod	%f28, %d62
1776	  fitod	%f29, %d62
1777	  fitod	%f30, %d62
1778	  fitod	%f31, %d62
1779_fitos_fitod_done:
1780
1781	/*
1782	 * Now convert data back into single precision
1783	 */
1784	srl	%g6, FITOS_RD_SHIFT, %g7
1785	and	%g7, FITOS_REG_MASK, %g7
1786	set	_fitos_fdtos_table, %g4
1787	sllx	%g7, 2, %g7
1788	jmp	%g4 + %g7
1789	  ba,pt	%xcc, _fitos_fdtos_done
1790	.empty
1791
1792_fitos_fdtos_table:
1793	  fdtos	%d62, %f0
1794	  fdtos	%d62, %f1
1795	  fdtos	%d62, %f2
1796	  fdtos	%d62, %f3
1797	  fdtos	%d62, %f4
1798	  fdtos	%d62, %f5
1799	  fdtos	%d62, %f6
1800	  fdtos	%d62, %f7
1801	  fdtos	%d62, %f8
1802	  fdtos	%d62, %f9
1803	  fdtos	%d62, %f10
1804	  fdtos	%d62, %f11
1805	  fdtos	%d62, %f12
1806	  fdtos	%d62, %f13
1807	  fdtos	%d62, %f14
1808	  fdtos	%d62, %f15
1809	  fdtos	%d62, %f16
1810	  fdtos	%d62, %f17
1811	  fdtos	%d62, %f18
1812	  fdtos	%d62, %f19
1813	  fdtos	%d62, %f20
1814	  fdtos	%d62, %f21
1815	  fdtos	%d62, %f22
1816	  fdtos	%d62, %f23
1817	  fdtos	%d62, %f24
1818	  fdtos	%d62, %f25
1819	  fdtos	%d62, %f26
1820	  fdtos	%d62, %f27
1821	  fdtos	%d62, %f28
1822	  fdtos	%d62, %f29
1823	  fdtos	%d62, %f30
1824	  fdtos	%d62, %f31
1825_fitos_fdtos_done:
1826
1827	ldd	[%g1 + CPU_TMP1], %d62		! restore %d62
1828
1829#if DEBUG
1830	/*
1831	 * Update FPop_unfinished trap kstat
1832	 */
1833	set	fpustat+FPUSTAT_UNFIN_KSTAT, %g7
1834	ldx	[%g7], %g5
18351:
1836	add	%g5, 1, %g6
1837
1838	casxa	[%g7] ASI_N, %g5, %g6
1839	cmp	%g5, %g6
1840	bne,a,pn %xcc, 1b
1841	  or	%g0, %g6, %g5
1842
1843	/*
1844	 * Update fpu_sim_fitos kstat
1845	 */
1846	set	fpuinfo+FPUINFO_FITOS_KSTAT, %g7
1847	ldx	[%g7], %g5
18481:
1849	add	%g5, 1, %g6
1850
1851	casxa	[%g7] ASI_N, %g5, %g6
1852	cmp	%g5, %g6
1853	bne,a,pn %xcc, 1b
1854	  or	%g0, %g6, %g5
1855#endif /* DEBUG */
1856
1857	FAST_TRAP_DONE
1858
1859.fp_exception_cont:
1860	/*
1861	 * Let _fp_exception deal with simulating FPop instruction.
1862	 * Note that we need to pass %fsr in %g2 (already read above).
1863	 */
1864
1865	set	_fp_exception, %g1
1866	ba,pt	%xcc, sys_trap
1867	sub	%g0, 1, %g4
1868
1869
1870/*
1871 * Register windows
1872 */
1873.flushw:
1874.clean_windows:
1875	rdpr	%tnpc, %g1
1876	wrpr	%g1, %tpc
1877	add	%g1, 4, %g1
1878	wrpr	%g1, %tnpc
1879	set	trap, %g1
1880	mov	T_FLUSH_PCB, %g3
1881	ba,pt	%xcc, sys_trap
1882	sub	%g0, 1, %g4
1883
1884/*
1885 * .spill_clean: clean the previous window, restore the wstate, and
1886 * "done".
1887 *
1888 * Entry: %g7 contains new wstate
1889 */
1890.spill_clean:
1891	sethi	%hi(nwin_minus_one), %g5
1892	ld	[%g5 + %lo(nwin_minus_one)], %g5 ! %g5 = nwin - 1
1893	rdpr	%cwp, %g6			! %g6 = %cwp
1894	deccc	%g6				! %g6--
1895	movneg	%xcc, %g5, %g6			! if (%g6<0) %g6 = nwin-1
1896	wrpr	%g6, %cwp
1897	TT_TRACE_L(trace_win)
1898	clr	%l0
1899	clr	%l1
1900	clr	%l2
1901	clr	%l3
1902	clr	%l4
1903	clr	%l5
1904	clr	%l6
1905	clr	%l7
1906	wrpr	%g0, %g7, %wstate
1907	saved
1908	retry			! restores correct %cwp
1909
1910.fix_alignment:
1911	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
1912	ldn	[%g1 + CPU_THREAD], %g1	! load thread pointer
1913	ldn	[%g1 + T_PROCP], %g1
1914	mov	1, %g2
1915	stb	%g2, [%g1 + P_FIXALIGNMENT]
1916	FAST_TRAP_DONE
1917
1918#define	STDF_REG(REG, ADDR, TMP)		\
1919	sll	REG, 3, REG			;\
1920mark1:	set	start1, TMP			;\
1921	jmp	REG + TMP			;\
1922	  nop					;\
1923start1:	ba,pt	%xcc, done1			;\
1924	  std	%f0, [ADDR + CPU_TMP1]		;\
1925	ba,pt	%xcc, done1			;\
1926	  std	%f32, [ADDR + CPU_TMP1]		;\
1927	ba,pt	%xcc, done1			;\
1928	  std	%f2, [ADDR + CPU_TMP1]		;\
1929	ba,pt	%xcc, done1			;\
1930	  std	%f34, [ADDR + CPU_TMP1]		;\
1931	ba,pt	%xcc, done1			;\
1932	  std	%f4, [ADDR + CPU_TMP1]		;\
1933	ba,pt	%xcc, done1			;\
1934	  std	%f36, [ADDR + CPU_TMP1]		;\
1935	ba,pt	%xcc, done1			;\
1936	  std	%f6, [ADDR + CPU_TMP1]		;\
1937	ba,pt	%xcc, done1			;\
1938	  std	%f38, [ADDR + CPU_TMP1]		;\
1939	ba,pt	%xcc, done1			;\
1940	  std	%f8, [ADDR + CPU_TMP1]		;\
1941	ba,pt	%xcc, done1			;\
1942	  std	%f40, [ADDR + CPU_TMP1]		;\
1943	ba,pt	%xcc, done1			;\
1944	  std	%f10, [ADDR + CPU_TMP1]		;\
1945	ba,pt	%xcc, done1			;\
1946	  std	%f42, [ADDR + CPU_TMP1]		;\
1947	ba,pt	%xcc, done1			;\
1948	  std	%f12, [ADDR + CPU_TMP1]		;\
1949	ba,pt	%xcc, done1			;\
1950	  std	%f44, [ADDR + CPU_TMP1]		;\
1951	ba,pt	%xcc, done1			;\
1952	  std	%f14, [ADDR + CPU_TMP1]		;\
1953	ba,pt	%xcc, done1			;\
1954	  std	%f46, [ADDR + CPU_TMP1]		;\
1955	ba,pt	%xcc, done1			;\
1956	  std	%f16, [ADDR + CPU_TMP1]		;\
1957	ba,pt	%xcc, done1			;\
1958	  std	%f48, [ADDR + CPU_TMP1]		;\
1959	ba,pt	%xcc, done1			;\
1960	  std	%f18, [ADDR + CPU_TMP1]		;\
1961	ba,pt	%xcc, done1			;\
1962	  std	%f50, [ADDR + CPU_TMP1]		;\
1963	ba,pt	%xcc, done1			;\
1964	  std	%f20, [ADDR + CPU_TMP1]		;\
1965	ba,pt	%xcc, done1			;\
1966	  std	%f52, [ADDR + CPU_TMP1]		;\
1967	ba,pt	%xcc, done1			;\
1968	  std	%f22, [ADDR + CPU_TMP1]		;\
1969	ba,pt	%xcc, done1			;\
1970	  std	%f54, [ADDR + CPU_TMP1]		;\
1971	ba,pt	%xcc, done1			;\
1972	  std	%f24, [ADDR + CPU_TMP1]		;\
1973	ba,pt	%xcc, done1			;\
1974	  std	%f56, [ADDR + CPU_TMP1]		;\
1975	ba,pt	%xcc, done1			;\
1976	  std	%f26, [ADDR + CPU_TMP1]		;\
1977	ba,pt	%xcc, done1			;\
1978	  std	%f58, [ADDR + CPU_TMP1]		;\
1979	ba,pt	%xcc, done1			;\
1980	  std	%f28, [ADDR + CPU_TMP1]		;\
1981	ba,pt	%xcc, done1			;\
1982	  std	%f60, [ADDR + CPU_TMP1]		;\
1983	ba,pt	%xcc, done1			;\
1984	  std	%f30, [ADDR + CPU_TMP1]		;\
1985	ba,pt	%xcc, done1			;\
1986	  std	%f62, [ADDR + CPU_TMP1]		;\
1987done1:
1988
1989#define	LDDF_REG(REG, ADDR, TMP)		\
1990	sll	REG, 3, REG			;\
1991mark2:	set	start2, TMP			;\
1992	jmp	REG + TMP			;\
1993	  nop					;\
1994start2:	ba,pt	%xcc, done2			;\
1995	  ldd	[ADDR + CPU_TMP1], %f0		;\
1996	ba,pt	%xcc, done2			;\
1997	  ldd	[ADDR + CPU_TMP1], %f32		;\
1998	ba,pt	%xcc, done2			;\
1999	  ldd	[ADDR + CPU_TMP1], %f2		;\
2000	ba,pt	%xcc, done2			;\
2001	  ldd	[ADDR + CPU_TMP1], %f34		;\
2002	ba,pt	%xcc, done2			;\
2003	  ldd	[ADDR + CPU_TMP1], %f4		;\
2004	ba,pt	%xcc, done2			;\
2005	  ldd	[ADDR + CPU_TMP1], %f36		;\
2006	ba,pt	%xcc, done2			;\
2007	  ldd	[ADDR + CPU_TMP1], %f6		;\
2008	ba,pt	%xcc, done2			;\
2009	  ldd	[ADDR + CPU_TMP1], %f38		;\
2010	ba,pt	%xcc, done2			;\
2011	  ldd	[ADDR + CPU_TMP1], %f8		;\
2012	ba,pt	%xcc, done2			;\
2013	  ldd	[ADDR + CPU_TMP1], %f40		;\
2014	ba,pt	%xcc, done2			;\
2015	  ldd	[ADDR + CPU_TMP1], %f10		;\
2016	ba,pt	%xcc, done2			;\
2017	  ldd	[ADDR + CPU_TMP1], %f42		;\
2018	ba,pt	%xcc, done2			;\
2019	  ldd	[ADDR + CPU_TMP1], %f12		;\
2020	ba,pt	%xcc, done2			;\
2021	  ldd	[ADDR + CPU_TMP1], %f44		;\
2022	ba,pt	%xcc, done2			;\
2023	  ldd	[ADDR + CPU_TMP1], %f14		;\
2024	ba,pt	%xcc, done2			;\
2025	  ldd	[ADDR + CPU_TMP1], %f46		;\
2026	ba,pt	%xcc, done2			;\
2027	  ldd	[ADDR + CPU_TMP1], %f16		;\
2028	ba,pt	%xcc, done2			;\
2029	  ldd	[ADDR + CPU_TMP1], %f48		;\
2030	ba,pt	%xcc, done2			;\
2031	  ldd	[ADDR + CPU_TMP1], %f18		;\
2032	ba,pt	%xcc, done2			;\
2033	  ldd	[ADDR + CPU_TMP1], %f50		;\
2034	ba,pt	%xcc, done2			;\
2035	  ldd	[ADDR + CPU_TMP1], %f20		;\
2036	ba,pt	%xcc, done2			;\
2037	  ldd	[ADDR + CPU_TMP1], %f52		;\
2038	ba,pt	%xcc, done2			;\
2039	  ldd	[ADDR + CPU_TMP1], %f22		;\
2040	ba,pt	%xcc, done2			;\
2041	  ldd	[ADDR + CPU_TMP1], %f54		;\
2042	ba,pt	%xcc, done2			;\
2043	  ldd	[ADDR + CPU_TMP1], %f24		;\
2044	ba,pt	%xcc, done2			;\
2045	  ldd	[ADDR + CPU_TMP1], %f56		;\
2046	ba,pt	%xcc, done2			;\
2047	  ldd	[ADDR + CPU_TMP1], %f26		;\
2048	ba,pt	%xcc, done2			;\
2049	  ldd	[ADDR + CPU_TMP1], %f58		;\
2050	ba,pt	%xcc, done2			;\
2051	  ldd	[ADDR + CPU_TMP1], %f28		;\
2052	ba,pt	%xcc, done2			;\
2053	  ldd	[ADDR + CPU_TMP1], %f60		;\
2054	ba,pt	%xcc, done2			;\
2055	  ldd	[ADDR + CPU_TMP1], %f30		;\
2056	ba,pt	%xcc, done2			;\
2057	  ldd	[ADDR + CPU_TMP1], %f62		;\
2058done2:
2059
2060.lddf_exception_not_aligned:
2061	/* %g2 = sfar, %g3 = sfsr */
2062	mov	%g2, %g5		! stash sfar
2063#if defined(DEBUG) || defined(NEED_FPU_EXISTS)
2064	sethi	%hi(fpu_exists), %g2	! check fpu_exists
2065	ld	[%g2 + %lo(fpu_exists)], %g2
2066	brz,a,pn %g2, 4f
2067	  nop
2068#endif
2069	CPU_ADDR(%g1, %g4)
2070	or	%g0, 1, %g4
2071	st	%g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
2072
2073	rdpr	%tpc, %g2
2074	lda	[%g2]ASI_AIUP, %g6	! get the user's lddf instruction
2075	srl	%g6, 23, %g1		! using ldda or not?
2076	and	%g1, 1, %g1
2077	brz,a,pt %g1, 2f		! check for ldda instruction
2078	  nop
2079	srl	%g6, 13, %g1		! check immflag
2080	and	%g1, 1, %g1
2081	rdpr	%tstate, %g2		! %tstate in %g2
2082	brnz,a,pn %g1, 1f
2083	  srl	%g2, 31, %g1		! get asi from %tstate
2084	srl	%g6, 5, %g1		! get asi from instruction
2085	and	%g1, 0xFF, %g1		! imm_asi field
20861:
2087	cmp	%g1, ASI_P		! primary address space
2088	be,a,pt %icc, 2f
2089	  nop
2090	cmp	%g1, ASI_PNF		! primary no fault address space
2091	be,a,pt %icc, 2f
2092	  nop
2093	cmp	%g1, ASI_S		! secondary address space
2094	be,a,pt %icc, 2f
2095	  nop
2096	cmp	%g1, ASI_SNF		! secondary no fault address space
2097	bne,a,pn %icc, 3f
2098	  nop
20992:
2100	lduwa	[%g5]ASI_USER, %g7	! get first half of misaligned data
2101	add	%g5, 4, %g5		! increment misaligned data address
2102	lduwa	[%g5]ASI_USER, %g5	! get second half of misaligned data
2103
2104	sllx	%g7, 32, %g7
2105	or	%g5, %g7, %g5		! combine data
2106	CPU_ADDR(%g7, %g1)		! save data on a per-cpu basis
2107	stx	%g5, [%g7 + CPU_TMP1]	! save in cpu_tmp1
2108
2109	srl	%g6, 25, %g3		! %g6 has the instruction
2110	and	%g3, 0x1F, %g3		! %g3 has rd
2111	LDDF_REG(%g3, %g7, %g4)
2112
2113	CPU_ADDR(%g1, %g4)
2114	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
2115	FAST_TRAP_DONE
21163:
2117	CPU_ADDR(%g1, %g4)
2118	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
21194:
2120	set	T_USER, %g3		! trap type in %g3
2121	or	%g3, T_LDDF_ALIGN, %g3
2122	mov	%g5, %g2		! misaligned vaddr in %g2
2123	set	fpu_trap, %g1		! goto C for the little and
2124	ba,pt	%xcc, sys_trap		! no fault little asi's
2125	  sub	%g0, 1, %g4
2126
2127.stdf_exception_not_aligned:
2128	/* %g2 = sfar, %g3 = sfsr */
2129	mov	%g2, %g5
2130
2131#if defined(DEBUG) || defined(NEED_FPU_EXISTS)
2132	sethi	%hi(fpu_exists), %g7		! check fpu_exists
2133	ld	[%g7 + %lo(fpu_exists)], %g3
2134	brz,a,pn %g3, 4f
2135	  nop
2136#endif
2137	CPU_ADDR(%g1, %g4)
2138	or	%g0, 1, %g4
2139	st	%g4, [%g1 + CPU_TL1_HDLR] ! set tl1_hdlr flag
2140
2141	rdpr	%tpc, %g2
2142	lda	[%g2]ASI_AIUP, %g6	! get the user's stdf instruction
2143
2144	srl	%g6, 23, %g1		! using stda or not?
2145	and	%g1, 1, %g1
2146	brz,a,pt %g1, 2f		! check for stda instruction
2147	  nop
2148	srl	%g6, 13, %g1		! check immflag
2149	and	%g1, 1, %g1
2150	rdpr	%tstate, %g2		! %tstate in %g2
2151	brnz,a,pn %g1, 1f
2152	  srl	%g2, 31, %g1		! get asi from %tstate
2153	srl	%g6, 5, %g1		! get asi from instruction
2154	and	%g1, 0xff, %g1		! imm_asi field
21551:
2156	cmp	%g1, ASI_P		! primary address space
2157	be,a,pt %icc, 2f
2158	  nop
2159	cmp	%g1, ASI_S		! secondary address space
2160	bne,a,pn %icc, 3f
2161	  nop
21622:
2163	srl	%g6, 25, %g6
2164	and	%g6, 0x1F, %g6		! %g6 has rd
2165	CPU_ADDR(%g7, %g1)
2166	STDF_REG(%g6, %g7, %g4)		! STDF_REG(REG, ADDR, TMP)
2167
2168	ldx	[%g7 + CPU_TMP1], %g6
2169	srlx	%g6, 32, %g7
2170	stuwa	%g7, [%g5]ASI_USER	! first half
2171	add	%g5, 4, %g5		! increment misaligned data address
2172	stuwa	%g6, [%g5]ASI_USER	! second half
2173
2174	CPU_ADDR(%g1, %g4)
2175	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
2176	FAST_TRAP_DONE
21773:
2178	CPU_ADDR(%g1, %g4)
2179	st	%g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag
21804:
2181	set	T_USER, %g3		! trap type in %g3
2182	or	%g3, T_STDF_ALIGN, %g3
2183	mov	%g5, %g2		! misaligned vaddr in %g2
2184	set	fpu_trap, %g1		! goto C for the little and
2185	ba,pt	%xcc, sys_trap		! nofault little asi's
2186	  sub	%g0, 1, %g4
2187
2188#ifdef DEBUG_USER_TRAPTRACECTL
2189
2190.traptrace_freeze:
2191	mov	%l0, %g1 ; mov	%l1, %g2 ; mov	%l2, %g3 ; mov	%l4, %g4
2192	TT_TRACE_L(trace_win)
2193	mov	%g4, %l4 ; mov	%g3, %l2 ; mov	%g2, %l1 ; mov	%g1, %l0
2194	set	trap_freeze, %g1
2195	mov	1, %g2
2196	st	%g2, [%g1]
2197	FAST_TRAP_DONE
2198
2199.traptrace_unfreeze:
2200	set	trap_freeze, %g1
2201	st	%g0, [%g1]
2202	mov	%l0, %g1 ; mov	%l1, %g2 ; mov	%l2, %g3 ; mov	%l4, %g4
2203	TT_TRACE_L(trace_win)
2204	mov	%g4, %l4 ; mov	%g3, %l2 ; mov	%g2, %l1 ; mov	%g1, %l0
2205	FAST_TRAP_DONE
2206
2207#endif /* DEBUG_USER_TRAPTRACECTL */
2208
2209.getcc:
2210	CPU_ADDR(%g1, %g2)
2211	stx	%o0, [%g1 + CPU_TMP1]		! save %o0
2212	rdpr	%tstate, %g3			! get tstate
2213	srlx	%g3, PSR_TSTATE_CC_SHIFT, %o0	! shift ccr to V8 psr
2214	set	PSR_ICC, %g2
2215	and	%o0, %g2, %o0			! mask out the rest
2216	srl	%o0, PSR_ICC_SHIFT, %o0		! right justify
2217	wrpr	%g0, 0, %gl
2218	mov	%o0, %g1			! move ccr to normal %g1
2219	wrpr	%g0, 1, %gl
2220	! cannot assume globals retained their values after increasing %gl
2221	CPU_ADDR(%g1, %g2)
2222	ldx	[%g1 + CPU_TMP1], %o0		! restore %o0
2223	FAST_TRAP_DONE
2224
2225.setcc:
2226	CPU_ADDR(%g1, %g2)
2227	stx	%o0, [%g1 + CPU_TMP1]		! save %o0
2228	wrpr	%g0, 0, %gl
2229	mov	%g1, %o0
2230	wrpr	%g0, 1, %gl
2231	! cannot assume globals retained their values after increasing %gl
2232	CPU_ADDR(%g1, %g2)
2233	sll	%o0, PSR_ICC_SHIFT, %g2
2234	set	PSR_ICC, %g3
2235	and	%g2, %g3, %g2			! mask out rest
2236	sllx	%g2, PSR_TSTATE_CC_SHIFT, %g2
2237	rdpr	%tstate, %g3			! get tstate
2238	srl	%g3, 0, %g3			! clear upper word
2239	or	%g3, %g2, %g3			! or in new bits
2240	wrpr	%g3, %tstate
2241	ldx	[%g1 + CPU_TMP1], %o0		! restore %o0
2242	FAST_TRAP_DONE
2243
2244/*
2245 * getpsr(void)
2246 * Note that the xcc part of the ccr is not provided.
2247 * The V8 code shows why the V9 trap is not faster:
2248 * #define GETPSR_TRAP() \
2249 *      mov %psr, %i0; jmp %l2; rett %l2+4; nop;
2250 */
2251
2252	.type	.getpsr, #function
2253.getpsr:
2254	rdpr	%tstate, %g1			! get tstate
2255	srlx	%g1, PSR_TSTATE_CC_SHIFT, %o0	! shift ccr to V8 psr
2256	set	PSR_ICC, %g2
2257	and	%o0, %g2, %o0			! mask out the rest
2258
2259	rd	%fprs, %g1			! get fprs
2260	and	%g1, FPRS_FEF, %g2		! mask out dirty upper/lower
2261	sllx	%g2, PSR_FPRS_FEF_SHIFT, %g2	! shift fef to V8 psr.ef
2262	or	%o0, %g2, %o0			! or result into psr.ef
2263
2264	set	V9_PSR_IMPLVER, %g2		! SI assigned impl/ver: 0xef
2265	or	%o0, %g2, %o0			! or psr.impl/ver
2266	FAST_TRAP_DONE
2267	SET_SIZE(.getpsr)
2268
2269/*
2270 * setpsr(newpsr)
2271 * Note that there is no support for ccr.xcc in the V9 code.
2272 */
2273
2274	.type	.setpsr, #function
2275.setpsr:
2276	rdpr	%tstate, %g1			! get tstate
2277!	setx	TSTATE_V8_UBITS, %g2
2278	or 	%g0, CCR_ICC, %g3
2279	sllx	%g3, TSTATE_CCR_SHIFT, %g2
2280
2281	andn	%g1, %g2, %g1			! zero current user bits
2282	set	PSR_ICC, %g2
2283	and	%g2, %o0, %g2			! clear all but psr.icc bits
2284	sllx	%g2, PSR_TSTATE_CC_SHIFT, %g3	! shift to tstate.ccr.icc
2285	wrpr	%g1, %g3, %tstate		! write tstate
2286
2287	set	PSR_EF, %g2
2288	and	%g2, %o0, %g2			! clear all but fp enable bit
2289	srlx	%g2, PSR_FPRS_FEF_SHIFT, %g4	! shift ef to V9 fprs.fef
2290	wr	%g0, %g4, %fprs			! write fprs
2291
2292	CPU_ADDR(%g1, %g2)			! load CPU struct addr to %g1
2293	ldn	[%g1 + CPU_THREAD], %g2		! load thread pointer
2294	ldn	[%g2 + T_LWP], %g3		! load klwp pointer
2295	ldn	[%g3 + LWP_FPU], %g2		! get lwp_fpu pointer
2296	stuw	%g4, [%g2 + FPU_FPRS]		! write fef value to fpu_fprs
2297	srlx	%g4, 2, %g4			! shift fef value to bit 0
2298	stub	%g4, [%g2 + FPU_EN]		! write fef value to fpu_en
2299	FAST_TRAP_DONE
2300	SET_SIZE(.setpsr)
2301
2302/*
2303 * getlgrp
2304 * get home lgrpid on which the calling thread is currently executing.
2305 */
2306	.type	.getlgrp, #function
2307.getlgrp:
2308	! Thanks for the incredibly helpful comments
2309	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
2310	ld	[%g1 + CPU_ID], %o0	! load cpu_id
2311	ldn	[%g1 + CPU_THREAD], %g2	! load thread pointer
2312	ldn	[%g2 + T_LPL], %g2	! load lpl pointer
2313	ld	[%g2 + LPL_LGRPID], %g1	! load lpl_lgrpid
2314	sra	%g1, 0, %o1
2315	FAST_TRAP_DONE
2316	SET_SIZE(.getlgrp)
2317
2318/*
2319 * Entry for old 4.x trap (trap 0).
2320 */
2321	ENTRY_NP(syscall_trap_4x)
2322	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
2323	ldn	[%g1 + CPU_THREAD], %g2	! load thread pointer
2324	ldn	[%g2 + T_LWP], %g2	! load klwp pointer
2325	ld	[%g2 + PCB_TRAP0], %g2	! lwp->lwp_pcb.pcb_trap0addr
2326	brz,pn	%g2, 1f			! has it been set?
2327	st	%l0, [%g1 + CPU_TMP1]	! delay - save some locals
2328	st	%l1, [%g1 + CPU_TMP2]
2329	rdpr	%tnpc, %l1		! save old tnpc
2330	wrpr	%g0, %g2, %tnpc		! setup tnpc
2331
2332	mov	%g1, %l0		! save CPU struct addr
2333	wrpr	%g0, 0, %gl
2334	mov	%l1, %g6		! pass tnpc to user code in %g6
2335	wrpr	%g0, 1, %gl
2336	ld	[%l0 + CPU_TMP2], %l1	! restore locals
2337	ld	[%l0 + CPU_TMP1], %l0
2338	FAST_TRAP_DONE_CHK_INTR
23391:
2340	!
2341	! check for old syscall mmap which is the only different one which
2342	! must be the same.  Others are handled in the compatibility library.
2343	!
2344	mov	%g1, %l0		! save CPU struct addr
2345	wrpr	%g0, 0, %gl
2346	cmp	%g1, OSYS_mmap		! compare to old 4.x mmap
2347	movz	%icc, SYS_mmap, %g1
2348	wrpr	%g0, 1, %gl
2349	ld	[%l0 + CPU_TMP1], %l0
2350	SYSCALL(syscall_trap32)
2351	SET_SIZE(syscall_trap_4x)
2352
2353/*
2354 * Handler for software trap 9.
2355 * Set trap0 emulation address for old 4.x system call trap.
2356 * XXX - this should be a system call.
2357 */
2358	ENTRY_NP(set_trap0_addr)
2359	CPU_ADDR(%g1, %g2)		! load CPU struct addr to %g1 using %g2
2360	st	%l0, [%g1 + CPU_TMP1]	! save some locals
2361	st	%l1, [%g1 + CPU_TMP2]
2362	mov	%g1, %l0	! preserve CPU addr
2363	wrpr	%g0, 0, %gl
2364	mov	%g1, %l1
2365	wrpr	%g0, 1, %gl
2366	! cannot assume globals retained their values after increasing %gl
2367	ldn	[%l0 + CPU_THREAD], %g2	! load thread pointer
2368	ldn	[%g2 + T_LWP], %g2	! load klwp pointer
2369	andn	%l1, 3, %l1		! force alignment
2370	st	%l1, [%g2 + PCB_TRAP0]	! lwp->lwp_pcb.pcb_trap0addr
2371	ld	[%l0 + CPU_TMP2], %l1	! restore locals
2372	ld	[%l0 + CPU_TMP1], %l0
2373	FAST_TRAP_DONE
2374	SET_SIZE(set_trap0_addr)
2375
2376/*
2377 * mmu_trap_tl1
2378 * trap handler for unexpected mmu traps.
2379 * simply checks if the trap was a user lddf/stdf alignment trap, in which
2380 * case we go to fpu_trap or a user trap from the window handler, in which
2381 * case we go save the state on the pcb.  Otherwise, we go to ptl1_panic.
2382 */
2383	.type	mmu_trap_tl1, #function
2384mmu_trap_tl1:
2385#ifdef	TRAPTRACE
2386	TRACE_PTR(%g5, %g6)
2387	GET_TRACE_TICK(%g6)
2388	stxa	%g6, [%g5 + TRAP_ENT_TICK]%asi
2389	TRACE_SAVE_TL_GL_REGS(%g5, %g6)
2390	rdpr	%tt, %g6
2391	stha	%g6, [%g5 + TRAP_ENT_TT]%asi
2392	rdpr	%tstate, %g6
2393	stxa	%g6, [%g5 + TRAP_ENT_TSTATE]%asi
2394	stna	%sp, [%g5 + TRAP_ENT_SP]%asi
2395	stna	%g0, [%g5 + TRAP_ENT_TR]%asi
2396	rdpr	%tpc, %g6
2397	stna	%g6, [%g5 + TRAP_ENT_TPC]%asi
2398	MMU_FAULT_STATUS_AREA(%g6)
2399	ldx	[%g6 + MMFSA_D_ADDR], %g6
2400	stna	%g6, [%g5 + TRAP_ENT_F1]%asi !  MMU fault address
2401	CPU_PADDR(%g7, %g6);
2402	add	%g7, CPU_TL1_HDLR, %g7
2403	lda	[%g7]ASI_MEM, %g6
2404	stna	%g6, [%g5 + TRAP_ENT_F2]%asi
2405	MMU_FAULT_STATUS_AREA(%g6)
2406	ldx	[%g6 + MMFSA_D_TYPE], %g7 ! XXXQ should be a MMFSA_F_ constant?
2407	ldx	[%g6 + MMFSA_D_CTX], %g6
2408	sllx	%g6, SFSR_CTX_SHIFT, %g6
2409	or	%g6, %g7, %g6
2410	stna	%g6, [%g5 + TRAP_ENT_F3]%asi ! MMU context/type
2411	set	0xdeadbeef, %g6
2412	stna	%g6, [%g5 + TRAP_ENT_F4]%asi
2413	TRACE_NEXT(%g5, %g6, %g7)
2414#endif /* TRAPTRACE */
2415	CPU_PADDR(%g7, %g6);
2416	add     %g7, CPU_TL1_HDLR, %g7		! %g7 = &cpu_m.tl1_hdlr (PA)
2417	lda	[%g7]ASI_MEM, %g6
2418	brz,a,pt %g6, 1f
2419	  nop
2420	sta     %g0, [%g7]ASI_MEM
2421	! XXXQ need to setup registers for sfmmu_mmu_trap?
2422	ba,a,pt	%xcc, sfmmu_mmu_trap		! handle page faults
24231:
2424	rdpr	%tpc, %g7
2425	/* in user_rtt? */
2426	set	rtt_fill_start, %g6
2427	cmp	%g7, %g6
2428	blu,pn	%xcc, 6f
2429	 .empty
2430	set	rtt_fill_end, %g6
2431	cmp	%g7, %g6
2432	bgeu,pn %xcc, 6f
2433	 nop
2434	set	fault_rtt_fn1, %g7
2435	ba,a	7f
24366:
2437	! check to see if the trap pc is in a window spill/fill handling
2438	rdpr	%tpc, %g7
2439	/* tpc should be in the trap table */
2440	set	trap_table, %g6
2441	cmp	%g7, %g6
2442	blu,a,pn %xcc, ptl1_panic
2443	  mov	PTL1_BAD_MMUTRAP, %g1
2444	set	etrap_table, %g6
2445	cmp	%g7, %g6
2446	bgeu,a,pn %xcc, ptl1_panic
2447	  mov	PTL1_BAD_MMUTRAP, %g1
2448	! pc is inside the trap table, convert to trap type
2449	srl	%g7, 5, %g6		! XXXQ need #define
2450	and	%g6, 0x1ff, %g6		! XXXQ need #define
2451	! and check for a window trap type
2452	and	%g6, WTRAP_TTMASK, %g6
2453	cmp	%g6, WTRAP_TYPE
2454	bne,a,pn %xcc, ptl1_panic
2455	  mov	PTL1_BAD_MMUTRAP, %g1
2456	andn	%g7, WTRAP_ALIGN, %g7	/* 128 byte aligned */
2457	add	%g7, WTRAP_FAULTOFF, %g7
2458
24597:
2460	! Arguments are passed in the global set active after the
2461	! 'done' instruction. Before switching sets, must save
2462	! the calculated next pc
2463	wrpr	%g0, %g7, %tnpc
2464	wrpr	%g0, 1, %gl
2465	rdpr	%tt, %g5
2466	MMU_FAULT_STATUS_AREA(%g7)
2467	cmp	%g5, T_ALIGNMENT
2468	be,pn	%xcc, 1f
2469	ldx	[%g7 + MMFSA_D_ADDR], %g6
2470	ldx	[%g7 + MMFSA_D_CTX], %g7
2471	srlx	%g6, MMU_PAGESHIFT, %g6		/* align address */
2472	cmp	%g7, USER_CONTEXT_TYPE
2473	sllx	%g6, MMU_PAGESHIFT, %g6
2474	movgu	%icc, USER_CONTEXT_TYPE, %g7
2475	or	%g6, %g7, %g6			/* TAG_ACCESS */
24761:
2477	done
2478	SET_SIZE(mmu_trap_tl1)
2479
2480/*
2481 * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers.  These
2482 * traps are valid only when kmdb is loaded.  When the debugger is active,
2483 * the code below is rewritten to transfer control to the appropriate
2484 * debugger entry points.
2485 */
2486	.global	kmdb_trap
2487	.align	8
2488kmdb_trap:
2489	ba,a	trap_table0
2490	jmp	%g1 + 0
2491	nop
2492
2493	.global	kmdb_trap_tl1
2494	.align	8
2495kmdb_trap_tl1:
2496	ba,a	trap_table0
2497	jmp	%g1 + 0
2498	nop
2499
2500/*
2501 * This entry is copied from OBP's trap table during boot.
2502 */
2503	.global	obp_bpt
2504	.align	8
2505obp_bpt:
2506	NOT
2507
2508
2509
2510#ifdef	TRAPTRACE
2511/*
2512 * TRAPTRACE support.
2513 * labels here are branched to with "rd %pc, %g7" in the delay slot.
2514 * Return is done by "jmp %g7 + 4".
2515 */
2516
2517trace_dmmu:
2518	TRACE_PTR(%g3, %g6)
2519	GET_TRACE_TICK(%g6)
2520	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
2521	TRACE_SAVE_TL_GL_REGS(%g3, %g6)
2522	rdpr	%tt, %g6
2523	stha	%g6, [%g3 + TRAP_ENT_TT]%asi
2524	rdpr	%tstate, %g6
2525	stxa	%g6, [%g3 + TRAP_ENT_TSTATE]%asi
2526	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
2527	rdpr	%tpc, %g6
2528	stna	%g6, [%g3 + TRAP_ENT_TPC]%asi
2529	MMU_FAULT_STATUS_AREA(%g6)
2530	ldx	[%g6 + MMFSA_D_ADDR], %g4
2531	stxa	%g4, [%g3 + TRAP_ENT_TR]%asi
2532	ldx	[%g6 + MMFSA_D_CTX], %g4
2533	stxa	%g4, [%g3 + TRAP_ENT_F1]%asi
2534	ldx	[%g6 + MMFSA_D_TYPE], %g4
2535	stxa	%g4, [%g3 + TRAP_ENT_F2]%asi
2536	stxa	%g6, [%g3 + TRAP_ENT_F3]%asi
2537	stna	%g0, [%g3 + TRAP_ENT_F4]%asi
2538	TRACE_NEXT(%g3, %g4, %g5)
2539	jmp	%g7 + 4
2540	nop
2541
2542trace_immu:
2543	TRACE_PTR(%g3, %g6)
2544	GET_TRACE_TICK(%g6)
2545	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
2546	TRACE_SAVE_TL_GL_REGS(%g3, %g6)
2547	rdpr	%tt, %g6
2548	stha	%g6, [%g3 + TRAP_ENT_TT]%asi
2549	rdpr	%tstate, %g6
2550	stxa	%g6, [%g3 + TRAP_ENT_TSTATE]%asi
2551	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
2552	rdpr	%tpc, %g6
2553	stna	%g6, [%g3 + TRAP_ENT_TPC]%asi
2554	MMU_FAULT_STATUS_AREA(%g6)
2555	ldx	[%g6 + MMFSA_I_ADDR], %g4
2556	stxa	%g4, [%g3 + TRAP_ENT_TR]%asi
2557	ldx	[%g6 + MMFSA_I_CTX], %g4
2558	stxa	%g4, [%g3 + TRAP_ENT_F1]%asi
2559	ldx	[%g6 + MMFSA_I_TYPE], %g4
2560	stxa	%g4, [%g3 + TRAP_ENT_F2]%asi
2561	stxa	%g6, [%g3 + TRAP_ENT_F3]%asi
2562	stna	%g0, [%g3 + TRAP_ENT_F4]%asi
2563	TRACE_NEXT(%g3, %g4, %g5)
2564	jmp	%g7 + 4
2565	nop
2566
2567trace_gen:
2568	TRACE_PTR(%g3, %g6)
2569	GET_TRACE_TICK(%g6)
2570	stxa	%g6, [%g3 + TRAP_ENT_TICK]%asi
2571	TRACE_SAVE_TL_GL_REGS(%g3, %g6)
2572	rdpr	%tt, %g6
2573	stha	%g6, [%g3 + TRAP_ENT_TT]%asi
2574	rdpr	%tstate, %g6
2575	stxa	%g6, [%g3 + TRAP_ENT_TSTATE]%asi
2576	stna	%sp, [%g3 + TRAP_ENT_SP]%asi
2577	rdpr	%tpc, %g6
2578	stna	%g6, [%g3 + TRAP_ENT_TPC]%asi
2579	stna	%g0, [%g3 + TRAP_ENT_TR]%asi
2580	stna	%g0, [%g3 + TRAP_ENT_F1]%asi
2581	stna	%g0, [%g3 + TRAP_ENT_F2]%asi
2582	stna	%g0, [%g3 + TRAP_ENT_F3]%asi
2583	stna	%g0, [%g3 + TRAP_ENT_F4]%asi
2584	TRACE_NEXT(%g3, %g4, %g5)
2585	jmp	%g7 + 4
2586	nop
2587
2588trace_win:
2589	TRACE_WIN_INFO(0, %l0, %l1, %l2)
2590	! Keep the locals as clean as possible, caller cleans %l4
2591	clr	%l2
2592	clr	%l1
2593	jmp	%l4 + 4
2594	  clr	%l0
2595
2596/*
2597 * Trace a tsb hit
2598 * g1 = tsbe pointer (in/clobbered)
2599 * g2 = tag access register (in)
2600 * g3 - g4 = scratch (clobbered)
2601 * g5 = tsbe data (in)
2602 * g6 = scratch (clobbered)
2603 * g7 = pc we jumped here from (in)
2604 */
2605
2606	! Do not disturb %g5, it will be used after the trace
2607	ALTENTRY(trace_tsbhit)
2608	TRACE_TSBHIT(0)
2609	jmp	%g7 + 4
2610	nop
2611
2612/*
2613 * Trace a TSB miss
2614 *
2615 * g1 = tsb8k pointer (in)
2616 * g2 = tag access register (in)
2617 * g3 = tsb4m pointer (in)
2618 * g4 = tsbe tag (in/clobbered)
2619 * g5 - g6 = scratch (clobbered)
2620 * g7 = pc we jumped here from (in)
2621 */
2622	.global	trace_tsbmiss
2623trace_tsbmiss:
2624	membar	#Sync
2625	sethi	%hi(FLUSH_ADDR), %g6
2626	flush	%g6
2627	TRACE_PTR(%g5, %g6)
2628	GET_TRACE_TICK(%g6)
2629	stxa	%g6, [%g5 + TRAP_ENT_TICK]%asi
2630	stna	%g2, [%g5 + TRAP_ENT_SP]%asi		! tag access
2631	stna	%g4, [%g5 + TRAP_ENT_F1]%asi		! XXX? tsb tag
2632	rdpr	%tnpc, %g6
2633	stna	%g6, [%g5 + TRAP_ENT_F2]%asi
2634	stna	%g1, [%g5 + TRAP_ENT_F3]%asi		! tsb8k pointer
2635	rdpr	%tpc, %g6
2636	stna	%g6, [%g5 + TRAP_ENT_TPC]%asi
2637	TRACE_SAVE_TL_GL_REGS(%g5, %g6)
2638	rdpr	%tt, %g6
2639	or	%g6, TT_MMU_MISS, %g4
2640	stha	%g4, [%g5 + TRAP_ENT_TT]%asi
2641	mov	MMFSA_D_ADDR, %g4
2642	cmp	%g6, FAST_IMMU_MISS_TT
2643	move	%xcc, MMFSA_I_ADDR, %g4
2644	cmp	%g6, T_INSTR_MMU_MISS
2645	move	%xcc, MMFSA_I_ADDR, %g4
2646	MMU_FAULT_STATUS_AREA(%g6)
2647	ldx	[%g6 + %g4], %g6
2648	stxa	%g6, [%g5 + TRAP_ENT_TSTATE]%asi	! tag target
2649	cmp	%g4, MMFSA_D_ADDR
2650	move	%xcc, MMFSA_D_CTX, %g4
2651	movne	%xcc, MMFSA_I_CTX, %g4
2652	MMU_FAULT_STATUS_AREA(%g6)
2653	ldx	[%g6 + %g4], %g6
2654	stxa	%g6, [%g5 + TRAP_ENT_F4]%asi		! context ID
2655	stna	%g3, [%g5 + TRAP_ENT_TR]%asi		! tsb4m pointer
2656	TRACE_NEXT(%g5, %g4, %g6)
2657	jmp	%g7 + 4
2658	nop
2659
2660/*
2661 * g2 = tag access register (in)
2662 * g3 = ctx type (0, 1 or 2) (in) (not used)
2663 */
2664trace_dataprot:
2665	membar	#Sync
2666	sethi	%hi(FLUSH_ADDR), %g6
2667	flush	%g6
2668	TRACE_PTR(%g1, %g6)
2669	GET_TRACE_TICK(%g6)
2670	stxa	%g6, [%g1 + TRAP_ENT_TICK]%asi
2671	rdpr	%tpc, %g6
2672	stna	%g6, [%g1 + TRAP_ENT_TPC]%asi
2673	rdpr	%tstate, %g6
2674	stxa	%g6, [%g1 + TRAP_ENT_TSTATE]%asi
2675	stna	%g2, [%g1 + TRAP_ENT_SP]%asi		! tag access reg
2676	stna	%g0, [%g1 + TRAP_ENT_F1]%asi
2677	stna	%g0, [%g1 + TRAP_ENT_F2]%asi
2678	stna	%g0, [%g1 + TRAP_ENT_F3]%asi
2679	stna	%g0, [%g1 + TRAP_ENT_F4]%asi
2680	TRACE_SAVE_TL_GL_REGS(%g1, %g6)
2681	rdpr	%tt, %g6
2682	stha	%g6, [%g1 + TRAP_ENT_TT]%asi
2683	mov	MMFSA_D_CTX, %g4
2684	cmp	%g6, FAST_IMMU_MISS_TT
2685	move	%xcc, MMFSA_I_CTX, %g4
2686	cmp	%g6, T_INSTR_MMU_MISS
2687	move	%xcc, MMFSA_I_CTX, %g4
2688	MMU_FAULT_STATUS_AREA(%g6)
2689	ldx	[%g6 + %g4], %g6
2690	stxa	%g6, [%g1 + TRAP_ENT_TR]%asi	! context ID
2691	TRACE_NEXT(%g1, %g4, %g5)
2692	jmp	%g7 + 4
2693	nop
2694
2695#endif /* TRAPTRACE */
2696
2697/*
2698 * Handle watchdog reset trap. Enable the MMU using the MMU_ENABLE
2699 * HV service, which requires the return target to be specified as a VA
2700 * since we are enabling the MMU. We set the target to ptl1_panic.
2701 */
2702
2703	.type	.watchdog_trap, #function
2704.watchdog_trap:
2705	mov	1, %o0
2706	setx	ptl1_panic, %g2, %o1
2707	mov	MMU_ENABLE, %o5
2708	ta	FAST_TRAP
2709	done
2710	SET_SIZE(.watchdog_trap)
2711/*
2712 * synthesize for trap(): SFAR in %g2, SFSR in %g3
2713 */
2714	.type	.dmmu_exc_lddf_not_aligned, #function
2715.dmmu_exc_lddf_not_aligned:
2716	MMU_FAULT_STATUS_AREA(%g3)
2717	ldx	[%g3 + MMFSA_D_ADDR], %g2
2718	/* Fault type not available in MMU fault status area */
2719	mov	MMFSA_F_UNALIGN, %g1
2720	ldx	[%g3 + MMFSA_D_CTX], %g3
2721	sllx	%g3, SFSR_CTX_SHIFT, %g3
2722	btst	1, %sp
2723	bnz,pt	%xcc, .lddf_exception_not_aligned
2724	or	%g3, %g1, %g3			/* SFSR */
2725	ba,a,pt	%xcc, .mmu_exception_not_aligned
2726	SET_SIZE(.dmmu_exc_lddf_not_aligned)
2727
2728/*
2729 * synthesize for trap(): SFAR in %g2, SFSR in %g3
2730 */
2731	.type	.dmmu_exc_stdf_not_aligned, #function
2732.dmmu_exc_stdf_not_aligned:
2733	MMU_FAULT_STATUS_AREA(%g3)
2734	ldx	[%g3 + MMFSA_D_ADDR], %g2
2735	/* Fault type not available in MMU fault status area */
2736	mov	MMFSA_F_UNALIGN, %g1
2737	ldx	[%g3 + MMFSA_D_CTX], %g3
2738	sllx	%g3, SFSR_CTX_SHIFT, %g3
2739	btst	1, %sp
2740	bnz,pt	%xcc, .stdf_exception_not_aligned
2741	or	%g3, %g1, %g3			/* SFSR */
2742	ba,a,pt	%xcc, .mmu_exception_not_aligned
2743	SET_SIZE(.dmmu_exc_stdf_not_aligned)
2744
2745	.type	.dmmu_exception, #function
2746.dmmu_exception:
2747	MMU_FAULT_STATUS_AREA(%g3)
2748	ldx	[%g3 + MMFSA_D_ADDR], %g2
2749	ldx	[%g3 + MMFSA_D_TYPE], %g1
2750	ldx	[%g3 + MMFSA_D_CTX], %g4
2751	srlx	%g2, MMU_PAGESHIFT, %g2		/* align address */
2752	sllx	%g2, MMU_PAGESHIFT, %g2
2753	sllx	%g4, SFSR_CTX_SHIFT, %g3
2754	or	%g3, %g1, %g3			/* SFSR */
2755	cmp	%g4, USER_CONTEXT_TYPE
2756	movgeu	%icc, USER_CONTEXT_TYPE, %g4
2757	or	%g2, %g4, %g2			/* TAG_ACCESS */
2758	ba,pt	%xcc, .mmu_exception_end
2759	mov	T_DATA_EXCEPTION, %g1
2760	SET_SIZE(.dmmu_exception)
2761
2762/*
2763 * Firmware on some platforms treats missing execute permission
2764 * as an exception instead of an IMMU miss. Solaris and OBP both
2765 * expect an IMMU miss.  The expectation is that the sun4v spec
2766 * will change, and the current handling will be correct.
2767 *
2768 * We simply fold these 2 paths together. This is done in order to
2769 * handle the non-coherent I-cache case.
2770 */
2771   .type    .immu_exception, #function
2772.immu_exception:
2773	MMU_FAULT_STATUS_AREA(%g3)
2774	rdpr	%tpc, %g2
2775	ldx	[%g3 + MMFSA_I_TYPE], %g1
2776	ldx	[%g3 + MMFSA_I_CTX], %g3
2777	sllx	%g3, SFSR_CTX_SHIFT, %g3
2778	or	%g3, %g1, %g3
2779	cmp	%g1, MMFSA_F_PROT
2780	be,a,pt	%icc, sfmmu_slow_immu_miss
2781	  wrpr	%g0, T_INSTR_MMU_MISS, %tt
2782	ba,pt	%xcc, .mmu_exception_end
2783	  mov	T_INSTR_EXCEPTION, %g1
2784	SET_SIZE(.immu_exception)
2785
2786/*
2787 * fast_trap_done, fast_trap_done_chk_intr:
2788 *
2789 * Due to the design of UltraSPARC pipeline, pending interrupts are not
2790 * taken immediately after a RETRY or DONE instruction which causes IE to
2791 * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed
2792 * to execute first before taking any interrupts. If that instruction
2793 * results in other traps, and if the corresponding trap handler runs
2794 * entirely at TL=1 with interrupts disabled, then pending interrupts
2795 * won't be taken until after yet another instruction following the %tpc
2796 * or %tnpc.
2797 *
2798 * A malicious user program can use this feature to block out interrupts
2799 * for extended durations, which can result in send_mondo_timeout kernel
2800 * panic.
2801 *
2802 * This problem is addressed by servicing any pending interrupts via
2803 * sys_trap before returning back to the user mode from a fast trap
2804 * handler. The "done" instruction within a fast trap handler, which
2805 * runs entirely at TL=1 with interrupts disabled, is replaced with the
2806 * FAST_TRAP_DONE macro, which branches control to this fast_trap_done
2807 * entry point.
2808 *
2809 * We check for any pending interrupts here and force a sys_trap to
2810 * service those interrupts, if any. To minimize overhead, pending
2811 * interrupts are checked if the %tpc happens to be at 16K boundary,
2812 * which allows a malicious program to execute at most 4K consecutive
2813 * instructions before we service any pending interrupts. If a worst
2814 * case fast trap handler takes about 2 usec, then interrupts will be
2815 * blocked for at most 8 msec, less than a clock tick.
2816 *
2817 * For the cases where we don't know if the %tpc will cross a 16K
2818 * boundary, we can't use the above optimization and always process
2819 * any pending interrupts via fast_frap_done_chk_intr entry point.
2820 *
2821 * Entry Conditions:
2822 * 	%pstate		am:0 priv:1 ie:0
2823 * 			globals are AG (not normal globals)
2824 */
2825
2826	.global	fast_trap_done, fast_trap_done_chk_intr
2827fast_trap_done:
2828	rdpr	%tpc, %g5
2829	sethi	%hi(0xffffc000), %g6	! 1's complement of 0x3fff
2830	andncc	%g5, %g6, %g0		! check lower 14 bits of %tpc
2831	bz,pn	%icc, 1f		! branch if zero (lower 32 bits only)
2832	nop
2833	done
2834
2835fast_trap_done_chk_intr:
28361:	rd	SOFTINT, %g6
2837	brnz,pn	%g6, 2f		! branch if any pending intr
2838	nop
2839	done
2840
28412:
2842	/*
2843	 * We get here if there are any pending interrupts.
2844	 * Adjust %tpc/%tnpc as we'll be resuming via "retry"
2845	 * instruction.
2846	 */
2847	rdpr	%tnpc, %g5
2848	wrpr	%g0, %g5, %tpc
2849	add	%g5, 4, %g5
2850	wrpr	%g0, %g5, %tnpc
2851
2852	/*
2853	 * Force a dummy sys_trap call so that interrupts can be serviced.
2854	 */
2855	set	fast_trap_dummy_call, %g1
2856	ba,pt	%xcc, sys_trap
2857	  mov	-1, %g4
2858
2859fast_trap_dummy_call:
2860	retl
2861	nop
2862
2863/*
2864 * Currently the brand syscall interposition code is not enabled by
2865 * default.  Instead, when a branded zone is first booted the brand
2866 * infrastructure will patch the trap table so that the syscall
2867 * entry points are redirected to syscall_wrapper32 and syscall_wrapper
2868 * for ILP32 and LP64 syscalls respectively.  this is done in
2869 * brand_plat_interposition_enable().  Note that the syscall wrappers
2870 * below do not collect any trap trace data since the syscall hot patch
2871 * points are reached after trap trace data has already been collected.
2872 */
2873#define	BRAND_CALLBACK(callback_id)					    \
2874	CPU_ADDR(%g2, %g1)		/* load CPU struct addr to %g2	*/ ;\
2875	ldn	[%g2 + CPU_THREAD], %g3	/* load thread pointer		*/ ;\
2876	ldn	[%g3 + T_PROCP], %g3	/* get proc pointer		*/ ;\
2877	ldn	[%g3 + P_BRAND], %g3	/* get brand pointer		*/ ;\
2878	brz	%g3, 1f			/* No brand?  No callback. 	*/ ;\
2879	nop 								   ;\
2880	ldn	[%g3 + B_MACHOPS], %g3	/* get machops list		*/ ;\
2881	ldn	[%g3 + (callback_id << 3)], %g3 			   ;\
2882	brz	%g3, 1f							   ;\
2883	/*								    \
2884	 * This isn't pretty.  We want a low-latency way for the callback   \
2885	 * routine to decline to do anything.  We just pass in an address   \
2886	 * the routine can directly jmp back to, pretending that nothing    \
2887	 * has happened.						    \
2888	 * 								    \
2889	 * %g1: return address (where the brand handler jumps back to)	    \
2890	 * %g2: address of CPU structure				    \
2891	 * %g3: address of brand handler (where we will jump to)	    \
2892	 */								    \
2893	mov	%pc, %g1						   ;\
2894	add	%g1, 16, %g1						   ;\
2895	jmp	%g3							   ;\
2896	nop								   ;\
28971:
2898
2899	ENTRY_NP(syscall_wrapper32)
2900	BRAND_CALLBACK(BRAND_CB_SYSCALL32)
2901	SYSCALL_NOTT(syscall_trap32)
2902	SET_SIZE(syscall_wrapper32)
2903
2904	ENTRY_NP(syscall_wrapper)
2905	BRAND_CALLBACK(BRAND_CB_SYSCALL)
2906	SYSCALL_NOTT(syscall_trap)
2907	SET_SIZE(syscall_wrapper)
2908
2909#endif	/* lint */
2910