]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sun4v/sun4v/exception.S
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sun4v / sun4v / exception.S
1 /*
2  * Copyright (c) 2006 Kip Macy <kmacy@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #include <machine/asm.h>
29 __FBSDID("$FreeBSD$")
30
31 #include "opt_compat.h"
32 #include "opt_ddb.h"
33 #include "opt_simulator.h"
34 #include "opt_trap_trace.h"
35
36 #include <machine/asi.h>
37 #include <machine/asmacros.h>
38 #include <machine/frame.h>
39 #include <machine/fsr.h>
40 #include <machine/hypervisorvar.h>
41 #include <machine/intr_machdep.h>
42 #include <machine/ktr.h>
43 #include <machine/mmu.h>
44 #include <machine/pcb.h>
45 #include <machine/pstate.h>
46 #include <machine/trap.h>
47 #include <machine/tstate.h>
48 #include <machine/utrap.h>
49 #include <machine/wstate.h>
50
51 #include "assym.s"
52
53 #define PMAP_DEBUG
54
55 #define SPILL_FILL_MAGIC_TRAP_ON        nop
56 #define SPILL_FILL_MAGIC_TRAP_OFF       nop
57
58 #define REGSIZE         8
59
60         .register %g2,#ignore
61         .register %g3,#ignore
62         .register %g6,#ignore
63         .register %g7,#ignore
64
65         .globl trap_conversion
66
67 #define PCB_REG %g6
68
69 #define PUTCHAR(x) \
70 0:                              ; \
71         mov     x, %o0          ; \
72         mov     CONS_PUTCHAR, %o5       ; \
73         ta      FAST_TRAP       ; \
74         brnz    %o0, 0b         ; \
75           nop
76
77 /*      
78  * Atomically set the reference bit in a tte.
79  */
80 #define TTE_SET_BIT(r1, r2, r3, bit) \
81         add     r1, TTE_DATA, r1 ; \
82         ldx     [r1], r2 ; \
83 9:      or      r2, bit, r3 ; \
84         casxa   [r1] ASI_N, r2, r3 ; \
85         cmp     r2, r3 ; \
86         bne,pn  %xcc, 9b ; \
87          mov    r3, r2
88
89 #define TTE_SET_REF(r1, r2, r3)         TTE_SET_BIT(r1, r2, r3, TD_REF)
90 #define TTE_SET_W(r1, r2, r3)           TTE_SET_BIT(r1, r2, r3, TD_W)
91
92                 
93 /*
94  * Macros for spilling and filling live windows.
95  * Here we use the more complicated [regaddr] format which requires
96  * us to interleave setting the globals in order to be able to use
97  * imm_asi - we don't ever implicitly assume kernel context as in
98  * Solaris' spill/fill handlers so that we have the option of using
99  * block initializing stores - twin doubleword loads could also be
100  * advantageous but will require an additional macro
101  *
102  */
103
104
105 #define SPILL(storer, base, size) \
106         storer  %l0, [base + (0 * size)] ; \
107         storer  %l1, [base + (1 * size)] ; \
108         storer  %l2, [base + (2 * size)] ; \
109         storer  %l3, [base + (3 * size)] ; \
110         storer  %l4, [base + (4 * size)] ; \
111         storer  %l5, [base + (5 * size)] ; \
112         storer  %l6, [base + (6 * size)] ; \
113         storer  %l7, [base + (7 * size)] ; \
114         storer  %i0, [base + (8 * size)] ; \
115         storer  %i1, [base + (9 * size)] ; \
116         storer  %i2, [base + (10 * size)] ; \
117         storer  %i3, [base + (11 * size)] ; \
118         storer  %i4, [base + (12 * size)] ; \
119         storer  %i5, [base + (13 * size)] ; \
120         storer  %i6, [base + (14 * size)] ; \
121         storer  %i7, [base + (15 * size)]
122
123 #define SPILL_ASI(storer, bias, size, asi) \
124         mov     0 + bias, %g1                   ;\
125         storer  %l0, [%sp + %g1]asi             ;\
126         mov     size + bias, %g2                ;\
127         storer  %l1, [%sp + %g2]asi             ;\
128         mov     (2 * size) + bias, %g3          ;\
129         storer  %l2, [%sp + %g3]asi             ;\
130         mov     (3 * size) + bias, %g4          ;\
131         storer  %l3, [%sp + %g4]asi             ;\
132         add     %sp,  (4 * size), %g5           ;\
133         storer  %l4, [%g5 + %g1]asi             ;\
134         storer  %l5, [%g5 + %g2]asi             ;\
135         storer  %l6, [%g5 + %g3]asi             ;\
136         storer  %l7, [%g5 + %g4]asi             ;\
137         add     %g5,  (4 * size), %g5           ;\
138         storer  %i0, [%g5 + %g1]asi             ;\
139         storer  %i1, [%g5 + %g2]asi             ;\
140         storer  %i2, [%g5 + %g3]asi             ;\
141         storer  %i3, [%g5 + %g4]asi             ;\
142         add     %g5,  (4 * size), %g5           ;\
143         storer  %i4, [%g5 + %g1]asi             ;\
144         storer  %i5, [%g5 + %g2]asi             ;\
145         storer  %i6, [%g5 + %g3]asi             ;\
146         storer  %i7, [%g5 + %g4]asi  
147
148 /* 16 instructions */
149 #define SPILL_ASI_64 \
150         stxa    %l0, [%g1 + 0x0]%asi             ;\
151         stxa    %i0, [%g1 + 0x40]%asi             ;\
152         stxa    %l1, [%g1 + 0x8]%asi              ;\
153         stxa    %l2, [%g1 + 0x10]%asi             ;\
154         stxa    %l3, [%g1 + 0x18]%asi             ;\
155         stxa    %l4, [%g1 + 0x20]%asi             ;\
156         stxa    %l5, [%g1 + 0x28]%asi             ;\
157         stxa    %l6, [%g1 + 0x30]%asi             ;\
158         stxa    %l7, [%g1 + 0x38]%asi             ;\
159         stxa    %i1, [%g1 + 0x48]%asi             ;\
160         stxa    %i2, [%g1 + 0x50]%asi             ;\
161         stxa    %i3, [%g1 + 0x58]%asi             ;\
162         stxa    %i4, [%g1 + 0x60]%asi             ;\
163         stxa    %i5, [%g1 + 0x68]%asi             ;\
164         stxa    %i6, [%g1 + 0x70]%asi             ;\
165         stxa    %i7, [%g1 + 0x78]%asi  
166
167 /* 23 instructions */
168 #define FILL(loader, bias, size, asi) \
169         mov     0 + bias, %g1                   ;\
170         loader  [%sp + %g1]asi, %l0             ;\
171         mov     size + bias, %g2                ;\
172         loader  [%sp + %g2]asi, %l1             ;\
173         mov     (2 * size) + bias, %g3          ;\
174         loader  [%sp + %g3]asi, %l2             ;\
175         mov     (3 * size) + bias, %g4          ;\
176         loader  [%sp + %g4]asi, %l3             ;\
177         add     %sp, (4 * size), %g5            ;\
178         loader  [%g5 + %g1]asi, %l4             ;\
179         loader  [%g5 + %g2]asi, %l5             ;\
180         loader  [%g5 + %g3]asi, %l6             ;\
181         loader  [%g5 + %g4]asi, %l7             ;\
182         add     %g5, (4 * size), %g5            ;\
183         loader  [%g5 + %g1]asi, %i0             ;\
184         loader  [%g5 + %g2]asi, %i1             ;\
185         loader  [%g5 + %g3]asi, %i2             ;\
186         loader  [%g5 + %g4]asi, %i3             ;\
187         add     %g5, (4 * size), %g5            ;\
188         loader  [%g5 + %g1]asi, %i4             ;\
189         loader  [%g5 + %g2]asi, %i5             ;\
190         loader  [%g5 + %g3]asi, %i6             ;\
191         loader  [%g5 + %g4]asi, %i7
192
193 #define SPILL_ASI_SET(storer, size) \
194         storer  %l0, [%g1 + (0 * size)]%asi     ;\
195         storer  %l1, [%g1 + (1 * size)]%asi     ;\
196         storer  %l2, [%g1 + (2 * size)]%asi     ;\
197         storer  %l3, [%g1 + (3 * size)]%asi     ;\
198         storer  %l4, [%g1 + (4 * size)]%asi     ;\
199         storer  %l5, [%g1 + (5 * size)]%asi     ;\
200         storer  %l6, [%g1 + (6 * size)]%asi     ;\
201         storer  %l7, [%g1 + (7 * size)]%asi     ;\
202         storer  %i0, [%g1 + (8 * size)]%asi     ;\
203         storer  %i1, [%g1 + (9 * size)]%asi     ;\
204         storer  %i2, [%g1 + (10 * size)]%asi     ;\
205         storer  %i3, [%g1 + (11 * size)]%asi     ;\
206         storer  %i4, [%g1 + (12 * size)]%asi     ;\
207         storer  %i5, [%g1 + (13 * size)]%asi     ;\
208         storer  %i6, [%g1 + (14 * size)]%asi     ;\
209         storer  %i7, [%g1 + (15 * size)]%asi 
210
211 /* 16 instructions */
212 #define FILL_ASI_SET(loader, size) \
213         loader  [%g1 + 0x0]%asi, %l0            ;\
214         loader  [%g1 + (size * 1)]%asi, %l1     ;\
215         loader  [%g1 + (size * 2)]%asi, %l2     ;\
216         loader  [%g1 + (size * 3)]%asi, %l3     ;\
217         loader  [%g1 + (size * 4)]%asi, %l4     ;\
218         loader  [%g1 + (size * 5)]%asi, %l5     ;\
219         loader  [%g1 + (size * 6)]%asi, %l6     ;\
220         loader  [%g1 + (size * 7)]%asi, %l7     ;\
221         loader  [%g1 + (size * 8)]%asi, %i0     ;\
222         loader  [%g1 + (size * 9)]%asi, %i1     ;\
223         loader  [%g1 + (size * 10)]%asi, %i2    ;\
224         loader  [%g1 + (size * 11)]%asi, %i3    ;\
225         loader  [%g1 + (size * 12)]%asi, %i4    ;\
226         loader  [%g1 + (size * 13)]%asi, %i5    ;\
227         loader  [%g1 + (size * 14)]%asi, %i6    ;\
228         loader  [%g1 + (size * 15)]%asi, %i7    
229         
230 /* 9 instructions */
231 #define FILL_DW \
232         prefetch [%g1 + 0x40], #one_read        ;\
233         ldda    [%g1 + 0]%asi, %l0              ;\
234         ldda    [%g1 + 0x10]%asi, %l2           ;\
235         ldda    [%g1 + 0x20]%asi, %l4           ;\
236         ldda    [%g1 + 0x30]%asi, %l6           ;\
237         ldda    [%g1 + 0x40]%asi, %i0           ;\
238         ldda    [%g1 + 0x50]%asi, %i2           ;\
239         ldda    [%g1 + 0x60]%asi, %i4           ;\
240         ldda    [%g1 + 0x70]%asi, %i6           
241
242 #include <sun4v/sun4v/wbuf.S>   
243         /*
244          * Clean window traps occur when %cleanwin is zero to ensure that data
245          * is not leaked between address spaces in registers.
246          */
247         .macro  clean_window
248         clr     %o0
249         clr     %o1
250         clr     %o2
251         clr     %o3
252         clr     %o4
253         clr     %o5
254         clr     %o6
255         clr     %o7
256         clr     %l0
257         clr     %l1
258         clr     %l2
259         clr     %l3
260         clr     %l4
261         clr     %l5
262         clr     %l6
263         rdpr    %cleanwin, %l7
264         inc     %l7
265         wrpr    %l7, 0, %cleanwin
266         clr     %l7
267         retry
268         .align  128
269         .endm
270
271         .macro  tl0_split
272         .endm
273
274         .macro  tl0_setup       type
275         rdpr    %tt, %g3
276         sub     %g0, 1, %g4
277         set     trap, %g1
278         ba      %xcc, tl0_trap
279           mov   \type, %g2
280         .endm
281
282         /*
283          * Generic trap type.  Call trap() with the specified type.
284          */
285         .macro  tl0_gen         type
286         tl0_setup \type
287         .align  32
288         .endm
289
290         /*
291          * This is used to suck up the massive swaths of reserved trap types.
292          * Generates count "reserved" trap vectors.
293          */
294
295         .macro  tl0_reserved    count
296         .rept   \count
297         tl0_gen T_RESERVED
298         .align  32
299         .endr
300         .endm
301
302         .macro  tl1_setup       type
303         rdpr    %tt, %g3
304         sub     %g0, 1, %g4
305         set     trap, %g1
306         ba      %xcc, tl1_trap
307           mov   \type, %g2
308         .endm
309
310         .macro  tl1_gen         type
311         tl1_setup \type
312         .align  32
313         .endm
314
315         .macro  tl1_reserved    count
316         .rept   \count
317         tl1_gen T_RESERVED
318         .endr
319         .endm
320
321         .macro  insn_excptn
322         GET_MMFSA_SCRATCH(%g1)                  
323         mov     MMFSA_D_ADDR, %g2
324         ldxa    [%g1 + %g2]ASI_REAL, %g3
325         sub     %g0, 1, %g4
326         set     trap, %g1
327         ba,pt   %xcc, tl0_trap 
328           mov   T_INSTRUCTION_EXCEPTION, %g2
329
330         .align  32
331         .endm
332
333         .macro  insn_miss
334         GET_MMFSA_SCRATCH(%g1)  
335         mov     MMFSA_I_TYPE, %g2 
336         mov     MMFSA_I_ADDR, %g3
337         mov     MMFSA_I_CTX, %g7 
338         ldxa    [%g1 + %g2]ASI_REAL, %g4
339         ba,pt   %xcc, tsb_miss_handler
340           ldxa  [%g1 + %g3]ASI_REAL, %g5
341         .align  32
342         .endm
343         
344         .macro  data_excptn
345         GET_MMFSA_SCRATCH(%g1)                  
346         mov     MMFSA_D_ADDR, %g2
347         ba,pt   %xcc, data_excptn_fault
348         ldxa    [%g1 + %g2]ASI_REAL, %g3
349         .align  32
350         .endm
351
352 ENTRY(data_excptn_fault)
353         mov     MMFSA_D_CTX, %g7 
354         ldxa    [%g1 + %g7]ASI_REAL, %g4
355         sllx    %g4, TRAP_CTX_SHIFT, %g4
356         or      %g4, T_DATA_EXCEPTION, %g2
357         set     trap, %g1
358         ba,pt   %xcc, tl0_trap 
359           sub   %g0, 1, %g4
360 END(data_excptn_fault)
361
362         .macro  data_miss
363         GET_MMFSA_SCRATCH(%g1)                  
364         mov     MMFSA_D_TYPE, %g2 
365         mov     MMFSA_D_ADDR, %g3
366         mov     MMFSA_D_CTX, %g7 
367         ldxa    [%g1 + %g2]ASI_REAL, %g4
368         ba,pt   %xcc, tsb_miss_handler
369           ldxa  [%g1 + %g3]ASI_REAL, %g5
370         .align  32
371         .endm
372
373         .macro  data_prot
374         GET_MMFSA_SCRATCH(%g1)          
375         mov     MMFSA_D_ADDR, %g3
376         mov     MMFSA_D_CTX,  %g7
377         ba,pt   %xcc, tsb_miss_handler
378           ldxa  [%g1 + %g3]ASI_REAL, %g5
379         .align  32
380         .endm
381
382         .macro  tl0_align
383         GET_MMFSA_SCRATCH(%g1)  
384         mov     MMFSA_D_ADDR, %g3
385         mov     MMFSA_D_CTX,  %g7
386         ba,pt   %xcc, align_fault
387           ldxa  [%g1 + %g3]ASI_REAL, %g3
388         .align  32
389         .endm
390
391 ENTRY(align_fault)
392         ldxa    [%g1 + %g7]ASI_REAL, %g4
393         sllx    %g4, TRAP_CTX_SHIFT, %g4
394         or      %g4, T_MEM_ADDRESS_NOT_ALIGNED, %g2
395         set     trap, %g1
396         ba,pt   %xcc, tl0_trap
397           sub   %g0, 1, %g4
398 END(align_fault)
399                 
400         .macro  cpu_mondo
401         ba,a,pt %xcc, cpu_mondo
402         .align  32
403         .endm
404
405         .macro  dev_mondo
406         ba,a,pt %xcc, dev_mondo
407         .align  32
408         .endm
409
410         .macro  resumable_error
411         !MAGIC_TRAP_ON
412         !MAGIC_EXIT
413         clr     %g3
414         sub     %g0, 1, %g4
415         set     trap, %g1
416         ba,pt   %xcc, tl0_trap
417           mov   T_RESUMABLE_ERROR, %g2
418         .align  32
419         .endm
420
421         .macro  nonresumable_error
422         clr     %g3
423         sub     %g0, 1, %g4
424         set     trap, %g1
425         ba,pt   %xcc, tl0_trap
426           mov   T_NONRESUMABLE_ERROR, %g2
427         .align  32
428         .endm
429
430
431 #define ALIGN_128       .align  128
432 #define SYNC            #Sync
433 #define LOOKASIDE       #Lookaside
434
435 #ifdef USE_FAST_SPILLFILL
436 #define spill_64bit_asi(asival, asival_unaligned, target)       \
437         wr      %g0, asival, %asi  ;            \
438         add     %sp, SPOFF, %g1    ;            \
439         SPILL_ASI_64               ;            \
440         membar  LOOKASIDE          ;            \
441         saved                      ;            \
442         retry                      ;            \
443         .skip (31-21)*4            ;            \
444         ba,a,pt %xcc, fault_64bit_##target ; \
445         ALIGN_128       
446
447 #define spill_64clean(asival, asival_unaligned, target)         \
448         wr      %g0, asival, %asi  ;            \
449         add     %sp, SPOFF, %g1    ;            \
450         SPILL_ASI_64               ;            \
451         membar  LOOKASIDE          ;            \
452         b       spill_clean        ;            \
453           mov   WSTATE_USER64, %g7 ;            \
454         .skip (31-21)*4            ;            \
455         ba,a,pt %xcc, fault_64bit_##target ;    \
456         ALIGN_128       
457
458 #define fill_64bit_asi(asival, asival_unaligned, target)        \
459         add     %sp, SPOFF, %g1    ;            \
460         wr      %g0, asival, %asi  ;            \
461         FILL_DW                    ;            \
462         restored                   ;            \
463         retry                      ;            \
464         .skip (31-13)*4            ;            \
465         ba,a,pt %xcc, fault_64bit_##target ; \
466         ALIGN_128       
467 #else
468 #define spill_64bit_asi(asival, asival_unaligned, target)       \
469         wr      %g0, asival_unaligned, %asi ;   \
470         add     %sp, SPOFF, %g1   ;             \
471         SPILL_ASI_SET(stxa, 8)     ;            \
472         saved                      ;            \
473         retry                      ;            \
474         .skip (31-20)*4            ;            \
475         ba,a,pt %xcc, fault_64bit_##target ; \
476         ALIGN_128       
477
478 #define spill_64clean(asival, asival_unaligned, target)         \
479         wr      %g0, asival_unaligned, %asi  ;            \
480         add     %sp, SPOFF, %g1    ;            \
481         SPILL_ASI_SET(stxa, 8)     ;            \
482         b       spill_clean        ;            \
483           mov   WSTATE_USER64, %g7 ;            \
484         .skip (31-20)*4            ;            \
485         ba,a,pt %xcc, fault_64bit_##target ;    \
486         ALIGN_128       
487
488 #define fill_64bit_asi(asival, asival_unaligned, target)        \
489         wr      %g0, asival_unaligned, %asi  ;  \
490         add     %sp, SPOFF, %g1   ;             \
491         FILL_ASI_SET(ldxa, 8)      ;            \
492         restored                   ;            \
493         retry                      ;            \
494         .skip (31-20)*4            ;            \
495         ba,a,pt %xcc, fault_64bit_##target ; \
496         ALIGN_128       
497 #endif
498
499 #define spill_32bit_asi(asi, target)            \
500         srl     %sp, 0, %sp     ;               \
501         SPILL_FILL_MAGIC_TRAP_ON;               \
502         SPILL_ASI(sta, 0, 4, asi)       ;       \
503         saved                   ;               \
504         SPILL_FILL_MAGIC_TRAP_OFF;              \
505         retry                   ;               \
506         .skip (31-28)*4         ;               \
507         ba,a,pt %xcc, fault_32bit_##target ; \
508         ALIGN_128
509
510 #define spill_32clean(asi, target)              \
511         srl     %sp, 0, %sp     ;               \
512         SPILL_FILL_MAGIC_TRAP_ON;               \
513         SPILL_ASI(sta, 0, 4, asi)       ;       \
514         b       spill_clean     ;               \
515           mov   WSTATE_USER32, %g7 ;            \
516         .skip (31-27)*4         ;               \
517         ba,a,pt    %xcc, fault_32bit_##target ; \
518         ALIGN_128       
519         
520 #define fill_32bit_asi(asi, target)             \
521         srl     %sp, 0, %sp     ;               \
522         SPILL_FILL_MAGIC_TRAP_ON;               \
523         FILL(lda, 0, 4, asi)    ;               \
524         restored                ;               \
525         retry                   ;               \
526         .skip (31-27)*4         ;               \
527         ba,a,pt %xcc, fault_32bit_##target ; \
528         ALIGN_128       
529
530 .align 128
531 ENTRY(fill_64bit_slow_fn0)                      
532 fill_slow_start:                
533         FILL_ASI_SET(ldxa, 8);                  
534         restored                ;               
535         retry                   ;               
536         .skip (31-18)*4            ;            
537         ba,a,pt %xcc, fault_64bit_fn0 ;
538         .align 128      
539 END(fill_64bit_slow_fn0)
540 ENTRY(fill_64bit_slow_not)                      
541         FILL_ASI_SET(ldxa, 8);                  
542         restored                ;               
543         retry                   ;               
544         .skip (31-18)*4            ;            
545         ba,a,pt %xcc, fault_64bit_not ; 
546         .align 128      
547 END(fill_64bit_slow_not)
548 fill_slow_end:  
549                 
550         .macro  spill_32bit_primary_sn0
551         spill_32bit_asi(ASI_AIUP, sn0)
552         .endm
553
554         .macro  spill_64bit_primary_sn0
555         spill_64bit_asi(ASI_LDSTBI_AIUP, ASI_AIUP, sn0)
556         .endm
557
558         .macro spill_32clean_primary_sn0
559         spill_32clean(ASI_AIUP, sn0)
560         .endm
561                         
562         .macro spill_64clean_primary_sn0
563         spill_64clean(ASI_LDSTBI_AIUP, ASI_AIUP, sn0)
564         .endm
565
566         .macro spill_32bit_nucleus_not
567         spill_32bit_asi(ASI_N, not)
568         .endm
569
570         .macro spill_64bit_nucleus_not
571         spill_64bit_asi(ASI_LDSTBI_N, ASI_N, not)
572         .endm
573
574         .macro  spill_32bit_secondary_so0
575         spill_32bit_asi(ASI_AIUS, so0)
576         .endm
577
578         .macro  spill_64bit_secondary_so0
579         spill_64bit_asi(ASI_LDSTBI_AIUS, ASI_AIUS, so0)
580         .endm
581         
582         .macro  fill_32bit_primary_fn0
583         fill_32bit_asi(ASI_AIUP, fn0)
584         .endm
585
586         .macro  fill_64bit_primary_fn0
587         fill_64bit_asi(ASI_LDSTBI_AIUP, ASI_AIUP, fn0)
588         .endm
589
590         .macro fill_32bit_nucleus_not
591         fill_32bit_asi(ASI_N, not)
592         .endm
593
594         .macro fill_64bit_nucleus_not
595         fill_64bit_asi(ASI_LDSTBI_N, ASI_N, not)
596         .endm
597
598         .macro  spill_32bit_tt1_primary_sn1
599         ba,a,pt %xcc, fault_32bit_sn1
600           nop
601         .align 128
602         .endm
603
604         .macro  spill_64bit_tt1_primary_sn1 
605         ba,a,pt %xcc, fault_64bit_sn1
606           nop
607         .align 128
608         .endm
609
610         .macro  spill_64bit_ktt1_sk
611         ba,a,pt %xcc, fault_64bit_sk
612           nop
613         .align 128
614         .endm
615
616         .macro  spill_mixed_ktt1_sk
617         btst    1, %sp
618         bz,a,pt %xcc, fault_32bit_sk
619           srl   %sp, 0, %sp
620         ba,a,pt %xcc, fault_64bit_sk
621           nop
622         .align 128
623         .endm
624
625         .macro  spill_32bit_tt1_secondary_so1
626         ba,a,pt %xcc, fault_32bit_so1
627           nop
628         .align 128
629         .endm
630
631         .macro  spill_64bit_tt1_secondary_so1
632         ba,a,pt %xcc, fault_64bit_so1
633           nop
634         .align 128
635         .endm
636
637         .macro  spill_mixed
638 !       MAGIC_EXIT
639         nop
640         .align  128
641         .endm
642
643         .macro  fill_mixed
644 !       MAGIC_EXIT
645         nop
646         .align  128
647         .endm
648
649         .macro  tl1_align
650         ba,a,pt %xcc, tl1_trap
651         .align  32
652         .endm           
653                 
654         .macro  tl0_pil_entry level, mask
655         wrpr    %g0, 1, %gl
656         set     \mask, %g1
657         clr     %g2
658         clr     %g3
659         wr      %g1, 0, %clear_softint
660         ba      %xcc, tl0_intr
661           mov   \level, %g4
662         .align  32
663         .endm
664
665 #define INTR(level, traplvl)                                            \
666         tl ## traplvl ## _pil_entry     level, 1 << level
667
668 #define TICK(traplvl) \
669         tl ## traplvl ## _pil_entry     PIL_TICK, 1
670
671 #define INTR_LEVEL(tl)                                                  \
672         INTR(1, tl) ;                                                   \
673         INTR(2, tl) ;                                                   \
674         INTR(3, tl) ;                                                   \
675         INTR(4, tl) ;                                                   \
676         INTR(5, tl) ;                                                   \
677         INTR(6, tl) ;                                                   \
678         INTR(7, tl) ;                                                   \
679         INTR(8, tl) ;                                                   \
680         INTR(9, tl) ;                                                   \
681         INTR(10, tl) ;                                                  \
682         INTR(11, tl) ;                                                  \
683         INTR(12, tl) ;                                                  \
684         INTR(13, tl) ;                                                  \
685 tick_ ## tl ## _entry:                                                  \
686         TICK(tl) ;                                                      \
687         INTR(15, tl) ;
688
689         .macro  tl0_pil
690         INTR_LEVEL(0)
691         .endm
692
693
694         .macro  tl0_syscall
695         clr     %g3
696         sub     %g0, 1, %g4
697         set     syscall, %g1
698         ba      %xcc, tl0_trap
699           mov   T_SYSCALL, %g2
700         .align  32
701         .endm
702
703 #ifdef KDTRACE
704         .macro  dtrace_fasttrap
705         sethi   %hi(dtrace_fasttrap_probe_ptr), %g4
706         ldx     [%g4 + %lo(dtrace_fasttrap_probe_ptr)], %g4
707         set     dtrace_fasttrap_probe, %g1
708         brnz,pn %g4, tl0_utrap
709           sub   %g0, 1, %g4
710         .align  32
711         .endm
712
713         .macro  dtrace_pid
714         set     dtrace_pid_probe, %g1
715         ba,pt   %xcc, tl0_utrap
716           sub   %g0, 1, %g4
717         .align  32
718         .endm
719
720         .macro  dtrace_return
721         set     dtrace_return_probe, %g1
722         ba,pt   %xcc, tl0_utrap
723           sub   %g0, 1, %g4
724         .align 32
725         .endm
726 #else
727         .macro  dtrace_fasttrap
728         nop
729         .align 32
730         .endm
731                 
732         .macro  dtrace_pid
733         nop
734         .align 32
735         .endm
736
737         .macro  dtrace_return
738         nop
739         .align 32
740         .endm
741 #endif  
742
743         ! fetch FP context into local registers
744         .macro  tl0_fpemu_context
745         GET_PCB(PCB_REG)                        ! 3 instructions
746         ldx     [PCB_REG + PCB_TSTATE], %l5     ! %tstate
747         ldx     [PCB_REG + PCB_TPC], %l6        ! %tpc
748         ldx     [PCB_REG + PCB_TNPC], %l7       ! %tnpc
749         ldx     [PCB_REG + PCB_TT], %g2         ! %tt
750         ba,a,pt %xcc, tl0_fpemu_context
751         .align  32
752         .endm
753
754 ENTRY(tl0_fpemu_context)
755         mov     %g2, %o0
756         clr     %o1
757         ldx     [PCB_REG + PCB_SFAR], %o4
758         
759         rd      %fprs, %l1
760         or      %l1, FPRS_FEF, %l2
761         wr      %l2, 0, %fprs
762         stx     %fsr, [PCB_REG + PCB_PAD]
763         ldx     [PCB_REG + PCB_PAD], %l4
764         wr      %l1, 0, %fprs
765                 
766         sub     %fp, CCFSZ, %sp 
767         done    
768 END(tl0_fpemu_context)
769         
770         .macro  tl0_fp_restore
771         GET_PCB(PCB_REG)                        ! 3 instructions
772         ldx     [%g6 + PCB_FLAGS], %g1
773         ba,pt   %xcc, tl0_fp_restore
774           wr    %g0, FPRS_FEF, %fprs
775         .align  32
776         .endm
777
778         .macro tl0_fp_enable
779         GET_PCB(PCB_REG)                        ! 3 instructions
780         ldx     [PCB_REG + PCB_FLAGS], %g1
781         andcc   %g1, PCB_FEF, %g0
782         bnz,pt  %xcc, tl0_fp_restore            
783           wr    %g0, FPRS_FEF, %fprs
784         retry
785         .align  32
786         .endm
787         
788 ENTRY(tl0_fp_restore)
789         andn    %g1, PCB_FEF, %g1
790         stx     %g1, [%g6 + PCB_FLAGS]
791         
792         ldd     [PCB_REG + PCB_UFP + (0 * 64)], %f0
793         ldd     [PCB_REG + PCB_UFP + (1 * 64)], %f16
794         ldd     [PCB_REG + PCB_UFP + (2 * 64)], %f32
795         ldd     [PCB_REG + PCB_UFP + (3 * 64)], %f48
796         retry
797 END(tl0_fp_restore)
798
799         .macro  tl1_insn_excptn
800          nop
801         .align  32
802         .endm
803
804
805         .macro  tl1_soft        count
806         .rept   \count
807         tl1_gen T_SOFT | T_KERNEL
808         .endr
809         .endm
810
811         .sect   .trap
812         .align  0x8000
813         .globl  tl0_base
814 tl0_base:
815         tl0_reserved    8                               ! 0x0-0x7
816 tl0_insn_excptn:
817         insn_excptn                                     ! 0x8
818 tl0_insn_miss:
819         insn_miss                                       ! 0x9
820         tl0_reserved    6                               ! 0xa-0xf
821 tl0_insn_illegal:
822         tl0_gen         T_ILLEGAL_INSTRUCTION           ! 0x10
823 tl0_priv_opcode:
824         tl0_gen         T_PRIVILEGED_OPCODE             ! 0x11
825         tl0_reserved    14                              ! 0x12-0x1f
826 tl0_fp_disabled:
827         tl0_fp_enable                                   ! 0x20
828 tl0_fp_ieee:
829         tl0_gen         T_FP_EXCEPTION_IEEE_754         ! 0x21
830 tl0_fp_other:
831         tl0_gen         T_FP_EXCEPTION_OTHER            ! 0x22
832 tl0_tag_ovflw:
833         tl0_gen         T_TAG_OVERFLOW                  ! 0x23
834 tl0_clean_window:
835         clean_window                                    ! 0x24
836 tl0_divide:
837         tl0_gen         T_DIVISION_BY_ZERO              ! 0x28
838         tl0_reserved    7                               ! 0x29-0x2f
839 tl0_data_excptn:
840         data_excptn                                     ! 0x30
841 tl0_data_miss:
842         data_miss                                       ! 0x31
843         tl0_reserved    2                               ! 0x32-0x33
844 tl0_align:
845         tl0_align                                       ! 0x34
846 tl0_align_lddf:
847         tl0_gen         T_RESERVED                      ! 0x35
848 tl0_align_stdf:
849         tl0_gen         T_RESERVED                      ! 0x36
850 tl0_priv_action:
851         tl0_gen         T_PRIVILEGED_ACTION             ! 0x37
852         tl0_reserved    9                               ! 0x38-0x40
853 tl0_intr_level_41:
854         tl0_pil                                         ! 0x41-0x4f
855         tl0_reserved    18                              ! 0x50-0x61
856 tl0_watch_virt_62:
857         tl0_gen         T_VA_WATCHPOINT                 ! 0x62
858         tl0_reserved    9                               ! 0x63-0x6b
859 tl0_data_prot_6c:       
860         data_prot                                       ! 0x6c
861         tl0_reserved    9                               ! 0x6d-0x75
862 tl0_breakpoint_76:
863         tl0_gen         T_BREAKPOINT                    ! 0x76
864         tl0_reserved    5                               ! 0x77-0x7b
865 tl0_cpu_mondo_7c:
866         cpu_mondo                                       ! 0x7c
867 tl0_dev_mondo_7d:       
868         dev_mondo                                       ! 0x7d  
869 tl0_resumable_error_7e:
870         resumable_error                                 ! 0x7e
871 tl0_nonresumable_error_7f:      
872         nonresumable_error                              ! 0x7f  
873 tl0_spill_n_normal_80:
874 tl0_spill_0_normal:     
875         tl0_reserved            4                       ! 0x80
876 tl0_spill_1_normal:     
877         spill_32bit_primary_sn0                         ! 0x84
878 tl0_spill_2_normal:     
879         spill_64bit_primary_sn0                         ! 0x88
880 tl0_spill_3_normal:     
881         spill_32clean_primary_sn0                       ! 0x8c
882 tl0_spill_4_normal:     
883         spill_64clean_primary_sn0                       ! 0x90
884 tl0_spill_5_normal:     
885         spill_32bit_nucleus_not                         ! 0x94
886 tl0_spill_6_normal:     
887         spill_64bit_nucleus_not                         ! 0x98
888 tl0_spill_7_normal:     
889         spill_mixed                                     ! 0x9c
890 tl0_spill_0_other:
891         tl0_reserved            4                       ! 0xa0
892 tl0_spill_1_other:
893         spill_32bit_secondary_so0                       ! 0xa4
894 tl0_spill_2_other:
895         spill_64bit_secondary_so0                       ! 0xa8
896 tl0_spill_3_other:
897         spill_32bit_secondary_so0                       ! 0xac
898 tl0_spill_4_other:
899         spill_64bit_secondary_so0                       ! 0xb0
900 tl0_spill_5_other:
901         tl0_reserved            4                       ! 0xb4
902 tl0_spill_6_other:
903         tl0_reserved            4                       ! 0xb8
904 tl0_spill_7_other:
905         tl0_reserved            4                       ! 0xbc
906 tl0_fill_n_normal:
907         tl0_reserved            4                       ! 0xc0
908 tl0_fill_1_normal:      
909         fill_32bit_primary_fn0                          ! 0xc4 
910 tl0_fill_2_normal:      
911         fill_64bit_primary_fn0                          ! 0xc8
912 tl0_fill_3_normal:      
913         fill_32bit_primary_fn0                          ! 0xcc
914 tl0_fill_4_normal:      
915         fill_64bit_primary_fn0                          ! 0xd0
916 tl0_fill_5_normal:      
917         fill_32bit_nucleus_not                          ! 0xd4
918 tl0_fill_6_normal:      
919         fill_64bit_nucleus_not                          ! 0xd8
920 tl0_fill_7_normal:      
921         fill_mixed                                      ! 0xdc
922 tl0_fill_n_other_e0:
923         tl0_reserved            32                      ! 0xe0-0xff
924 tl0_soft_100:
925         tl0_gen         T_SYSCALL                       ! 0x100
926         tl0_gen         T_BREAKPOINT                    ! 0x101
927         tl0_gen         T_DIVISION_BY_ZERO              ! 0x102
928         tl0_reserved    1                               ! 0x103
929         tl0_gen         T_CLEAN_WINDOW                  ! 0x104
930         tl0_gen         T_RANGE_CHECK                   ! 0x105
931         tl0_gen         T_FIX_ALIGNMENT                 ! 0x106
932         tl0_gen         T_INTEGER_OVERFLOW              ! 0x107
933         tl0_gen         T_SYSCALL                       ! 0x108
934         tl0_gen         T_SYSCALL                       ! 0x109
935         tl0_fp_restore                                  ! 0x10a
936         tl0_fpemu_context                               ! 0x10b
937         tl0_reserved    4                               ! 0x10c-0x10f
938         tl0_gen         T_TRAP_INSTRUCTION_16           ! 0x110
939         tl0_gen         T_TRAP_INSTRUCTION_17           ! 0x111
940         tl0_gen         T_TRAP_INSTRUCTION_18           ! 0x112
941         tl0_gen         T_TRAP_INSTRUCTION_19           ! 0x113
942         tl0_gen         T_TRAP_INSTRUCTION_20           ! 0x114
943         tl0_gen         T_TRAP_INSTRUCTION_21           ! 0x115
944         tl0_gen         T_TRAP_INSTRUCTION_22           ! 0x116
945         tl0_gen         T_TRAP_INSTRUCTION_23           ! 0x117
946         tl0_gen         T_TRAP_INSTRUCTION_24           ! 0x118
947         tl0_gen         T_TRAP_INSTRUCTION_25           ! 0x119
948         tl0_gen         T_TRAP_INSTRUCTION_26           ! 0x11a
949         tl0_gen         T_TRAP_INSTRUCTION_27           ! 0x11b
950         tl0_gen         T_TRAP_INSTRUCTION_28           ! 0x11c
951         tl0_gen         T_TRAP_INSTRUCTION_29           ! 0x11d
952         tl0_gen         T_TRAP_INSTRUCTION_30           ! 0x11e
953         tl0_gen         T_TRAP_INSTRUCTION_31           ! 0x11f
954         tl0_reserved    24                              ! 0x120-0x137
955 tl0_dtrace_pid:                                         
956         dtrace_pid                                      ! 0x138
957 tl0_dtrace_fasttrap:                                    
958         dtrace_fasttrap                                 ! 0x139
959 tl0_dtrace_return:                                      
960         dtrace_return                                   ! 0x13a
961         tl0_reserved    5                               ! 0x13b - 0x13f
962         tl0_gen         T_SYSCALL                       ! 0x140       LP64 system call
963         tl0_syscall                                     ! 0x141
964         tl0_gen         T_SYSCALL                       ! 0x142
965         tl0_gen         T_SYSCALL                       ! 0x143
966         tl0_reserved    188                             ! 0x144-0x1ff
967 tl1_base:
968         tl1_reserved    9                               ! 0x200-0x208
969 tl1_insn_miss_209:
970         insn_miss                                       ! 0x209
971         tl1_reserved    26                              ! 0x20a-0x223
972 tl1_clean_window_224:
973         clean_window                                    ! 0x224
974 tl1_divide_228:
975         tl1_reserved    8                               ! 0x228-0x22f
976 tl1_data_excptn_230:
977         data_excptn                                     ! 0x230
978 tl1_data_miss_231:
979         data_miss                                       ! 0x231
980         tl1_reserved    2                               ! 0x232-0x233
981 tl1_align:
982         tl1_align                                       ! 0x234
983         tl1_reserved    55                              ! 0x235-0x26b
984 tl1_data_prot:
985         data_prot                                       ! 0x26c
986         tl1_reserved    18                              ! 0x26c-0x27e
987 tl1_nonresumable_error: 
988         nonresumable_error                              ! 0x27f 
989 tl1_spill_n_normal:
990 tl1_spill_0_normal:     
991         tl1_reserved            4                       ! 0x280
992 tl1_spill_1_normal:
993         spill_32bit_tt1_primary_sn1                     ! 0x284
994 tl1_spill_2_normal:
995         spill_64bit_tt1_primary_sn1                     ! 0x288
996 tl1_spill_3_normal:
997         spill_32bit_tt1_primary_sn1                     ! 0x28c
998 tl1_spill_4_normal:
999         spill_64bit_tt1_primary_sn1                     ! 0x290
1000 tl1_spill_5_normal:
1001         tl1_reserved            4                       ! 0x294
1002 tl1_spill_6_normal:
1003         spill_64bit_ktt1_sk                             ! 0x298
1004 tl1_spill_7_normal:
1005         spill_mixed_ktt1_sk                             ! 0x29c
1006 tl1_spill_n_other:
1007 tl1_spill_0_other:      
1008         tl1_reserved            4                       ! 0x2a0
1009 tl1_spill_1_other:      
1010         spill_32bit_tt1_secondary_so1                   ! 0x2a4
1011 tl1_spill_2_other:      
1012         spill_64bit_tt1_secondary_so1                   ! 0x2a8
1013 tl1_spill_3_other:      
1014         spill_32bit_tt1_secondary_so1                   ! 0x2ac
1015 tl1_spill_4_other:      
1016         spill_64bit_tt1_secondary_so1                   ! 0x2b0
1017 tl1_spill_5_other:      
1018         tl1_reserved            4                       ! 0x2b4
1019 tl1_spill_6_other:      
1020         tl1_reserved            4                       ! 0x2b8
1021 tl1_spill_7_other:      
1022         tl1_reserved            4                       ! 0x2bc
1023 tl1_fill_n_normal:
1024         tl1_reserved            32                      ! 0x2c0-0x2df
1025 tl1_fill_n_other:
1026         tl1_reserved            32                      ! 0x2e0-0x2ff
1027 tl1_soft_traps:
1028         tl1_reserved            256
1029 .globl tl1_end
1030 tl1_end:                                        
1031
1032 spill_clean:
1033         sethi   %hi(nwin_minus_one), %g5
1034         ld      [%g5 + %lo(nwin_minus_one)], %g5
1035         rdpr    %cwp, %g6
1036         deccc   %g6
1037         movneg  %xcc, %g5, %g6                          ! if (--%cwp < 0) %g6 = nwin-1
1038         wrpr    %g6, %cwp
1039         clr     %l0
1040         clr     %l1
1041         clr     %l2
1042         clr     %l3
1043         clr     %l4
1044         clr     %l5
1045         clr     %l6
1046         clr     %l7
1047         wrpr    %g0, %g7, %wstate
1048         saved
1049         retry
1050
1051         
1052         
1053 #define KWBUF64_TO_STACK(SBP,SPP,TMP) \
1054         ldx     [SBP + (0*8)], TMP; \
1055         stx     TMP, [SPP + SPOFF + 0]; \
1056         ldx     [SBP + (1*8)], TMP; \
1057         stx     TMP, [SPP + SPOFF + 8]; \
1058         ldx     [SBP + (2*8)], TMP; \
1059         stx     TMP, [SPP + SPOFF + 16]; \
1060         ldx     [SBP + (3*8)], TMP; \
1061         stx     TMP, [SPP + SPOFF + 24]; \
1062         ldx     [SBP + (4*8)], TMP; \
1063         stx     TMP, [SPP + SPOFF + 32]; \
1064         ldx     [SBP + (5*8)], TMP; \
1065         stx     TMP, [SPP + SPOFF + 40]; \
1066         ldx     [SBP + (6*8)], TMP; \
1067         stx     TMP, [SPP + SPOFF + 48]; \
1068         ldx     [SBP + (7*8)], TMP; \
1069         stx     TMP, [SPP + SPOFF + 56]; \
1070         ldx     [SBP + (8*8)], TMP; \
1071         stx     TMP, [SPP + SPOFF + 64]; \
1072         ldx     [SBP + (9*8)], TMP; \
1073         stx     TMP, [SPP + SPOFF + 72]; \
1074         ldx     [SBP + (10*8)], TMP; \
1075         stx     TMP, [SPP + SPOFF + 80]; \
1076         ldx     [SBP + (11*8)], TMP; \
1077         stx     TMP, [SPP + SPOFF + 88]; \
1078         ldx     [SBP + (12*8)], TMP; \
1079         stx     TMP, [SPP + SPOFF + 96]; \
1080         ldx     [SBP + (13*8)], TMP; \
1081         stx     TMP, [SPP + SPOFF + 104]; \
1082         ldx     [SBP + (14*8)], TMP; \
1083         stx     TMP, [SPP + SPOFF + 112]; \
1084         ldx     [SBP + (15*8)], TMP; \
1085         stx     TMP, [SPP + SPOFF + 120];
1086
1087
1088 #define fill_64bit_rtt(asi_num)                         \
1089         wr      %g0, asi_num, %asi                              ;\
1090         rdpr    %cwp, %g1                                       ;\
1091         sub     %g1, 1, %g1                                     ;\
1092         wrpr    %g1, %cwp                                       ;\
1093         ldxa    [%sp + SPOFF + 0]%asi, %l0                      ;\
1094         ldxa    [%sp + SPOFF + 8]%asi, %l1                      ;\
1095         ldxa    [%sp + SPOFF + 16]%asi, %l2                     ;\
1096         ldxa    [%sp + SPOFF + 24]%asi, %l3                     ;\
1097         ldxa    [%sp + SPOFF + 32]%asi, %l4                     ;\
1098         ldxa    [%sp + SPOFF + 40]%asi, %l5                     ;\
1099         ldxa    [%sp + SPOFF + 48]%asi, %l6                     ;\
1100         ldxa    [%sp + SPOFF + 56]%asi, %l7                     ;\
1101         ldxa    [%sp + SPOFF + 64]%asi, %i0                     ;\
1102         ldxa    [%sp + SPOFF + 72]%asi, %i1                     ;\
1103         ldxa    [%sp + SPOFF + 80]%asi, %i2                     ;\
1104         ldxa    [%sp + SPOFF + 88]%asi, %i3                     ;\
1105         ldxa    [%sp + SPOFF + 96]%asi, %i4                     ;\
1106         ldxa    [%sp + SPOFF + 104]%asi, %i5                    ;\
1107         ldxa    [%sp + SPOFF + 112]%asi, %i6                    ;\
1108         ldxa    [%sp + SPOFF + 120]%asi, %i7                    ;\
1109         restored                                                ;\
1110         add     %g1, 1, %g1                                     ;\
1111         wrpr    %g1, %cwp
1112
1113
1114         
1115         
1116 ENTRY(utl0)
1117         SAVE_GLOBALS(%l7)
1118         rd      %asi, %g1
1119         SAVE_OUTS(%l7)
1120         stx     %g1, [%l7 + TF_ASI]
1121         GET_PCPU_SCRATCH_SLOW(%g6)
1122         wrpr    %g0, PSTATE_KERNEL, %pstate     ! enable ints
1123
1124         brnz    %o1, common_utrap
1125           nop           
1126         call    spinlock_enter
1127           nop
1128 common_uintr:   
1129         jmpl    %l3, %o7                        ! call interrupt handler
1130           mov   %l7, %o0
1131         call    spinlock_exit
1132           nop
1133         ba,pt   %xcc, user_rtt
1134           nop
1135 common_utrap:
1136         jmpl    %l3, %o7                        ! call trap handler / syscall
1137           mov   %l7, %o0
1138
1139         ldx     [PCPU_REG + PC_CURPCB], %g6
1140         ldx     [%g6 + PCB_KSTACK], %g6
1141         sub     %g6, TF_SIZEOF, %sp
1142         add     %sp, REGOFF + SPOFF, %l7
1143 ENTRY(user_rtt)
1144         ! pil handling needs to be re-visited
1145         wrpr    %g0, PIL_TICK, %pil
1146         ldx     [PCPU(CURTHREAD)], %l4
1147         lduw    [%l4 + TD_FLAGS], %l1
1148         ldx     [%l4 + TD_MD + MD_SAVED_PIL], %l0
1149         set     TDF_ASTPENDING | TDF_NEEDRESCHED, %l2
1150         and     %l1, %l2, %l1
1151         brz,a,pt %l1, 1f
1152          nop
1153
1154         ! handle AST and retry return
1155         wrpr    %g0, %l0, %pil
1156         call    ast
1157           mov   %l7, %o0
1158         ba,pt   %xcc, user_rtt
1159          nop
1160
1161 1:      
1162         ldx     [PCPU_REG + PC_CURPCB], %g6
1163         ldx     [%g6 + PCB_NSAVED], %l1
1164         brz,a,pt %l1, 2f
1165           nop
1166         wrpr    %g0, %l0, %pil
1167         mov     T_SPILL, %o1
1168         call    trap
1169           mov   %l7, %o0
1170         ba,pt   %xcc, user_rtt
1171          nop
1172 2:
1173
1174         ld      [%l7 + TF_WSTATE], %l3  
1175         !
1176         ! restore user globals and outs
1177         !
1178         rdpr    %pstate, %l1
1179         ldx     [%l7 + TF_ASI], %g1
1180         wrpr    %l1, PSTATE_IE, %pstate
1181         wr      %g1, 0, %asi
1182         RESTORE_GLOBALS_USER(%l7)
1183         wrpr    %g0, 1, %gl
1184         RESTORE_OUTS(%l7)
1185
1186         wrpr    %g0, 0, %pil    ! drop pil to 0
1187         wrpr    %g0, 1, %tl     ! raise tl -> 1 before setting pcontext
1188         
1189         mov     MMU_CID_S, %g1
1190         GET_MMU_CONTEXT(%g1, %g2)
1191         mov     MMU_CID_P, %g1
1192         sethi   %hi(FLUSH_ADDR), %g3
1193         SET_MMU_CONTEXT(%g1, %g2)
1194         flush   %g3                             ! flush required by immu
1195                                                 ! hangover from US I
1196         !
1197         ! setup trap regs
1198         !
1199
1200         ldx     [%l7 + TF_TPC], %g1
1201         ldx     [%l7 + TF_TNPC], %g2
1202         ldx     [%l7 + TF_TSTATE], %l0
1203         ldx     [%l7 + TF_FPRS], %l1
1204
1205         wrpr    %g1, %tpc
1206         wrpr    %g2, %tnpc
1207         andn    %l0, TSTATE_CWP_MASK, %g6
1208
1209         wr      %g0, FPRS_FEF, %fprs
1210         ldx     [%l7 + TF_FSR], %fsr
1211         wr      %l1, 0, %fprs   
1212
1213
1214                 !
1215         ! switch "other" windows back to "normal" windows and
1216         ! restore to window we originally trapped in
1217         !
1218         rdpr    %otherwin, %g1
1219         wrpr    %g0, 0, %otherwin
1220         add     %l3, WSTATE_CLEAN_OFFSET, %l3   ! convert to "clean" wstate
1221         wrpr    %g0, %l3, %wstate
1222         wrpr    %g0, %g1, %canrestore
1223         
1224         rdpr    %canrestore, %g1
1225         brnz    %g1, 3f
1226           nop                           ! no trap, use restore directly
1227         rdpr    %cwp, %g1
1228         wrpr    %g1, %g6, %tstate       ! needed by wbuf recovery code
1229         ! hand craft the restore to avoid getting to TL > 2
1230         rdpr    %wstate, %g1
1231         btst    1, %g1
1232         beq     4f
1233           nop
1234         .global rtt_fill_start
1235 rtt_fill_start:
1236 #if 0
1237         fill_32bit_rtt(ASI_AIUP)
1238         ba,a    3f
1239 #endif
1240 4:
1241         membar  #Lookaside
1242         fill_64bit_rtt(ASI_AIUP)
1243         .global rtt_fill_end
1244 rtt_fill_end:
1245 3:
1246         restore                         ! should not trap
1247 2:
1248         
1249         !
1250         ! set %cleanwin to %canrestore
1251         ! set %tstate to the correct %cwp
1252         ! retry resumes user execution
1253         !
1254         rdpr    %canrestore, %g1
1255         wrpr    %g0, %g1, %cleanwin
1256         rdpr    %cwp, %g1
1257         wrpr    %g1, %g6, %tstate
1258         retry
1259 END(user_rtt)
1260 END(utl0)               
1261
1262 ENTRY(ktl0)
1263         nop
1264         SAVE_GLOBALS(%l7)
1265         rd      %asi, %g1
1266         SAVE_OUTS(%l7)
1267         stx     %g1, [%l7 + TF_ASI]
1268         GET_PCPU_SCRATCH_SLOW(%g6)              ! we really shouldn't need this ...     
1269         wrpr    %g0, PSTATE_KERNEL, %pstate     ! enable interrupts
1270
1271         brnz    %o1, common_ktrap
1272           nop   
1273         call    spinlock_enter
1274           nop
1275 common_kintr:   
1276         jmpl    %l3, %o7                        ! call trap handler
1277           mov   %l7, %o0
1278         call    spinlock_exit
1279           nop
1280         b       common_rtt
1281           nop
1282 common_ktrap:
1283         jmpl    %l3, %o7                        ! call trap handler
1284           mov   %l7, %o0
1285         
1286 ENTRY(krtt)
1287 common_rtt:     
1288         !
1289         ! restore globals and outs
1290         !
1291         rdpr    %pstate, %l1
1292         ldx     [%l7 + TF_ASI], %g1
1293         wrpr    %l1, PSTATE_IE, %pstate
1294         wr      %g1, 0, %asi    
1295
1296         RESTORE_GLOBALS_KERNEL(%l7)
1297         
1298         ! switch to global set 1
1299         wrpr    %g0, 1, %gl
1300         RESTORE_OUTS(%l7)
1301 #ifdef notyet
1302         !
1303         ! set %pil from max(old pil, cur_thread_spl)
1304         !
1305         ldn     [%l0 + T_CPU], %l0
1306         ld      [%l0 + CPU_BASE_SPL], %l0
1307         cmp     %l6, %l0
1308         movg    %xcc, %l6, %l0
1309         wrpr    %g0, %l0, %pil
1310 #endif
1311         GET_PCPU_SCRATCH
1312         ldx     [PCPU(CURTHREAD)], %l0
1313         ldx     [%l0 + TD_MD + MD_SAVED_PIL], %l0
1314         wrpr    %g0, %l0, %pil
1315         !
1316         ! raise tl
1317         ! setup trap regs
1318         ! restore to window we originally trapped in
1319         !
1320         wrpr    %g0, 1, %tl
1321         
1322         ldx     [%l7 + TF_TSTATE], %l0
1323         ldx     [%l7 + TF_TPC], %g1
1324         ldx     [%l7 + TF_TNPC], %g2
1325         ldx     [%l7 + TF_FPRS], %l1
1326                         
1327         andn    %l0, TSTATE_CWP_MASK, %g6
1328         wrpr    %g1, %tpc
1329         wrpr    %g2, %tnpc
1330
1331
1332         wr      %g0, FPRS_FEF, %fprs
1333         ldx     [%l7 + TF_FSR], %fsr
1334         wr      %l1, 0, %fprs   
1335         
1336         rdpr    %canrestore, %g1
1337         brnz    %g1, 3f
1338           nop                           ! can use restore directly
1339         rdpr    %cwp, %g1
1340         wrpr    %g1, %g6, %tstate       ! needed by wbuf recovery code
1341
1342         ! avoid going above TL2
1343         fill_64bit_rtt(ASI_N)
1344
1345 3:
1346         restore
1347         !
1348         ! set %tstate to the correct %cwp
1349         !
1350         rdpr    %cwp, %g1
1351         wrpr    %g1, %g6, %tstate
1352         retry
1353 END(krtt)       
1354 END(ktl0)
1355
1356
1357
1358 ENTRY(tl0_ktrap)
1359         GET_PCPU_SCRATCH
1360         set     ktl0, %g6
1361         
1362         save    %sp, -(CCFSZ + TF_SIZEOF), %sp
1363                 
1364         brz     %g2, 2f
1365           nop
1366         or      %g2, T_KERNEL, %g2      
1367 2:                      
1368         ! if the kwbuf is full we need to save to the stack now
1369         ld      [PCPU_REG + PC_KWBUF_FULL], %o0   
1370         brz,pt  %o0, 1f
1371         nop
1372         st      %g0, [PCPU_REG + PC_KWBUF_FULL]
1373         ldx     [PCPU_REG + PC_KWBUF_SP], %o1
1374         add     PCPU_REG, PC_KWBUF, %o0
1375         KWBUF64_TO_STACK(%o0, %o1, %o2)
1376 1:                      
1377         ba,a,pt %xcc, win_saved
1378 END(tl0_ktrap)  
1379         
1380
1381         ! register convention:  
1382         ! %g2=level %g1=mask
1383         
1384 ENTRY(tl0_intr)
1385         SET(intr_handlers, %g7, %g6)
1386         sllx    %g4, IH_SHIFT, %g7
1387         ldx     [%g6 + %g7], %g1        ! pointer to interrupt handler
1388         rdpr    %pil, %g5
1389         mov     %g5, %g4
1390                                 
1391         ! %g1           pc of trap handler
1392         ! %g2, %g3      args of trap handler
1393         ! %g2           software trap type
1394         ! %g3           additional argument to trap
1395         ! %g4           desired pil
1396         ! %g5, %g6      temps
1397         ! %g7           saved
1398
1399         ! %l0, %l1      temps
1400         ! %l3           saved %g1
1401         ! %l4           flags
1402         ! %l5           memory fault info
1403         ! %l6           %pil for priv traps
1404         ! %l7           trapframe
1405
1406 ENTRY(tl0_trap)
1407         /* if we're at tl2 we have some extra work to do */
1408         rdpr    %tl, %g5
1409         cmp     %g5, 2
1410         be,pn   %xcc, tl1_trap
1411           nop
1412         
1413         rdpr    %tstate, %g5
1414         btst    TSTATE_PRIV, %g5
1415         and     %g5, TSTATE_CWP_MASK, %g6
1416         wrpr    %g0, %g6, %cwp
1417         bnz,pn  %xcc, tl0_ktrap
1418           nop
1419 ENTRY(tl0_utrap)
1420         GET_PCPU_SCRATCH
1421
1422         and     %g2, TRAP_MASK, %g4
1423         cmp     %g4, UT_MAX
1424         bge,a,pt %xcc, tl0_skip_utrap
1425           nop
1426         
1427         ldx     [PCPU(CURTHREAD)], %g5
1428         ldx     [%g5 + TD_PROC], %g5
1429         ldx     [%g5 + P_MD + MD_UTRAP], %g5
1430         brz,pn  %g5, tl0_skip_utrap
1431           sllx  %g4, PTR_SHIFT, %g6
1432         ldx     [%g5 + %g6], %g5
1433         brz,pn  %g5, tl0_skip_utrap     
1434           nop
1435
1436         mov     %g4, %g2
1437         mov     %g5, %g4
1438         
1439         ! 0) save trap state to memory  
1440         ldx     [PCPU_REG + PC_CURPCB], %g6     
1441         rdpr    %tstate, %g5
1442         stx     %g5, [%g6 + PCB_TSTATE]
1443         rdpr    %tpc, %g5
1444         stx     %g5, [%g6 + PCB_TPC]
1445         rdpr    %tnpc, %g5
1446         stx     %g5, [%g6 + PCB_TNPC]
1447         stx     %g2, [%g6 + PCB_TT]
1448         stx     %g3, [%g6 + PCB_SFAR]
1449         
1450         wrpr    %g4, %tnpc
1451         done
1452 tl0_skip_utrap: 
1453
1454 #ifdef  notyet
1455         /* we need to determine from the hardware the number of register windows */
1456         sethi   %hi(nwin_minus_one), %g5
1457         ld      [%g5 + %lo(nwin_minus_one)], %g5
1458 #else
1459         mov     nwin_minus_one, %g5
1460 #endif
1461         ldx     [PCPU_REG + PC_CURPCB], %g6     
1462         wrpr    %g0, %g5, %cleanwin
1463         ldx     [%g6 + PCB_KSTACK], %g6
1464         brnz,pt %g6, 5f
1465           nop
1466         set     PCPU_PAGES*PAGE_SIZE - PC_SIZEOF, %g6
1467         add     %g7, %g6, %g6
1468         sub     %g6, SPOFF + CCFSZ, %g6
1469         mov     T_KSTACK_FAULT, %g2
1470         set     trap, %g3
1471 5:      
1472         sub     %g6, TF_SIZEOF, %g6
1473
1474         save    %g6, 0, %sp
1475         rdpr    %canrestore, %l0
1476         rdpr    %wstate, %l1
1477         wrpr    %g0, 0, %canrestore
1478         sllx    %l1, WSTATE_SHIFT, %l1
1479         wrpr    %l1, WSTATE_K64, %wstate
1480         wrpr    %g0, %l0, %otherwin
1481         !
1482         ! set pcontext to run kernel
1483         !
1484         mov     KCONTEXT, %l0
1485         mov     MMU_CID_P, %l1
1486         sethi   %hi(FLUSH_ADDR), %l2
1487         SET_MMU_CONTEXT(%l1, %l0)
1488         flush   %l2                     ! flush/membar required by immu for 
1489                                         ! consistency guarantee
1490         set     utl0, %g6
1491 win_saved:
1492         mov     %g1, %l3                ! set trap/interrupt for tl0
1493 #ifdef TRAP_TRACING
1494         GET_PCPU_SCRATCH
1495         rdpr    %tl, %g1
1496         dec     %g1     
1497         sll     %g1, RW_SHIFT, %g1
1498         add     %g1, PC_TSBWBUF, %g1
1499         add     PCPU_REG, %g1, %g1
1500         wr      %g0, ASI_N, %asi
1501         TTRACE_ADD_SAFE(%g1, 0, 0, 0, 0, 0)
1502         mov     %l3, %g1
1503 #endif  
1504         mov     %g2, %o1                ! trap type
1505         mov     %g3, %o2                ! fault info if set
1506         mov     %g5, %l6                ! %pil if priv trap
1507         !
1508         ! save state in trapframe
1509         !
1510         add     %sp, REGOFF + SPOFF, %l7
1511         rdpr    %tpc, %l0
1512         rdpr    %tnpc, %l1
1513         rdpr    %tstate, %l2
1514         stx     %l0, [%l7 + TF_TPC]
1515         rd      %fprs, %l0
1516         stx     %l1, [%l7 + TF_TNPC]
1517         stx     %l2, [%l7 + TF_TSTATE]
1518         stx     %l0, [%l7 + TF_FPRS]
1519
1520         /*
1521          * According to the sparc64 port fp must me enabled
1522          * before reading %fsr
1523          */
1524         wr      %g0, FPRS_FEF, %fprs
1525         stx     %fsr, [%l7 + TF_FSR]
1526         wr      %g0, 0, %fprs
1527         !
1528         !  setup pil
1529         !
1530         brlz,pt %g4, 1f
1531           nop
1532 #if 0
1533 #ifdef PMAP_DEBUG
1534         rdpr    %pil, %l0
1535         cmp     %g4, %l0
1536         bge,pt  %xcc, 10f
1537           nop
1538         call    panic
1539 10:     
1540 #endif
1541 #endif
1542         wrpr    %g0, %g4, %pil
1543 1:              
1544         wrpr    %g0, %g6, %tnpc
1545
1546         ! save g7 before it can be overwritten by PCPU when returning from an interrupt 
1547         wrpr    %g0, 0, %gl
1548         stx     %g7, [%l7 + TF_G7]              
1549         wrpr    %g0, 1, %gl
1550         
1551         rdpr    %cwp, %l0
1552         set     TSTATE_KERNEL, %l1
1553         wrpr    %l1, %l0, %tstate
1554         done    
1555 END(tl0_utrap)
1556 END(tl0_trap)
1557 END(tl0_intr)
1558
1559
1560 /* 
1561  * workaround for CPP brokenness
1562  */
1563 #define LOADLOAD #LoadLoad
1564 #define LOADSTORE #LoadStore 
1565 #define STORESTORE #StoreStore
1566
1567
1568 #define WORKING
1569 #ifdef WORKING
1570 #define ENTER LOADLOAD
1571 #define EXIT LOADSTORE|STORESTORE
1572 #else
1573 #define ENTER #Sync
1574 #define EXIT  #Sync
1575 #endif
1576
1577 #define THE_LOCK_ENTER(addr, lock_bit, oldval, newval, label1) \
1578         mov     1, lock_bit     ; \
1579         add     addr, 8, addr   ; \
1580         sllx    lock_bit, 56, lock_bit ; \
1581 label1:                         ; \
1582         ldxa    [addr]%asi, oldval;     \
1583         or      oldval, lock_bit, newval; \
1584         andn    oldval, lock_bit, oldval; \
1585         casxa   [addr]%asi, oldval, newval; \
1586         cmp     newval, oldval  ; \
1587         bne,pn  %xcc, label1 ## b       ; \
1588           membar ENTER  ; \
1589         sub     addr, 8, addr   ;
1590
1591 #define THE_LOCK_EXIT(addr, lock_bit, tmp)\
1592         membar  EXIT ; \
1593         ldxa    [addr + 8]%asi, tmp ; \
1594         andn    tmp, lock_bit, tmp ; \
1595         stxa    tmp, [addr + 8]%asi ; 
1596
1597 #define HASH_LOOKUP(addr, tag, searchtag, faillabel, matchlabel) \
1598         ldda    [addr]%asi, tag ; \
1599         cmp     tag, %g0        ; \
1600         be,pn   %xcc, faillabel ; \
1601           nop                   ; \
1602         cmp     tag, searchtag  ; \
1603         be,pn   %xcc, matchlabel ;\
1604           nop
1605
1606 #define RESTORE_TRAPWIN(pcpu, cansave, label1, label2) \
1607         brz     cansave, label1 ## f; \
1608           nop                   ; \
1609         restore                 ; \
1610         ba,a,pt %xcc, label2 ## f ; \
1611 label1:                         ; \
1612         rdpr    %tl, cansave    ; \
1613         dec     cansave         ; \
1614         sll     cansave, RW_SHIFT, cansave ; \
1615         add     cansave, PC_TSBWBUF, cansave ; \
1616         add     pcpu, cansave, cansave ; \
1617         RESTORE_LOCALS_ASI(cansave) ; \
1618 label2: 
1619
1620 ENTRY(hash_bucket_lock)
1621         wr      %g0, ASI_N, %asi 
1622         rdpr    %pstate, %o1
1623         and     %o1, PSTATE_INTR_DISABLE, %o2
1624         wrpr    %o2, %pstate
1625         THE_LOCK_ENTER(%o0, %o3, %o4, %o5, 1)
1626         mov     %o1, %o0
1627         retl
1628           nop
1629 END(hash_bucket_lock)
1630
1631
1632 ENTRY(hash_bucket_unlock)
1633         mov     1, %g2
1634         wr      %g0, ASI_N, %asi
1635         sllx    %g2, 56, %g2
1636         THE_LOCK_EXIT(%o0, %g2, %g3)
1637         wrpr    %o1, %pstate
1638         retl      
1639           nop
1640 END(hash_bucket_unlock)
1641
1642                         
1643 ! %g3==trap type
1644 ! %g4==fault type (if data miss)
1645 ! %g5==fault addr
1646 ! internal usage:
1647 ! %g1==absolute index
1648 ! %g2==hash base, pointer to hash entry
1649 ! %g3==flag bits, TSB (RA)
1650 ! %g4==fault type,entry tag
1651 ! %g5==tag
1652 ! %g6==context
1653 ! %g7 temp
1654 ENTRY(tsb_miss_handler)
1655         ldxa    [%g1 + %g7]ASI_REAL, %g6        ! load in the context
1656
1657         GET_HASH_SCRATCH_USER(%g2)
1658         GET_TSB_SCRATCH_USER(%g4)
1659
1660         brnz,pn %g6, 2f
1661           nop   
1662         GET_HASH_SCRATCH_KERNEL(%g2)
1663         GET_TSB_SCRATCH_KERNEL(%g4)
1664 2:
1665
1666         rdpr    %tl, %g1                        ! need to use real addresses?
1667         mov     ASI_LDTD_N, %g3
1668         wr      %g0, ASI_N, %asi
1669         dec     %g1
1670         GET_PCPU_SCRATCH
1671
1672         brz,pt  %g1, 3f                 ! for tl == 1
1673           nop
1674         sethi   %uhi(VM_MIN_DIRECT_ADDRESS), %g1
1675         wr      %g0, ASI_REAL, %asi
1676         sllx    %g1, 32, %g1
1677         mov     ASI_LDTD_REAL, %g3
1678         andn    %g2, %g1, %g2
1679         andn    %g4, %g1, %g4
1680         andn    %g7, %g1, %g7
1681 3:      
1682 #ifdef notyet
1683         rdpr    %cansave, %g1
1684         /* XXX use save operation if %g1 > 0 and tl == 1 */
1685 #endif
1686         rdpr    %tl, %g1
1687         dec     %g1     
1688         sll     %g1, RW_SHIFT, %g1
1689         add     %g1, PC_TSBWBUF, %g1
1690         add     PCPU_REG, %g1, %g1
1691 #ifdef TRAP_TRACING     
1692         TTRACE_ADD_SAFE(%g1, 0, 0, 0, 0, 0)
1693 #endif  
1694         SAVE_LOCALS_ASI(%g1)
1695         mov     0, %g1                  ! cansave is 0
1696         ! %g1 == %cansave
1697         ! %g2 == hash scratch value
1698         ! %g3 == TWDW ASI
1699         ! %g4 == TSB RA
1700         ! %g5 == fault addr
1701         ! %g6 == context
1702
1703         srlx    %g5, TTARGET_VA_SHIFT, %l0
1704         sllx    %g6, TTARGET_CTX_SHIFT, %l1
1705         or      %l0, %l1, %l2                   ! %l2 == search tag
1706
1707 tsb_miss_compute_hash_addr:
1708         sethi   %hi(PAGE_SIZE), %l0
1709         sub     %l0, 1, %l1                     ! %l1==PAGE_MASK
1710
1711         and     %g2, %l1, %l3                   ! size stored in lower 13 bits
1712         andn    %g2, %l1, %g2                   ! actual VA/RA of hash
1713
1714         ! XXX only handle 8k page miss
1715         ! calculate hash index
1716         srlx    %g5, PAGE_SHIFT, %l4            ! absolute hash index
1717         sllx    %l3, (PAGE_SHIFT - THE_SHIFT), %l0 ! size of hash in THEs
1718         sub     %l0, 1, %l5                     ! THE_MASK
1719         and     %l4, %l5, %l5                   ! masked hash index
1720         sllx    %l5, THE_SHIFT, %l5             ! masked hash offset
1721         ! fetch hash entries - exit when we find what were looking for 
1722
1723         ! %g2==entry base
1724         add     %g2, %l5, %g2                   ! base + offset == entry base
1725         
1726
1727         THE_LOCK_ENTER(%g2, %l0, %l7, %l6, 6)
1728         
1729         ! %g1 == cansave
1730         ! %g2 == THE
1731         ! %g3 == TWDW ASI
1732         ! %g4 == TSB RA
1733         ! %g5 == fault addr
1734         ! %g6 == context
1735         ! %g7 == PCPU_REG
1736         ! %l0 == VTD_LOCK
1737         ! %l1 == PAGE_MASK
1738         ! %l2 == search tag
1739         ! %l4 == absolute index
1740
1741         ! %l3 == ASI
1742         ! %l5 == saved head of bucket
1743         ! %l6 == tag
1744         ! %l7 == data
1745
1746         rd      %asi, %l3
1747         wr      %g0, %g3, %asi
1748         mov     %g2, %l5                        ! save head of bucket
1749         rdpr    %tt, %g3                        ! reload trap type
1750
1751 tsb_miss_lookup_0:
1752         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1753 tsb_miss_lookup_1:
1754         add     %g2, 16, %g2
1755         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1756 tsb_miss_lookup_2:
1757         add     %g2, 16, %g2
1758         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1759 #if HASH_ENTRY_SHIFT > 2 
1760 tsb_miss_lookup_3:
1761         add     %g2, 16, %g2
1762         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1763 tsb_miss_lookup_4:
1764         add     %g2, 16, %g2
1765         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1766 tsb_miss_lookup_5:
1767         add     %g2, 16, %g2
1768         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1769 tsb_miss_lookup_6:
1770         add     %g2, 16, %g2
1771         HASH_LOOKUP(%g2, %l6, %l2, tsb_miss_not_found, tsb_miss_found)
1772 #endif                  
1773 tsb_miss_collision:     
1774         add     %g2, 16, %g2
1775         ldda    [%g2]%asi, %l6
1776         
1777         sethi   %uhi(VM_MIN_DIRECT_ADDRESS), %g3
1778         cmp     %l3, ASI_N
1779         sllx    %g3, 32, %g3
1780         beq,pt  %xcc, 7f
1781           nop
1782         andn    %l7, %g3, %l7                   ! generate real address
1783 7:
1784         srl     %l6, 0, %l6
1785         sethi   %hi(0xcafebabe), %g3
1786         mov     %l7, %g2
1787         or      %g3, %lo(0xcafebabe), %g3
1788         cmp     %g3, %l6
1789         rdpr    %tt, %g3        
1790         beq,pt %xcc, tsb_miss_lookup_0
1791           nop
1792
1793 tsb_miss_not_found:     
1794         ! we need to jump to tl0_trap to drop us back down to tl0
1795         ! and take us to trap(...) to service the fault
1796         wr      %g0, %l3, %asi
1797         THE_LOCK_EXIT(%l5, %l0, %g2)
1798
1799         andn    %g5, %l1, %g5                   ! fault page PA
1800
1801         RESTORE_TRAPWIN(PCPU_REG, %g1, 14, 15)
1802
1803         ! convert hardware trap type to kernel trap type
1804         set     trap_conversion, %g2
1805         sllx    %g3, INT_SHIFT, %g3
1806         ld      [%g2 + %g3], %g2
1807         
1808         sethi   %hi(trap), %g1
1809         or      %g6, %g5, %g3                   ! trap data
1810         sub     %g0, 1, %g4                     ! pil info
1811         ba      %xcc, tl0_trap
1812           or    %g1, %lo(trap), %g1
1813
1814 tsb_miss_found:
1815
1816         wr      %g0, %l3, %asi
1817         cmp     %g3, TT_DATA_MISS               ! TSB data miss
1818         be,pt   %xcc, 9f
1819           or    %l7, VTD_REF, %l7               ! set referenced unconditionally
1820         cmp     %g3, TT_INSTRUCTION_MISS        ! TSB instruction miss
1821         be,pt   %xcc, 9f
1822           nop
1823         cmp     %g3, TT_DATA_PROTECTION         ! protection fault
1824         bne,pn  %xcc, unsupported_fault_trap    ! we don't handle any other fault types currently
1825           nop
1826         andcc   %l7, VTD_SW_W, %g0              ! write enabled?
1827         bz,a,pn %xcc, prot_fault_trap           ! write to read only page
1828           nop
1829         or      %l7, VTD_W, %l7                 ! add modifed bit 
1830 9:      
1831
1832         andn    %l7, %l0, %l7                   ! remove lock bit
1833         
1834         and     %g4, %l1, %g3                   ! shift of TSB in pages
1835         andn    %g4, %l1, %l3                   ! TSB real address
1836
1837         mov     1, %l2  
1838         add     %g3, (PAGE_SHIFT - TTE_SHIFT), %g3 ! add shift value for number of ttes / page
1839         sllx    %l2, %g3, %g3                   ! nttes
1840
1841         subx    %g3, 1, %g3                     ! TSB_MASK
1842         and     %g3, %l4, %g3                   ! masked index
1843         sllx    %g3, TTE_SHIFT, %g3             ! masked byte offset
1844         add     %g3, %l3, %g3                   ! TTE RA
1845
1846         rdpr    %tl, %l2                        ! don't track misses for kernel context
1847         brz,pn  %g6, 13f
1848           dec   %l2
1849         brnz,pn %l2, 13f                        ! don't track misses at tl > 1
1850           nop
1851         ldx     [PCPU(PMAP)], %l1
1852         ld      [%l1 + PM_TSB_MISS_COUNT], %l3
1853         add     1, %l3, %l3
1854         st      %l3, [%l1 + PM_TSB_MISS_COUNT]
1855
1856         !       if the data value is zero then this is not a capacity miss
1857         ldda    [%g3]ASI_LDTD_N, %l2
1858         brz,pt  %l3, 13f
1859           nop
1860         !       compare the tag bits - if they're the same we're merely 
1861         !       changing the mapping
1862         brz,pt  %l3, 13f
1863           nop
1864         cmp     %l6, %l2
1865         beq,pt  %xcc, 13f
1866           nop
1867                         
1868         ld      [%l1 + PM_TSB_CAP_MISS_COUNT], %l3
1869         add     1, %l3, %l3
1870         st      %l3, [%l1 + PM_TSB_CAP_MISS_COUNT]
1871
1872 13:     stxa    %g0, [%g3 + 8]%asi              ! invalidate data
1873         membar  #StoreStore
1874
1875         stxa    %l6, [%g3]%asi                  ! store tag
1876         stxa    %l7, [%g3 + 8]%asi              ! store data
1877         stxa    %l7, [%g2 + 8]%asi              ! update TTE with ref bit  
1878         membar  #StoreLoad
1879         
1880         THE_LOCK_EXIT(%l5, %l0, %l7)
1881         RESTORE_TRAPWIN(PCPU_REG, %g1, 13, 16)  
1882 upgrade_demap:
1883         rdpr    %tt, %g3
1884         cmp     %g3, TT_DATA_PROTECTION
1885         beq,pn  %xcc, demap_begin
1886           sethi %hi(PAGE_SIZE), %g1  
1887         retry
1888 demap_begin:
1889         dec     %g1
1890         mov     %o0, %g1
1891         mov     %o1, %g2
1892         mov     %o2, %g3
1893         mov     MAP_DTLB, %o2
1894         mov     %g5, %o0
1895         mov     %g6, %o1                                                        
1896         ta      MMU_UNMAP_ADDR
1897         mov     %g1, %o0
1898         mov     %g2, %o1
1899         mov     %g3, %o2
1900         retry
1901 END(tsb_miss_handler)
1902
1903
1904 /*
1905  * Write to read-only page
1906  */
1907 ! %g1 == cansave
1908 ! %g4 == tag
1909 ! %g5 == fault addr
1910 ! %g6 == context
1911 ! %l0 == VTD_LOCK
1912 ! %l5 == head of bucket
1913         
1914 ENTRY(prot_fault_trap)
1915         THE_LOCK_EXIT(%l5, %l0, %g2)
1916         RESTORE_TRAPWIN(PCPU_REG, %g1, 14, 15)
1917         sethi   %hi(trap), %g1
1918         mov     T_DATA_PROTECTION, %g2                  
1919         or      %g5, %g6, %g3
1920         sub     %g0, 1, %g4
1921         ba      %xcc, tl0_trap
1922           or    %g1, %lo(trap), %g1
1923 END(prot_fault_trap)
1924 /*
1925  * Programming error
1926  */
1927 ENTRY(unsupported_fault_trap)
1928         add     0x20, %g3, %g1
1929         PUTCHAR(0x5b)
1930         PUTCHAR(%g1)
1931         PUTCHAR(0x5d)
1932 END(unsupported_fault_trap)
1933
1934
1935 /*
1936  * Freshly forked processes come here when switched to for the first time.
1937  * The arguments to fork_exit() have been setup in the locals, we must move
1938  * them to the outs.
1939  */
1940 ENTRY(fork_trampoline)
1941         mov     %l0, %o0
1942         mov     %l1, %o1
1943         call    fork_exit
1944           mov   %l2, %o2
1945         ba,pt   %xcc, user_rtt
1946           add     %sp, CCFSZ + SPOFF, %l7
1947 END(fork_trampoline)
1948
1949
1950
1951         .comm   intrnames, IV_NAMLEN
1952         .comm   eintrnames, 0
1953
1954         .comm   intrcnt, IV_MAX * 8
1955         .comm   eintrcnt, 0
1956
1957 #define TRAP_ENTRY_SHIFT        5
1958 #define TRAP_ENTRY_MASK         0x1ff
1959 ENTRY(tl1_trap)
1960         ! assume no tl1 handler   
1961         rdpr    %tpc, %g7
1962
1963         set     rtt_fill_start, %g6
1964         cmp     %g7, %g6
1965         blu,pn  %xcc, 1f
1966          .empty
1967         set     rtt_fill_end, %g6
1968         cmp     %g7, %g6
1969         bgeu,pn %xcc, 1f
1970          nop
1971         set     fault_rtt_fn1, %g7
1972         ba,a,pt %xcc, 4f
1973 1:
1974 #ifdef USING_OPTIMIZED_SPILL_FILL
1975         set     fill_slow_start, %g6
1976         cmp     %g7, %g6
1977         bleu,a,pn %xcc, 2f
1978           nop
1979         set     fill_slow_end, %g6
1980         cmp     %g7, %g6
1981         blu,a,pn %xcc, 3f
1982           nop
1983 #endif
1984 2:              
1985         set     tl1_end, %g6
1986         cmp     %g7, %g6
1987         bgeu,a,pn %xcc, ptl1_panic
1988           mov   PTL1_BAD_TRAP, %g1
1989         ! tpc is in the trap table
1990         ! convert to trap index
1991         srl     %g7, TRAP_ENTRY_SHIFT, %g6
1992         and     %g6, TRAP_ENTRY_MASK, %g6
1993         ! check for window trap type
1994         and     %g6, WTRAP_TTMASK, %g6
1995         cmp     %g6, WTRAP_TYPE
1996         bne,a,pn %xcc, ptl1_panic
1997           mov   PTL1_BAD_NOT_WTRAP, %g1
1998 3:              
1999         andn    %g7, WTRAP_ALIGN, %g7
2000         add     %g7, WTRAP_FAULTOFF, %g7
2001 4:      
2002         wrpr    %g0, %g7, %tnpc
2003         wrpr    %g0, 1, %gl
2004         rdpr    %tt, %g2
2005         GET_MMFSA_SCRATCH(%g7)
2006         
2007         ! convert hardware trap type to kernel trap type
2008         set     trap_conversion, %g1
2009         sllx    %g2, INT_SHIFT, %g2
2010         ld      [%g1 + %g2], %g2
2011         
2012         wr      %g0, ASI_REAL, %asi
2013         ldxa    [%g7 + MMFSA_D_ADDR]%asi, %g3
2014         ldxa    [%g7 + MMFSA_D_CTX]%asi, %g7
2015         ! XXX we're only handling page faults here 
2016         srlx    %g3, PAGE_SHIFT, %g3 
2017         sllx    %g3, PAGE_SHIFT, %g3    ! mask off bottom
2018         or      %g3, %g7, %g3
2019         done
2020 #ifdef notyet
2021         sllx    %g7, TRAP_CTX_SHIFT, %g7
2022         or      %g7, %g5, %g5
2023         done
2024 #endif  
2025 END(tl1_trap)