[SPARC64]: Get rid of fast IRQ feature.
[linux-3.10.git] / arch / sparc64 / kernel / entry.S
1 /* $Id: entry.S,v 1.144 2002/02/09 19:49:30 davem Exp $
2  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
3  *
4  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
5  * Copyright (C) 1996 Eddie C. Dost        (ecd@skynet.be)
6  * Copyright (C) 1996 Miguel de Icaza      (miguel@nuclecu.unam.mx)
7  * Copyright (C) 1996,98,99 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
8  */
9
10 #include <linux/config.h>
11 #include <linux/errno.h>
12
13 #include <asm/head.h>
14 #include <asm/asi.h>
15 #include <asm/smp.h>
16 #include <asm/ptrace.h>
17 #include <asm/page.h>
18 #include <asm/signal.h>
19 #include <asm/pgtable.h>
20 #include <asm/processor.h>
21 #include <asm/visasm.h>
22 #include <asm/estate.h>
23 #include <asm/auxio.h>
24
25 /* #define SYSCALL_TRACING      1 */
26
27 #define curptr      g6
28
29 #define NR_SYSCALLS 284      /* Each OS is different... */
30
31         .text
32         .align          32
33
34         .globl          sparc64_vpte_patchme1
35         .globl          sparc64_vpte_patchme2
36 /*
37  * On a second level vpte miss, check whether the original fault is to the OBP 
38  * range (note that this is only possible for instruction miss, data misses to
39  * obp range do not use vpte). If so, go back directly to the faulting address.
40  * This is because we want to read the tpc, otherwise we have no way of knowing
41  * the 8k aligned faulting address if we are using >8k kernel pagesize. This
42  * also ensures no vpte range addresses are dropped into tlb while obp is
43  * executing (see inherit_locked_prom_mappings() rant).
44  */
45 sparc64_vpte_nucleus:
46         /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
47         mov             0xf, %g5
48         sllx            %g5, 28, %g5
49
50         /* Is addr >= LOW_OBP_ADDRESS?  */
51         cmp             %g4, %g5
52         blu,pn          %xcc, sparc64_vpte_patchme1
53          mov            0x1, %g5
54
55         /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
56         sllx            %g5, 32, %g5
57
58         /* Is addr < HI_OBP_ADDRESS?  */
59         cmp             %g4, %g5
60         blu,pn          %xcc, obp_iaddr_patch
61          nop
62
63         /* These two instructions are patched by paginig_init().  */
64 sparc64_vpte_patchme1:
65         sethi           %hi(0), %g5
66 sparc64_vpte_patchme2:
67         or              %g5, %lo(0), %g5
68
69         /* With kernel PGD in %g5, branch back into dtlb_backend.  */
70         ba,pt           %xcc, sparc64_kpte_continue
71          andn           %g1, 0x3, %g1   /* Finish PMD offset adjustment.  */
72
73 vpte_noent:
74         /* Restore previous TAG_ACCESS, %g5 is zero, and we will
75          * skip over the trap instruction so that the top level
76          * TLB miss handler will thing this %g5 value is just an
77          * invalid PTE, thus branching to full fault processing.
78          */
79         mov             TLB_SFSR, %g1
80         stxa            %g4, [%g1 + %g1] ASI_DMMU
81         done
82
83         .globl          obp_iaddr_patch
84 obp_iaddr_patch:
85         /* These two instructions patched by inherit_prom_mappings().  */
86         sethi           %hi(0), %g5
87         or              %g5, %lo(0), %g5
88
89         /* Behave as if we are at TL0.  */
90         wrpr            %g0, 1, %tl
91         rdpr            %tpc, %g4       /* Find original faulting iaddr */
92         srlx            %g4, 13, %g4    /* Throw out context bits */
93         sllx            %g4, 13, %g4    /* g4 has vpn + ctx0 now */
94
95         /* Restore previous TAG_ACCESS.  */
96         mov             TLB_SFSR, %g1
97         stxa            %g4, [%g1 + %g1] ASI_IMMU
98
99         /* Get PMD offset.  */
100         srlx            %g4, 23, %g6
101         and             %g6, 0x7ff, %g6
102         sllx            %g6, 2, %g6
103
104         /* Load PMD, is it valid?  */
105         lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
106         brz,pn          %g5, longpath
107          sllx           %g5, 11, %g5
108
109         /* Get PTE offset.  */
110         srlx            %g4, 13, %g6
111         and             %g6, 0x3ff, %g6
112         sllx            %g6, 3, %g6
113
114         /* Load PTE.  */
115         ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
116         brgez,pn        %g5, longpath
117          nop
118
119         /* TLB load and return from trap.  */
120         stxa            %g5, [%g0] ASI_ITLB_DATA_IN
121         retry
122
123         .globl          obp_daddr_patch
124 obp_daddr_patch:
125         /* These two instructions patched by inherit_prom_mappings().  */
126         sethi           %hi(0), %g5
127         or              %g5, %lo(0), %g5
128
129         /* Get PMD offset.  */
130         srlx            %g4, 23, %g6
131         and             %g6, 0x7ff, %g6
132         sllx            %g6, 2, %g6
133
134         /* Load PMD, is it valid?  */
135         lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
136         brz,pn          %g5, longpath
137          sllx           %g5, 11, %g5
138
139         /* Get PTE offset.  */
140         srlx            %g4, 13, %g6
141         and             %g6, 0x3ff, %g6
142         sllx            %g6, 3, %g6
143
144         /* Load PTE.  */
145         ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
146         brgez,pn        %g5, longpath
147          nop
148
149         /* TLB load and return from trap.  */
150         stxa            %g5, [%g0] ASI_DTLB_DATA_IN
151         retry
152
153 /*
154  * On a first level data miss, check whether this is to the OBP range (note
155  * that such accesses can be made by prom, as well as by kernel using
156  * prom_getproperty on "address"), and if so, do not use vpte access ...
157  * rather, use information saved during inherit_prom_mappings() using 8k
158  * pagesize.
159  */
160 kvmap:
161         /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
162         mov             0xf, %g5
163         sllx            %g5, 28, %g5
164
165         /* Is addr >= LOW_OBP_ADDRESS?  */
166         cmp             %g4, %g5
167         blu,pn          %xcc, vmalloc_addr
168          mov            0x1, %g5
169
170         /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
171         sllx            %g5, 32, %g5
172
173         /* Is addr < HI_OBP_ADDRESS?  */
174         cmp             %g4, %g5
175         blu,pn          %xcc, obp_daddr_patch
176          nop
177
178 vmalloc_addr:
179         /* If we get here, a vmalloc addr accessed, load kernel VPTE.  */
180         ldxa            [%g3 + %g6] ASI_N, %g5
181         brgez,pn        %g5, longpath
182          nop
183
184         /* PTE is valid, load into TLB and return from trap.  */
185         stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
186         retry
187
188         /* This is trivial with the new code... */
189         .globl          do_fpdis
190 do_fpdis:
191         sethi           %hi(TSTATE_PEF), %g4                                    ! IEU0
192         rdpr            %tstate, %g5
193         andcc           %g5, %g4, %g0
194         be,pt           %xcc, 1f
195          nop
196         rd              %fprs, %g5
197         andcc           %g5, FPRS_FEF, %g0
198         be,pt           %xcc, 1f
199          nop
200
201         /* Legal state when DCR_IFPOE is set in Cheetah %dcr. */
202         sethi           %hi(109f), %g7
203         ba,pt           %xcc, etrap
204 109:     or             %g7, %lo(109b), %g7
205         add             %g0, %g0, %g0
206         ba,a,pt         %xcc, rtrap_clr_l6
207
208 1:      ldub            [%g6 + TI_FPSAVED], %g5                                 ! Load  Group
209         wr              %g0, FPRS_FEF, %fprs                                    ! LSU   Group+4bubbles
210         andcc           %g5, FPRS_FEF, %g0                                      ! IEU1  Group
211         be,a,pt         %icc, 1f                                                ! CTI
212          clr            %g7                                                     ! IEU0
213         ldx             [%g6 + TI_GSR], %g7                                     ! Load  Group
214 1:      andcc           %g5, FPRS_DL, %g0                                       ! IEU1
215         bne,pn          %icc, 2f                                                ! CTI
216          fzero          %f0                                                     ! FPA
217         andcc           %g5, FPRS_DU, %g0                                       ! IEU1  Group
218         bne,pn          %icc, 1f                                                ! CTI
219          fzero          %f2                                                     ! FPA
220         faddd           %f0, %f2, %f4
221         fmuld           %f0, %f2, %f6
222         faddd           %f0, %f2, %f8
223         fmuld           %f0, %f2, %f10
224         faddd           %f0, %f2, %f12
225         fmuld           %f0, %f2, %f14
226         faddd           %f0, %f2, %f16
227         fmuld           %f0, %f2, %f18
228         faddd           %f0, %f2, %f20
229         fmuld           %f0, %f2, %f22
230         faddd           %f0, %f2, %f24
231         fmuld           %f0, %f2, %f26
232         faddd           %f0, %f2, %f28
233         fmuld           %f0, %f2, %f30
234         faddd           %f0, %f2, %f32
235         fmuld           %f0, %f2, %f34
236         faddd           %f0, %f2, %f36
237         fmuld           %f0, %f2, %f38
238         faddd           %f0, %f2, %f40
239         fmuld           %f0, %f2, %f42
240         faddd           %f0, %f2, %f44
241         fmuld           %f0, %f2, %f46
242         faddd           %f0, %f2, %f48
243         fmuld           %f0, %f2, %f50
244         faddd           %f0, %f2, %f52
245         fmuld           %f0, %f2, %f54
246         faddd           %f0, %f2, %f56
247         fmuld           %f0, %f2, %f58
248         b,pt            %xcc, fpdis_exit2
249          faddd          %f0, %f2, %f60
250 1:      mov             SECONDARY_CONTEXT, %g3
251         add             %g6, TI_FPREGS + 0x80, %g1
252         faddd           %f0, %f2, %f4
253         fmuld           %f0, %f2, %f6
254         ldxa            [%g3] ASI_DMMU, %g5
255 cplus_fptrap_insn_1:
256         sethi           %hi(0), %g2
257         stxa            %g2, [%g3] ASI_DMMU
258         membar          #Sync
259         add             %g6, TI_FPREGS + 0xc0, %g2
260         faddd           %f0, %f2, %f8
261         fmuld           %f0, %f2, %f10
262         ldda            [%g1] ASI_BLK_S, %f32   ! grrr, where is ASI_BLK_NUCLEUS 8-(
263         ldda            [%g2] ASI_BLK_S, %f48
264         faddd           %f0, %f2, %f12
265         fmuld           %f0, %f2, %f14
266         faddd           %f0, %f2, %f16
267         fmuld           %f0, %f2, %f18
268         faddd           %f0, %f2, %f20
269         fmuld           %f0, %f2, %f22
270         faddd           %f0, %f2, %f24
271         fmuld           %f0, %f2, %f26
272         faddd           %f0, %f2, %f28
273         fmuld           %f0, %f2, %f30
274         membar          #Sync
275         b,pt            %xcc, fpdis_exit
276          nop
277 2:      andcc           %g5, FPRS_DU, %g0
278         bne,pt          %icc, 3f
279          fzero          %f32
280         mov             SECONDARY_CONTEXT, %g3
281         fzero           %f34
282         ldxa            [%g3] ASI_DMMU, %g5
283         add             %g6, TI_FPREGS, %g1
284 cplus_fptrap_insn_2:
285         sethi           %hi(0), %g2
286         stxa            %g2, [%g3] ASI_DMMU
287         membar          #Sync
288         add             %g6, TI_FPREGS + 0x40, %g2
289         faddd           %f32, %f34, %f36
290         fmuld           %f32, %f34, %f38
291         ldda            [%g1] ASI_BLK_S, %f0    ! grrr, where is ASI_BLK_NUCLEUS 8-(
292         ldda            [%g2] ASI_BLK_S, %f16
293         faddd           %f32, %f34, %f40
294         fmuld           %f32, %f34, %f42
295         faddd           %f32, %f34, %f44
296         fmuld           %f32, %f34, %f46
297         faddd           %f32, %f34, %f48
298         fmuld           %f32, %f34, %f50
299         faddd           %f32, %f34, %f52
300         fmuld           %f32, %f34, %f54
301         faddd           %f32, %f34, %f56
302         fmuld           %f32, %f34, %f58
303         faddd           %f32, %f34, %f60
304         fmuld           %f32, %f34, %f62
305         membar          #Sync
306         ba,pt           %xcc, fpdis_exit
307          nop
308 3:      mov             SECONDARY_CONTEXT, %g3
309         add             %g6, TI_FPREGS, %g1
310         ldxa            [%g3] ASI_DMMU, %g5
311 cplus_fptrap_insn_3:
312         sethi           %hi(0), %g2
313         stxa            %g2, [%g3] ASI_DMMU
314         membar          #Sync
315         mov             0x40, %g2
316         ldda            [%g1] ASI_BLK_S, %f0            ! grrr, where is ASI_BLK_NUCLEUS 8-(
317         ldda            [%g1 + %g2] ASI_BLK_S, %f16
318         add             %g1, 0x80, %g1
319         ldda            [%g1] ASI_BLK_S, %f32
320         ldda            [%g1 + %g2] ASI_BLK_S, %f48
321         membar          #Sync
322 fpdis_exit:
323         stxa            %g5, [%g3] ASI_DMMU
324         membar          #Sync
325 fpdis_exit2:
326         wr              %g7, 0, %gsr
327         ldx             [%g6 + TI_XFSR], %fsr
328         rdpr            %tstate, %g3
329         or              %g3, %g4, %g3           ! anal...
330         wrpr            %g3, %tstate
331         wr              %g0, FPRS_FEF, %fprs    ! clean DU/DL bits
332         retry
333
334         .align          32
335 fp_other_bounce:
336         call            do_fpother
337          add            %sp, PTREGS_OFF, %o0
338         ba,pt           %xcc, rtrap
339          clr            %l6
340
341         .globl          do_fpother_check_fitos
342         .align          32
343 do_fpother_check_fitos:
344         sethi           %hi(fp_other_bounce - 4), %g7
345         or              %g7, %lo(fp_other_bounce - 4), %g7
346
347         /* NOTE: Need to preserve %g7 until we fully commit
348          *       to the fitos fixup.
349          */
350         stx             %fsr, [%g6 + TI_XFSR]
351         rdpr            %tstate, %g3
352         andcc           %g3, TSTATE_PRIV, %g0
353         bne,pn          %xcc, do_fptrap_after_fsr
354          nop
355         ldx             [%g6 + TI_XFSR], %g3
356         srlx            %g3, 14, %g1
357         and             %g1, 7, %g1
358         cmp             %g1, 2                  ! Unfinished FP-OP
359         bne,pn          %xcc, do_fptrap_after_fsr
360          sethi          %hi(1 << 23), %g1       ! Inexact
361         andcc           %g3, %g1, %g0
362         bne,pn          %xcc, do_fptrap_after_fsr
363          rdpr           %tpc, %g1
364         lduwa           [%g1] ASI_AIUP, %g3     ! This cannot ever fail
365 #define FITOS_MASK      0xc1f83fe0
366 #define FITOS_COMPARE   0x81a01880
367         sethi           %hi(FITOS_MASK), %g1
368         or              %g1, %lo(FITOS_MASK), %g1
369         and             %g3, %g1, %g1
370         sethi           %hi(FITOS_COMPARE), %g2
371         or              %g2, %lo(FITOS_COMPARE), %g2
372         cmp             %g1, %g2
373         bne,pn          %xcc, do_fptrap_after_fsr
374          nop
375         std             %f62, [%g6 + TI_FPREGS + (62 * 4)]
376         sethi           %hi(fitos_table_1), %g1
377         and             %g3, 0x1f, %g2
378         or              %g1, %lo(fitos_table_1),  %g1
379         sllx            %g2, 2, %g2
380         jmpl            %g1 + %g2, %g0
381          ba,pt          %xcc, fitos_emul_continue
382
383 fitos_table_1:
384         fitod           %f0, %f62
385         fitod           %f1, %f62
386         fitod           %f2, %f62
387         fitod           %f3, %f62
388         fitod           %f4, %f62
389         fitod           %f5, %f62
390         fitod           %f6, %f62
391         fitod           %f7, %f62
392         fitod           %f8, %f62
393         fitod           %f9, %f62
394         fitod           %f10, %f62
395         fitod           %f11, %f62
396         fitod           %f12, %f62
397         fitod           %f13, %f62
398         fitod           %f14, %f62
399         fitod           %f15, %f62
400         fitod           %f16, %f62
401         fitod           %f17, %f62
402         fitod           %f18, %f62
403         fitod           %f19, %f62
404         fitod           %f20, %f62
405         fitod           %f21, %f62
406         fitod           %f22, %f62
407         fitod           %f23, %f62
408         fitod           %f24, %f62
409         fitod           %f25, %f62
410         fitod           %f26, %f62
411         fitod           %f27, %f62
412         fitod           %f28, %f62
413         fitod           %f29, %f62
414         fitod           %f30, %f62
415         fitod           %f31, %f62
416
417 fitos_emul_continue:
418         sethi           %hi(fitos_table_2), %g1
419         srl             %g3, 25, %g2
420         or              %g1, %lo(fitos_table_2), %g1
421         and             %g2, 0x1f, %g2
422         sllx            %g2, 2, %g2
423         jmpl            %g1 + %g2, %g0
424          ba,pt          %xcc, fitos_emul_fini
425
426 fitos_table_2:
427         fdtos           %f62, %f0
428         fdtos           %f62, %f1
429         fdtos           %f62, %f2
430         fdtos           %f62, %f3
431         fdtos           %f62, %f4
432         fdtos           %f62, %f5
433         fdtos           %f62, %f6
434         fdtos           %f62, %f7
435         fdtos           %f62, %f8
436         fdtos           %f62, %f9
437         fdtos           %f62, %f10
438         fdtos           %f62, %f11
439         fdtos           %f62, %f12
440         fdtos           %f62, %f13
441         fdtos           %f62, %f14
442         fdtos           %f62, %f15
443         fdtos           %f62, %f16
444         fdtos           %f62, %f17
445         fdtos           %f62, %f18
446         fdtos           %f62, %f19
447         fdtos           %f62, %f20
448         fdtos           %f62, %f21
449         fdtos           %f62, %f22
450         fdtos           %f62, %f23
451         fdtos           %f62, %f24
452         fdtos           %f62, %f25
453         fdtos           %f62, %f26
454         fdtos           %f62, %f27
455         fdtos           %f62, %f28
456         fdtos           %f62, %f29
457         fdtos           %f62, %f30
458         fdtos           %f62, %f31
459
460 fitos_emul_fini:
461         ldd             [%g6 + TI_FPREGS + (62 * 4)], %f62
462         done
463
464         .globl          do_fptrap
465         .align          32
466 do_fptrap:
467         stx             %fsr, [%g6 + TI_XFSR]
468 do_fptrap_after_fsr:
469         ldub            [%g6 + TI_FPSAVED], %g3
470         rd              %fprs, %g1
471         or              %g3, %g1, %g3
472         stb             %g3, [%g6 + TI_FPSAVED]
473         rd              %gsr, %g3
474         stx             %g3, [%g6 + TI_GSR]
475         mov             SECONDARY_CONTEXT, %g3
476         ldxa            [%g3] ASI_DMMU, %g5
477 cplus_fptrap_insn_4:
478         sethi           %hi(0), %g2
479         stxa            %g2, [%g3] ASI_DMMU
480         membar          #Sync
481         add             %g6, TI_FPREGS, %g2
482         andcc           %g1, FPRS_DL, %g0
483         be,pn           %icc, 4f
484          mov            0x40, %g3
485         stda            %f0, [%g2] ASI_BLK_S
486         stda            %f16, [%g2 + %g3] ASI_BLK_S
487         andcc           %g1, FPRS_DU, %g0
488         be,pn           %icc, 5f
489 4:       add            %g2, 128, %g2
490         stda            %f32, [%g2] ASI_BLK_S
491         stda            %f48, [%g2 + %g3] ASI_BLK_S
492 5:      mov             SECONDARY_CONTEXT, %g1
493         membar          #Sync
494         stxa            %g5, [%g1] ASI_DMMU
495         membar          #Sync
496         ba,pt           %xcc, etrap
497          wr             %g0, 0, %fprs
498
499 cplus_fptrap_1:
500         sethi           %hi(CTX_CHEETAH_PLUS_CTX0), %g2
501
502         .globl          cheetah_plus_patch_fpdis
503 cheetah_plus_patch_fpdis:
504         /* We configure the dTLB512_0 for 4MB pages and the
505          * dTLB512_1 for 8K pages when in context zero.
506          */
507         sethi                   %hi(cplus_fptrap_1), %o0
508         lduw                    [%o0 + %lo(cplus_fptrap_1)], %o1
509
510         set                     cplus_fptrap_insn_1, %o2
511         stw                     %o1, [%o2]
512         flush                   %o2
513         set                     cplus_fptrap_insn_2, %o2
514         stw                     %o1, [%o2]
515         flush                   %o2
516         set                     cplus_fptrap_insn_3, %o2
517         stw                     %o1, [%o2]
518         flush                   %o2
519         set                     cplus_fptrap_insn_4, %o2
520         stw                     %o1, [%o2]
521         flush                   %o2
522
523         retl
524          nop
525
526         /* The registers for cross calls will be:
527          *
528          * DATA 0: [low 32-bits]  Address of function to call, jmp to this
529          *         [high 32-bits] MMU Context Argument 0, place in %g5
530          * DATA 1: Address Argument 1, place in %g6
531          * DATA 2: Address Argument 2, place in %g7
532          *
533          * With this method we can do most of the cross-call tlb/cache
534          * flushing very quickly.
535          *
536          * Current CPU's IRQ worklist table is locked into %g1,
537          * don't touch.
538          */
539         .text
540         .align          32
541         .globl          do_ivec
542 do_ivec:
543         mov             0x40, %g3
544         ldxa            [%g3 + %g0] ASI_INTR_R, %g3
545         sethi           %hi(KERNBASE), %g4
546         cmp             %g3, %g4
547         bgeu,pn         %xcc, do_ivec_xcall
548          srlx           %g3, 32, %g5
549         stxa            %g0, [%g0] ASI_INTR_RECEIVE
550         membar          #Sync
551
552         sethi           %hi(ivector_table), %g2
553         sllx            %g3, 5, %g3
554         or              %g2, %lo(ivector_table), %g2
555         add             %g2, %g3, %g3
556         ldx             [%g3 + 0x08], %g2       /* irq_info */
557         ldub            [%g3 + 0x04], %g4       /* pil */
558         brz,pn          %g2, do_ivec_spurious
559          mov            1, %g2
560
561         sllx            %g2, %g4, %g2
562         sllx            %g4, 2, %g4
563         lduw            [%g6 + %g4], %g5        /* g5 = irq_work(cpu, pil) */
564         stw             %g5, [%g3 + 0x00]       /* bucket->irq_chain = g5 */
565         stw             %g3, [%g6 + %g4]        /* irq_work(cpu, pil) = bucket */
566         wr              %g2, 0x0, %set_softint
567         retry
568 do_ivec_xcall:
569         mov             0x50, %g1
570
571         ldxa            [%g1 + %g0] ASI_INTR_R, %g1
572         srl             %g3, 0, %g3
573         mov             0x60, %g7
574         ldxa            [%g7 + %g0] ASI_INTR_R, %g7
575         stxa            %g0, [%g0] ASI_INTR_RECEIVE
576         membar          #Sync
577         ba,pt           %xcc, 1f
578          nop
579
580         .align          32
581 1:      jmpl            %g3, %g0
582          nop
583
584 do_ivec_spurious:
585         stw             %g3, [%g6 + 0x00]       /* irq_work(cpu, 0) = bucket */
586         rdpr            %pstate, %g5
587
588         wrpr            %g5, PSTATE_IG | PSTATE_AG, %pstate
589         sethi           %hi(109f), %g7
590         ba,pt           %xcc, etrap
591 109:     or             %g7, %lo(109b), %g7
592         call            catch_disabled_ivec
593          add            %sp, PTREGS_OFF, %o0
594         ba,pt           %xcc, rtrap
595          clr            %l6
596
597         .globl          save_alternate_globals
598 save_alternate_globals: /* %o0 = save_area */
599         rdpr            %pstate, %o5
600         andn            %o5, PSTATE_IE, %o1
601         wrpr            %o1, PSTATE_AG, %pstate
602         stx             %g0, [%o0 + 0x00]
603         stx             %g1, [%o0 + 0x08]
604         stx             %g2, [%o0 + 0x10]
605         stx             %g3, [%o0 + 0x18]
606         stx             %g4, [%o0 + 0x20]
607         stx             %g5, [%o0 + 0x28]
608         stx             %g6, [%o0 + 0x30]
609         stx             %g7, [%o0 + 0x38]
610         wrpr            %o1, PSTATE_IG, %pstate
611         stx             %g0, [%o0 + 0x40]
612         stx             %g1, [%o0 + 0x48]
613         stx             %g2, [%o0 + 0x50]
614         stx             %g3, [%o0 + 0x58]
615         stx             %g4, [%o0 + 0x60]
616         stx             %g5, [%o0 + 0x68]
617         stx             %g6, [%o0 + 0x70]
618         stx             %g7, [%o0 + 0x78]
619         wrpr            %o1, PSTATE_MG, %pstate
620         stx             %g0, [%o0 + 0x80]
621         stx             %g1, [%o0 + 0x88]
622         stx             %g2, [%o0 + 0x90]
623         stx             %g3, [%o0 + 0x98]
624         stx             %g4, [%o0 + 0xa0]
625         stx             %g5, [%o0 + 0xa8]
626         stx             %g6, [%o0 + 0xb0]
627         stx             %g7, [%o0 + 0xb8]
628         wrpr            %o5, 0x0, %pstate
629         retl
630          nop
631
632         .globl          restore_alternate_globals
633 restore_alternate_globals: /* %o0 = save_area */
634         rdpr            %pstate, %o5
635         andn            %o5, PSTATE_IE, %o1
636         wrpr            %o1, PSTATE_AG, %pstate
637         ldx             [%o0 + 0x00], %g0
638         ldx             [%o0 + 0x08], %g1
639         ldx             [%o0 + 0x10], %g2
640         ldx             [%o0 + 0x18], %g3
641         ldx             [%o0 + 0x20], %g4
642         ldx             [%o0 + 0x28], %g5
643         ldx             [%o0 + 0x30], %g6
644         ldx             [%o0 + 0x38], %g7
645         wrpr            %o1, PSTATE_IG, %pstate
646         ldx             [%o0 + 0x40], %g0
647         ldx             [%o0 + 0x48], %g1
648         ldx             [%o0 + 0x50], %g2
649         ldx             [%o0 + 0x58], %g3
650         ldx             [%o0 + 0x60], %g4
651         ldx             [%o0 + 0x68], %g5
652         ldx             [%o0 + 0x70], %g6
653         ldx             [%o0 + 0x78], %g7
654         wrpr            %o1, PSTATE_MG, %pstate
655         ldx             [%o0 + 0x80], %g0
656         ldx             [%o0 + 0x88], %g1
657         ldx             [%o0 + 0x90], %g2
658         ldx             [%o0 + 0x98], %g3
659         ldx             [%o0 + 0xa0], %g4
660         ldx             [%o0 + 0xa8], %g5
661         ldx             [%o0 + 0xb0], %g6
662         ldx             [%o0 + 0xb8], %g7
663         wrpr            %o5, 0x0, %pstate
664         retl
665          nop
666
667         .globl          getcc, setcc
668 getcc:
669         ldx             [%o0 + PT_V9_TSTATE], %o1
670         srlx            %o1, 32, %o1
671         and             %o1, 0xf, %o1
672         retl
673          stx            %o1, [%o0 + PT_V9_G1]
674 setcc:
675         ldx             [%o0 + PT_V9_TSTATE], %o1
676         ldx             [%o0 + PT_V9_G1], %o2
677         or              %g0, %ulo(TSTATE_ICC), %o3
678         sllx            %o3, 32, %o3
679         andn            %o1, %o3, %o1
680         sllx            %o2, 32, %o2
681         and             %o2, %o3, %o2
682         or              %o1, %o2, %o1
683         retl
684          stx            %o1, [%o0 + PT_V9_TSTATE]
685
686         .globl          utrap, utrap_ill
687 utrap:  brz,pn          %g1, etrap
688          nop
689         save            %sp, -128, %sp
690         rdpr            %tstate, %l6
691         rdpr            %cwp, %l7
692         andn            %l6, TSTATE_CWP, %l6
693         wrpr            %l6, %l7, %tstate
694         rdpr            %tpc, %l6
695         rdpr            %tnpc, %l7
696         wrpr            %g1, 0, %tnpc
697         done
698 utrap_ill:
699         call            bad_trap
700          add            %sp, PTREGS_OFF, %o0
701         ba,pt           %xcc, rtrap
702          clr            %l6
703
704         /* XXX Here is stuff we still need to write... -DaveM XXX */
705         .globl          netbsd_syscall
706 netbsd_syscall:
707         retl
708          nop
709
710         /* These next few routines must be sure to clear the
711          * SFSR FaultValid bit so that the fast tlb data protection
712          * handler does not flush the wrong context and lock up the
713          * box.
714          */
715         .globl          __do_data_access_exception
716         .globl          __do_data_access_exception_tl1
717 __do_data_access_exception_tl1:
718         rdpr            %pstate, %g4
719         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
720         mov             TLB_SFSR, %g3
721         mov             DMMU_SFAR, %g5
722         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
723         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
724         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
725         membar          #Sync
726         ba,pt           %xcc, winfix_dax
727          rdpr           %tpc, %g3
728 __do_data_access_exception:
729         rdpr            %pstate, %g4
730         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
731         mov             TLB_SFSR, %g3
732         mov             DMMU_SFAR, %g5
733         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
734         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
735         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
736         membar          #Sync
737         sethi           %hi(109f), %g7
738         ba,pt           %xcc, etrap
739 109:     or             %g7, %lo(109b), %g7
740         mov             %l4, %o1
741         mov             %l5, %o2
742         call            data_access_exception
743          add            %sp, PTREGS_OFF, %o0
744         ba,pt           %xcc, rtrap
745          clr            %l6
746
747         .globl          __do_instruction_access_exception
748         .globl          __do_instruction_access_exception_tl1
749 __do_instruction_access_exception_tl1:
750         rdpr            %pstate, %g4
751         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
752         mov             TLB_SFSR, %g3
753         mov             DMMU_SFAR, %g5
754         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
755         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
756         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
757         membar          #Sync
758         sethi           %hi(109f), %g7
759         ba,pt           %xcc, etraptl1
760 109:     or             %g7, %lo(109b), %g7
761         mov             %l4, %o1
762         mov             %l5, %o2
763         call            instruction_access_exception_tl1
764          add            %sp, PTREGS_OFF, %o0
765         ba,pt           %xcc, rtrap
766          clr            %l6
767
768 __do_instruction_access_exception:
769         rdpr            %pstate, %g4
770         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
771         mov             TLB_SFSR, %g3
772         mov             DMMU_SFAR, %g5
773         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
774         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
775         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
776         membar          #Sync
777         sethi           %hi(109f), %g7
778         ba,pt           %xcc, etrap
779 109:     or             %g7, %lo(109b), %g7
780         mov             %l4, %o1
781         mov             %l5, %o2
782         call            instruction_access_exception
783          add            %sp, PTREGS_OFF, %o0
784         ba,pt           %xcc, rtrap
785          clr            %l6
786
787         /* This is the trap handler entry point for ECC correctable
788          * errors.  They are corrected, but we listen for the trap
789          * so that the event can be logged.
790          *
791          * Disrupting errors are either:
792          * 1) single-bit ECC errors during UDB reads to system
793          *    memory
794          * 2) data parity errors during write-back events
795          *
796          * As far as I can make out from the manual, the CEE trap
797          * is only for correctable errors during memory read
798          * accesses by the front-end of the processor.
799          *
800          * The code below is only for trap level 1 CEE events,
801          * as it is the only situation where we can safely record
802          * and log.  For trap level >1 we just clear the CE bit
803          * in the AFSR and return.
804          */
805
806         /* Our trap handling infrastructure allows us to preserve
807          * two 64-bit values during etrap for arguments to
808          * subsequent C code.  Therefore we encode the information
809          * as follows:
810          *
811          * value 1) Full 64-bits of AFAR
812          * value 2) Low 33-bits of AFSR, then bits 33-->42
813          *          are UDBL error status and bits 43-->52
814          *          are UDBH error status
815          */
816         .align  64
817         .globl  cee_trap
818 cee_trap:
819         ldxa    [%g0] ASI_AFSR, %g1             ! Read AFSR
820         ldxa    [%g0] ASI_AFAR, %g2             ! Read AFAR
821         sllx    %g1, 31, %g1                    ! Clear reserved bits
822         srlx    %g1, 31, %g1                    ! in AFSR
823
824         /* NOTE: UltraSparc-I/II have high and low UDB error
825          *       registers, corresponding to the two UDB units
826          *       present on those chips.  UltraSparc-IIi only
827          *       has a single UDB, called "SDB" in the manual.
828          *       For IIi the upper UDB register always reads
829          *       as zero so for our purposes things will just
830          *       work with the checks below.
831          */
832         ldxa    [%g0] ASI_UDBL_ERROR_R, %g3     ! Read UDB-Low error status
833         andcc   %g3, (1 << 8), %g4              ! Check CE bit
834         sllx    %g3, (64 - 10), %g3             ! Clear reserved bits
835         srlx    %g3, (64 - 10), %g3             ! in UDB-Low error status
836
837         sllx    %g3, (33 + 0), %g3              ! Shift up to encoding area
838         or      %g1, %g3, %g1                   ! Or it in
839         be,pn   %xcc, 1f                        ! Branch if CE bit was clear
840          nop
841         stxa    %g4, [%g0] ASI_UDB_ERROR_W      ! Clear CE sticky bit in UDBL
842         membar  #Sync                           ! Synchronize ASI stores
843 1:      mov     0x18, %g5                       ! Addr of UDB-High error status
844         ldxa    [%g5] ASI_UDBH_ERROR_R, %g3     ! Read it
845
846         andcc   %g3, (1 << 8), %g4              ! Check CE bit
847         sllx    %g3, (64 - 10), %g3             ! Clear reserved bits
848         srlx    %g3, (64 - 10), %g3             ! in UDB-High error status
849         sllx    %g3, (33 + 10), %g3             ! Shift up to encoding area
850         or      %g1, %g3, %g1                   ! Or it in
851         be,pn   %xcc, 1f                        ! Branch if CE bit was clear
852          nop
853         nop
854
855         stxa    %g4, [%g5] ASI_UDB_ERROR_W      ! Clear CE sticky bit in UDBH
856         membar  #Sync                           ! Synchronize ASI stores
857 1:      mov     1, %g5                          ! AFSR CE bit is
858         sllx    %g5, 20, %g5                    ! bit 20
859         stxa    %g5, [%g0] ASI_AFSR             ! Clear CE sticky bit in AFSR
860         membar  #Sync                           ! Synchronize ASI stores
861         sllx    %g2, (64 - 41), %g2             ! Clear reserved bits
862         srlx    %g2, (64 - 41), %g2             ! in latched AFAR
863
864         andn    %g2, 0x0f, %g2                  ! Finish resv bit clearing
865         mov     %g1, %g4                        ! Move AFSR+UDB* into save reg
866         mov     %g2, %g5                        ! Move AFAR into save reg
867         rdpr    %pil, %g2
868         wrpr    %g0, 15, %pil
869         ba,pt   %xcc, etrap_irq
870          rd     %pc, %g7
871         mov     %l4, %o0
872
873         mov     %l5, %o1
874         call    cee_log
875          add    %sp, PTREGS_OFF, %o2
876         ba,a,pt %xcc, rtrap_irq
877
878         /* Capture I/D/E-cache state into per-cpu error scoreboard.
879          *
880          * %g1:         (TL>=0) ? 1 : 0
881          * %g2:         scratch
882          * %g3:         scratch
883          * %g4:         AFSR
884          * %g5:         AFAR
885          * %g6:         current thread ptr
886          * %g7:         scratch
887          */
888 #define CHEETAH_LOG_ERROR                                               \
889         /* Put "TL1" software bit into AFSR. */                         \
890         and             %g1, 0x1, %g1;                                  \
891         sllx            %g1, 63, %g2;                                   \
892         or              %g4, %g2, %g4;                                  \
893         /* Get log entry pointer for this cpu at this trap level. */    \
894         BRANCH_IF_JALAPENO(g2,g3,50f)                                   \
895         ldxa            [%g0] ASI_SAFARI_CONFIG, %g2;                   \
896         srlx            %g2, 17, %g2;                                   \
897         ba,pt           %xcc, 60f;                                      \
898          and            %g2, 0x3ff, %g2;                                \
899 50:     ldxa            [%g0] ASI_JBUS_CONFIG, %g2;                     \
900         srlx            %g2, 17, %g2;                                   \
901         and             %g2, 0x1f, %g2;                                 \
902 60:     sllx            %g2, 9, %g2;                                    \
903         sethi           %hi(cheetah_error_log), %g3;                    \
904         ldx             [%g3 + %lo(cheetah_error_log)], %g3;            \
905         brz,pn          %g3, 80f;                                       \
906          nop;                                                           \
907         add             %g3, %g2, %g3;                                  \
908         sllx            %g1, 8, %g1;                                    \
909         add             %g3, %g1, %g1;                                  \
910         /* %g1 holds pointer to the top of the logging scoreboard */    \
911         ldx             [%g1 + 0x0], %g7;                               \
912         cmp             %g7, -1;                                        \
913         bne,pn          %xcc, 80f;                                      \
914          nop;                                                           \
915         stx             %g4, [%g1 + 0x0];                               \
916         stx             %g5, [%g1 + 0x8];                               \
917         add             %g1, 0x10, %g1;                                 \
918         /* %g1 now points to D-cache logging area */                    \
919         set             0x3ff8, %g2;    /* DC_addr mask         */      \
920         and             %g5, %g2, %g2;  /* DC_addr bits of AFAR */      \
921         srlx            %g5, 12, %g3;                                   \
922         or              %g3, 1, %g3;    /* PHYS tag + valid     */      \
923 10:     ldxa            [%g2] ASI_DCACHE_TAG, %g7;                      \
924         cmp             %g3, %g7;       /* TAG match?           */      \
925         bne,pt          %xcc, 13f;                                      \
926          nop;                                                           \
927         /* Yep, what we want, capture state. */                         \
928         stx             %g2, [%g1 + 0x20];                              \
929         stx             %g7, [%g1 + 0x28];                              \
930         /* A membar Sync is required before and after utag access. */   \
931         membar          #Sync;                                          \
932         ldxa            [%g2] ASI_DCACHE_UTAG, %g7;                     \
933         membar          #Sync;                                          \
934         stx             %g7, [%g1 + 0x30];                              \
935         ldxa            [%g2] ASI_DCACHE_SNOOP_TAG, %g7;                \
936         stx             %g7, [%g1 + 0x38];                              \
937         clr             %g3;                                            \
938 12:     ldxa            [%g2 + %g3] ASI_DCACHE_DATA, %g7;               \
939         stx             %g7, [%g1];                                     \
940         add             %g3, (1 << 5), %g3;                             \
941         cmp             %g3, (4 << 5);                                  \
942         bl,pt           %xcc, 12b;                                      \
943          add            %g1, 0x8, %g1;                                  \
944         ba,pt           %xcc, 20f;                                      \
945          add            %g1, 0x20, %g1;                                 \
946 13:     sethi           %hi(1 << 14), %g7;                              \
947         add             %g2, %g7, %g2;                                  \
948         srlx            %g2, 14, %g7;                                   \
949         cmp             %g7, 4;                                         \
950         bl,pt           %xcc, 10b;                                      \
951          nop;                                                           \
952         add             %g1, 0x40, %g1;                                 \
953 20:     /* %g1 now points to I-cache logging area */                    \
954         set             0x1fe0, %g2;    /* IC_addr mask         */      \
955         and             %g5, %g2, %g2;  /* IC_addr bits of AFAR */      \
956         sllx            %g2, 1, %g2;    /* IC_addr[13:6]==VA[12:5] */   \
957         srlx            %g5, (13 - 8), %g3; /* Make PTAG */             \
958         andn            %g3, 0xff, %g3; /* Mask off undefined bits */   \
959 21:     ldxa            [%g2] ASI_IC_TAG, %g7;                          \
960         andn            %g7, 0xff, %g7;                                 \
961         cmp             %g3, %g7;                                       \
962         bne,pt          %xcc, 23f;                                      \
963          nop;                                                           \
964         /* Yep, what we want, capture state. */                         \
965         stx             %g2, [%g1 + 0x40];                              \
966         stx             %g7, [%g1 + 0x48];                              \
967         add             %g2, (1 << 3), %g2;                             \
968         ldxa            [%g2] ASI_IC_TAG, %g7;                          \
969         add             %g2, (1 << 3), %g2;                             \
970         stx             %g7, [%g1 + 0x50];                              \
971         ldxa            [%g2] ASI_IC_TAG, %g7;                          \
972         add             %g2, (1 << 3), %g2;                             \
973         stx             %g7, [%g1 + 0x60];                              \
974         ldxa            [%g2] ASI_IC_TAG, %g7;                          \
975         stx             %g7, [%g1 + 0x68];                              \
976         sub             %g2, (3 << 3), %g2;                             \
977         ldxa            [%g2] ASI_IC_STAG, %g7;                         \
978         stx             %g7, [%g1 + 0x58];                              \
979         clr             %g3;                                            \
980         srlx            %g2, 2, %g2;                                    \
981 22:     ldxa            [%g2 + %g3] ASI_IC_INSTR, %g7;                  \
982         stx             %g7, [%g1];                                     \
983         add             %g3, (1 << 3), %g3;                             \
984         cmp             %g3, (8 << 3);                                  \
985         bl,pt           %xcc, 22b;                                      \
986          add            %g1, 0x8, %g1;                                  \
987         ba,pt           %xcc, 30f;                                      \
988          add            %g1, 0x30, %g1;                                 \
989 23:     sethi           %hi(1 << 14), %g7;                              \
990         add             %g2, %g7, %g2;                                  \
991         srlx            %g2, 14, %g7;                                   \
992         cmp             %g7, 4;                                         \
993         bl,pt           %xcc, 21b;                                      \
994          nop;                                                           \
995         add             %g1, 0x70, %g1;                                 \
996 30:     /* %g1 now points to E-cache logging area */                    \
997         andn            %g5, (32 - 1), %g2;     /* E-cache subblock */  \
998         stx             %g2, [%g1 + 0x20];                              \
999         ldxa            [%g2] ASI_EC_TAG_DATA, %g7;                     \
1000         stx             %g7, [%g1 + 0x28];                              \
1001         ldxa            [%g2] ASI_EC_R, %g0;                            \
1002         clr             %g3;                                            \
1003 31:     ldxa            [%g3] ASI_EC_DATA, %g7;                         \
1004         stx             %g7, [%g1 + %g3];                               \
1005         add             %g3, 0x8, %g3;                                  \
1006         cmp             %g3, 0x20;                                      \
1007         bl,pt           %xcc, 31b;                                      \
1008          nop;                                                           \
1009 80:     /* DONE */
1010
1011         /* These get patched into the trap table at boot time
1012          * once we know we have a cheetah processor.
1013          */
1014         .globl          cheetah_fecc_trap_vector, cheetah_fecc_trap_vector_tl1
1015 cheetah_fecc_trap_vector:
1016         membar          #Sync
1017         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1018         andn            %g1, DCU_DC | DCU_IC, %g1
1019         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1020         membar          #Sync
1021         sethi           %hi(cheetah_fast_ecc), %g2
1022         jmpl            %g2 + %lo(cheetah_fast_ecc), %g0
1023          mov            0, %g1
1024 cheetah_fecc_trap_vector_tl1:
1025         membar          #Sync
1026         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1027         andn            %g1, DCU_DC | DCU_IC, %g1
1028         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1029         membar          #Sync
1030         sethi           %hi(cheetah_fast_ecc), %g2
1031         jmpl            %g2 + %lo(cheetah_fast_ecc), %g0
1032          mov            1, %g1
1033         .globl  cheetah_cee_trap_vector, cheetah_cee_trap_vector_tl1
1034 cheetah_cee_trap_vector:
1035         membar          #Sync
1036         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1037         andn            %g1, DCU_IC, %g1
1038         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1039         membar          #Sync
1040         sethi           %hi(cheetah_cee), %g2
1041         jmpl            %g2 + %lo(cheetah_cee), %g0
1042          mov            0, %g1
1043 cheetah_cee_trap_vector_tl1:
1044         membar          #Sync
1045         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1046         andn            %g1, DCU_IC, %g1
1047         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1048         membar          #Sync
1049         sethi           %hi(cheetah_cee), %g2
1050         jmpl            %g2 + %lo(cheetah_cee), %g0
1051          mov            1, %g1
1052         .globl  cheetah_deferred_trap_vector, cheetah_deferred_trap_vector_tl1
1053 cheetah_deferred_trap_vector:
1054         membar          #Sync
1055         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1;
1056         andn            %g1, DCU_DC | DCU_IC, %g1;
1057         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG;
1058         membar          #Sync;
1059         sethi           %hi(cheetah_deferred_trap), %g2
1060         jmpl            %g2 + %lo(cheetah_deferred_trap), %g0
1061          mov            0, %g1
1062 cheetah_deferred_trap_vector_tl1:
1063         membar          #Sync;
1064         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1;
1065         andn            %g1, DCU_DC | DCU_IC, %g1;
1066         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG;
1067         membar          #Sync;
1068         sethi           %hi(cheetah_deferred_trap), %g2
1069         jmpl            %g2 + %lo(cheetah_deferred_trap), %g0
1070          mov            1, %g1
1071
1072         /* Cheetah+ specific traps. These are for the new I/D cache parity
1073          * error traps.  The first argument to cheetah_plus_parity_handler
1074          * is encoded as follows:
1075          *
1076          * Bit0:        0=dcache,1=icache
1077          * Bit1:        0=recoverable,1=unrecoverable
1078          */
1079         .globl          cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1
1080 cheetah_plus_dcpe_trap_vector:
1081         membar          #Sync
1082         sethi           %hi(do_cheetah_plus_data_parity), %g7
1083         jmpl            %g7 + %lo(do_cheetah_plus_data_parity), %g0
1084          nop
1085         nop
1086         nop
1087         nop
1088         nop
1089
1090 do_cheetah_plus_data_parity:
1091         ba,pt           %xcc, etrap
1092          rd             %pc, %g7
1093         mov             0x0, %o0
1094         call            cheetah_plus_parity_error
1095          add            %sp, PTREGS_OFF, %o1
1096         ba,pt           %xcc, rtrap
1097          clr            %l6
1098
1099 cheetah_plus_dcpe_trap_vector_tl1:
1100         membar          #Sync
1101         wrpr            PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
1102         sethi           %hi(do_dcpe_tl1), %g3
1103         jmpl            %g3 + %lo(do_dcpe_tl1), %g0
1104          nop
1105         nop
1106         nop
1107         nop
1108
1109         .globl          cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1
1110 cheetah_plus_icpe_trap_vector:
1111         membar          #Sync
1112         sethi           %hi(do_cheetah_plus_insn_parity), %g7
1113         jmpl            %g7 + %lo(do_cheetah_plus_insn_parity), %g0
1114          nop
1115         nop
1116         nop
1117         nop
1118         nop
1119
1120 do_cheetah_plus_insn_parity:
1121         ba,pt           %xcc, etrap
1122          rd             %pc, %g7
1123         mov             0x1, %o0
1124         call            cheetah_plus_parity_error
1125          add            %sp, PTREGS_OFF, %o1
1126         ba,pt           %xcc, rtrap
1127          clr            %l6
1128
1129 cheetah_plus_icpe_trap_vector_tl1:
1130         membar          #Sync
1131         wrpr            PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
1132         sethi           %hi(do_icpe_tl1), %g3
1133         jmpl            %g3 + %lo(do_icpe_tl1), %g0
1134          nop
1135         nop
1136         nop
1137         nop
1138
1139         /* If we take one of these traps when tl >= 1, then we
1140          * jump to interrupt globals.  If some trap level above us
1141          * was also using interrupt globals, we cannot recover.
1142          * We may use all interrupt global registers except %g6.
1143          */
1144         .globl          do_dcpe_tl1, do_icpe_tl1
1145 do_dcpe_tl1:
1146         rdpr            %tl, %g1                ! Save original trap level
1147         mov             1, %g2                  ! Setup TSTATE checking loop
1148         sethi           %hi(TSTATE_IG), %g3     ! TSTATE mask bit
1149 1:      wrpr            %g2, %tl                ! Set trap level to check
1150         rdpr            %tstate, %g4            ! Read TSTATE for this level
1151         andcc           %g4, %g3, %g0           ! Interrupt globals in use?
1152         bne,a,pn        %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
1153          wrpr           %g1, %tl                ! Restore original trap level
1154         add             %g2, 1, %g2             ! Next trap level
1155         cmp             %g2, %g1                ! Hit them all yet?
1156         ble,pt          %icc, 1b                ! Not yet
1157          nop
1158         wrpr            %g1, %tl                ! Restore original trap level
1159 do_dcpe_tl1_nonfatal:   /* Ok we may use interrupt globals safely. */
1160         /* Reset D-cache parity */
1161         sethi           %hi(1 << 16), %g1       ! D-cache size
1162         mov             (1 << 5), %g2           ! D-cache line size
1163         sub             %g1, %g2, %g1           ! Move down 1 cacheline
1164 1:      srl             %g1, 14, %g3            ! Compute UTAG
1165         membar          #Sync
1166         stxa            %g3, [%g1] ASI_DCACHE_UTAG
1167         membar          #Sync
1168         sub             %g2, 8, %g3             ! 64-bit data word within line
1169 2:      membar          #Sync
1170         stxa            %g0, [%g1 + %g3] ASI_DCACHE_DATA
1171         membar          #Sync
1172         subcc           %g3, 8, %g3             ! Next 64-bit data word
1173         bge,pt          %icc, 2b
1174          nop
1175         subcc           %g1, %g2, %g1           ! Next cacheline
1176         bge,pt          %icc, 1b
1177          nop
1178         ba,pt           %xcc, dcpe_icpe_tl1_common
1179          nop
1180
1181 do_dcpe_tl1_fatal:
1182         sethi           %hi(1f), %g7
1183         ba,pt           %xcc, etraptl1
1184 1:      or              %g7, %lo(1b), %g7
1185         mov             0x2, %o0
1186         call            cheetah_plus_parity_error
1187          add            %sp, PTREGS_OFF, %o1
1188         ba,pt           %xcc, rtrap
1189          clr            %l6
1190
1191 do_icpe_tl1:
1192         rdpr            %tl, %g1                ! Save original trap level
1193         mov             1, %g2                  ! Setup TSTATE checking loop
1194         sethi           %hi(TSTATE_IG), %g3     ! TSTATE mask bit
1195 1:      wrpr            %g2, %tl                ! Set trap level to check
1196         rdpr            %tstate, %g4            ! Read TSTATE for this level
1197         andcc           %g4, %g3, %g0           ! Interrupt globals in use?
1198         bne,a,pn        %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
1199          wrpr           %g1, %tl                ! Restore original trap level
1200         add             %g2, 1, %g2             ! Next trap level
1201         cmp             %g2, %g1                ! Hit them all yet?
1202         ble,pt          %icc, 1b                ! Not yet
1203          nop
1204         wrpr            %g1, %tl                ! Restore original trap level
1205 do_icpe_tl1_nonfatal:   /* Ok we may use interrupt globals safely. */
1206         /* Flush I-cache */
1207         sethi           %hi(1 << 15), %g1       ! I-cache size
1208         mov             (1 << 5), %g2           ! I-cache line size
1209         sub             %g1, %g2, %g1
1210 1:      or              %g1, (2 << 3), %g3
1211         stxa            %g0, [%g3] ASI_IC_TAG
1212         membar          #Sync
1213         subcc           %g1, %g2, %g1
1214         bge,pt          %icc, 1b
1215          nop
1216         ba,pt           %xcc, dcpe_icpe_tl1_common
1217          nop
1218
1219 do_icpe_tl1_fatal:
1220         sethi           %hi(1f), %g7
1221         ba,pt           %xcc, etraptl1
1222 1:      or              %g7, %lo(1b), %g7
1223         mov             0x3, %o0
1224         call            cheetah_plus_parity_error
1225          add            %sp, PTREGS_OFF, %o1
1226         ba,pt           %xcc, rtrap
1227          clr            %l6
1228         
1229 dcpe_icpe_tl1_common:
1230         /* Flush D-cache, re-enable D/I caches in DCU and finally
1231          * retry the trapping instruction.
1232          */
1233         sethi           %hi(1 << 16), %g1       ! D-cache size
1234         mov             (1 << 5), %g2           ! D-cache line size
1235         sub             %g1, %g2, %g1
1236 1:      stxa            %g0, [%g1] ASI_DCACHE_TAG
1237         membar          #Sync
1238         subcc           %g1, %g2, %g1
1239         bge,pt          %icc, 1b
1240          nop
1241         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1242         or              %g1, (DCU_DC | DCU_IC), %g1
1243         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1244         membar          #Sync
1245         retry
1246
1247         /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
1248          * in the trap table.  That code has done a memory barrier
1249          * and has disabled both the I-cache and D-cache in the DCU
1250          * control register.  The I-cache is disabled so that we may
1251          * capture the corrupted cache line, and the D-cache is disabled
1252          * because corrupt data may have been placed there and we don't
1253          * want to reference it.
1254          *
1255          * %g1 is one if this trap occurred at %tl >= 1.
1256          *
1257          * Next, we turn off error reporting so that we don't recurse.
1258          */
1259         .globl          cheetah_fast_ecc
1260 cheetah_fast_ecc:
1261         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1262         andn            %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
1263         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1264         membar          #Sync
1265
1266         /* Fetch and clear AFSR/AFAR */
1267         ldxa            [%g0] ASI_AFSR, %g4
1268         ldxa            [%g0] ASI_AFAR, %g5
1269         stxa            %g4, [%g0] ASI_AFSR
1270         membar          #Sync
1271
1272         CHEETAH_LOG_ERROR
1273
1274         rdpr            %pil, %g2
1275         wrpr            %g0, 15, %pil
1276         ba,pt           %xcc, etrap_irq
1277          rd             %pc, %g7
1278         mov             %l4, %o1
1279         mov             %l5, %o2
1280         call            cheetah_fecc_handler
1281          add            %sp, PTREGS_OFF, %o0
1282         ba,a,pt         %xcc, rtrap_irq
1283
1284         /* Our caller has disabled I-cache and performed membar Sync. */
1285         .globl          cheetah_cee
1286 cheetah_cee:
1287         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1288         andn            %g2, ESTATE_ERROR_CEEN, %g2
1289         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1290         membar          #Sync
1291
1292         /* Fetch and clear AFSR/AFAR */
1293         ldxa            [%g0] ASI_AFSR, %g4
1294         ldxa            [%g0] ASI_AFAR, %g5
1295         stxa            %g4, [%g0] ASI_AFSR
1296         membar          #Sync
1297
1298         CHEETAH_LOG_ERROR
1299
1300         rdpr            %pil, %g2
1301         wrpr            %g0, 15, %pil
1302         ba,pt           %xcc, etrap_irq
1303          rd             %pc, %g7
1304         mov             %l4, %o1
1305         mov             %l5, %o2
1306         call            cheetah_cee_handler
1307          add            %sp, PTREGS_OFF, %o0
1308         ba,a,pt         %xcc, rtrap_irq
1309
1310         /* Our caller has disabled I-cache+D-cache and performed membar Sync. */
1311         .globl          cheetah_deferred_trap
1312 cheetah_deferred_trap:
1313         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1314         andn            %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
1315         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1316         membar          #Sync
1317
1318         /* Fetch and clear AFSR/AFAR */
1319         ldxa            [%g0] ASI_AFSR, %g4
1320         ldxa            [%g0] ASI_AFAR, %g5
1321         stxa            %g4, [%g0] ASI_AFSR
1322         membar          #Sync
1323
1324         CHEETAH_LOG_ERROR
1325
1326         rdpr            %pil, %g2
1327         wrpr            %g0, 15, %pil
1328         ba,pt           %xcc, etrap_irq
1329          rd             %pc, %g7
1330         mov             %l4, %o1
1331         mov             %l5, %o2
1332         call            cheetah_deferred_handler
1333          add            %sp, PTREGS_OFF, %o0
1334         ba,a,pt         %xcc, rtrap_irq
1335
1336         .globl          __do_privact
1337 __do_privact:
1338         mov             TLB_SFSR, %g3
1339         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
1340         membar          #Sync
1341         sethi           %hi(109f), %g7
1342         ba,pt           %xcc, etrap
1343 109:    or              %g7, %lo(109b), %g7
1344         call            do_privact
1345          add            %sp, PTREGS_OFF, %o0
1346         ba,pt           %xcc, rtrap
1347          clr            %l6
1348
1349         .globl          do_mna
1350 do_mna:
1351         rdpr            %tl, %g3
1352         cmp             %g3, 1
1353
1354         /* Setup %g4/%g5 now as they are used in the
1355          * winfixup code.
1356          */
1357         mov             TLB_SFSR, %g3
1358         mov             DMMU_SFAR, %g4
1359         ldxa            [%g4] ASI_DMMU, %g4
1360         ldxa            [%g3] ASI_DMMU, %g5
1361         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
1362         membar          #Sync
1363         bgu,pn          %icc, winfix_mna
1364          rdpr           %tpc, %g3
1365
1366 1:      sethi           %hi(109f), %g7
1367         ba,pt           %xcc, etrap
1368 109:     or             %g7, %lo(109b), %g7
1369         mov             %l4, %o1
1370         mov             %l5, %o2
1371         call            mem_address_unaligned
1372          add            %sp, PTREGS_OFF, %o0
1373         ba,pt           %xcc, rtrap
1374          clr            %l6
1375
1376         .globl          do_lddfmna
1377 do_lddfmna:
1378         sethi           %hi(109f), %g7
1379         mov             TLB_SFSR, %g4
1380         ldxa            [%g4] ASI_DMMU, %g5
1381         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
1382         membar          #Sync
1383         mov             DMMU_SFAR, %g4
1384         ldxa            [%g4] ASI_DMMU, %g4
1385         ba,pt           %xcc, etrap
1386 109:     or             %g7, %lo(109b), %g7
1387         mov             %l4, %o1
1388         mov             %l5, %o2
1389         call            handle_lddfmna
1390          add            %sp, PTREGS_OFF, %o0
1391         ba,pt           %xcc, rtrap
1392          clr            %l6
1393
1394         .globl          do_stdfmna
1395 do_stdfmna:
1396         sethi           %hi(109f), %g7
1397         mov             TLB_SFSR, %g4
1398         ldxa            [%g4] ASI_DMMU, %g5
1399         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
1400         membar          #Sync
1401         mov             DMMU_SFAR, %g4
1402         ldxa            [%g4] ASI_DMMU, %g4
1403         ba,pt           %xcc, etrap
1404 109:     or             %g7, %lo(109b), %g7
1405         mov             %l4, %o1
1406         mov             %l5, %o2
1407         call            handle_stdfmna
1408          add            %sp, PTREGS_OFF, %o0
1409         ba,pt           %xcc, rtrap
1410          clr            %l6
1411
1412         .globl  breakpoint_trap
1413 breakpoint_trap:
1414         call            sparc_breakpoint
1415          add            %sp, PTREGS_OFF, %o0
1416         ba,pt           %xcc, rtrap
1417          nop
1418
1419 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
1420     defined(CONFIG_SOLARIS_EMUL_MODULE)
1421         /* SunOS uses syscall zero as the 'indirect syscall' it looks
1422          * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
1423          * This is complete brain damage.
1424          */
1425         .globl  sunos_indir
1426 sunos_indir:
1427         srl             %o0, 0, %o0
1428         mov             %o7, %l4
1429         cmp             %o0, NR_SYSCALLS
1430         blu,a,pt        %icc, 1f
1431          sll            %o0, 0x2, %o0
1432         sethi           %hi(sunos_nosys), %l6
1433         b,pt            %xcc, 2f
1434          or             %l6, %lo(sunos_nosys), %l6
1435 1:      sethi           %hi(sunos_sys_table), %l7
1436         or              %l7, %lo(sunos_sys_table), %l7
1437         lduw            [%l7 + %o0], %l6
1438 2:      mov             %o1, %o0
1439         mov             %o2, %o1
1440         mov             %o3, %o2
1441         mov             %o4, %o3
1442         mov             %o5, %o4
1443         call            %l6
1444          mov            %l4, %o7
1445
1446         .globl  sunos_getpid
1447 sunos_getpid:
1448         call    sys_getppid
1449          nop
1450         call    sys_getpid
1451          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1452         b,pt    %xcc, ret_sys_call
1453          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1454
1455         /* SunOS getuid() returns uid in %o0 and euid in %o1 */
1456         .globl  sunos_getuid
1457 sunos_getuid:
1458         call    sys32_geteuid16
1459          nop
1460         call    sys32_getuid16
1461          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1462         b,pt    %xcc, ret_sys_call
1463          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1464
1465         /* SunOS getgid() returns gid in %o0 and egid in %o1 */
1466         .globl  sunos_getgid
1467 sunos_getgid:
1468         call    sys32_getegid16
1469          nop
1470         call    sys32_getgid16
1471          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1472         b,pt    %xcc, ret_sys_call
1473          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1474 #endif
1475
1476         /* SunOS's execv() call only specifies the argv argument, the
1477          * environment settings are the same as the calling processes.
1478          */
1479         .globl  sunos_execv
1480 sys_execve:
1481         sethi           %hi(sparc_execve), %g1
1482         ba,pt           %xcc, execve_merge
1483          or             %g1, %lo(sparc_execve), %g1
1484 #ifdef CONFIG_COMPAT
1485         .globl  sys_execve
1486 sunos_execv:
1487         stx             %g0, [%sp + PTREGS_OFF + PT_V9_I2]
1488         .globl  sys32_execve
1489 sys32_execve:
1490         sethi           %hi(sparc32_execve), %g1
1491         or              %g1, %lo(sparc32_execve), %g1
1492 #endif
1493 execve_merge:
1494         flushw
1495         jmpl            %g1, %g0
1496          add            %sp, PTREGS_OFF, %o0
1497
1498         .globl  sys_pipe, sys_sigpause, sys_nis_syscall
1499         .globl  sys_sigsuspend, sys_rt_sigsuspend
1500         .globl  sys_rt_sigreturn
1501         .globl  sys_ptrace
1502         .globl  sys_sigaltstack
1503         .align  32
1504 sys_pipe:       ba,pt           %xcc, sparc_pipe
1505                  add            %sp, PTREGS_OFF, %o0
1506 sys_nis_syscall:ba,pt           %xcc, c_sys_nis_syscall
1507                  add            %sp, PTREGS_OFF, %o0
1508 sys_memory_ordering:
1509                 ba,pt           %xcc, sparc_memory_ordering
1510                  add            %sp, PTREGS_OFF, %o1
1511 sys_sigaltstack:ba,pt           %xcc, do_sigaltstack
1512                  add            %i6, STACK_BIAS, %o2
1513 #ifdef CONFIG_COMPAT
1514         .globl  sys32_sigstack
1515 sys32_sigstack: ba,pt           %xcc, do_sys32_sigstack
1516                  mov            %i6, %o2
1517         .globl  sys32_sigaltstack
1518 sys32_sigaltstack:
1519                 ba,pt           %xcc, do_sys32_sigaltstack
1520                  mov            %i6, %o2
1521 #endif
1522                 .align          32
1523 sys_sigsuspend: add             %sp, PTREGS_OFF, %o0
1524                 call            do_sigsuspend
1525                  add            %o7, 1f-.-4, %o7
1526                 nop
1527 sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
1528                 add             %sp, PTREGS_OFF, %o2
1529                 call            do_rt_sigsuspend
1530                  add            %o7, 1f-.-4, %o7
1531                 nop
1532 #ifdef CONFIG_COMPAT
1533         .globl  sys32_rt_sigsuspend
1534 sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
1535                 srl             %o0, 0, %o0
1536                 add             %sp, PTREGS_OFF, %o2
1537                 call            do_rt_sigsuspend32
1538                  add            %o7, 1f-.-4, %o7
1539 #endif
1540                 /* NOTE: %o0 has a correct value already */
1541 sys_sigpause:   add             %sp, PTREGS_OFF, %o1
1542                 call            do_sigpause
1543                  add            %o7, 1f-.-4, %o7
1544                 nop
1545 #ifdef CONFIG_COMPAT
1546         .globl  sys32_sigreturn
1547 sys32_sigreturn:
1548                 add             %sp, PTREGS_OFF, %o0
1549                 call            do_sigreturn32
1550                  add            %o7, 1f-.-4, %o7
1551                 nop
1552 #endif
1553 sys_rt_sigreturn:
1554                 add             %sp, PTREGS_OFF, %o0
1555                 call            do_rt_sigreturn
1556                  add            %o7, 1f-.-4, %o7
1557                 nop
1558 #ifdef CONFIG_COMPAT
1559         .globl  sys32_rt_sigreturn
1560 sys32_rt_sigreturn:
1561                 add             %sp, PTREGS_OFF, %o0
1562                 call            do_rt_sigreturn32
1563                  add            %o7, 1f-.-4, %o7
1564                 nop
1565 #endif
1566 sys_ptrace:     add             %sp, PTREGS_OFF, %o0
1567                 call            do_ptrace
1568                  add            %o7, 1f-.-4, %o7
1569                 nop
1570                 .align          32
1571 1:              ldx             [%curptr + TI_FLAGS], %l5
1572                 andcc           %l5, _TIF_SYSCALL_TRACE, %g0
1573                 be,pt           %icc, rtrap
1574                  clr            %l6
1575                 call            syscall_trace
1576                  nop
1577
1578                 ba,pt           %xcc, rtrap
1579                  clr            %l6
1580
1581         /* This is how fork() was meant to be done, 8 instruction entry.
1582          *
1583          * I questioned the following code briefly, let me clear things
1584          * up so you must not reason on it like I did.
1585          *
1586          * Know the fork_kpsr etc. we use in the sparc32 port?  We don't
1587          * need it here because the only piece of window state we copy to
1588          * the child is the CWP register.  Even if the parent sleeps,
1589          * we are safe because we stuck it into pt_regs of the parent
1590          * so it will not change.
1591          *
1592          * XXX This raises the question, whether we can do the same on
1593          * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim.  The
1594          * XXX answer is yes.  We stick fork_kpsr in UREG_G0 and
1595          * XXX fork_kwim in UREG_G1 (global registers are considered
1596          * XXX volatile across a system call in the sparc ABI I think
1597          * XXX if it isn't we can use regs->y instead, anyone who depends
1598          * XXX upon the Y register being preserved across a fork deserves
1599          * XXX to lose).
1600          *
1601          * In fact we should take advantage of that fact for other things
1602          * during system calls...
1603          */
1604         .globl  sys_fork, sys_vfork, sys_clone, sparc_exit
1605         .globl  ret_from_syscall
1606         .align  32
1607 sys_vfork:      /* Under Linux, vfork and fork are just special cases of clone. */
1608                 sethi           %hi(0x4000 | 0x0100 | SIGCHLD), %o0
1609                 or              %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
1610                 ba,pt           %xcc, sys_clone
1611 sys_fork:        clr            %o1
1612                 mov             SIGCHLD, %o0
1613 sys_clone:      flushw
1614                 movrz           %o1, %fp, %o1
1615                 mov             0, %o3
1616                 ba,pt           %xcc, sparc_do_fork
1617                  add            %sp, PTREGS_OFF, %o2
1618 ret_from_syscall:
1619                 /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in
1620                  * %o7 for us.  Check performance counter stuff too.
1621                  */
1622                 andn            %o7, _TIF_NEWCHILD, %l0
1623                 stx             %l0, [%g6 + TI_FLAGS]
1624                 call            schedule_tail
1625                  mov            %g7, %o0
1626                 andcc           %l0, _TIF_PERFCTR, %g0
1627                 be,pt           %icc, 1f
1628                  nop
1629                 ldx             [%g6 + TI_PCR], %o7
1630                 wr              %g0, %o7, %pcr
1631
1632                 /* Blackbird errata workaround.  See commentary in
1633                  * smp.c:smp_percpu_timer_interrupt() for more
1634                  * information.
1635                  */
1636                 ba,pt           %xcc, 99f
1637                  nop
1638                 .align          64
1639 99:             wr              %g0, %g0, %pic
1640                 rd              %pic, %g0
1641
1642 1:              b,pt            %xcc, ret_sys_call
1643                  ldx            [%sp + PTREGS_OFF + PT_V9_I0], %o0
1644 sparc_exit:     wrpr            %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate
1645                 rdpr            %otherwin, %g1
1646                 rdpr            %cansave, %g3
1647                 add             %g3, %g1, %g3
1648                 wrpr            %g3, 0x0, %cansave
1649                 wrpr            %g0, 0x0, %otherwin
1650                 wrpr            %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
1651                 ba,pt           %xcc, sys_exit
1652                  stb            %g0, [%g6 + TI_WSAVED]
1653
1654 linux_sparc_ni_syscall:
1655         sethi           %hi(sys_ni_syscall), %l7
1656         b,pt            %xcc, 4f
1657          or             %l7, %lo(sys_ni_syscall), %l7
1658
1659 linux_syscall_trace32:
1660         call            syscall_trace
1661          nop
1662         srl             %i0, 0, %o0
1663         mov             %i4, %o4
1664         srl             %i1, 0, %o1
1665         srl             %i2, 0, %o2
1666         b,pt            %xcc, 2f
1667          srl            %i3, 0, %o3
1668
1669 linux_syscall_trace:
1670         call            syscall_trace
1671          nop
1672         mov             %i0, %o0
1673         mov             %i1, %o1
1674         mov             %i2, %o2
1675         mov             %i3, %o3
1676         b,pt            %xcc, 2f
1677          mov            %i4, %o4
1678
1679
1680         /* Linux 32-bit and SunOS system calls enter here... */
1681         .align  32
1682         .globl  linux_sparc_syscall32
1683 linux_sparc_syscall32:
1684         /* Direct access to user regs, much faster. */
1685         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
1686         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
1687          srl            %i0, 0, %o0                             ! IEU0
1688         sll             %g1, 2, %l4                             ! IEU0  Group
1689 #ifdef SYSCALL_TRACING
1690         call            syscall_trace_entry
1691          add            %sp, PTREGS_OFF, %o0
1692         srl             %i0, 0, %o0
1693 #endif
1694         srl             %i4, 0, %o4                             ! IEU1
1695         lduw            [%l7 + %l4], %l7                        ! Load
1696         srl             %i1, 0, %o1                             ! IEU0  Group
1697         ldx             [%curptr + TI_FLAGS], %l0               ! Load
1698
1699         srl             %i5, 0, %o5                             ! IEU1
1700         srl             %i2, 0, %o2                             ! IEU0  Group
1701         andcc           %l0, _TIF_SYSCALL_TRACE, %g0            ! IEU0  Group
1702         bne,pn          %icc, linux_syscall_trace32             ! CTI
1703          mov            %i0, %l5                                ! IEU1
1704         call            %l7                                     ! CTI   Group brk forced
1705          srl            %i3, 0, %o3                             ! IEU0
1706         ba,a,pt         %xcc, 3f
1707
1708         /* Linux native and SunOS system calls enter here... */
1709         .align  32
1710         .globl  linux_sparc_syscall, ret_sys_call
1711 linux_sparc_syscall:
1712         /* Direct access to user regs, much faster. */
1713         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
1714         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
1715          mov            %i0, %o0                                ! IEU0
1716         sll             %g1, 2, %l4                             ! IEU0  Group
1717 #ifdef SYSCALL_TRACING
1718         call            syscall_trace_entry
1719          add            %sp, PTREGS_OFF, %o0
1720         mov             %i0, %o0
1721 #endif
1722         mov             %i1, %o1                                ! IEU1
1723         lduw            [%l7 + %l4], %l7                        ! Load
1724 4:      mov             %i2, %o2                                ! IEU0  Group
1725         ldx             [%curptr + TI_FLAGS], %l0               ! Load
1726
1727         mov             %i3, %o3                                ! IEU1
1728         mov             %i4, %o4                                ! IEU0  Group
1729         andcc           %l0, _TIF_SYSCALL_TRACE, %g0            ! IEU1  Group+1 bubble
1730         bne,pn          %icc, linux_syscall_trace               ! CTI   Group
1731          mov            %i0, %l5                                ! IEU0
1732 2:      call            %l7                                     ! CTI   Group brk forced
1733          mov            %i5, %o5                                ! IEU0
1734         nop
1735
1736 3:      stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1737 ret_sys_call:
1738 #ifdef SYSCALL_TRACING
1739         mov             %o0, %o1
1740         call            syscall_trace_exit
1741          add            %sp, PTREGS_OFF, %o0
1742         mov             %o1, %o0
1743 #endif
1744         ldx             [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
1745         ldx             [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
1746         sra             %o0, 0, %o0
1747         mov             %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
1748         sllx            %g2, 32, %g2
1749
1750         /* Check if force_successful_syscall_return()
1751          * was invoked.
1752          */
1753         ldx             [%curptr + TI_FLAGS], %l0
1754         andcc           %l0, _TIF_SYSCALL_SUCCESS, %g0
1755         be,pt           %icc, 1f
1756          andn           %l0, _TIF_SYSCALL_SUCCESS, %l0
1757         ba,pt           %xcc, 80f
1758          stx            %l0, [%curptr + TI_FLAGS]
1759
1760 1:
1761         cmp             %o0, -ERESTART_RESTARTBLOCK
1762         bgeu,pn         %xcc, 1f
1763          andcc          %l0, _TIF_SYSCALL_TRACE, %l6    
1764 80:
1765         /* System call success, clear Carry condition code. */
1766         andn            %g3, %g2, %g3
1767         stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]  
1768         bne,pn          %icc, linux_syscall_trace2
1769          add            %l1, 0x4, %l2                   ! npc = npc+4
1770         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1771         ba,pt           %xcc, rtrap_clr_l6
1772          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1773
1774 1:
1775         /* System call failure, set Carry condition code.
1776          * Also, get abs(errno) to return to the process.
1777          */
1778         andcc           %l0, _TIF_SYSCALL_TRACE, %l6    
1779         sub             %g0, %o0, %o0
1780         or              %g3, %g2, %g3
1781         stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1782         mov             1, %l6
1783         stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
1784         bne,pn          %icc, linux_syscall_trace2
1785          add            %l1, 0x4, %l2                   ! npc = npc+4
1786         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1787
1788         b,pt            %xcc, rtrap
1789          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1790 linux_syscall_trace2:
1791         call            syscall_trace
1792          nop
1793         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1794         ba,pt           %xcc, rtrap
1795          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1796
1797         .align          32
1798         .globl          __flushw_user
1799 __flushw_user:
1800         rdpr            %otherwin, %g1
1801         brz,pn          %g1, 2f
1802          clr            %g2
1803 1:      save            %sp, -128, %sp
1804         rdpr            %otherwin, %g1
1805         brnz,pt         %g1, 1b
1806          add            %g2, 1, %g2
1807 1:      sub             %g2, 1, %g2
1808         brnz,pt         %g2, 1b
1809          restore        %g0, %g0, %g0
1810 2:      retl
1811          nop