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