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