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