]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sparc64/sparc64/exception.S
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sparc64 / sparc64 / exception.S
1 /*-
2  * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. Berkeley Software Design Inc's name may not be used to endorse or
13  *    promote products derived from this software without specific prior
14  *    written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *      BSDI $Id: locore.s,v 1.36.2.15 1999/08/23 22:34:41 cp Exp $
29  */
30 /*-
31  * Copyright (c) 2001 Jake Burkholder.
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms, with or without
35  * modification, are permitted provided that the following conditions
36  * are met:
37  * 1. Redistributions of source code must retain the above copyright
38  *    notice, this list of conditions and the following disclaimer.
39  * 2. Redistributions in binary form must reproduce the above copyright
40  *    notice, this list of conditions and the following disclaimer in the
41  *    documentation and/or other materials provided with the distribution.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53  * SUCH DAMAGE.
54  */
55
56 #include <machine/asm.h>
57 __FBSDID("$FreeBSD$");
58
59 #include "opt_compat.h"
60 #include "opt_ddb.h"
61
62 #include <machine/asi.h>
63 #include <machine/asmacros.h>
64 #include <machine/frame.h>
65 #include <machine/fsr.h>
66 #include <machine/intr_machdep.h>
67 #include <machine/ktr.h>
68 #include <machine/pcb.h>
69 #include <machine/pstate.h>
70 #include <machine/trap.h>
71 #include <machine/tsb.h>
72 #include <machine/tstate.h>
73 #include <machine/utrap.h>
74 #include <machine/wstate.h>
75
76 #include "assym.s"
77
78 #define TSB_KERNEL_MASK 0x0
79 #define TSB_KERNEL      0x0
80
81         .register %g2,#ignore
82         .register %g3,#ignore
83         .register %g6,#ignore
84         .register %g7,#ignore
85
86 /*
87  * Atomically set the reference bit in a TTE.
88  */
89 #define TTE_SET_BIT(r1, r2, r3, bit) \
90         add     r1, TTE_DATA, r1 ; \
91         ldx     [r1], r2 ; \
92 9:      or      r2, bit, r3 ; \
93         casxa   [r1] ASI_N, r2, r3 ; \
94         cmp     r2, r3 ; \
95         bne,pn  %xcc, 9b ; \
96          mov    r3, r2
97
98 #define TTE_SET_REF(r1, r2, r3)         TTE_SET_BIT(r1, r2, r3, TD_REF)
99 #define TTE_SET_W(r1, r2, r3)           TTE_SET_BIT(r1, r2, r3, TD_W)
100
101 /*
102  * Macros for spilling and filling live windows.
103  *
104  * NOTE: These macros use exactly 16 instructions, and it is assumed that the
105  * handler will not use more than 24 instructions total, to leave room for
106  * resume vectors which occupy the last 8 instructions.
107  */
108
109 #define SPILL(storer, base, size, asi) \
110         storer  %l0, [base + (0 * size)] asi ; \
111         storer  %l1, [base + (1 * size)] asi ; \
112         storer  %l2, [base + (2 * size)] asi ; \
113         storer  %l3, [base + (3 * size)] asi ; \
114         storer  %l4, [base + (4 * size)] asi ; \
115         storer  %l5, [base + (5 * size)] asi ; \
116         storer  %l6, [base + (6 * size)] asi ; \
117         storer  %l7, [base + (7 * size)] asi ; \
118         storer  %i0, [base + (8 * size)] asi ; \
119         storer  %i1, [base + (9 * size)] asi ; \
120         storer  %i2, [base + (10 * size)] asi ; \
121         storer  %i3, [base + (11 * size)] asi ; \
122         storer  %i4, [base + (12 * size)] asi ; \
123         storer  %i5, [base + (13 * size)] asi ; \
124         storer  %i6, [base + (14 * size)] asi ; \
125         storer  %i7, [base + (15 * size)] asi
126
127 #define FILL(loader, base, size, asi) \
128         loader  [base + (0 * size)] asi, %l0 ; \
129         loader  [base + (1 * size)] asi, %l1 ; \
130         loader  [base + (2 * size)] asi, %l2 ; \
131         loader  [base + (3 * size)] asi, %l3 ; \
132         loader  [base + (4 * size)] asi, %l4 ; \
133         loader  [base + (5 * size)] asi, %l5 ; \
134         loader  [base + (6 * size)] asi, %l6 ; \
135         loader  [base + (7 * size)] asi, %l7 ; \
136         loader  [base + (8 * size)] asi, %i0 ; \
137         loader  [base + (9 * size)] asi, %i1 ; \
138         loader  [base + (10 * size)] asi, %i2 ; \
139         loader  [base + (11 * size)] asi, %i3 ; \
140         loader  [base + (12 * size)] asi, %i4 ; \
141         loader  [base + (13 * size)] asi, %i5 ; \
142         loader  [base + (14 * size)] asi, %i6 ; \
143         loader  [base + (15 * size)] asi, %i7
144
145 #define ERRATUM50(reg)  mov reg, reg
146
147 #define KSTACK_SLOP     1024
148
149 /*
150  * Sanity check the kernel stack and bail out if it's wrong.
151  * XXX: doesn't handle being on the panic stack.
152  */
153 #define KSTACK_CHECK \
154         dec     16, ASP_REG ; \
155         stx     %g1, [ASP_REG + 0] ; \
156         stx     %g2, [ASP_REG + 8] ; \
157         add     %sp, SPOFF, %g1 ; \
158         andcc   %g1, (1 << PTR_SHIFT) - 1, %g0 ; \
159         bnz,a   %xcc, tl1_kstack_fault ; \
160          inc    16, ASP_REG ; \
161         ldx     [PCPU(CURTHREAD)], %g2 ; \
162         ldx     [%g2 + TD_KSTACK], %g2 ; \
163         add     %g2, KSTACK_SLOP, %g2 ; \
164         subcc   %g1, %g2, %g1 ; \
165         ble,a   %xcc, tl1_kstack_fault ; \
166          inc    16, ASP_REG ; \
167         set     KSTACK_PAGES * PAGE_SIZE, %g2 ; \
168         cmp     %g1, %g2 ; \
169         bgt,a   %xcc, tl1_kstack_fault ; \
170          inc    16, ASP_REG ; \
171         ldx     [ASP_REG + 8], %g2 ; \
172         ldx     [ASP_REG + 0], %g1 ; \
173         inc     16, ASP_REG
174
175         .globl  tl_text_begin
176 tl_text_begin:
177         nop
178
179 ENTRY(tl1_kstack_fault)
180         rdpr    %tl, %g1
181 1:      cmp     %g1, 2
182         be,a    2f
183          nop
184
185 #if KTR_COMPILE & KTR_TRAP
186         CATR(KTR_TRAP, "tl1_kstack_fault: tl=%#lx tpc=%#lx tnpc=%#lx"
187             , %g2, %g3, %g4, 7, 8, 9)
188         rdpr    %tl, %g3
189         stx     %g3, [%g2 + KTR_PARM1]
190         rdpr    %tpc, %g3
191         stx     %g3, [%g2 + KTR_PARM1]
192         rdpr    %tnpc, %g3
193         stx     %g3, [%g2 + KTR_PARM1]
194 9:
195 #endif
196
197         sub     %g1, 1, %g1
198         wrpr    %g1, 0, %tl
199         ba,a    %xcc, 1b
200          nop
201
202 2:
203 #if KTR_COMPILE & KTR_TRAP
204         CATR(KTR_TRAP,
205             "tl1_kstack_fault: sp=%#lx ks=%#lx cr=%#lx cs=%#lx ow=%#lx ws=%#lx"
206             , %g1, %g2, %g3, 7, 8, 9)
207         add     %sp, SPOFF, %g2
208         stx     %g2, [%g1 + KTR_PARM1]
209         ldx     [PCPU(CURTHREAD)], %g2
210         ldx     [%g2 + TD_KSTACK], %g2
211         stx     %g2, [%g1 + KTR_PARM2]
212         rdpr    %canrestore, %g2
213         stx     %g2, [%g1 + KTR_PARM3]
214         rdpr    %cansave, %g2
215         stx     %g2, [%g1 + KTR_PARM4]
216         rdpr    %otherwin, %g2
217         stx     %g2, [%g1 + KTR_PARM5]
218         rdpr    %wstate, %g2
219         stx     %g2, [%g1 + KTR_PARM6]
220 9:
221 #endif
222
223         wrpr    %g0, 0, %canrestore
224         wrpr    %g0, 6, %cansave
225         wrpr    %g0, 0, %otherwin
226         wrpr    %g0, WSTATE_KERNEL, %wstate
227
228         sub     ASP_REG, SPOFF + CCFSZ, %sp
229         clr     %fp
230
231         set     trap, %o2
232         ba      %xcc, tl1_trap
233          mov    T_KSTACK_FAULT | T_KERNEL, %o0
234 END(tl1_kstack_fault)
235
236 /*
237  * Magic to resume from a spill or fill trap.  If we get an alignment or an
238  * MMU fault during a spill or a fill, this macro will detect the fault and
239  * resume at a set instruction offset in the trap handler.
240  *
241  * To check if the previous trap was a spill/fill we convert the trapped pc
242  * to a trap type and verify that it is in the range of spill/fill vectors.
243  * The spill/fill vectors are types 0x80-0xff and 0x280-0x2ff, masking off the
244  * tl bit allows us to detect both ranges with one test.
245  *
246  * This is:
247  *      0x80 <= (((%tpc - %tba) >> 5) & ~0x200) < 0x100
248  *
249  * To calculate the new pc we take advantage of the xor feature of wrpr.
250  * Forcing all the low bits of the trapped pc on we can produce any offset
251  * into the spill/fill vector.  The size of a spill/fill trap vector is 0x80.
252  *
253  *      0x7f ^ 0x1f == 0x60
254  *      0x1f == (0x80 - 0x60) - 1
255  *
256  * Which are the offset and xor value used to resume from alignment faults.
257  */
258
259 /*
260  * Determine if we have trapped inside of a spill/fill vector, and if so resume
261  * at a fixed instruction offset in the trap vector.  Must be called on
262  * alternate globals.
263  */
264 #define RESUME_SPILLFILL_MAGIC(stxa_g0_sfsr, xor) \
265         dec     16, ASP_REG ; \
266         stx     %g1, [ASP_REG + 0] ; \
267         stx     %g2, [ASP_REG + 8] ; \
268         rdpr    %tpc, %g1 ; \
269         ERRATUM50(%g1) ; \
270         rdpr    %tba, %g2 ; \
271         sub     %g1, %g2, %g2 ; \
272         srlx    %g2, 5, %g2 ; \
273         andn    %g2, 0x200, %g2 ; \
274         cmp     %g2, 0x80 ; \
275         blu,pt  %xcc, 9f ; \
276          cmp    %g2, 0x100 ; \
277         bgeu,pt %xcc, 9f ; \
278          or     %g1, 0x7f, %g1 ; \
279         wrpr    %g1, xor, %tnpc ; \
280         stxa_g0_sfsr ; \
281         ldx     [ASP_REG + 8], %g2 ; \
282         ldx     [ASP_REG + 0], %g1 ; \
283         inc     16, ASP_REG ; \
284         done ; \
285 9:      ldx     [ASP_REG + 8], %g2 ; \
286         ldx     [ASP_REG + 0], %g1 ; \
287         inc     16, ASP_REG
288
289 /*
290  * For certain faults we need to clear the SFSR MMU register before returning.
291  */
292 #define RSF_CLR_SFSR \
293         wr      %g0, ASI_DMMU, %asi ; \
294         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
295
296 #define RSF_XOR(off)    ((0x80 - off) - 1)
297
298 /*
299  * Instruction offsets in spill and fill trap handlers for handling certain
300  * nested traps, and corresponding xor constants for wrpr.
301  */
302 #define RSF_OFF_ALIGN   0x60
303 #define RSF_OFF_MMU     0x70
304
305 #define RESUME_SPILLFILL_ALIGN \
306         RESUME_SPILLFILL_MAGIC(RSF_CLR_SFSR, RSF_XOR(RSF_OFF_ALIGN))
307 #define RESUME_SPILLFILL_MMU \
308         RESUME_SPILLFILL_MAGIC(EMPTY, RSF_XOR(RSF_OFF_MMU))
309 #define RESUME_SPILLFILL_MMU_CLR_SFSR \
310         RESUME_SPILLFILL_MAGIC(RSF_CLR_SFSR, RSF_XOR(RSF_OFF_MMU))
311
312 /*
313  * Constant to add to %tnpc when taking a fill trap just before returning to
314  * user mode.
315  */
316 #define RSF_FILL_INC    tl0_ret_fill_end - tl0_ret_fill
317
318 /*
319  * Generate a T_SPILL or T_FILL trap if the window operation fails.
320  */
321 #define RSF_TRAP(type) \
322         ba      %xcc, tl0_sftrap ; \
323          mov    type, %g2 ; \
324         .align  16
325
326 /*
327  * Game over if the window operation fails.
328  */
329 #define RSF_FATAL(type) \
330         ba      %xcc, rsf_fatal ; \
331          mov    type, %g2 ; \
332         .align  16
333
334 /*
335  * Magic to resume from a failed fill a few instructions after the corrsponding
336  * restore.  This is used on return from the kernel to usermode.
337  */
338 #define RSF_FILL_MAGIC \
339         rdpr    %tnpc, %g1 ; \
340         add     %g1, RSF_FILL_INC, %g1 ; \
341         wrpr    %g1, 0, %tnpc ; \
342         done ; \
343         .align  16
344
345 /*
346  * Spill to the pcb if a spill to the user stack in kernel mode fails.
347  */
348 #define RSF_SPILL_TOPCB \
349         ba,a    %xcc, tl1_spill_topcb ; \
350          nop ; \
351         .align  16
352
353 ENTRY(rsf_fatal)
354 #if KTR_COMPILE & KTR_TRAP
355         CATR(KTR_TRAP, "rsf_fatal: bad window trap tt=%#lx type=%#lx"
356             , %g1, %g3, %g4, 7, 8, 9)
357         rdpr    %tt, %g3
358         stx     %g3, [%g1 + KTR_PARM1]
359         stx     %g2, [%g1 + KTR_PARM2]
360 9:
361 #endif
362
363         KSTACK_CHECK
364
365         sir
366 END(rsf_fatal)
367
368         .comm   intrnames, IV_NAMLEN
369         .comm   eintrnames, 0
370
371         .comm   intrcnt, IV_MAX * 8
372         .comm   eintrcnt, 0
373
374 /*
375  * Trap table and associated macros
376  *
377  * Due to its size a trap table is an inherently hard thing to represent in
378  * code in a clean way.  There are approximately 1024 vectors, of 8 or 32
379  * instructions each, many of which are identical.  The way that this is
380  * layed out is the instructions (8 or 32) for the actual trap vector appear
381  * as an AS macro.  In general this code branches to tl0_trap or tl1_trap,
382  * but if not supporting code can be placed just after the definition of the
383  * macro.  The macros are then instantiated in a different section (.trap),
384  * which is setup to be placed by the linker at the beginning of .text, and the
385  * code around the macros is moved to the end of trap table.  In this way the
386  * code that must be sequential in memory can be split up, and located near
387  * its supporting code so that it is easier to follow.
388  */
389
390         /*
391          * Clean window traps occur when %cleanwin is zero to ensure that data
392          * is not leaked between address spaces in registers.
393          */
394         .macro  clean_window
395         clr     %o0
396         clr     %o1
397         clr     %o2
398         clr     %o3
399         clr     %o4
400         clr     %o5
401         clr     %o6
402         clr     %o7
403         clr     %l0
404         clr     %l1
405         clr     %l2
406         clr     %l3
407         clr     %l4
408         clr     %l5
409         clr     %l6
410         rdpr    %cleanwin, %l7
411         inc     %l7
412         wrpr    %l7, 0, %cleanwin
413         clr     %l7
414         retry
415         .align  128
416         .endm
417
418         /*
419          * Stack fixups for entry from user mode.  We are still running on the
420          * user stack, and with its live registers, so we must save soon.  We
421          * are on alternate globals so we do have some registers.  Set the
422          * transitional window state, and do the save.  If this traps we
423          * attempt to spill a window to the user stack.  If this fails, we
424          * spill the window to the pcb and continue.  Spilling to the pcb
425          * must not fail.
426          *
427          * NOTE: Must be called with alternate globals and clobbers %g1.
428          */
429
430         .macro  tl0_split
431         rdpr    %wstate, %g1
432         wrpr    %g1, WSTATE_TRANSITION, %wstate
433         save
434         .endm
435
436         .macro  tl0_setup       type
437         tl0_split
438         clr     %o1
439         set     trap, %o2
440         ba      %xcc, tl0_utrap
441          mov    \type, %o0
442         .endm
443
444         /*
445          * Generic trap type.  Call trap() with the specified type.
446          */
447         .macro  tl0_gen         type
448         tl0_setup \type
449         .align  32
450         .endm
451
452         /*
453          * This is used to suck up the massive swaths of reserved trap types.
454          * Generates count "reserved" trap vectors.
455          */
456         .macro  tl0_reserved    count
457         .rept   \count
458         tl0_gen T_RESERVED
459         .endr
460         .endm
461
462         .macro  tl1_split
463         rdpr    %wstate, %g1
464         wrpr    %g1, WSTATE_NESTED, %wstate
465         save    %sp, -(CCFSZ + TF_SIZEOF), %sp
466         .endm
467
468         .macro  tl1_setup       type
469         tl1_split
470         clr     %o1
471         set     trap, %o2
472         ba      %xcc, tl1_trap
473          mov    \type | T_KERNEL, %o0
474         .endm
475
476         .macro  tl1_gen         type
477         tl1_setup \type
478         .align  32
479         .endm
480
481         .macro  tl1_reserved    count
482         .rept   \count
483         tl1_gen T_RESERVED
484         .endr
485         .endm
486
487         .macro  tl0_insn_excptn
488         wrpr    %g0, PSTATE_ALT, %pstate
489         wr      %g0, ASI_IMMU, %asi
490         rdpr    %tpc, %g3
491         ldxa    [%g0 + AA_IMMU_SFSR] %asi, %g4
492         /*
493          * XXX in theory, a store to AA_IMMU_SFSR must be immediately
494          * followed by a DONE, FLUSH or RETRY for USIII.  In practice,
495          * this triggers a RED state exception though.
496          */
497         stxa    %g0, [%g0 + AA_IMMU_SFSR] %asi
498         membar  #Sync
499         ba      %xcc, tl0_sfsr_trap
500          mov    T_INSTRUCTION_EXCEPTION, %g2
501         .align  32
502         .endm
503
504         .macro  tl0_data_excptn
505         wrpr    %g0, PSTATE_ALT, %pstate
506         wr      %g0, ASI_DMMU, %asi
507         ldxa    [%g0 + AA_DMMU_SFAR] %asi, %g3
508         ldxa    [%g0 + AA_DMMU_SFSR] %asi, %g4
509         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
510         membar  #Sync
511         ba      %xcc, tl0_sfsr_trap
512          mov    T_DATA_EXCEPTION, %g2
513         .align  32
514         .endm
515
516         .macro  tl0_align
517         wr      %g0, ASI_DMMU, %asi
518         ldxa    [%g0 + AA_DMMU_SFAR] %asi, %g3
519         ldxa    [%g0 + AA_DMMU_SFSR] %asi, %g4
520         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
521         membar  #Sync
522         ba      %xcc, tl0_sfsr_trap
523          mov    T_MEM_ADDRESS_NOT_ALIGNED, %g2
524         .align  32
525         .endm
526
527 ENTRY(tl0_sfsr_trap)
528         tl0_split
529         clr     %o1
530         set     trap, %o2
531         mov     %g3, %o4
532         mov     %g4, %o5
533         ba      %xcc, tl0_utrap
534          mov    %g2, %o0
535 END(tl0_sfsr_trap)
536
537         .macro  tl0_intr level, mask
538         tl0_split
539         set     \mask, %o1
540         ba      %xcc, tl0_intr
541          mov    \level, %o0
542         .align  32
543         .endm
544
545 #define INTR(level, traplvl)                                            \
546         tl ## traplvl ## _intr  level, 1 << level
547
548 #define TICK(traplvl) \
549         tl ## traplvl ## _intr  PIL_TICK, 0x10001
550
551 #define INTR_LEVEL(tl)                                                  \
552         INTR(1, tl) ;                                                   \
553         INTR(2, tl) ;                                                   \
554         INTR(3, tl) ;                                                   \
555         INTR(4, tl) ;                                                   \
556         INTR(5, tl) ;                                                   \
557         INTR(6, tl) ;                                                   \
558         INTR(7, tl) ;                                                   \
559         INTR(8, tl) ;                                                   \
560         INTR(9, tl) ;                                                   \
561         INTR(10, tl) ;                                                  \
562         INTR(11, tl) ;                                                  \
563         INTR(12, tl) ;                                                  \
564         INTR(13, tl) ;                                                  \
565         TICK(tl) ;                                                      \
566         INTR(15, tl) ;
567
568         .macro  tl0_intr_level
569         INTR_LEVEL(0)
570         .endm
571
572         .macro  intr_vector
573         ldxa    [%g0] ASI_INTR_RECEIVE, %g1
574         andcc   %g1, IRSR_BUSY, %g0
575         bnz,a,pt %xcc, intr_vector
576          nop
577         sir
578         .align  32
579         .endm
580
581         .macro  tl0_immu_miss
582         /*
583          * Load the context and the virtual page number from the tag access
584          * register.  We ignore the context.
585          */
586         wr      %g0, ASI_IMMU, %asi
587         ldxa    [%g0 + AA_IMMU_TAR] %asi, %g1
588
589         /*
590          * Initialize the page size walker.
591          */
592         mov     TS_MIN, %g2
593
594         /*
595          * Loop over all supported page sizes.
596          */
597
598         /*
599          * Compute the page shift for the page size we are currently looking
600          * for.
601          */
602 1:      add     %g2, %g2, %g3
603         add     %g3, %g2, %g3
604         add     %g3, PAGE_SHIFT, %g3
605
606         /*
607          * Extract the virtual page number from the contents of the tag
608          * access register.
609          */
610         srlx    %g1, %g3, %g3
611
612         /*
613          * Compute the TTE bucket address.
614          */
615         ldxa    [%g0 + AA_IMMU_TSB] %asi, %g5
616         and     %g3, TSB_BUCKET_MASK, %g4
617         sllx    %g4, TSB_BUCKET_SHIFT + TTE_SHIFT, %g4
618         add     %g4, %g5, %g4
619
620         /*
621          * Compute the TTE tag target.
622          */
623         sllx    %g3, TV_SIZE_BITS, %g3
624         or      %g3, %g2, %g3
625
626         /*
627          * Loop over the TTEs in this bucket.
628          */
629
630         /*
631          * Load the TTE.  Note that this instruction may fault, clobbering
632          * the contents of the tag access register, %g5, %g6, and %g7.  We
633          * do not use %g5, and %g6 and %g7 are not used until this instruction
634          * completes successfully.
635          */
636 2:      ldda    [%g4] ASI_NUCLEUS_QUAD_LDD, %g6 /*, %g7 */
637
638         /*
639          * Check that it's valid and executable and that the TTE tags match.
640          */
641         brgez,pn %g7, 3f
642          andcc  %g7, TD_EXEC, %g0
643         bz,pn   %xcc, 3f
644          cmp    %g3, %g6
645         bne,pn  %xcc, 3f
646          EMPTY
647
648         /*
649          * We matched a TTE, load the TLB.
650          */
651
652         /*
653          * Set the reference bit, if it's currently clear.
654          */
655          andcc  %g7, TD_REF, %g0
656         bz,a,pn %xcc, tl0_immu_miss_set_ref
657          nop
658
659         /*
660          * Load the TTE tag and data into the TLB and retry the instruction.
661          */
662         stxa    %g1, [%g0 + AA_IMMU_TAR] %asi
663         stxa    %g7, [%g0] ASI_ITLB_DATA_IN_REG
664         retry
665
666         /*
667          * Advance to the next TTE in this bucket, and check the low bits
668          * of the bucket pointer to see if we've finished the bucket.
669          */
670 3:      add     %g4, 1 << TTE_SHIFT, %g4
671         andcc   %g4, (1 << (TSB_BUCKET_SHIFT + TTE_SHIFT)) - 1, %g0
672         bnz,pt  %xcc, 2b
673          EMPTY
674
675         /*
676          * See if we just checked the largest page size, and advance to the
677          * next one if not.
678          */
679          cmp    %g2, TS_MAX
680         bne,pt  %xcc, 1b
681          add    %g2, 1, %g2
682
683         /*
684          * Not in user TSB, call C code.
685          */
686         ba,a    %xcc, tl0_immu_miss_trap
687         .align  128
688         .endm
689
690 ENTRY(tl0_immu_miss_set_ref)
691         /*
692          * Set the reference bit.
693          */
694         TTE_SET_REF(%g4, %g2, %g3)
695
696         /*
697          * May have become invalid during casxa, in which case start over.
698          */
699         brgez,pn %g2, 1f
700          nop
701
702         /*
703          * Load the TTE tag and data into the TLB and retry the instruction.
704          */
705         stxa    %g1, [%g0 + AA_IMMU_TAR] %asi
706         stxa    %g2, [%g0] ASI_ITLB_DATA_IN_REG
707 1:      retry
708 END(tl0_immu_miss_set_ref)
709
710 ENTRY(tl0_immu_miss_trap)
711         /*
712          * Put back the contents of the tag access register, in case we
713          * faulted.
714          */
715         sethi   %hi(KERNBASE), %g2
716         stxa    %g1, [%g0 + AA_IMMU_TAR] %asi
717         flush   %g2
718
719         /*
720          * Switch to alternate globals.
721          */
722         wrpr    %g0, PSTATE_ALT, %pstate
723
724         /*
725          * Reload the tag access register.
726          */
727         ldxa    [%g0 + AA_IMMU_TAR] %asi, %g2
728
729         /*
730          * Save the tag access register, and call common trap code.
731          */
732         tl0_split
733         clr     %o1
734         set     trap, %o2
735         mov     %g2, %o3
736         ba      %xcc, tl0_utrap
737          mov    T_INSTRUCTION_MISS, %o0
738 END(tl0_immu_miss_trap)
739
740         .macro  tl0_dmmu_miss
741         /*
742          * Load the context and the virtual page number from the tag access
743          * register.  We ignore the context.
744          */
745         wr      %g0, ASI_DMMU, %asi
746         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g1
747
748         /*
749          * Initialize the page size walker.
750          */
751 tl1_dmmu_miss_user:
752         mov     TS_MIN, %g2
753
754         /*
755          * Loop over all supported page sizes.
756          */
757
758         /*
759          * Compute the page shift for the page size we are currently looking
760          * for.
761          */
762 1:      add     %g2, %g2, %g3
763         add     %g3, %g2, %g3
764         add     %g3, PAGE_SHIFT, %g3
765
766         /*
767          * Extract the virtual page number from the contents of the tag
768          * access register.
769          */
770         srlx    %g1, %g3, %g3
771
772         /*
773          * Compute the TTE bucket address.
774          */
775         ldxa    [%g0 + AA_DMMU_TSB] %asi, %g5
776         and     %g3, TSB_BUCKET_MASK, %g4
777         sllx    %g4, TSB_BUCKET_SHIFT + TTE_SHIFT, %g4
778         add     %g4, %g5, %g4
779
780         /*
781          * Compute the TTE tag target.
782          */
783         sllx    %g3, TV_SIZE_BITS, %g3
784         or      %g3, %g2, %g3
785
786         /*
787          * Loop over the TTEs in this bucket.
788          */
789
790         /*
791          * Load the TTE.  Note that this instruction may fault, clobbering
792          * the contents of the tag access register, %g5, %g6, and %g7.  We
793          * do not use %g5, and %g6 and %g7 are not used until this instruction
794          * completes successfully.
795          */
796 2:      ldda    [%g4] ASI_NUCLEUS_QUAD_LDD, %g6 /*, %g7 */
797
798         /*
799          * Check that it's valid and that the virtual page numbers match.
800          */
801         brgez,pn %g7, 3f
802          cmp    %g3, %g6
803         bne,pn  %xcc, 3f
804          EMPTY
805
806         /*
807          * We matched a TTE, load the TLB.
808          */
809
810         /*
811          * Set the reference bit, if it's currently clear.
812          */
813          andcc  %g7, TD_REF, %g0
814         bz,a,pn %xcc, tl0_dmmu_miss_set_ref
815          nop
816
817         /*
818          * Load the TTE tag and data into the TLB and retry the instruction.
819          */
820         stxa    %g1, [%g0 + AA_DMMU_TAR] %asi
821         stxa    %g7, [%g0] ASI_DTLB_DATA_IN_REG
822         retry
823
824         /*
825          * Advance to the next TTE in this bucket, and check the low bits
826          * of the bucket pointer to see if we've finished the bucket.
827          */
828 3:      add     %g4, 1 << TTE_SHIFT, %g4
829         andcc   %g4, (1 << (TSB_BUCKET_SHIFT + TTE_SHIFT)) - 1, %g0
830         bnz,pt  %xcc, 2b
831          EMPTY
832
833         /*
834          * See if we just checked the largest page size, and advance to the
835          * next one if not.
836          */
837          cmp    %g2, TS_MAX
838         bne,pt  %xcc, 1b
839          add    %g2, 1, %g2
840
841         /*
842          * Not in user TSB, call C code.
843          */
844         ba,a    %xcc, tl0_dmmu_miss_trap
845         .align  128
846         .endm
847
848 ENTRY(tl0_dmmu_miss_set_ref)
849         /*
850          * Set the reference bit.
851          */
852         TTE_SET_REF(%g4, %g2, %g3)
853
854         /*
855          * May have become invalid during casxa, in which case start over.
856          */
857         brgez,pn %g2, 1f
858          nop
859
860         /*
861          * Load the TTE tag and data into the TLB and retry the instruction.
862          */
863         stxa    %g1, [%g0 + AA_DMMU_TAR] %asi
864         stxa    %g2, [%g0] ASI_DTLB_DATA_IN_REG
865 1:      retry
866 END(tl0_dmmu_miss_set_ref)
867
868 ENTRY(tl0_dmmu_miss_trap)
869         /*
870          * Put back the contents of the tag access register, in case we
871          * faulted.
872          */
873         stxa    %g1, [%g0 + AA_DMMU_TAR] %asi
874         membar  #Sync
875
876         /*
877          * Switch to alternate globals.
878          */
879         wrpr    %g0, PSTATE_ALT, %pstate
880
881         /*
882          * Check if we actually came from the kernel.
883          */
884         rdpr    %tl, %g1
885         cmp     %g1, 1
886         bgt,a,pn %xcc, 1f
887          nop
888
889         /*
890          * Reload the tag access register.
891          */
892         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g2
893
894         /*
895          * Save the tag access register and call common trap code.
896          */
897         tl0_split
898         clr     %o1
899         set     trap, %o2
900         mov     %g2, %o3
901         ba      %xcc, tl0_utrap
902          mov    T_DATA_MISS, %o0
903
904         /*
905          * Handle faults during window spill/fill.
906          */
907 1:      RESUME_SPILLFILL_MMU
908
909         /*
910          * Reload the tag access register.
911          */
912         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g2
913
914         tl1_split
915         clr     %o1
916         set     trap, %o2
917         mov     %g2, %o3
918         ba      %xcc, tl1_trap
919          mov    T_DATA_MISS | T_KERNEL, %o0
920 END(tl0_dmmu_miss_trap)
921
922         .macro  tl0_dmmu_prot
923         ba,a    %xcc, tl0_dmmu_prot_1
924          nop
925         .align  128
926         .endm
927
928 ENTRY(tl0_dmmu_prot_1)
929         /*
930          * Load the context and the virtual page number from the tag access
931          * register.  We ignore the context.
932          */
933         wr      %g0, ASI_DMMU, %asi
934         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g1
935
936         /*
937          * Initialize the page size walker.
938          */
939 tl1_dmmu_prot_user:
940         mov     TS_MIN, %g2
941
942         /*
943          * Loop over all supported page sizes.
944          */
945
946         /*
947          * Compute the page shift for the page size we are currently looking
948          * for.
949          */
950 1:      add     %g2, %g2, %g3
951         add     %g3, %g2, %g3
952         add     %g3, PAGE_SHIFT, %g3
953
954         /*
955          * Extract the virtual page number from the contents of the tag
956          * access register.
957          */
958         srlx    %g1, %g3, %g3
959
960         /*
961          * Compute the TTE bucket address.
962          */
963         ldxa    [%g0 + AA_DMMU_TSB] %asi, %g5
964         and     %g3, TSB_BUCKET_MASK, %g4
965         sllx    %g4, TSB_BUCKET_SHIFT + TTE_SHIFT, %g4
966         add     %g4, %g5, %g4
967
968         /*
969          * Compute the TTE tag target.
970          */
971         sllx    %g3, TV_SIZE_BITS, %g3
972         or      %g3, %g2, %g3
973
974         /*
975          * Loop over the TTEs in this bucket.
976          */
977
978         /*
979          * Load the TTE.  Note that this instruction may fault, clobbering
980          * the contents of the tag access register, %g5, %g6, and %g7.  We
981          * do not use %g5, and %g6 and %g7 are not used until this instruction
982          * completes successfully.
983          */
984 2:      ldda    [%g4] ASI_NUCLEUS_QUAD_LDD, %g6 /*, %g7 */
985
986         /*
987          * Check that it's valid and writable and that the virtual page
988          * numbers match.
989          */
990         brgez,pn %g7, 4f
991          andcc  %g7, TD_SW, %g0
992         bz,pn   %xcc, 4f
993          cmp    %g3, %g6
994         bne,pn  %xcc, 4f
995          nop
996
997         /*
998          * Set the hardware write bit.
999          */
1000         TTE_SET_W(%g4, %g2, %g3)
1001
1002         /*
1003          * Delete the old TLB entry and clear the SFSR.
1004          */
1005         srlx    %g1, PAGE_SHIFT, %g3
1006         sllx    %g3, PAGE_SHIFT, %g3
1007         stxa    %g0, [%g3] ASI_DMMU_DEMAP
1008         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
1009         membar  #Sync
1010
1011         /*
1012          * May have become invalid during casxa, in which case start over.
1013          */
1014         brgez,pn %g2, 3f
1015          or     %g2, TD_W, %g2
1016
1017         /*
1018          * Load the TTE data into the TLB and retry the instruction.
1019          */
1020         stxa    %g1, [%g0 + AA_DMMU_TAR] %asi
1021         stxa    %g2, [%g0] ASI_DTLB_DATA_IN_REG
1022 3:      retry
1023
1024         /*
1025          * Check the low bits to see if we've finished the bucket.
1026          */
1027 4:      add     %g4, 1 << TTE_SHIFT, %g4
1028         andcc   %g4, (1 << (TSB_BUCKET_SHIFT + TTE_SHIFT)) - 1, %g0
1029         bnz,pt  %xcc, 2b
1030          EMPTY
1031
1032         /*
1033          * See if we just checked the largest page size, and advance to the
1034          * next one if not.
1035          */
1036          cmp    %g2, TS_MAX
1037         bne,pt  %xcc, 1b
1038          add    %g2, 1, %g2
1039
1040         /*
1041          * Not in user TSB, call C code.
1042          */
1043         ba,a    %xcc, tl0_dmmu_prot_trap
1044          nop
1045 END(tl0_dmmu_prot_1)
1046
1047 ENTRY(tl0_dmmu_prot_trap)
1048         /*
1049          * Put back the contents of the tag access register, in case we
1050          * faulted.
1051          */
1052         stxa    %g1, [%g0 + AA_DMMU_TAR] %asi
1053         membar  #Sync
1054
1055         /*
1056          * Switch to alternate globals.
1057          */
1058         wrpr    %g0, PSTATE_ALT, %pstate
1059
1060         /*
1061          * Check if we actually came from the kernel.
1062          */
1063         rdpr    %tl, %g1
1064         cmp     %g1, 1
1065         bgt,a,pn %xcc, 1f
1066          nop
1067
1068         /*
1069          * Load the SFAR, SFSR and TAR.
1070          */
1071         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g2
1072         ldxa    [%g0 + AA_DMMU_SFAR] %asi, %g3
1073         ldxa    [%g0 + AA_DMMU_SFSR] %asi, %g4
1074         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
1075         membar  #Sync
1076
1077         /*
1078          * Save the MMU registers and call common trap code.
1079          */
1080         tl0_split
1081         clr     %o1
1082         set     trap, %o2
1083         mov     %g2, %o3
1084         mov     %g3, %o4
1085         mov     %g4, %o5
1086         ba      %xcc, tl0_utrap
1087          mov    T_DATA_PROTECTION, %o0
1088
1089         /*
1090          * Handle faults during window spill/fill.
1091          */
1092 1:      RESUME_SPILLFILL_MMU_CLR_SFSR
1093
1094         /*
1095          * Load the SFAR, SFSR and TAR.  Clear the SFSR.
1096          */
1097         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g2
1098         ldxa    [%g0 + AA_DMMU_SFAR] %asi, %g3
1099         ldxa    [%g0 + AA_DMMU_SFSR] %asi, %g4
1100         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
1101         membar  #Sync
1102
1103         tl1_split
1104         clr     %o1
1105         set     trap, %o2
1106         mov     %g2, %o3
1107         mov     %g3, %o4
1108         mov     %g4, %o5
1109         ba      %xcc, tl1_trap
1110          mov    T_DATA_PROTECTION | T_KERNEL, %o0
1111 END(tl0_dmmu_prot_trap)
1112
1113         .macro  tl0_spill_0_n
1114         wr      %g0, ASI_AIUP, %asi
1115         SPILL(stxa, %sp + SPOFF, 8, %asi)
1116         saved
1117         retry
1118         .align  32
1119         RSF_TRAP(T_SPILL)
1120         RSF_TRAP(T_SPILL)
1121         .endm
1122
1123         .macro  tl0_spill_1_n
1124         wr      %g0, ASI_AIUP, %asi
1125         SPILL(stwa, %sp, 4, %asi)
1126         saved
1127         retry
1128         .align  32
1129         RSF_TRAP(T_SPILL)
1130         RSF_TRAP(T_SPILL)
1131         .endm
1132
1133         .macro  tl0_fill_0_n
1134         wr      %g0, ASI_AIUP, %asi
1135         FILL(ldxa, %sp + SPOFF, 8, %asi)
1136         restored
1137         retry
1138         .align  32
1139         RSF_TRAP(T_FILL)
1140         RSF_TRAP(T_FILL)
1141         .endm
1142
1143         .macro  tl0_fill_1_n
1144         wr      %g0, ASI_AIUP, %asi
1145         FILL(lduwa, %sp, 4, %asi)
1146         restored
1147         retry
1148         .align  32
1149         RSF_TRAP(T_FILL)
1150         RSF_TRAP(T_FILL)
1151         .endm
1152
1153 ENTRY(tl0_sftrap)
1154         rdpr    %tstate, %g1
1155         and     %g1, TSTATE_CWP_MASK, %g1
1156         wrpr    %g1, 0, %cwp
1157         tl0_split
1158         clr     %o1
1159         set     trap, %o2
1160         ba      %xcc, tl0_trap
1161          mov    %g2, %o0
1162 END(tl0_sftrap)
1163
1164         .macro  tl0_spill_bad   count
1165         .rept   \count
1166         sir
1167         .align  128
1168         .endr
1169         .endm
1170
1171         .macro  tl0_fill_bad    count
1172         .rept   \count
1173         sir
1174         .align  128
1175         .endr
1176         .endm
1177
1178         .macro  tl0_syscall
1179         tl0_split
1180         clr     %o1
1181         set     syscall, %o2
1182         ba      %xcc, tl0_trap
1183          mov    T_SYSCALL, %o0
1184         .align  32
1185         .endm
1186
1187         .macro  tl0_fp_restore
1188         ba,a    %xcc, tl0_fp_restore
1189          nop
1190         .align  32
1191         .endm
1192
1193 ENTRY(tl0_fp_restore)
1194         ldx     [PCB_REG + PCB_FLAGS], %g1
1195         andn    %g1, PCB_FEF, %g1
1196         stx     %g1, [PCB_REG + PCB_FLAGS]
1197
1198         wr      %g0, FPRS_FEF, %fprs
1199         wr      %g0, ASI_BLK_S, %asi
1200         ldda    [PCB_REG + PCB_UFP + (0 * 64)] %asi, %f0
1201         ldda    [PCB_REG + PCB_UFP + (1 * 64)] %asi, %f16
1202         ldda    [PCB_REG + PCB_UFP + (2 * 64)] %asi, %f32
1203         ldda    [PCB_REG + PCB_UFP + (3 * 64)] %asi, %f48
1204         membar  #Sync
1205         done
1206 END(tl0_fp_restore)
1207
1208         .macro  tl1_insn_excptn
1209         wrpr    %g0, PSTATE_ALT, %pstate
1210         wr      %g0, ASI_IMMU, %asi
1211         rdpr    %tpc, %g3
1212         ldxa    [%g0 + AA_IMMU_SFSR] %asi, %g4
1213         /*
1214          * XXX in theory, a store to AA_IMMU_SFSR must be immediately
1215          * followed by a DONE, FLUSH or RETRY for USIII.  In practice,
1216          * this triggers a RED state exception though.
1217          */
1218         stxa    %g0, [%g0 + AA_IMMU_SFSR] %asi
1219         membar  #Sync
1220         ba      %xcc, tl1_insn_exceptn_trap
1221          mov    T_INSTRUCTION_EXCEPTION | T_KERNEL, %g2
1222         .align  32
1223         .endm
1224
1225 ENTRY(tl1_insn_exceptn_trap)
1226         tl1_split
1227         clr     %o1
1228         set     trap, %o2
1229         mov     %g3, %o4
1230         mov     %g4, %o5
1231         ba      %xcc, tl1_trap
1232          mov    %g2, %o0
1233 END(tl1_insn_exceptn_trap)
1234
1235         .macro  tl1_fp_disabled
1236         ba,a    %xcc, tl1_fp_disabled_1
1237          nop
1238         .align  32
1239         .endm
1240
1241 ENTRY(tl1_fp_disabled_1)
1242         rdpr    %tpc, %g1
1243         set     fpu_fault_begin, %g2
1244         sub     %g1, %g2, %g1
1245         cmp     %g1, fpu_fault_size
1246         bgeu,a,pn %xcc, 1f
1247          nop
1248
1249         wr      %g0, FPRS_FEF, %fprs
1250         wr      %g0, ASI_BLK_S, %asi
1251         ldda    [PCB_REG + PCB_KFP + (0 * 64)] %asi, %f0
1252         ldda    [PCB_REG + PCB_KFP + (1 * 64)] %asi, %f16
1253         ldda    [PCB_REG + PCB_KFP + (2 * 64)] %asi, %f32
1254         ldda    [PCB_REG + PCB_KFP + (3 * 64)] %asi, %f48
1255         membar  #Sync
1256         retry
1257
1258 1:      tl1_split
1259         clr     %o1
1260         set     trap, %o2
1261         ba      %xcc, tl1_trap
1262          mov    T_FP_DISABLED | T_KERNEL, %o0
1263 END(tl1_fp_disabled_1)
1264
1265         .macro  tl1_data_excptn
1266         wrpr    %g0, PSTATE_ALT, %pstate
1267         ba,a    %xcc, tl1_data_excptn_trap
1268          nop
1269         .align  32
1270         .endm
1271
1272 ENTRY(tl1_data_excptn_trap)
1273         RESUME_SPILLFILL_MMU_CLR_SFSR
1274         ba      %xcc, tl1_sfsr_trap
1275          mov    T_DATA_EXCEPTION | T_KERNEL, %g2
1276 END(tl1_data_excptn_trap)
1277
1278         .macro  tl1_align
1279         ba,a    %xcc, tl1_align_trap
1280          nop
1281         .align  32
1282         .endm
1283
1284 ENTRY(tl1_align_trap)
1285         RESUME_SPILLFILL_ALIGN
1286         ba      %xcc, tl1_sfsr_trap
1287          mov    T_MEM_ADDRESS_NOT_ALIGNED | T_KERNEL, %g2
1288 END(tl1_data_excptn_trap)
1289
1290 ENTRY(tl1_sfsr_trap)
1291         wr      %g0, ASI_DMMU, %asi
1292         ldxa    [%g0 + AA_DMMU_SFAR] %asi, %g3
1293         ldxa    [%g0 + AA_DMMU_SFSR] %asi, %g4
1294         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
1295         membar  #Sync
1296
1297         tl1_split
1298         clr     %o1
1299         set     trap, %o2
1300         mov     %g3, %o4
1301         mov     %g4, %o5
1302         ba      %xcc, tl1_trap
1303          mov    %g2, %o0
1304 END(tl1_sfsr_trap)
1305
1306         .macro  tl1_intr level, mask
1307         tl1_split
1308         set     \mask, %o1
1309         ba      %xcc, tl1_intr
1310          mov    \level, %o0
1311         .align  32
1312         .endm
1313
1314         .macro  tl1_intr_level
1315         INTR_LEVEL(1)
1316         .endm
1317
1318         .macro  tl1_immu_miss
1319         /*
1320          * Load the context and the virtual page number from the tag access
1321          * register.  We ignore the context.
1322          */
1323         wr      %g0, ASI_IMMU, %asi
1324         ldxa    [%g0 + AA_IMMU_TAR] %asi, %g5
1325
1326         /*
1327          * Compute the address of the TTE.  The TSB mask and address of the
1328          * TSB are patched at startup.
1329          */
1330         .globl  tl1_immu_miss_patch_1
1331 tl1_immu_miss_patch_1:
1332         sethi   %hi(TSB_KERNEL_MASK), %g6
1333         or      %g6, %lo(TSB_KERNEL_MASK), %g6
1334         sethi   %hi(TSB_KERNEL), %g7
1335
1336         srlx    %g5, TAR_VPN_SHIFT, %g5
1337         and     %g5, %g6, %g6
1338         sllx    %g6, TTE_SHIFT, %g6
1339         add     %g6, %g7, %g6
1340
1341         /*
1342          * Load the TTE.
1343          */
1344         ldda    [%g6] ASI_NUCLEUS_QUAD_LDD, %g6 /*, %g7 */
1345
1346         /*
1347          * Check that it's valid and executable and that the virtual page
1348          * numbers match.
1349          */
1350         brgez,pn %g7, tl1_immu_miss_trap
1351          andcc  %g7, TD_EXEC, %g0
1352         bz,pn   %xcc, tl1_immu_miss_trap
1353          srlx   %g6, TV_SIZE_BITS, %g6
1354         cmp     %g5, %g6
1355         bne,pn  %xcc, tl1_immu_miss_trap
1356          EMPTY
1357
1358         /*
1359          * Set the reference bit if it's currently clear.
1360          */
1361          andcc  %g7, TD_REF, %g0
1362         bz,a,pn %xcc, tl1_immu_miss_set_ref
1363          nop
1364
1365         /*
1366          * Load the TTE data into the TLB and retry the instruction.
1367          */
1368         stxa    %g7, [%g0] ASI_ITLB_DATA_IN_REG
1369         retry
1370         .align  128
1371         .endm
1372
1373 ENTRY(tl1_immu_miss_set_ref)
1374         /*
1375          * Recompute the TTE address, which we clobbered loading the TTE.
1376          * The TSB mask and address of the TSB are patched at startup.
1377          */
1378         .globl  tl1_immu_miss_patch_2
1379 tl1_immu_miss_patch_2:
1380         sethi   %hi(TSB_KERNEL_MASK), %g6
1381         or      %g6, %lo(TSB_KERNEL_MASK), %g6
1382         sethi   %hi(TSB_KERNEL), %g7
1383
1384         and     %g5, %g6, %g5
1385         sllx    %g5, TTE_SHIFT, %g5
1386         add     %g5, %g7, %g5
1387
1388         /*
1389          * Set the reference bit.
1390          */
1391         TTE_SET_REF(%g5, %g6, %g7)
1392
1393         /*
1394          * May have become invalid during casxa, in which case start over.
1395          */
1396         brgez,pn %g6, 1f
1397          nop
1398
1399         /*
1400          * Load the TTE data into the TLB and retry the instruction.
1401          */
1402         stxa    %g6, [%g0] ASI_ITLB_DATA_IN_REG
1403 1:      retry
1404 END(tl1_immu_miss_set_ref)
1405
1406 ENTRY(tl1_immu_miss_trap)
1407         /*
1408          * Switch to alternate globals.
1409          */
1410         wrpr    %g0, PSTATE_ALT, %pstate
1411
1412         ldxa    [%g0 + AA_IMMU_TAR] %asi, %g2
1413
1414         tl1_split
1415         clr     %o1
1416         set     trap, %o2
1417         mov     %g2, %o3
1418         ba      %xcc, tl1_trap
1419          mov    T_INSTRUCTION_MISS | T_KERNEL, %o0
1420 END(tl1_immu_miss_trap)
1421
1422         .macro  tl1_dmmu_miss
1423         /*
1424          * Load the context and the virtual page number from the tag access
1425          * register.
1426          */
1427         wr      %g0, ASI_DMMU, %asi
1428         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g5
1429
1430         /*
1431          * Extract the context from the contents of the tag access register.
1432          * If it's non-zero this is a fault on a user address.  Note that the
1433          * faulting address is passed in %g1.
1434          */
1435         sllx    %g5, 64 - TAR_VPN_SHIFT, %g6
1436         brnz,a,pn %g6, tl1_dmmu_miss_user
1437          mov    %g5, %g1
1438
1439         /*
1440          * Check for the direct mapped physical region.  These addresses have
1441          * the high bit set so they are negative.
1442          */
1443         brlz,pn %g5, tl1_dmmu_miss_direct
1444          EMPTY
1445
1446         /*
1447          * Compute the address of the TTE.  The TSB mask and address of the
1448          * TSB are patched at startup.
1449          */
1450         .globl  tl1_dmmu_miss_patch_1
1451 tl1_dmmu_miss_patch_1:
1452         sethi   %hi(TSB_KERNEL_MASK), %g6
1453         or      %g6, %lo(TSB_KERNEL_MASK), %g6
1454         sethi   %hi(TSB_KERNEL), %g7
1455
1456         srlx    %g5, TAR_VPN_SHIFT, %g5
1457         and     %g5, %g6, %g6
1458         sllx    %g6, TTE_SHIFT, %g6
1459         add     %g6, %g7, %g6
1460
1461         /*
1462          * Load the TTE.
1463          */
1464         ldda    [%g6] ASI_NUCLEUS_QUAD_LDD, %g6 /*, %g7 */
1465
1466         /*
1467          * Check that it's valid and that the virtual page numbers match.
1468          */
1469         brgez,pn %g7, tl1_dmmu_miss_trap
1470          srlx   %g6, TV_SIZE_BITS, %g6
1471         cmp     %g5, %g6
1472         bne,pn %xcc, tl1_dmmu_miss_trap
1473          EMPTY
1474
1475         /*
1476          * Set the reference bit if it's currently clear.
1477          */
1478          andcc  %g7, TD_REF, %g0
1479         bz,a,pt %xcc, tl1_dmmu_miss_set_ref
1480          nop
1481
1482         /*
1483          * Load the TTE data into the TLB and retry the instruction.
1484          */
1485         stxa    %g7, [%g0] ASI_DTLB_DATA_IN_REG
1486         retry
1487         .align  128
1488         .endm
1489
1490 ENTRY(tl1_dmmu_miss_set_ref)
1491         /*
1492          * Recompute the TTE address, which we clobbered loading the TTE.
1493          * The TSB mask and address of the TSB are patched at startup.
1494          */
1495         .globl  tl1_dmmu_miss_patch_2
1496 tl1_dmmu_miss_patch_2:
1497         sethi   %hi(TSB_KERNEL_MASK), %g6
1498         or      %g6, %lo(TSB_KERNEL_MASK), %g6
1499         sethi   %hi(TSB_KERNEL), %g7
1500
1501         and     %g5, %g6, %g5
1502         sllx    %g5, TTE_SHIFT, %g5
1503         add     %g5, %g7, %g5
1504
1505         /*
1506          * Set the reference bit.
1507          */
1508         TTE_SET_REF(%g5, %g6, %g7)
1509
1510         /*
1511          * May have become invalid during casxa, in which case start over.
1512          */
1513         brgez,pn %g6, 1f
1514          nop
1515
1516         /*
1517          * Load the TTE data into the TLB and retry the instruction.
1518          */
1519         stxa    %g6, [%g0] ASI_DTLB_DATA_IN_REG
1520 1:      retry
1521 END(tl1_dmmu_miss_set_ref)
1522
1523 ENTRY(tl1_dmmu_miss_trap)
1524         /*
1525          * Switch to alternate globals.
1526          */
1527         wrpr    %g0, PSTATE_ALT, %pstate
1528
1529         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g2
1530
1531         KSTACK_CHECK
1532
1533         tl1_split
1534         clr     %o1
1535         set     trap, %o2
1536         mov     %g2, %o3
1537         ba      %xcc, tl1_trap
1538          mov    T_DATA_MISS | T_KERNEL, %o0
1539 END(tl1_dmmu_miss_trap)
1540
1541 ENTRY(tl1_dmmu_miss_direct)
1542         /*
1543          * Mask off the high bits of the virtual address to get the physical
1544          * address, and or in the TTE bits.  The virtual address bits that
1545          * correspond to the TTE valid and page size bits are left set, so
1546          * they don't have to be included in the TTE bits below.  We know they
1547          * are set because the virtual address is in the upper va hole.
1548          */
1549         setx    TLB_DIRECT_TO_TTE_MASK, %g7, %g6
1550         and     %g5, %g6, %g5
1551         or      %g5, TD_CP | TD_CV | TD_W, %g5
1552
1553         /*
1554          * Load the TTE data into the TLB and retry the instruction.
1555          */
1556         stxa    %g5, [%g0] ASI_DTLB_DATA_IN_REG
1557         retry
1558 END(tl1_dmmu_miss_direct)
1559
1560         .macro  tl1_dmmu_prot
1561         ba,a    %xcc, tl1_dmmu_prot_1
1562          nop
1563         .align  128
1564         .endm
1565
1566 ENTRY(tl1_dmmu_prot_1)
1567         /*
1568          * Load the context and the virtual page number from the tag access
1569          * register.
1570          */
1571         wr      %g0, ASI_DMMU, %asi
1572         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g5
1573
1574         /*
1575          * Extract the context from the contents of the tag access register.
1576          * If it's non-zero this is a fault on a user address.  Note that the
1577          * faulting address is passed in %g1.
1578          */
1579         sllx    %g5, 64 - TAR_VPN_SHIFT, %g6
1580         brnz,a,pn %g6, tl1_dmmu_prot_user
1581          mov    %g5, %g1
1582
1583         /*
1584          * Compute the address of the TTE.  The TSB mask and address of the
1585          * TSB are patched at startup.
1586          */
1587         .globl  tl1_dmmu_prot_patch_1
1588 tl1_dmmu_prot_patch_1:
1589         sethi   %hi(TSB_KERNEL_MASK), %g6
1590         or      %g6, %lo(TSB_KERNEL_MASK), %g6
1591         sethi   %hi(TSB_KERNEL), %g7
1592
1593         srlx    %g5, TAR_VPN_SHIFT, %g5
1594         and     %g5, %g6, %g6
1595         sllx    %g6, TTE_SHIFT, %g6
1596         add     %g6, %g7, %g6
1597
1598         /*
1599          * Load the TTE.
1600          */
1601         ldda    [%g6] ASI_NUCLEUS_QUAD_LDD, %g6 /*, %g7 */
1602
1603         /*
1604          * Check that it's valid and writeable and that the virtual page
1605          * numbers match.
1606          */
1607         brgez,pn %g7, tl1_dmmu_prot_trap
1608          andcc  %g7, TD_SW, %g0
1609         bz,pn   %xcc, tl1_dmmu_prot_trap
1610          srlx   %g6, TV_SIZE_BITS, %g6
1611         cmp     %g5, %g6
1612         bne,pn  %xcc, tl1_dmmu_prot_trap
1613          EMPTY
1614
1615         /*
1616          * Delete the old TLB entry and clear the SFSR.
1617          */
1618          sllx   %g5, TAR_VPN_SHIFT, %g6
1619         or      %g6, TLB_DEMAP_NUCLEUS, %g6
1620         stxa    %g0, [%g6] ASI_DMMU_DEMAP
1621         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
1622         membar  #Sync
1623
1624         /*
1625          * Recompute the TTE address, which we clobbered loading the TTE.
1626          * The TSB mask and address of the TSB are patched at startup.
1627          */
1628         .globl  tl1_dmmu_prot_patch_2
1629 tl1_dmmu_prot_patch_2:
1630         sethi   %hi(TSB_KERNEL_MASK), %g6
1631         or      %g6, %lo(TSB_KERNEL_MASK), %g6
1632         sethi   %hi(TSB_KERNEL), %g7
1633
1634         and     %g5, %g6, %g5
1635         sllx    %g5, TTE_SHIFT, %g5
1636         add     %g5, %g7, %g5
1637
1638         /*
1639          * Set the hardware write bit.
1640          */
1641         TTE_SET_W(%g5, %g6, %g7)
1642
1643         /*
1644          * May have become invalid during casxa, in which case start over.
1645          */
1646         brgez,pn %g6, 1f
1647          or     %g6, TD_W, %g6
1648
1649         /*
1650          * Load the TTE data into the TLB and retry the instruction.
1651          */
1652         stxa    %g6, [%g0] ASI_DTLB_DATA_IN_REG
1653 1:      retry
1654 END(tl1_dmmu_prot_1)
1655
1656 ENTRY(tl1_dmmu_prot_trap)
1657         /*
1658          * Switch to alternate globals.
1659          */
1660         wrpr    %g0, PSTATE_ALT, %pstate
1661
1662         /*
1663          * Load the SFAR, SFSR and TAR.  Clear the SFSR.
1664          */
1665         ldxa    [%g0 + AA_DMMU_TAR] %asi, %g2
1666         ldxa    [%g0 + AA_DMMU_SFAR] %asi, %g3
1667         ldxa    [%g0 + AA_DMMU_SFSR] %asi, %g4
1668         stxa    %g0, [%g0 + AA_DMMU_SFSR] %asi
1669         membar  #Sync
1670
1671         tl1_split
1672         clr     %o1
1673         set     trap, %o2
1674         mov     %g2, %o3
1675         mov     %g3, %o4
1676         mov     %g4, %o5
1677         ba      %xcc, tl1_trap
1678          mov    T_DATA_PROTECTION | T_KERNEL, %o0
1679 END(tl1_dmmu_prot_trap)
1680
1681         .macro  tl1_spill_0_n
1682         SPILL(stx, %sp + SPOFF, 8, EMPTY)
1683         saved
1684         retry
1685         .align  32
1686         RSF_FATAL(T_SPILL)
1687         RSF_FATAL(T_SPILL)
1688         .endm
1689
1690         .macro  tl1_spill_2_n
1691         wr      %g0, ASI_AIUP, %asi
1692         SPILL(stxa, %sp + SPOFF, 8, %asi)
1693         saved
1694         retry
1695         .align  32
1696         RSF_SPILL_TOPCB
1697         RSF_SPILL_TOPCB
1698         .endm
1699
1700         .macro  tl1_spill_3_n
1701         wr      %g0, ASI_AIUP, %asi
1702         SPILL(stwa, %sp, 4, %asi)
1703         saved
1704         retry
1705         .align  32
1706         RSF_SPILL_TOPCB
1707         RSF_SPILL_TOPCB
1708         .endm
1709
1710         .macro  tl1_spill_7_n
1711         btst    1, %sp
1712         bnz,a,pn %xcc, tl1_spill_0_n
1713          nop
1714         srl     %sp, 0, %sp
1715         SPILL(stw, %sp, 4, EMPTY)
1716         saved
1717         retry
1718         .align  32
1719         RSF_FATAL(T_SPILL)
1720         RSF_FATAL(T_SPILL)
1721         .endm
1722
1723         .macro  tl1_spill_0_o
1724         wr      %g0, ASI_AIUP, %asi
1725         SPILL(stxa, %sp + SPOFF, 8, %asi)
1726         saved
1727         retry
1728         .align  32
1729         RSF_SPILL_TOPCB
1730         RSF_SPILL_TOPCB
1731         .endm
1732
1733         .macro  tl1_spill_1_o
1734         wr      %g0, ASI_AIUP, %asi
1735         SPILL(stwa, %sp, 4, %asi)
1736         saved
1737         retry
1738         .align  32
1739         RSF_SPILL_TOPCB
1740         RSF_SPILL_TOPCB
1741         .endm
1742
1743         .macro  tl1_spill_2_o
1744         RSF_SPILL_TOPCB
1745         .align  128
1746         .endm
1747
1748         .macro  tl1_fill_0_n
1749         FILL(ldx, %sp + SPOFF, 8, EMPTY)
1750         restored
1751         retry
1752         .align  32
1753         RSF_FATAL(T_FILL)
1754         RSF_FATAL(T_FILL)
1755         .endm
1756
1757         .macro  tl1_fill_2_n
1758         wr      %g0, ASI_AIUP, %asi
1759         FILL(ldxa, %sp + SPOFF, 8, %asi)
1760         restored
1761         retry
1762         .align 32
1763         RSF_FILL_MAGIC
1764         RSF_FILL_MAGIC
1765         .endm
1766
1767         .macro  tl1_fill_3_n
1768         wr      %g0, ASI_AIUP, %asi
1769         FILL(lduwa, %sp, 4, %asi)
1770         restored
1771         retry
1772         .align 32
1773         RSF_FILL_MAGIC
1774         RSF_FILL_MAGIC
1775         .endm
1776
1777         .macro  tl1_fill_7_n
1778         btst    1, %sp
1779         bnz,a,pt %xcc, tl1_fill_0_n
1780          nop
1781         srl     %sp, 0, %sp
1782         FILL(lduw, %sp, 4, EMPTY)
1783         restored
1784         retry
1785         .align  32
1786         RSF_FATAL(T_FILL)
1787         RSF_FATAL(T_FILL)
1788         .endm
1789
1790 /*
1791  * This is used to spill windows that are still occupied with user
1792  * data on kernel entry to the pcb.
1793  */
1794 ENTRY(tl1_spill_topcb)
1795         wrpr    %g0, PSTATE_ALT, %pstate
1796
1797         /* Free some globals for our use. */
1798         dec     24, ASP_REG
1799         stx     %g1, [ASP_REG + 0]
1800         stx     %g2, [ASP_REG + 8]
1801         stx     %g3, [ASP_REG + 16]
1802
1803         ldx     [PCB_REG + PCB_NSAVED], %g1
1804
1805         sllx    %g1, PTR_SHIFT, %g2
1806         add     %g2, PCB_REG, %g2
1807         stx     %sp, [%g2 + PCB_RWSP]
1808
1809         sllx    %g1, RW_SHIFT, %g2
1810         add     %g2, PCB_REG, %g2
1811         SPILL(stx, %g2 + PCB_RW, 8, EMPTY)
1812
1813         inc     %g1
1814         stx     %g1, [PCB_REG + PCB_NSAVED]
1815
1816 #if KTR_COMPILE & KTR_TRAP
1817         CATR(KTR_TRAP, "tl1_spill_topcb: pc=%#lx npc=%#lx sp=%#lx nsaved=%d"
1818            , %g1, %g2, %g3, 7, 8, 9)
1819         rdpr    %tpc, %g2
1820         stx     %g2, [%g1 + KTR_PARM1]
1821         rdpr    %tnpc, %g2
1822         stx     %g2, [%g1 + KTR_PARM2]
1823         stx     %sp, [%g1 + KTR_PARM3]
1824         ldx     [PCB_REG + PCB_NSAVED], %g2
1825         stx     %g2, [%g1 + KTR_PARM4]
1826 9:
1827 #endif
1828
1829         saved
1830
1831         ldx     [ASP_REG + 16], %g3
1832         ldx     [ASP_REG + 8], %g2
1833         ldx     [ASP_REG + 0], %g1
1834         inc     24, ASP_REG
1835         retry
1836 END(tl1_spill_topcb)
1837
1838         .macro  tl1_spill_bad   count
1839         .rept   \count
1840         sir
1841         .align  128
1842         .endr
1843         .endm
1844
1845         .macro  tl1_fill_bad    count
1846         .rept   \count
1847         sir
1848         .align  128
1849         .endr
1850         .endm
1851
1852         .macro  tl1_soft        count
1853         .rept   \count
1854         tl1_gen T_SOFT | T_KERNEL
1855         .endr
1856         .endm
1857
1858         .sect   .trap
1859         .globl  tl_trap_begin
1860 tl_trap_begin:
1861         nop
1862
1863         .align  0x8000
1864         .globl  tl0_base
1865
1866 tl0_base:
1867         tl0_reserved    8                               ! 0x0-0x7
1868 tl0_insn_excptn:
1869         tl0_insn_excptn                                 ! 0x8
1870         tl0_reserved    1                               ! 0x9
1871 tl0_insn_error:
1872         tl0_gen         T_INSTRUCTION_ERROR             ! 0xa
1873         tl0_reserved    5                               ! 0xb-0xf
1874 tl0_insn_illegal:
1875         tl0_gen         T_ILLEGAL_INSTRUCTION           ! 0x10
1876 tl0_priv_opcode:
1877         tl0_gen         T_PRIVILEGED_OPCODE             ! 0x11
1878         tl0_reserved    14                              ! 0x12-0x1f
1879 tl0_fp_disabled:
1880         tl0_gen         T_FP_DISABLED                   ! 0x20
1881 tl0_fp_ieee:
1882         tl0_gen         T_FP_EXCEPTION_IEEE_754         ! 0x21
1883 tl0_fp_other:
1884         tl0_gen         T_FP_EXCEPTION_OTHER            ! 0x22
1885 tl0_tag_ovflw:
1886         tl0_gen         T_TAG_OVERFLOW                  ! 0x23
1887 tl0_clean_window:
1888         clean_window                                    ! 0x24
1889 tl0_divide:
1890         tl0_gen         T_DIVISION_BY_ZERO              ! 0x28
1891         tl0_reserved    7                               ! 0x29-0x2f
1892 tl0_data_excptn:
1893         tl0_data_excptn                                 ! 0x30
1894         tl0_reserved    1                               ! 0x31
1895 tl0_data_error:
1896         tl0_gen         T_DATA_ERROR                    ! 0x32
1897         tl0_reserved    1                               ! 0x33
1898 tl0_align:
1899         tl0_align                                       ! 0x34
1900 tl0_align_lddf:
1901         tl0_gen         T_RESERVED                      ! 0x35
1902 tl0_align_stdf:
1903         tl0_gen         T_RESERVED                      ! 0x36
1904 tl0_priv_action:
1905         tl0_gen         T_PRIVILEGED_ACTION             ! 0x37
1906         tl0_reserved    9                               ! 0x38-0x40
1907 tl0_intr_level:
1908         tl0_intr_level                                  ! 0x41-0x4f
1909         tl0_reserved    16                              ! 0x50-0x5f
1910 tl0_intr_vector:
1911         intr_vector                                     ! 0x60
1912 tl0_watch_phys:
1913         tl0_gen         T_PA_WATCHPOINT                 ! 0x61
1914 tl0_watch_virt:
1915         tl0_gen         T_VA_WATCHPOINT                 ! 0x62
1916 tl0_ecc:
1917         tl0_gen         T_CORRECTED_ECC_ERROR           ! 0x63
1918 tl0_immu_miss:
1919         tl0_immu_miss                                   ! 0x64
1920 tl0_dmmu_miss:
1921         tl0_dmmu_miss                                   ! 0x68
1922 tl0_dmmu_prot:
1923         tl0_dmmu_prot                                   ! 0x6c
1924         tl0_reserved    16                              ! 0x70-0x7f
1925 tl0_spill_0_n:
1926         tl0_spill_0_n                                   ! 0x80
1927 tl0_spill_1_n:
1928         tl0_spill_1_n                                   ! 0x84
1929         tl0_spill_bad   14                              ! 0x88-0xbf
1930 tl0_fill_0_n:
1931         tl0_fill_0_n                                    ! 0xc0
1932 tl0_fill_1_n:
1933         tl0_fill_1_n                                    ! 0xc4
1934         tl0_fill_bad    14                              ! 0xc8-0xff
1935 tl0_soft:
1936         tl0_gen         T_SYSCALL                       ! 0x100
1937         tl0_gen         T_BREAKPOINT                    ! 0x101
1938         tl0_gen         T_DIVISION_BY_ZERO              ! 0x102
1939         tl0_reserved    1                               ! 0x103
1940         tl0_gen         T_CLEAN_WINDOW                  ! 0x104
1941         tl0_gen         T_RANGE_CHECK                   ! 0x105
1942         tl0_gen         T_FIX_ALIGNMENT                 ! 0x106
1943         tl0_gen         T_INTEGER_OVERFLOW              ! 0x107
1944         tl0_gen         T_SYSCALL                       ! 0x108
1945         tl0_gen         T_SYSCALL                       ! 0x109
1946         tl0_fp_restore                                  ! 0x10a
1947         tl0_reserved    5                               ! 0x10b-0x10f
1948         tl0_gen         T_TRAP_INSTRUCTION_16           ! 0x110
1949         tl0_gen         T_TRAP_INSTRUCTION_17           ! 0x111
1950         tl0_gen         T_TRAP_INSTRUCTION_18           ! 0x112
1951         tl0_gen         T_TRAP_INSTRUCTION_19           ! 0x113
1952         tl0_gen         T_TRAP_INSTRUCTION_20           ! 0x114
1953         tl0_gen         T_TRAP_INSTRUCTION_21           ! 0x115
1954         tl0_gen         T_TRAP_INSTRUCTION_22           ! 0x116
1955         tl0_gen         T_TRAP_INSTRUCTION_23           ! 0x117
1956         tl0_gen         T_TRAP_INSTRUCTION_24           ! 0x118
1957         tl0_gen         T_TRAP_INSTRUCTION_25           ! 0x119
1958         tl0_gen         T_TRAP_INSTRUCTION_26           ! 0x11a
1959         tl0_gen         T_TRAP_INSTRUCTION_27           ! 0x11b
1960         tl0_gen         T_TRAP_INSTRUCTION_28           ! 0x11c
1961         tl0_gen         T_TRAP_INSTRUCTION_29           ! 0x11d
1962         tl0_gen         T_TRAP_INSTRUCTION_30           ! 0x11e
1963         tl0_gen         T_TRAP_INSTRUCTION_31           ! 0x11f
1964         tl0_reserved    32                              ! 0x120-0x13f
1965         tl0_gen         T_SYSCALL                       ! 0x140
1966         tl0_syscall                                     ! 0x141
1967         tl0_gen         T_SYSCALL                       ! 0x142
1968         tl0_gen         T_SYSCALL                       ! 0x143
1969         tl0_reserved    188                             ! 0x144-0x1ff
1970
1971 tl1_base:
1972         tl1_reserved    8                               ! 0x200-0x207
1973 tl1_insn_excptn:
1974         tl1_insn_excptn                                 ! 0x208
1975         tl1_reserved    1                               ! 0x209
1976 tl1_insn_error:
1977         tl1_gen         T_INSTRUCTION_ERROR             ! 0x20a
1978         tl1_reserved    5                               ! 0x20b-0x20f
1979 tl1_insn_illegal:
1980         tl1_gen         T_ILLEGAL_INSTRUCTION           ! 0x210
1981 tl1_priv_opcode:
1982         tl1_gen         T_PRIVILEGED_OPCODE             ! 0x211
1983         tl1_reserved    14                              ! 0x212-0x21f
1984 tl1_fp_disabled:
1985         tl1_fp_disabled                                 ! 0x220
1986 tl1_fp_ieee:
1987         tl1_gen         T_FP_EXCEPTION_IEEE_754         ! 0x221
1988 tl1_fp_other:
1989         tl1_gen         T_FP_EXCEPTION_OTHER            ! 0x222
1990 tl1_tag_ovflw:
1991         tl1_gen         T_TAG_OVERFLOW                  ! 0x223
1992 tl1_clean_window:
1993         clean_window                                    ! 0x224
1994 tl1_divide:
1995         tl1_gen         T_DIVISION_BY_ZERO              ! 0x228
1996         tl1_reserved    7                               ! 0x229-0x22f
1997 tl1_data_excptn:
1998         tl1_data_excptn                                 ! 0x230
1999         tl1_reserved    1                               ! 0x231
2000 tl1_data_error:
2001         tl1_gen         T_DATA_ERROR                    ! 0x232
2002         tl1_reserved    1                               ! 0x233
2003 tl1_align:
2004         tl1_align                                       ! 0x234
2005 tl1_align_lddf:
2006         tl1_gen         T_RESERVED                      ! 0x235
2007 tl1_align_stdf:
2008         tl1_gen         T_RESERVED                      ! 0x236
2009 tl1_priv_action:
2010         tl1_gen         T_PRIVILEGED_ACTION             ! 0x237
2011         tl1_reserved    9                               ! 0x238-0x240
2012 tl1_intr_level:
2013         tl1_intr_level                                  ! 0x241-0x24f
2014         tl1_reserved    16                              ! 0x250-0x25f
2015 tl1_intr_vector:
2016         intr_vector                                     ! 0x260
2017 tl1_watch_phys:
2018         tl1_gen         T_PA_WATCHPOINT                 ! 0x261
2019 tl1_watch_virt:
2020         tl1_gen         T_VA_WATCHPOINT                 ! 0x262
2021 tl1_ecc:
2022         tl1_gen         T_CORRECTED_ECC_ERROR           ! 0x263
2023 tl1_immu_miss:
2024         tl1_immu_miss                                   ! 0x264
2025 tl1_dmmu_miss:
2026         tl1_dmmu_miss                                   ! 0x268
2027 tl1_dmmu_prot:
2028         tl1_dmmu_prot                                   ! 0x26c
2029         tl1_reserved    16                              ! 0x270-0x27f
2030 tl1_spill_0_n:
2031         tl1_spill_0_n                                   ! 0x280
2032         tl1_spill_bad   1                               ! 0x284
2033 tl1_spill_2_n:
2034         tl1_spill_2_n                                   ! 0x288
2035 tl1_spill_3_n:
2036         tl1_spill_3_n                                   ! 0x28c
2037         tl1_spill_bad   3                               ! 0x290-0x29b
2038 tl1_spill_7_n:
2039         tl1_spill_7_n                                   ! 0x29c
2040 tl1_spill_0_o:
2041         tl1_spill_0_o                                   ! 0x2a0
2042 tl1_spill_1_o:
2043         tl1_spill_1_o                                   ! 0x2a4
2044 tl1_spill_2_o:
2045         tl1_spill_2_o                                   ! 0x2a8
2046         tl1_spill_bad   5                               ! 0x2ac-0x2bf
2047 tl1_fill_0_n:
2048         tl1_fill_0_n                                    ! 0x2c0
2049         tl1_fill_bad    1                               ! 0x2c4
2050 tl1_fill_2_n:
2051         tl1_fill_2_n                                    ! 0x2c8
2052 tl1_fill_3_n:
2053         tl1_fill_3_n                                    ! 0x2cc
2054         tl1_fill_bad    3                               ! 0x2d0-0x2db
2055 tl1_fill_7_n:
2056         tl1_fill_7_n                                    ! 0x2dc
2057         tl1_fill_bad    8                               ! 0x2e0-0x2ff
2058         tl1_reserved    1                               ! 0x300
2059 tl1_breakpoint:
2060         tl1_gen         T_BREAKPOINT                    ! 0x301
2061         tl1_gen         T_RSTRWP_PHYS                   ! 0x302
2062         tl1_gen         T_RSTRWP_VIRT                   ! 0x303
2063         tl1_reserved    252                             ! 0x304-0x3ff
2064
2065         .globl  tl_trap_end
2066 tl_trap_end:
2067         nop
2068
2069 /*
2070  * User trap entry point
2071  *
2072  * void tl0_utrap(u_long type, u_long o1, u_long o2, u_long tar, u_long sfar,
2073  *     u_long sfsr)
2074  *
2075  * This handles redirecting a trap back to usermode as a user trap.  The user
2076  * program must have first registered a trap handler with the kernel using
2077  * sysarch(SPARC_UTRAP_INSTALL).  The trap handler is passed enough state
2078  * for it to return to the trapping code directly, it will not return through
2079  * the kernel.  The trap type is passed in %o0, all out registers must be
2080  * passed through to tl0_trap or to usermode untouched.  Note that the
2081  * parameters passed in out registers may be used by the user trap handler.
2082  * Do not change the registers they are passed in or you will break the ABI.
2083  *
2084  * If the trap type allows user traps, setup state to execute the user trap
2085  * handler and bounce back to usermode, otherwise branch to tl0_trap.
2086  */
2087 ENTRY(tl0_utrap)
2088         /*
2089          * Check if the trap type allows user traps.
2090          */
2091         cmp     %o0, UT_MAX
2092         bge,a,pt %xcc, tl0_trap
2093          nop
2094
2095         /*
2096          * Load the user trap handler from the utrap table.
2097          */
2098         ldx     [PCPU(CURTHREAD)], %l0
2099         ldx     [%l0 + TD_PROC], %l0
2100         ldx     [%l0 + P_MD + MD_UTRAP], %l0
2101         brz,pt  %l0, tl0_trap
2102          sllx   %o0, PTR_SHIFT, %l1
2103         ldx     [%l0 + %l1], %l0
2104         brz,a,pt %l0, tl0_trap
2105          nop
2106
2107         /*
2108          * If the save we did on entry to the kernel had to spill a window
2109          * to the pcb, pretend we took a spill trap instead.  Any windows
2110          * that are in the pcb must be copied out or the fill handler will
2111          * not be able to find them, since the user trap handler returns
2112          * directly to the trapping code.  Note that we only support precise
2113          * user traps, which implies that the condition that caused the trap
2114          * in the first place is still valid, so it will occur again when we
2115          * re-execute the trapping instruction.
2116          */
2117         ldx     [PCB_REG + PCB_NSAVED], %l1
2118         brnz,a,pn %l1, tl0_trap
2119          mov    T_SPILL, %o0
2120
2121         /*
2122          * Pass %fsr in %l4, %tstate in %l5, %tpc in %l6 and %tnpc in %l7.
2123          * The ABI specifies only %l6 and %l7, but we need to pass %fsr or
2124          * it may be clobbered by an interrupt before the user trap code
2125          * can read it, and we must pass %tstate in order to restore %ccr
2126          * and %asi.  The %fsr must be stored to memory, so we use the
2127          * temporary stack for that.
2128          */
2129         rd      %fprs, %l1
2130         or      %l1, FPRS_FEF, %l2
2131         wr      %l2, 0, %fprs
2132         dec     8, ASP_REG
2133         stx     %fsr, [ASP_REG]
2134         ldx     [ASP_REG], %l4
2135         inc     8, ASP_REG
2136         wr      %l1, 0, %fprs
2137
2138         rdpr    %tstate, %l5
2139         rdpr    %tpc, %l6
2140         rdpr    %tnpc, %l7
2141
2142         /*
2143          * Setup %tnpc to return to.
2144          */
2145         wrpr    %l0, 0, %tnpc
2146
2147         /*
2148          * Setup %wstate for return, clear WSTATE_TRANSITION.
2149          */
2150         rdpr    %wstate, %l1
2151         and     %l1, WSTATE_NORMAL_MASK, %l1
2152         wrpr    %l1, 0, %wstate
2153
2154         /*
2155          * Setup %tstate for return, change the saved cwp to point to the
2156          * current window instead of the window at the time of the trap.
2157          */
2158         andn    %l5, TSTATE_CWP_MASK, %l1
2159         rdpr    %cwp, %l2
2160         wrpr    %l1, %l2, %tstate
2161
2162         /*
2163          * Setup %sp.  Userland processes will crash if this is not setup.
2164          */
2165         sub     %fp, CCFSZ, %sp
2166
2167         /*
2168          * Execute the user trap handler.
2169          */
2170         done
2171 END(tl0_utrap)
2172
2173 /*
2174  * (Real) User trap entry point
2175  *
2176  * void tl0_trap(u_int type, u_long o1, u_long o2, u_long tar, u_long sfsr,
2177  *     u_int sfsr)
2178  *
2179  * The following setup has been performed:
2180  *      - the windows have been split and the active user window has been saved
2181  *        (maybe just to the pcb)
2182  *      - we are on alternate globals and interrupts are disabled
2183  *
2184  * We switch to the kernel stack, build a trapframe, switch to normal
2185  * globals, enable interrupts and call trap.
2186  *
2187  * NOTE: We must be very careful setting up the per-cpu pointer.  We know that
2188  * it has been pre-set in alternate globals, so we read it from there and setup
2189  * the normal %g7 *before* enabling interrupts.  This avoids any possibility
2190  * of cpu migration and using the wrong pcpup.
2191  */
2192 ENTRY(tl0_trap)
2193         /*
2194          * Force kernel store order.
2195          */
2196         wrpr    %g0, PSTATE_ALT, %pstate
2197
2198         rdpr    %tstate, %l0
2199         rdpr    %tpc, %l1
2200         rdpr    %tnpc, %l2
2201         rd      %y, %l3
2202         rd      %fprs, %l4
2203         rdpr    %wstate, %l5
2204
2205 #if KTR_COMPILE & KTR_TRAP
2206         CATR(KTR_TRAP,
2207             "tl0_trap: td=%p type=%#x pil=%#lx pc=%#lx npc=%#lx sp=%#lx"
2208             , %g1, %g2, %g3, 7, 8, 9)
2209         ldx     [PCPU(CURTHREAD)], %g2
2210         stx     %g2, [%g1 + KTR_PARM1]
2211         stx     %o0, [%g1 + KTR_PARM2]
2212         rdpr    %pil, %g2
2213         stx     %g2, [%g1 + KTR_PARM3]
2214         stx     %l1, [%g1 + KTR_PARM4]
2215         stx     %l2, [%g1 + KTR_PARM5]
2216         stx     %i6, [%g1 + KTR_PARM6]
2217 9:
2218 #endif
2219
2220 1:      and     %l5, WSTATE_NORMAL_MASK, %l5
2221         sllx    %l5, WSTATE_OTHER_SHIFT, %l5
2222         wrpr    %l5, WSTATE_KERNEL, %wstate
2223         rdpr    %canrestore, %l6
2224         wrpr    %l6, 0, %otherwin
2225         wrpr    %g0, 0, %canrestore
2226
2227         sub     PCB_REG, SPOFF + CCFSZ + TF_SIZEOF, %sp
2228
2229         stx     %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
2230         stx     %o1, [%sp + SPOFF + CCFSZ + TF_LEVEL]
2231         stx     %o3, [%sp + SPOFF + CCFSZ + TF_TAR]
2232         stx     %o4, [%sp + SPOFF + CCFSZ + TF_SFAR]
2233         stx     %o5, [%sp + SPOFF + CCFSZ + TF_SFSR]
2234
2235         stx     %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
2236         stx     %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
2237         stx     %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
2238         stx     %l3, [%sp + SPOFF + CCFSZ + TF_Y]
2239         stx     %l4, [%sp + SPOFF + CCFSZ + TF_FPRS]
2240         stx     %l5, [%sp + SPOFF + CCFSZ + TF_WSTATE]
2241
2242         wr      %g0, FPRS_FEF, %fprs
2243         stx     %fsr, [%sp + SPOFF + CCFSZ + TF_FSR]
2244         rd      %gsr, %l6
2245         stx     %l6, [%sp + SPOFF + CCFSZ + TF_GSR]
2246         wr      %g0, 0, %fprs
2247
2248         mov     PCB_REG, %l0
2249         mov     PCPU_REG, %l1
2250         wrpr    %g0, PSTATE_NORMAL, %pstate
2251
2252         stx     %g6, [%sp + SPOFF + CCFSZ + TF_G6]
2253         stx     %g7, [%sp + SPOFF + CCFSZ + TF_G7]
2254
2255         mov     %l0, PCB_REG
2256         mov     %l1, PCPU_REG
2257         wrpr    %g0, PSTATE_KERNEL, %pstate
2258
2259         stx     %i0, [%sp + SPOFF + CCFSZ + TF_O0]
2260         stx     %i1, [%sp + SPOFF + CCFSZ + TF_O1]
2261         stx     %i2, [%sp + SPOFF + CCFSZ + TF_O2]
2262         stx     %i3, [%sp + SPOFF + CCFSZ + TF_O3]
2263         stx     %i4, [%sp + SPOFF + CCFSZ + TF_O4]
2264         stx     %i5, [%sp + SPOFF + CCFSZ + TF_O5]
2265         stx     %i6, [%sp + SPOFF + CCFSZ + TF_O6]
2266         stx     %i7, [%sp + SPOFF + CCFSZ + TF_O7]
2267
2268         stx     %g1, [%sp + SPOFF + CCFSZ + TF_G1]
2269         stx     %g2, [%sp + SPOFF + CCFSZ + TF_G2]
2270         stx     %g3, [%sp + SPOFF + CCFSZ + TF_G3]
2271         stx     %g4, [%sp + SPOFF + CCFSZ + TF_G4]
2272         stx     %g5, [%sp + SPOFF + CCFSZ + TF_G5]
2273
2274         set     tl0_ret - 8, %o7
2275         jmpl    %o2, %g0
2276          add    %sp, CCFSZ + SPOFF, %o0
2277 END(tl0_trap)
2278
2279 /*
2280  * void tl0_intr(u_int level, u_int mask)
2281  */
2282 ENTRY(tl0_intr)
2283         /*
2284          * Force kernel store order.
2285          */
2286         wrpr    %g0, PSTATE_ALT, %pstate
2287
2288         rdpr    %tstate, %l0
2289         rdpr    %tpc, %l1
2290         rdpr    %tnpc, %l2
2291         rd      %y, %l3
2292         rd      %fprs, %l4
2293         rdpr    %wstate, %l5
2294
2295 #if KTR_COMPILE & KTR_INTR
2296         CATR(KTR_INTR,
2297             "tl0_intr: td=%p level=%#x pil=%#lx pc=%#lx npc=%#lx sp=%#lx"
2298             , %g1, %g2, %g3, 7, 8, 9)
2299         ldx     [PCPU(CURTHREAD)], %g2
2300         stx     %g2, [%g1 + KTR_PARM1]
2301         stx     %o0, [%g1 + KTR_PARM2]
2302         rdpr    %pil, %g2
2303         stx     %g2, [%g1 + KTR_PARM3]
2304         stx     %l1, [%g1 + KTR_PARM4]
2305         stx     %l2, [%g1 + KTR_PARM5]
2306         stx     %i6, [%g1 + KTR_PARM6]
2307 9:
2308 #endif
2309
2310         wrpr    %o0, 0, %pil
2311         wr      %o1, 0, %clear_softint
2312
2313         and     %l5, WSTATE_NORMAL_MASK, %l5
2314         sllx    %l5, WSTATE_OTHER_SHIFT, %l5
2315         wrpr    %l5, WSTATE_KERNEL, %wstate
2316         rdpr    %canrestore, %l6
2317         wrpr    %l6, 0, %otherwin
2318         wrpr    %g0, 0, %canrestore
2319
2320         sub     PCB_REG, SPOFF + CCFSZ + TF_SIZEOF, %sp
2321
2322         stx     %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
2323         stx     %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
2324         stx     %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
2325         stx     %l3, [%sp + SPOFF + CCFSZ + TF_Y]
2326         stx     %l4, [%sp + SPOFF + CCFSZ + TF_FPRS]
2327         stx     %l5, [%sp + SPOFF + CCFSZ + TF_WSTATE]
2328
2329         wr      %g0, FPRS_FEF, %fprs
2330         stx     %fsr, [%sp + SPOFF + CCFSZ + TF_FSR]
2331         rd      %gsr, %l6
2332         stx     %l6, [%sp + SPOFF + CCFSZ + TF_GSR]
2333         wr      %g0, 0, %fprs
2334
2335         mov     %o0, %l3
2336         mov     T_INTERRUPT, %o1
2337
2338         stx     %o0, [%sp + SPOFF + CCFSZ + TF_LEVEL]
2339         stx     %o1, [%sp + SPOFF + CCFSZ + TF_TYPE]
2340
2341         mov     PCB_REG, %l0
2342         mov     PCPU_REG, %l1
2343         wrpr    %g0, PSTATE_NORMAL, %pstate
2344
2345         stx     %g1, [%sp + SPOFF + CCFSZ + TF_G1]
2346         stx     %g2, [%sp + SPOFF + CCFSZ + TF_G2]
2347         stx     %g3, [%sp + SPOFF + CCFSZ + TF_G3]
2348         stx     %g4, [%sp + SPOFF + CCFSZ + TF_G4]
2349         stx     %g5, [%sp + SPOFF + CCFSZ + TF_G5]
2350         stx     %g6, [%sp + SPOFF + CCFSZ + TF_G6]
2351         stx     %g7, [%sp + SPOFF + CCFSZ + TF_G7]
2352
2353         mov     %l0, PCB_REG
2354         mov     %l1, PCPU_REG
2355         wrpr    %g0, PSTATE_KERNEL, %pstate
2356
2357         stx     %i0, [%sp + SPOFF + CCFSZ + TF_O0]
2358         stx     %i1, [%sp + SPOFF + CCFSZ + TF_O1]
2359         stx     %i2, [%sp + SPOFF + CCFSZ + TF_O2]
2360         stx     %i3, [%sp + SPOFF + CCFSZ + TF_O3]
2361         stx     %i4, [%sp + SPOFF + CCFSZ + TF_O4]
2362         stx     %i5, [%sp + SPOFF + CCFSZ + TF_O5]
2363         stx     %i6, [%sp + SPOFF + CCFSZ + TF_O6]
2364         stx     %i7, [%sp + SPOFF + CCFSZ + TF_O7]
2365
2366         SET(intr_handlers, %l1, %l0)
2367         sllx    %l3, IH_SHIFT, %l1
2368         ldx     [%l0 + %l1], %l1
2369         KASSERT(%l1, "tl0_intr: ih null")
2370         call    %l1
2371          add    %sp, CCFSZ + SPOFF, %o0
2372
2373         /* %l3 contains PIL */
2374         SET(intrcnt, %l1, %l2)
2375         prefetcha [%l2] ASI_N, 1
2376         SET(pil_countp, %l1, %l0)
2377         sllx    %l3, 1, %l1
2378         lduh    [%l0 + %l1], %l0
2379         sllx    %l0, 3, %l0
2380         add     %l0, %l2, %l0
2381         ldx     [%l0], %l1
2382         inc     %l1
2383         stx     %l1, [%l0]
2384
2385         lduw    [PCPU(CNT) + V_INTR], %l0
2386         inc     %l0
2387         stw     %l0, [PCPU(CNT) + V_INTR]
2388
2389         ba,a    %xcc, tl0_ret
2390          nop
2391 END(tl0_intr)
2392
2393 /*
2394  * Initiate return to usermode.
2395  *
2396  * Called with a trapframe on the stack.  The window that was setup in
2397  * tl0_trap may have been used by "fast" trap handlers that pretend to be
2398  * leaf functions, so all ins and locals may have been clobbered since
2399  * then.
2400  *
2401  * This code is rather long and complicated.
2402  */
2403 ENTRY(tl0_ret)
2404         /*
2405          * Check for pending asts atomically with returning.  We must raise
2406          * the PIL before checking, and if no asts are found the PIL must
2407          * remain raised until the retry is executed, or we risk missing asts
2408          * caused by interrupts occuring after the test.  If the PIL is
2409          * lowered, as it is when we call ast, the check must be re-executed.
2410          */
2411         wrpr    %g0, PIL_TICK, %pil
2412         ldx     [PCPU(CURTHREAD)], %l0
2413         lduw    [%l0 + TD_FLAGS], %l1
2414         set     TDF_ASTPENDING | TDF_NEEDRESCHED, %l2
2415         and     %l1, %l2, %l1
2416         brz,a,pt %l1, 1f
2417          nop
2418
2419         /*
2420          * We have an AST.  Re-enable interrupts and handle it, then restart
2421          * the return sequence.
2422          */
2423         wrpr    %g0, 0, %pil
2424         call    ast
2425          add    %sp, CCFSZ + SPOFF, %o0
2426         ba,a    %xcc, tl0_ret
2427          nop
2428
2429         /*
2430          * Check for windows that were spilled to the pcb and need to be
2431          * copied out.  This must be the last thing that is done before the
2432          * return to usermode.  If there are still user windows in the cpu
2433          * and we call a nested function after this, which causes them to be
2434          * spilled to the pcb, they will not be copied out and the stack will
2435          * be inconsistent.
2436          */
2437 1:      ldx     [PCB_REG + PCB_NSAVED], %l1
2438         brz,a,pt %l1, 2f
2439          nop
2440         wrpr    %g0, 0, %pil
2441         mov     T_SPILL, %o0
2442         stx     %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
2443         call    trap
2444          add    %sp, SPOFF + CCFSZ, %o0
2445         ba,a    %xcc, tl0_ret
2446          nop
2447
2448         /*
2449          * Restore the out and most global registers from the trapframe.
2450          * The ins will become the outs when we restore below.
2451          */
2452 2:      ldx     [%sp + SPOFF + CCFSZ + TF_O0], %i0
2453         ldx     [%sp + SPOFF + CCFSZ + TF_O1], %i1
2454         ldx     [%sp + SPOFF + CCFSZ + TF_O2], %i2
2455         ldx     [%sp + SPOFF + CCFSZ + TF_O3], %i3
2456         ldx     [%sp + SPOFF + CCFSZ + TF_O4], %i4
2457         ldx     [%sp + SPOFF + CCFSZ + TF_O5], %i5
2458         ldx     [%sp + SPOFF + CCFSZ + TF_O6], %i6
2459         ldx     [%sp + SPOFF + CCFSZ + TF_O7], %i7
2460
2461         ldx     [%sp + SPOFF + CCFSZ + TF_G1], %g1
2462         ldx     [%sp + SPOFF + CCFSZ + TF_G2], %g2
2463         ldx     [%sp + SPOFF + CCFSZ + TF_G3], %g3
2464         ldx     [%sp + SPOFF + CCFSZ + TF_G4], %g4
2465         ldx     [%sp + SPOFF + CCFSZ + TF_G5], %g5
2466
2467         /*
2468          * Load everything we need to restore below before disabling
2469          * interrupts.
2470          */
2471         ldx     [%sp + SPOFF + CCFSZ + TF_FPRS], %l0
2472         ldx     [%sp + SPOFF + CCFSZ + TF_GSR], %l1
2473         ldx     [%sp + SPOFF + CCFSZ + TF_TNPC], %l2
2474         ldx     [%sp + SPOFF + CCFSZ + TF_TPC], %l3
2475         ldx     [%sp + SPOFF + CCFSZ + TF_TSTATE], %l4
2476         ldx     [%sp + SPOFF + CCFSZ + TF_Y], %l5
2477         ldx     [%sp + SPOFF + CCFSZ + TF_WSTATE], %l6
2478
2479         /*
2480          * Disable interrupts to restore the special globals.  They are not
2481          * saved and restored for all kernel traps, so an interrupt at the
2482          * wrong time would clobber them.
2483          */
2484         wrpr    %g0, PSTATE_NORMAL, %pstate
2485
2486         ldx     [%sp + SPOFF + CCFSZ + TF_G6], %g6
2487         ldx     [%sp + SPOFF + CCFSZ + TF_G7], %g7
2488
2489         /*
2490          * Switch to alternate globals.  This frees up some registers we
2491          * can use after the restore changes our window.
2492          */
2493         wrpr    %g0, PSTATE_ALT, %pstate
2494
2495         /*
2496          * Drop %pil to zero.  It must have been zero at the time of the
2497          * trap, since we were in usermode, but it was raised above in
2498          * order to check for asts atomically.  We have interrupts disabled
2499          * so any interrupts will not be serviced until we complete the
2500          * return to usermode.
2501          */
2502         wrpr    %g0, 0, %pil
2503
2504         /*
2505          * Save %fprs in an alternate global so it can be restored after the
2506          * restore instruction below.  If we restore it before the restore,
2507          * and the restore traps we may run for a while with floating point
2508          * enabled in the kernel, which we want to avoid.
2509          */
2510         mov     %l0, %g1
2511
2512         /*
2513          * Restore %fsr and %gsr.  These need floating point enabled in %fprs,
2514          * so we set it temporarily and then clear it.
2515          */
2516         wr      %g0, FPRS_FEF, %fprs
2517         ldx     [%sp + SPOFF + CCFSZ + TF_FSR], %fsr
2518         wr      %l1, 0, %gsr
2519         wr      %g0, 0, %fprs
2520
2521         /*
2522          * Restore program counters.  This could be done after the restore
2523          * but we're out of alternate globals to store them in...
2524          */
2525         wrpr    %l2, 0, %tnpc
2526         wrpr    %l3, 0, %tpc
2527
2528         /*
2529          * Save %tstate in an alternate global and clear the %cwp field.  %cwp
2530          * will be affected by the restore below and we need to make sure it
2531          * points to the current window at that time, not the window that was
2532          * active at the time of the trap.
2533          */
2534         andn    %l4, TSTATE_CWP_MASK, %g2
2535
2536         /*
2537          * Restore %y.  Could also be below if we had more alternate globals.
2538          */
2539         wr      %l5, 0, %y
2540
2541         /*
2542          * Setup %wstate for return.  We need to restore the user window state
2543          * which we saved in wstate.other when we trapped.  We also need to
2544          * set the transition bit so the restore will be handled specially
2545          * if it traps, use the xor feature of wrpr to do that.
2546          */
2547         srlx    %l6, WSTATE_OTHER_SHIFT, %g3
2548         wrpr    %g3, WSTATE_TRANSITION, %wstate
2549
2550         /*
2551          * Setup window management registers for return.  If not all user
2552          * windows were spilled in the kernel %otherwin will be non-zero,
2553          * so we need to transfer it to %canrestore to correctly restore
2554          * those windows.  Otherwise everything gets set to zero and the
2555          * restore below will fill a window directly from the user stack.
2556          */
2557         rdpr    %otherwin, %o0
2558         wrpr    %o0, 0, %canrestore
2559         wrpr    %g0, 0, %otherwin
2560         wrpr    %o0, 0, %cleanwin
2561
2562         /*
2563          * Now do the restore.  If this instruction causes a fill trap which
2564          * fails to fill a window from the user stack, we will resume at
2565          * tl0_ret_fill_end and call back into the kernel.
2566          */
2567         restore
2568 tl0_ret_fill:
2569
2570         /*
2571          * We made it.  We're back in the window that was active at the time
2572          * of the trap, and ready to return to usermode.
2573          */
2574
2575         /*
2576          * Restore %frps.  This was saved in an alternate global above.
2577          */
2578         wr      %g1, 0, %fprs
2579
2580         /*
2581          * Fixup %tstate so the saved %cwp points to the current window and
2582          * restore it.
2583          */
2584         rdpr    %cwp, %g4
2585         wrpr    %g2, %g4, %tstate
2586
2587         /*
2588          * Restore the user window state.  The transition bit was set above
2589          * for special handling of the restore, this clears it.
2590          */
2591         wrpr    %g3, 0, %wstate
2592
2593 #if KTR_COMPILE & KTR_TRAP
2594         CATR(KTR_TRAP, "tl0_ret: td=%#lx pil=%#lx pc=%#lx npc=%#lx sp=%#lx"
2595             , %g2, %g3, %g4, 7, 8, 9)
2596         ldx     [PCPU(CURTHREAD)], %g3
2597         stx     %g3, [%g2 + KTR_PARM1]
2598         rdpr    %pil, %g3
2599         stx     %g3, [%g2 + KTR_PARM2]
2600         rdpr    %tpc, %g3
2601         stx     %g3, [%g2 + KTR_PARM3]
2602         rdpr    %tnpc, %g3
2603         stx     %g3, [%g2 + KTR_PARM4]
2604         stx     %sp, [%g2 + KTR_PARM5]
2605 9:
2606 #endif
2607
2608         /*
2609          * Return to usermode.
2610          */
2611         retry
2612 tl0_ret_fill_end:
2613
2614 #if KTR_COMPILE & KTR_TRAP
2615         CATR(KTR_TRAP, "tl0_ret: fill magic ps=%#lx ws=%#lx sp=%#lx"
2616             , %l0, %l1, %l2, 7, 8, 9)
2617         rdpr    %pstate, %l1
2618         stx     %l1, [%l0 + KTR_PARM1]
2619         stx     %l5, [%l0 + KTR_PARM2]
2620         stx     %sp, [%l0 + KTR_PARM3]
2621 9:
2622 #endif
2623
2624         /*
2625          * The restore above caused a fill trap and the fill handler was
2626          * unable to fill a window from the user stack.  The special fill
2627          * handler recognized this and punted, sending us here.  We need
2628          * to carefully undo any state that was restored before the restore
2629          * was executed and call trap again.  Trap will copyin a window
2630          * from the user stack which will fault in the page we need so the
2631          * restore above will succeed when we try again.  If this fails
2632          * the process has trashed its stack, so we kill it.
2633          */
2634
2635         /*
2636          * Restore the kernel window state.  This was saved in %l6 above, and
2637          * since the restore failed we're back in the same window.
2638          */
2639         wrpr    %l6, 0, %wstate
2640
2641         /*
2642          * Restore the normal globals which have predefined values in the
2643          * kernel.  We clobbered them above restoring the user's globals
2644          * so this is very important.
2645          * XXX PSTATE_ALT must already be set.
2646          */
2647         wrpr    %g0, PSTATE_ALT, %pstate
2648         mov     PCB_REG, %o0
2649         mov     PCPU_REG, %o1
2650         wrpr    %g0, PSTATE_NORMAL, %pstate
2651         mov     %o0, PCB_REG
2652         mov     %o1, PCPU_REG
2653         wrpr    %g0, PSTATE_KERNEL, %pstate
2654
2655         /*
2656          * Simulate a fill trap and then start the whole return sequence over
2657          * again.  This is special because it only copies in 1 window, not 2
2658          * as we would for a normal failed fill.  This may be the first time
2659          * the process has been run, so there may not be 2 windows worth of
2660          * stack to copyin.
2661          */
2662         mov     T_FILL_RET, %o0
2663         stx     %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
2664         call    trap
2665          add    %sp, SPOFF + CCFSZ, %o0
2666         ba,a    %xcc, tl0_ret
2667          nop
2668 END(tl0_ret)
2669
2670 /*
2671  * Kernel trap entry point
2672  *
2673  * void tl1_trap(u_int type, u_long o1, u_long o2, u_long tar, u_long sfar,
2674  *     u_int sfsr)
2675  *
2676  * This is easy because the stack is already setup and the windows don't need
2677  * to be split.  We build a trapframe and call trap(), the same as above, but
2678  * the outs don't need to be saved.
2679  */
2680 ENTRY(tl1_trap)
2681         rdpr    %tstate, %l0
2682         rdpr    %tpc, %l1
2683         rdpr    %tnpc, %l2
2684         rdpr    %pil, %l3
2685         rd      %y, %l4
2686         rdpr    %wstate, %l5
2687
2688 #if KTR_COMPILE & KTR_TRAP
2689         CATR(KTR_TRAP, "tl1_trap: td=%p type=%#lx pil=%#lx pc=%#lx sp=%#lx"
2690             , %g1, %g2, %g3, 7, 8, 9)
2691         ldx     [PCPU(CURTHREAD)], %g2
2692         stx     %g2, [%g1 + KTR_PARM1]
2693         stx     %o0, [%g1 + KTR_PARM2]
2694         stx     %l3, [%g1 + KTR_PARM3]
2695         stx     %l1, [%g1 + KTR_PARM4]
2696         stx     %i6, [%g1 + KTR_PARM5]
2697 9:
2698 #endif
2699
2700         wrpr    %g0, 1, %tl
2701
2702         and     %l5, WSTATE_OTHER_MASK, %l5
2703         wrpr    %l5, WSTATE_KERNEL, %wstate
2704
2705         stx     %o0, [%sp + SPOFF + CCFSZ + TF_TYPE]
2706         stx     %o1, [%sp + SPOFF + CCFSZ + TF_LEVEL]
2707         stx     %o3, [%sp + SPOFF + CCFSZ + TF_TAR]
2708         stx     %o4, [%sp + SPOFF + CCFSZ + TF_SFAR]
2709         stx     %o5, [%sp + SPOFF + CCFSZ + TF_SFSR]
2710
2711         stx     %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
2712         stx     %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
2713         stx     %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
2714         stx     %l3, [%sp + SPOFF + CCFSZ + TF_PIL]
2715         stx     %l4, [%sp + SPOFF + CCFSZ + TF_Y]
2716
2717         mov     PCB_REG, %l0
2718         mov     PCPU_REG, %l1
2719         wrpr    %g0, PSTATE_NORMAL, %pstate
2720
2721         stx     %g6, [%sp + SPOFF + CCFSZ + TF_G6]
2722         stx     %g7, [%sp + SPOFF + CCFSZ + TF_G7]
2723
2724         mov     %l0, PCB_REG
2725         mov     %l1, PCPU_REG
2726         wrpr    %g0, PSTATE_KERNEL, %pstate
2727
2728         stx     %i0, [%sp + SPOFF + CCFSZ + TF_O0]
2729         stx     %i1, [%sp + SPOFF + CCFSZ + TF_O1]
2730         stx     %i2, [%sp + SPOFF + CCFSZ + TF_O2]
2731         stx     %i3, [%sp + SPOFF + CCFSZ + TF_O3]
2732         stx     %i4, [%sp + SPOFF + CCFSZ + TF_O4]
2733         stx     %i5, [%sp + SPOFF + CCFSZ + TF_O5]
2734         stx     %i6, [%sp + SPOFF + CCFSZ + TF_O6]
2735         stx     %i7, [%sp + SPOFF + CCFSZ + TF_O7]
2736
2737         stx     %g1, [%sp + SPOFF + CCFSZ + TF_G1]
2738         stx     %g2, [%sp + SPOFF + CCFSZ + TF_G2]
2739         stx     %g3, [%sp + SPOFF + CCFSZ + TF_G3]
2740         stx     %g4, [%sp + SPOFF + CCFSZ + TF_G4]
2741         stx     %g5, [%sp + SPOFF + CCFSZ + TF_G5]
2742
2743         set     tl1_ret - 8, %o7
2744         jmpl    %o2, %g0
2745          add    %sp, CCFSZ + SPOFF, %o0
2746 END(tl1_trap)
2747
2748 ENTRY(tl1_ret)
2749         ldx     [%sp + SPOFF + CCFSZ + TF_O0], %i0
2750         ldx     [%sp + SPOFF + CCFSZ + TF_O1], %i1
2751         ldx     [%sp + SPOFF + CCFSZ + TF_O2], %i2
2752         ldx     [%sp + SPOFF + CCFSZ + TF_O3], %i3
2753         ldx     [%sp + SPOFF + CCFSZ + TF_O4], %i4
2754         ldx     [%sp + SPOFF + CCFSZ + TF_O5], %i5
2755         ldx     [%sp + SPOFF + CCFSZ + TF_O6], %i6
2756         ldx     [%sp + SPOFF + CCFSZ + TF_O7], %i7
2757
2758         ldx     [%sp + SPOFF + CCFSZ + TF_G1], %g1
2759         ldx     [%sp + SPOFF + CCFSZ + TF_G2], %g2
2760         ldx     [%sp + SPOFF + CCFSZ + TF_G3], %g3
2761         ldx     [%sp + SPOFF + CCFSZ + TF_G4], %g4
2762         ldx     [%sp + SPOFF + CCFSZ + TF_G5], %g5
2763
2764         ldx     [%sp + SPOFF + CCFSZ + TF_TSTATE], %l0
2765         ldx     [%sp + SPOFF + CCFSZ + TF_TPC], %l1
2766         ldx     [%sp + SPOFF + CCFSZ + TF_TNPC], %l2
2767         ldx     [%sp + SPOFF + CCFSZ + TF_PIL], %l3
2768         ldx     [%sp + SPOFF + CCFSZ + TF_Y], %l4
2769
2770         set     VM_MIN_PROM_ADDRESS, %l5
2771         cmp     %l1, %l5
2772         bl,a,pt %xcc, 1f
2773          nop
2774         set     VM_MAX_PROM_ADDRESS, %l5
2775         cmp     %l1, %l5
2776         bg,a,pt %xcc, 1f
2777          nop
2778
2779         wrpr    %g0, PSTATE_NORMAL, %pstate
2780
2781         ldx     [%sp + SPOFF + CCFSZ + TF_G6], %g6
2782         ldx     [%sp + SPOFF + CCFSZ + TF_G7], %g7
2783
2784 1:      wrpr    %g0, PSTATE_ALT, %pstate
2785
2786         andn    %l0, TSTATE_CWP_MASK, %g1
2787         mov     %l1, %g2
2788         mov     %l2, %g3
2789
2790         wrpr    %l3, 0, %pil
2791         wr      %l4, 0, %y
2792
2793         restore
2794
2795         wrpr    %g0, 2, %tl
2796
2797         rdpr    %cwp, %g4
2798         wrpr    %g1, %g4, %tstate
2799         wrpr    %g2, 0, %tpc
2800         wrpr    %g3, 0, %tnpc
2801
2802 #if KTR_COMPILE & KTR_TRAP
2803         CATR(KTR_TRAP, "tl1_ret: td=%#lx pil=%#lx ts=%#lx pc=%#lx sp=%#lx"
2804             , %g2, %g3, %g4, 7, 8, 9)
2805         ldx     [PCPU(CURTHREAD)], %g3
2806         stx     %g3, [%g2 + KTR_PARM1]
2807         rdpr    %pil, %g3
2808         stx     %g3, [%g2 + KTR_PARM2]
2809         rdpr    %tstate, %g3
2810         stx     %g3, [%g2 + KTR_PARM3]
2811         rdpr    %tpc, %g3
2812         stx     %g3, [%g2 + KTR_PARM4]
2813         stx     %sp, [%g2 + KTR_PARM5]
2814 9:
2815 #endif
2816
2817         retry
2818 END(tl1_ret)
2819
2820 /*
2821  * void tl1_intr(u_int level, u_int mask)
2822  */
2823 ENTRY(tl1_intr)
2824         rdpr    %tstate, %l0
2825         rdpr    %tpc, %l1
2826         rdpr    %tnpc, %l2
2827         rdpr    %pil, %l3
2828         rd      %y, %l4
2829         rdpr    %wstate, %l5
2830
2831 #if KTR_COMPILE & KTR_INTR
2832         CATR(KTR_INTR,
2833             "tl1_intr: td=%p level=%#x pil=%#lx pc=%#lx sp=%#lx"
2834             , %g1, %g2, %g3, 7, 8, 9)
2835         ldx     [PCPU(CURTHREAD)], %g2
2836         stx     %g2, [%g1 + KTR_PARM1]
2837         stx     %o0, [%g1 + KTR_PARM2]
2838         stx     %l3, [%g1 + KTR_PARM3]
2839         stx     %l1, [%g1 + KTR_PARM4]
2840         stx     %i6, [%g1 + KTR_PARM5]
2841 9:
2842 #endif
2843
2844         wrpr    %o0, 0, %pil
2845         wr      %o1, 0, %clear_softint
2846
2847         wrpr    %g0, 1, %tl
2848
2849         and     %l5, WSTATE_OTHER_MASK, %l5
2850         wrpr    %l5, WSTATE_KERNEL, %wstate
2851
2852         stx     %l0, [%sp + SPOFF + CCFSZ + TF_TSTATE]
2853         stx     %l1, [%sp + SPOFF + CCFSZ + TF_TPC]
2854         stx     %l2, [%sp + SPOFF + CCFSZ + TF_TNPC]
2855         stx     %l3, [%sp + SPOFF + CCFSZ + TF_PIL]
2856         stx     %l4, [%sp + SPOFF + CCFSZ + TF_Y]
2857
2858         mov     %o0, %l7
2859         mov     T_INTERRUPT | T_KERNEL, %o1
2860
2861         stx     %o0, [%sp + SPOFF + CCFSZ + TF_LEVEL]
2862         stx     %o1, [%sp + SPOFF + CCFSZ + TF_TYPE]
2863
2864         stx     %i6, [%sp + SPOFF + CCFSZ + TF_O6]
2865         stx     %i7, [%sp + SPOFF + CCFSZ + TF_O7]
2866
2867         mov     PCB_REG, %l4
2868         mov     PCPU_REG, %l5
2869         wrpr    %g0, PSTATE_NORMAL, %pstate
2870
2871         stx     %g1, [%sp + SPOFF + CCFSZ + TF_G1]
2872         stx     %g2, [%sp + SPOFF + CCFSZ + TF_G2]
2873         stx     %g3, [%sp + SPOFF + CCFSZ + TF_G3]
2874         stx     %g4, [%sp + SPOFF + CCFSZ + TF_G4]
2875         stx     %g5, [%sp + SPOFF + CCFSZ + TF_G5]
2876
2877         mov     %l4, PCB_REG
2878         mov     %l5, PCPU_REG
2879         wrpr    %g0, PSTATE_KERNEL, %pstate
2880
2881         SET(intr_handlers, %l5, %l4)
2882         sllx    %l7, IH_SHIFT, %l5
2883         ldx     [%l4 + %l5], %l5
2884         KASSERT(%l5, "tl1_intr: ih null")
2885         call    %l5
2886          add    %sp, CCFSZ + SPOFF, %o0
2887
2888         /* %l7 contains PIL */
2889         SET(intrcnt, %l5, %l4)
2890         prefetcha [%l4] ASI_N, 1
2891         SET(pil_countp, %l5, %l6)
2892         sllx    %l7, 1, %l5
2893         lduh    [%l5 + %l6], %l5
2894         sllx    %l5, 3, %l5
2895         add     %l5, %l4, %l4
2896         ldx     [%l4], %l5
2897         inc     %l5
2898         stx     %l5, [%l4]
2899
2900         lduw    [PCPU(CNT) + V_INTR], %l4
2901         inc     %l4
2902         stw     %l4, [PCPU(CNT) + V_INTR]
2903
2904         ldx     [%sp + SPOFF + CCFSZ + TF_Y], %l4
2905
2906         ldx     [%sp + SPOFF + CCFSZ + TF_G1], %g1
2907         ldx     [%sp + SPOFF + CCFSZ + TF_G2], %g2
2908         ldx     [%sp + SPOFF + CCFSZ + TF_G3], %g3
2909         ldx     [%sp + SPOFF + CCFSZ + TF_G4], %g4
2910         ldx     [%sp + SPOFF + CCFSZ + TF_G5], %g5
2911
2912         wrpr    %g0, PSTATE_ALT, %pstate
2913
2914         andn    %l0, TSTATE_CWP_MASK, %g1
2915         mov     %l1, %g2
2916         mov     %l2, %g3
2917         wrpr    %l3, 0, %pil
2918         wr      %l4, 0, %y
2919
2920         restore
2921
2922         wrpr    %g0, 2, %tl
2923
2924         rdpr    %cwp, %g4
2925         wrpr    %g1, %g4, %tstate
2926         wrpr    %g2, 0, %tpc
2927         wrpr    %g3, 0, %tnpc
2928
2929 #if KTR_COMPILE & KTR_INTR
2930         CATR(KTR_INTR, "tl1_intr: td=%#x pil=%#lx ts=%#lx pc=%#lx sp=%#lx"
2931             , %g2, %g3, %g4, 7, 8, 9)
2932         ldx     [PCPU(CURTHREAD)], %g3
2933         stx     %g3, [%g2 + KTR_PARM1]
2934         rdpr    %pil, %g3
2935         stx     %g3, [%g2 + KTR_PARM2]
2936         rdpr    %tstate, %g3
2937         stx     %g3, [%g2 + KTR_PARM3]
2938         rdpr    %tpc, %g3
2939         stx     %g3, [%g2 + KTR_PARM4]
2940         stx     %sp, [%g2 + KTR_PARM5]
2941 9:
2942 #endif
2943
2944         retry
2945 END(tl1_intr)
2946
2947         .globl  tl_text_end
2948 tl_text_end:
2949         nop
2950
2951 /*
2952  * Freshly forked processes come here when switched to for the first time.
2953  * The arguments to fork_exit() have been setup in the locals, we must move
2954  * them to the outs.
2955  */
2956 ENTRY(fork_trampoline)
2957 #if KTR_COMPILE & KTR_PROC
2958         CATR(KTR_PROC, "fork_trampoline: td=%p (%s) cwp=%#lx"
2959             , %g1, %g2, %g3, 7, 8, 9)
2960         ldx     [PCPU(CURTHREAD)], %g2
2961         stx     %g2, [%g1 + KTR_PARM1]
2962         ldx     [%g2 + TD_PROC], %g2
2963         add     %g2, P_COMM, %g2
2964         stx     %g2, [%g1 + KTR_PARM2]
2965         rdpr    %cwp, %g2
2966         stx     %g2, [%g1 + KTR_PARM3]
2967 9:
2968 #endif
2969         mov     %l0, %o0
2970         mov     %l1, %o1
2971         call    fork_exit
2972          mov    %l2, %o2
2973         ba,a    %xcc, tl0_ret
2974          nop
2975 END(fork_trampoline)