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