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