[SPARC64]: Fix trap state reading for instruction_access_exception.
[firewire-audio.git] / arch / sparc64 / kernel / entry.S
blob6d0476ff4ff879eeb1c76e32ba5ac97baab6456f
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  */
10 #include <linux/config.h>
11 #include <linux/errno.h>
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>
25 #define curptr      g6
27 #define NR_SYSCALLS 284      /* Each OS is different... */
29         .text
30         .align          32
32         .globl          sparc64_vpte_patchme1
33         .globl          sparc64_vpte_patchme2
35  * On a second level vpte miss, check whether the original fault is to the OBP 
36  * range (note that this is only possible for instruction miss, data misses to
37  * obp range do not use vpte). If so, go back directly to the faulting address.
38  * This is because we want to read the tpc, otherwise we have no way of knowing
39  * the 8k aligned faulting address if we are using >8k kernel pagesize. This
40  * also ensures no vpte range addresses are dropped into tlb while obp is
41  * executing (see inherit_locked_prom_mappings() rant).
42  */
43 sparc64_vpte_nucleus:
44         /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
45         mov             0xf, %g5
46         sllx            %g5, 28, %g5
48         /* Is addr >= LOW_OBP_ADDRESS?  */
49         cmp             %g4, %g5
50         blu,pn          %xcc, sparc64_vpte_patchme1
51          mov            0x1, %g5
53         /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
54         sllx            %g5, 32, %g5
56         /* Is addr < HI_OBP_ADDRESS?  */
57         cmp             %g4, %g5
58         blu,pn          %xcc, obp_iaddr_patch
59          nop
61         /* These two instructions are patched by paginig_init().  */
62 sparc64_vpte_patchme1:
63         sethi           %hi(0), %g5
64 sparc64_vpte_patchme2:
65         or              %g5, %lo(0), %g5
67         /* With kernel PGD in %g5, branch back into dtlb_backend.  */
68         ba,pt           %xcc, sparc64_kpte_continue
69          andn           %g1, 0x3, %g1   /* Finish PMD offset adjustment.  */
71 vpte_noent:
72         /* Restore previous TAG_ACCESS, %g5 is zero, and we will
73          * skip over the trap instruction so that the top level
74          * TLB miss handler will thing this %g5 value is just an
75          * invalid PTE, thus branching to full fault processing.
76          */
77         mov             TLB_SFSR, %g1
78         stxa            %g4, [%g1 + %g1] ASI_DMMU
79         done
81         .globl          obp_iaddr_patch
82 obp_iaddr_patch:
83         /* These two instructions patched by inherit_prom_mappings().  */
84         sethi           %hi(0), %g5
85         or              %g5, %lo(0), %g5
87         /* Behave as if we are at TL0.  */
88         wrpr            %g0, 1, %tl
89         rdpr            %tpc, %g4       /* Find original faulting iaddr */
90         srlx            %g4, 13, %g4    /* Throw out context bits */
91         sllx            %g4, 13, %g4    /* g4 has vpn + ctx0 now */
93         /* Restore previous TAG_ACCESS.  */
94         mov             TLB_SFSR, %g1
95         stxa            %g4, [%g1 + %g1] ASI_IMMU
97         /* Get PMD offset.  */
98         srlx            %g4, 23, %g6
99         and             %g6, 0x7ff, %g6
100         sllx            %g6, 2, %g6
102         /* Load PMD, is it valid?  */
103         lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
104         brz,pn          %g5, longpath
105          sllx           %g5, 11, %g5
107         /* Get PTE offset.  */
108         srlx            %g4, 13, %g6
109         and             %g6, 0x3ff, %g6
110         sllx            %g6, 3, %g6
112         /* Load PTE.  */
113         ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
114         brgez,pn        %g5, longpath
115          nop
117         /* TLB load and return from trap.  */
118         stxa            %g5, [%g0] ASI_ITLB_DATA_IN
119         retry
121         .globl          obp_daddr_patch
122 obp_daddr_patch:
123         /* These two instructions patched by inherit_prom_mappings().  */
124         sethi           %hi(0), %g5
125         or              %g5, %lo(0), %g5
127         /* Get PMD offset.  */
128         srlx            %g4, 23, %g6
129         and             %g6, 0x7ff, %g6
130         sllx            %g6, 2, %g6
132         /* Load PMD, is it valid?  */
133         lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
134         brz,pn          %g5, longpath
135          sllx           %g5, 11, %g5
137         /* Get PTE offset.  */
138         srlx            %g4, 13, %g6
139         and             %g6, 0x3ff, %g6
140         sllx            %g6, 3, %g6
142         /* Load PTE.  */
143         ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
144         brgez,pn        %g5, longpath
145          nop
147         /* TLB load and return from trap.  */
148         stxa            %g5, [%g0] ASI_DTLB_DATA_IN
149         retry
152  * On a first level data miss, check whether this is to the OBP range (note
153  * that such accesses can be made by prom, as well as by kernel using
154  * prom_getproperty on "address"), and if so, do not use vpte access ...
155  * rather, use information saved during inherit_prom_mappings() using 8k
156  * pagesize.
157  */
158 kvmap:
159         /* Load 0xf0000000, which is LOW_OBP_ADDRESS.  */
160         mov             0xf, %g5
161         sllx            %g5, 28, %g5
163         /* Is addr >= LOW_OBP_ADDRESS?  */
164         cmp             %g4, %g5
165         blu,pn          %xcc, vmalloc_addr
166          mov            0x1, %g5
168         /* Load 0x100000000, which is HI_OBP_ADDRESS.  */
169         sllx            %g5, 32, %g5
171         /* Is addr < HI_OBP_ADDRESS?  */
172         cmp             %g4, %g5
173         blu,pn          %xcc, obp_daddr_patch
174          nop
176 vmalloc_addr:
177         /* If we get here, a vmalloc addr accessed, load kernel VPTE.  */
178         ldxa            [%g3 + %g6] ASI_N, %g5
179         brgez,pn        %g5, longpath
180          nop
182         /* PTE is valid, load into TLB and return from trap.  */
183         stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
184         retry
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
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
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
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
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
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
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
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
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
458 fitos_emul_fini:
459         ldd             [%g6 + TI_FPREGS + (62 * 4)], %f62
460         done
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
497 cplus_fptrap_1:
498         sethi           %hi(CTX_CHEETAH_PLUS_CTX0), %g2
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
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
521         retl
522          nop
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
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
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
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
576         .align          32
577 1:      jmpl            %g3, %g0
578          nop
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
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
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]
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
687         /* XXX Here is stuff we still need to write... -DaveM XXX */
688         .globl          netbsd_syscall
689 netbsd_syscall:
690         retl
691          nop
693         .globl          __do_data_access_exception
694         .globl          __do_data_access_exception_tl1
695 __do_data_access_exception_tl1:
696         rdpr            %pstate, %g4
697         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
698         mov             TLB_SFSR, %g3
699         mov             DMMU_SFAR, %g5
700         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
701         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
702         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
703         membar          #Sync
704         ba,pt           %xcc, winfix_dax
705          rdpr           %tpc, %g3
706 __do_data_access_exception:
707         rdpr            %pstate, %g4
708         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
709         mov             TLB_SFSR, %g3
710         mov             DMMU_SFAR, %g5
711         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
712         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
713         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
714         membar          #Sync
715         sethi           %hi(109f), %g7
716         ba,pt           %xcc, etrap
717 109:     or             %g7, %lo(109b), %g7
718         mov             %l4, %o1
719         mov             %l5, %o2
720         call            data_access_exception
721          add            %sp, PTREGS_OFF, %o0
722         ba,pt           %xcc, rtrap
723          clr            %l6
725         .globl          __do_instruction_access_exception
726         .globl          __do_instruction_access_exception_tl1
727 __do_instruction_access_exception_tl1:
728         rdpr            %pstate, %g4
729         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
730         mov             TLB_SFSR, %g3
731         ldxa            [%g3] ASI_IMMU, %g4     ! Get SFSR
732         rdpr            %tpc, %g5               ! IMMU has no SFAR, use TPC
733         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
734         membar          #Sync
735         sethi           %hi(109f), %g7
736         ba,pt           %xcc, etraptl1
737 109:     or             %g7, %lo(109b), %g7
738         mov             %l4, %o1
739         mov             %l5, %o2
740         call            instruction_access_exception_tl1
741          add            %sp, PTREGS_OFF, %o0
742         ba,pt           %xcc, rtrap
743          clr            %l6
745 __do_instruction_access_exception:
746         rdpr            %pstate, %g4
747         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
748         mov             TLB_SFSR, %g3
749         ldxa            [%g3] ASI_IMMU, %g4     ! Get SFSR
750         rdpr            %tpc, %g5               ! IMMU has no SFAR, use TPC
751         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
752         membar          #Sync
753         sethi           %hi(109f), %g7
754         ba,pt           %xcc, etrap
755 109:     or             %g7, %lo(109b), %g7
756         mov             %l4, %o1
757         mov             %l5, %o2
758         call            instruction_access_exception
759          add            %sp, PTREGS_OFF, %o0
760         ba,pt           %xcc, rtrap
761          clr            %l6
763         /* This is the trap handler entry point for ECC correctable
764          * errors.  They are corrected, but we listen for the trap
765          * so that the event can be logged.
766          *
767          * Disrupting errors are either:
768          * 1) single-bit ECC errors during UDB reads to system
769          *    memory
770          * 2) data parity errors during write-back events
771          *
772          * As far as I can make out from the manual, the CEE trap
773          * is only for correctable errors during memory read
774          * accesses by the front-end of the processor.
775          *
776          * The code below is only for trap level 1 CEE events,
777          * as it is the only situation where we can safely record
778          * and log.  For trap level >1 we just clear the CE bit
779          * in the AFSR and return.
780          */
782         /* Our trap handling infrastructure allows us to preserve
783          * two 64-bit values during etrap for arguments to
784          * subsequent C code.  Therefore we encode the information
785          * as follows:
786          *
787          * value 1) Full 64-bits of AFAR
788          * value 2) Low 33-bits of AFSR, then bits 33-->42
789          *          are UDBL error status and bits 43-->52
790          *          are UDBH error status
791          */
792         .align  64
793         .globl  cee_trap
794 cee_trap:
795         ldxa    [%g0] ASI_AFSR, %g1             ! Read AFSR
796         ldxa    [%g0] ASI_AFAR, %g2             ! Read AFAR
797         sllx    %g1, 31, %g1                    ! Clear reserved bits
798         srlx    %g1, 31, %g1                    ! in AFSR
800         /* NOTE: UltraSparc-I/II have high and low UDB error
801          *       registers, corresponding to the two UDB units
802          *       present on those chips.  UltraSparc-IIi only
803          *       has a single UDB, called "SDB" in the manual.
804          *       For IIi the upper UDB register always reads
805          *       as zero so for our purposes things will just
806          *       work with the checks below.
807          */
808         ldxa    [%g0] ASI_UDBL_ERROR_R, %g3     ! Read UDB-Low error status
809         andcc   %g3, (1 << 8), %g4              ! Check CE bit
810         sllx    %g3, (64 - 10), %g3             ! Clear reserved bits
811         srlx    %g3, (64 - 10), %g3             ! in UDB-Low error status
813         sllx    %g3, (33 + 0), %g3              ! Shift up to encoding area
814         or      %g1, %g3, %g1                   ! Or it in
815         be,pn   %xcc, 1f                        ! Branch if CE bit was clear
816          nop
817         stxa    %g4, [%g0] ASI_UDB_ERROR_W      ! Clear CE sticky bit in UDBL
818         membar  #Sync                           ! Synchronize ASI stores
819 1:      mov     0x18, %g5                       ! Addr of UDB-High error status
820         ldxa    [%g5] ASI_UDBH_ERROR_R, %g3     ! Read it
822         andcc   %g3, (1 << 8), %g4              ! Check CE bit
823         sllx    %g3, (64 - 10), %g3             ! Clear reserved bits
824         srlx    %g3, (64 - 10), %g3             ! in UDB-High error status
825         sllx    %g3, (33 + 10), %g3             ! Shift up to encoding area
826         or      %g1, %g3, %g1                   ! Or it in
827         be,pn   %xcc, 1f                        ! Branch if CE bit was clear
828          nop
829         nop
831         stxa    %g4, [%g5] ASI_UDB_ERROR_W      ! Clear CE sticky bit in UDBH
832         membar  #Sync                           ! Synchronize ASI stores
833 1:      mov     1, %g5                          ! AFSR CE bit is
834         sllx    %g5, 20, %g5                    ! bit 20
835         stxa    %g5, [%g0] ASI_AFSR             ! Clear CE sticky bit in AFSR
836         membar  #Sync                           ! Synchronize ASI stores
837         sllx    %g2, (64 - 41), %g2             ! Clear reserved bits
838         srlx    %g2, (64 - 41), %g2             ! in latched AFAR
840         andn    %g2, 0x0f, %g2                  ! Finish resv bit clearing
841         mov     %g1, %g4                        ! Move AFSR+UDB* into save reg
842         mov     %g2, %g5                        ! Move AFAR into save reg
843         rdpr    %pil, %g2
844         wrpr    %g0, 15, %pil
845         ba,pt   %xcc, etrap_irq
846          rd     %pc, %g7
847         mov     %l4, %o0
849         mov     %l5, %o1
850         call    cee_log
851          add    %sp, PTREGS_OFF, %o2
852         ba,a,pt %xcc, rtrap_irq
854         /* Capture I/D/E-cache state into per-cpu error scoreboard.
855          *
856          * %g1:         (TL>=0) ? 1 : 0
857          * %g2:         scratch
858          * %g3:         scratch
859          * %g4:         AFSR
860          * %g5:         AFAR
861          * %g6:         current thread ptr
862          * %g7:         scratch
863          */
864 #define CHEETAH_LOG_ERROR                                               \
865         /* Put "TL1" software bit into AFSR. */                         \
866         and             %g1, 0x1, %g1;                                  \
867         sllx            %g1, 63, %g2;                                   \
868         or              %g4, %g2, %g4;                                  \
869         /* Get log entry pointer for this cpu at this trap level. */    \
870         BRANCH_IF_JALAPENO(g2,g3,50f)                                   \
871         ldxa            [%g0] ASI_SAFARI_CONFIG, %g2;                   \
872         srlx            %g2, 17, %g2;                                   \
873         ba,pt           %xcc, 60f;                                      \
874          and            %g2, 0x3ff, %g2;                                \
875 50:     ldxa            [%g0] ASI_JBUS_CONFIG, %g2;                     \
876         srlx            %g2, 17, %g2;                                   \
877         and             %g2, 0x1f, %g2;                                 \
878 60:     sllx            %g2, 9, %g2;                                    \
879         sethi           %hi(cheetah_error_log), %g3;                    \
880         ldx             [%g3 + %lo(cheetah_error_log)], %g3;            \
881         brz,pn          %g3, 80f;                                       \
882          nop;                                                           \
883         add             %g3, %g2, %g3;                                  \
884         sllx            %g1, 8, %g1;                                    \
885         add             %g3, %g1, %g1;                                  \
886         /* %g1 holds pointer to the top of the logging scoreboard */    \
887         ldx             [%g1 + 0x0], %g7;                               \
888         cmp             %g7, -1;                                        \
889         bne,pn          %xcc, 80f;                                      \
890          nop;                                                           \
891         stx             %g4, [%g1 + 0x0];                               \
892         stx             %g5, [%g1 + 0x8];                               \
893         add             %g1, 0x10, %g1;                                 \
894         /* %g1 now points to D-cache logging area */                    \
895         set             0x3ff8, %g2;    /* DC_addr mask         */      \
896         and             %g5, %g2, %g2;  /* DC_addr bits of AFAR */      \
897         srlx            %g5, 12, %g3;                                   \
898         or              %g3, 1, %g3;    /* PHYS tag + valid     */      \
899 10:     ldxa            [%g2] ASI_DCACHE_TAG, %g7;                      \
900         cmp             %g3, %g7;       /* TAG match?           */      \
901         bne,pt          %xcc, 13f;                                      \
902          nop;                                                           \
903         /* Yep, what we want, capture state. */                         \
904         stx             %g2, [%g1 + 0x20];                              \
905         stx             %g7, [%g1 + 0x28];                              \
906         /* A membar Sync is required before and after utag access. */   \
907         membar          #Sync;                                          \
908         ldxa            [%g2] ASI_DCACHE_UTAG, %g7;                     \
909         membar          #Sync;                                          \
910         stx             %g7, [%g1 + 0x30];                              \
911         ldxa            [%g2] ASI_DCACHE_SNOOP_TAG, %g7;                \
912         stx             %g7, [%g1 + 0x38];                              \
913         clr             %g3;                                            \
914 12:     ldxa            [%g2 + %g3] ASI_DCACHE_DATA, %g7;               \
915         stx             %g7, [%g1];                                     \
916         add             %g3, (1 << 5), %g3;                             \
917         cmp             %g3, (4 << 5);                                  \
918         bl,pt           %xcc, 12b;                                      \
919          add            %g1, 0x8, %g1;                                  \
920         ba,pt           %xcc, 20f;                                      \
921          add            %g1, 0x20, %g1;                                 \
922 13:     sethi           %hi(1 << 14), %g7;                              \
923         add             %g2, %g7, %g2;                                  \
924         srlx            %g2, 14, %g7;                                   \
925         cmp             %g7, 4;                                         \
926         bl,pt           %xcc, 10b;                                      \
927          nop;                                                           \
928         add             %g1, 0x40, %g1;                                 \
929 20:     /* %g1 now points to I-cache logging area */                    \
930         set             0x1fe0, %g2;    /* IC_addr mask         */      \
931         and             %g5, %g2, %g2;  /* IC_addr bits of AFAR */      \
932         sllx            %g2, 1, %g2;    /* IC_addr[13:6]==VA[12:5] */   \
933         srlx            %g5, (13 - 8), %g3; /* Make PTAG */             \
934         andn            %g3, 0xff, %g3; /* Mask off undefined bits */   \
935 21:     ldxa            [%g2] ASI_IC_TAG, %g7;                          \
936         andn            %g7, 0xff, %g7;                                 \
937         cmp             %g3, %g7;                                       \
938         bne,pt          %xcc, 23f;                                      \
939          nop;                                                           \
940         /* Yep, what we want, capture state. */                         \
941         stx             %g2, [%g1 + 0x40];                              \
942         stx             %g7, [%g1 + 0x48];                              \
943         add             %g2, (1 << 3), %g2;                             \
944         ldxa            [%g2] ASI_IC_TAG, %g7;                          \
945         add             %g2, (1 << 3), %g2;                             \
946         stx             %g7, [%g1 + 0x50];                              \
947         ldxa            [%g2] ASI_IC_TAG, %g7;                          \
948         add             %g2, (1 << 3), %g2;                             \
949         stx             %g7, [%g1 + 0x60];                              \
950         ldxa            [%g2] ASI_IC_TAG, %g7;                          \
951         stx             %g7, [%g1 + 0x68];                              \
952         sub             %g2, (3 << 3), %g2;                             \
953         ldxa            [%g2] ASI_IC_STAG, %g7;                         \
954         stx             %g7, [%g1 + 0x58];                              \
955         clr             %g3;                                            \
956         srlx            %g2, 2, %g2;                                    \
957 22:     ldxa            [%g2 + %g3] ASI_IC_INSTR, %g7;                  \
958         stx             %g7, [%g1];                                     \
959         add             %g3, (1 << 3), %g3;                             \
960         cmp             %g3, (8 << 3);                                  \
961         bl,pt           %xcc, 22b;                                      \
962          add            %g1, 0x8, %g1;                                  \
963         ba,pt           %xcc, 30f;                                      \
964          add            %g1, 0x30, %g1;                                 \
965 23:     sethi           %hi(1 << 14), %g7;                              \
966         add             %g2, %g7, %g2;                                  \
967         srlx            %g2, 14, %g7;                                   \
968         cmp             %g7, 4;                                         \
969         bl,pt           %xcc, 21b;                                      \
970          nop;                                                           \
971         add             %g1, 0x70, %g1;                                 \
972 30:     /* %g1 now points to E-cache logging area */                    \
973         andn            %g5, (32 - 1), %g2;     /* E-cache subblock */  \
974         stx             %g2, [%g1 + 0x20];                              \
975         ldxa            [%g2] ASI_EC_TAG_DATA, %g7;                     \
976         stx             %g7, [%g1 + 0x28];                              \
977         ldxa            [%g2] ASI_EC_R, %g0;                            \
978         clr             %g3;                                            \
979 31:     ldxa            [%g3] ASI_EC_DATA, %g7;                         \
980         stx             %g7, [%g1 + %g3];                               \
981         add             %g3, 0x8, %g3;                                  \
982         cmp             %g3, 0x20;                                      \
983         bl,pt           %xcc, 31b;                                      \
984          nop;                                                           \
985 80:     /* DONE */
987         /* These get patched into the trap table at boot time
988          * once we know we have a cheetah processor.
989          */
990         .globl          cheetah_fecc_trap_vector, cheetah_fecc_trap_vector_tl1
991 cheetah_fecc_trap_vector:
992         membar          #Sync
993         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
994         andn            %g1, DCU_DC | DCU_IC, %g1
995         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
996         membar          #Sync
997         sethi           %hi(cheetah_fast_ecc), %g2
998         jmpl            %g2 + %lo(cheetah_fast_ecc), %g0
999          mov            0, %g1
1000 cheetah_fecc_trap_vector_tl1:
1001         membar          #Sync
1002         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1003         andn            %g1, DCU_DC | DCU_IC, %g1
1004         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1005         membar          #Sync
1006         sethi           %hi(cheetah_fast_ecc), %g2
1007         jmpl            %g2 + %lo(cheetah_fast_ecc), %g0
1008          mov            1, %g1
1009         .globl  cheetah_cee_trap_vector, cheetah_cee_trap_vector_tl1
1010 cheetah_cee_trap_vector:
1011         membar          #Sync
1012         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1013         andn            %g1, DCU_IC, %g1
1014         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1015         membar          #Sync
1016         sethi           %hi(cheetah_cee), %g2
1017         jmpl            %g2 + %lo(cheetah_cee), %g0
1018          mov            0, %g1
1019 cheetah_cee_trap_vector_tl1:
1020         membar          #Sync
1021         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1022         andn            %g1, DCU_IC, %g1
1023         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1024         membar          #Sync
1025         sethi           %hi(cheetah_cee), %g2
1026         jmpl            %g2 + %lo(cheetah_cee), %g0
1027          mov            1, %g1
1028         .globl  cheetah_deferred_trap_vector, cheetah_deferred_trap_vector_tl1
1029 cheetah_deferred_trap_vector:
1030         membar          #Sync
1031         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1;
1032         andn            %g1, DCU_DC | DCU_IC, %g1;
1033         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG;
1034         membar          #Sync;
1035         sethi           %hi(cheetah_deferred_trap), %g2
1036         jmpl            %g2 + %lo(cheetah_deferred_trap), %g0
1037          mov            0, %g1
1038 cheetah_deferred_trap_vector_tl1:
1039         membar          #Sync;
1040         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1;
1041         andn            %g1, DCU_DC | DCU_IC, %g1;
1042         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG;
1043         membar          #Sync;
1044         sethi           %hi(cheetah_deferred_trap), %g2
1045         jmpl            %g2 + %lo(cheetah_deferred_trap), %g0
1046          mov            1, %g1
1048         /* Cheetah+ specific traps. These are for the new I/D cache parity
1049          * error traps.  The first argument to cheetah_plus_parity_handler
1050          * is encoded as follows:
1051          *
1052          * Bit0:        0=dcache,1=icache
1053          * Bit1:        0=recoverable,1=unrecoverable
1054          */
1055         .globl          cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1
1056 cheetah_plus_dcpe_trap_vector:
1057         membar          #Sync
1058         sethi           %hi(do_cheetah_plus_data_parity), %g7
1059         jmpl            %g7 + %lo(do_cheetah_plus_data_parity), %g0
1060          nop
1061         nop
1062         nop
1063         nop
1064         nop
1066 do_cheetah_plus_data_parity:
1067         ba,pt           %xcc, etrap
1068          rd             %pc, %g7
1069         mov             0x0, %o0
1070         call            cheetah_plus_parity_error
1071          add            %sp, PTREGS_OFF, %o1
1072         ba,pt           %xcc, rtrap
1073          clr            %l6
1075 cheetah_plus_dcpe_trap_vector_tl1:
1076         membar          #Sync
1077         wrpr            PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
1078         sethi           %hi(do_dcpe_tl1), %g3
1079         jmpl            %g3 + %lo(do_dcpe_tl1), %g0
1080          nop
1081         nop
1082         nop
1083         nop
1085         .globl          cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1
1086 cheetah_plus_icpe_trap_vector:
1087         membar          #Sync
1088         sethi           %hi(do_cheetah_plus_insn_parity), %g7
1089         jmpl            %g7 + %lo(do_cheetah_plus_insn_parity), %g0
1090          nop
1091         nop
1092         nop
1093         nop
1094         nop
1096 do_cheetah_plus_insn_parity:
1097         ba,pt           %xcc, etrap
1098          rd             %pc, %g7
1099         mov             0x1, %o0
1100         call            cheetah_plus_parity_error
1101          add            %sp, PTREGS_OFF, %o1
1102         ba,pt           %xcc, rtrap
1103          clr            %l6
1105 cheetah_plus_icpe_trap_vector_tl1:
1106         membar          #Sync
1107         wrpr            PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
1108         sethi           %hi(do_icpe_tl1), %g3
1109         jmpl            %g3 + %lo(do_icpe_tl1), %g0
1110          nop
1111         nop
1112         nop
1113         nop
1115         /* If we take one of these traps when tl >= 1, then we
1116          * jump to interrupt globals.  If some trap level above us
1117          * was also using interrupt globals, we cannot recover.
1118          * We may use all interrupt global registers except %g6.
1119          */
1120         .globl          do_dcpe_tl1, do_icpe_tl1
1121 do_dcpe_tl1:
1122         rdpr            %tl, %g1                ! Save original trap level
1123         mov             1, %g2                  ! Setup TSTATE checking loop
1124         sethi           %hi(TSTATE_IG), %g3     ! TSTATE mask bit
1125 1:      wrpr            %g2, %tl                ! Set trap level to check
1126         rdpr            %tstate, %g4            ! Read TSTATE for this level
1127         andcc           %g4, %g3, %g0           ! Interrupt globals in use?
1128         bne,a,pn        %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
1129          wrpr           %g1, %tl                ! Restore original trap level
1130         add             %g2, 1, %g2             ! Next trap level
1131         cmp             %g2, %g1                ! Hit them all yet?
1132         ble,pt          %icc, 1b                ! Not yet
1133          nop
1134         wrpr            %g1, %tl                ! Restore original trap level
1135 do_dcpe_tl1_nonfatal:   /* Ok we may use interrupt globals safely. */
1136         /* Reset D-cache parity */
1137         sethi           %hi(1 << 16), %g1       ! D-cache size
1138         mov             (1 << 5), %g2           ! D-cache line size
1139         sub             %g1, %g2, %g1           ! Move down 1 cacheline
1140 1:      srl             %g1, 14, %g3            ! Compute UTAG
1141         membar          #Sync
1142         stxa            %g3, [%g1] ASI_DCACHE_UTAG
1143         membar          #Sync
1144         sub             %g2, 8, %g3             ! 64-bit data word within line
1145 2:      membar          #Sync
1146         stxa            %g0, [%g1 + %g3] ASI_DCACHE_DATA
1147         membar          #Sync
1148         subcc           %g3, 8, %g3             ! Next 64-bit data word
1149         bge,pt          %icc, 2b
1150          nop
1151         subcc           %g1, %g2, %g1           ! Next cacheline
1152         bge,pt          %icc, 1b
1153          nop
1154         ba,pt           %xcc, dcpe_icpe_tl1_common
1155          nop
1157 do_dcpe_tl1_fatal:
1158         sethi           %hi(1f), %g7
1159         ba,pt           %xcc, etraptl1
1160 1:      or              %g7, %lo(1b), %g7
1161         mov             0x2, %o0
1162         call            cheetah_plus_parity_error
1163          add            %sp, PTREGS_OFF, %o1
1164         ba,pt           %xcc, rtrap
1165          clr            %l6
1167 do_icpe_tl1:
1168         rdpr            %tl, %g1                ! Save original trap level
1169         mov             1, %g2                  ! Setup TSTATE checking loop
1170         sethi           %hi(TSTATE_IG), %g3     ! TSTATE mask bit
1171 1:      wrpr            %g2, %tl                ! Set trap level to check
1172         rdpr            %tstate, %g4            ! Read TSTATE for this level
1173         andcc           %g4, %g3, %g0           ! Interrupt globals in use?
1174         bne,a,pn        %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
1175          wrpr           %g1, %tl                ! Restore original trap level
1176         add             %g2, 1, %g2             ! Next trap level
1177         cmp             %g2, %g1                ! Hit them all yet?
1178         ble,pt          %icc, 1b                ! Not yet
1179          nop
1180         wrpr            %g1, %tl                ! Restore original trap level
1181 do_icpe_tl1_nonfatal:   /* Ok we may use interrupt globals safely. */
1182         /* Flush I-cache */
1183         sethi           %hi(1 << 15), %g1       ! I-cache size
1184         mov             (1 << 5), %g2           ! I-cache line size
1185         sub             %g1, %g2, %g1
1186 1:      or              %g1, (2 << 3), %g3
1187         stxa            %g0, [%g3] ASI_IC_TAG
1188         membar          #Sync
1189         subcc           %g1, %g2, %g1
1190         bge,pt          %icc, 1b
1191          nop
1192         ba,pt           %xcc, dcpe_icpe_tl1_common
1193          nop
1195 do_icpe_tl1_fatal:
1196         sethi           %hi(1f), %g7
1197         ba,pt           %xcc, etraptl1
1198 1:      or              %g7, %lo(1b), %g7
1199         mov             0x3, %o0
1200         call            cheetah_plus_parity_error
1201          add            %sp, PTREGS_OFF, %o1
1202         ba,pt           %xcc, rtrap
1203          clr            %l6
1204         
1205 dcpe_icpe_tl1_common:
1206         /* Flush D-cache, re-enable D/I caches in DCU and finally
1207          * retry the trapping instruction.
1208          */
1209         sethi           %hi(1 << 16), %g1       ! D-cache size
1210         mov             (1 << 5), %g2           ! D-cache line size
1211         sub             %g1, %g2, %g1
1212 1:      stxa            %g0, [%g1] ASI_DCACHE_TAG
1213         membar          #Sync
1214         subcc           %g1, %g2, %g1
1215         bge,pt          %icc, 1b
1216          nop
1217         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
1218         or              %g1, (DCU_DC | DCU_IC), %g1
1219         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
1220         membar          #Sync
1221         retry
1223         /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
1224          * in the trap table.  That code has done a memory barrier
1225          * and has disabled both the I-cache and D-cache in the DCU
1226          * control register.  The I-cache is disabled so that we may
1227          * capture the corrupted cache line, and the D-cache is disabled
1228          * because corrupt data may have been placed there and we don't
1229          * want to reference it.
1230          *
1231          * %g1 is one if this trap occurred at %tl >= 1.
1232          *
1233          * Next, we turn off error reporting so that we don't recurse.
1234          */
1235         .globl          cheetah_fast_ecc
1236 cheetah_fast_ecc:
1237         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1238         andn            %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
1239         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1240         membar          #Sync
1242         /* Fetch and clear AFSR/AFAR */
1243         ldxa            [%g0] ASI_AFSR, %g4
1244         ldxa            [%g0] ASI_AFAR, %g5
1245         stxa            %g4, [%g0] ASI_AFSR
1246         membar          #Sync
1248         CHEETAH_LOG_ERROR
1250         rdpr            %pil, %g2
1251         wrpr            %g0, 15, %pil
1252         ba,pt           %xcc, etrap_irq
1253          rd             %pc, %g7
1254         mov             %l4, %o1
1255         mov             %l5, %o2
1256         call            cheetah_fecc_handler
1257          add            %sp, PTREGS_OFF, %o0
1258         ba,a,pt         %xcc, rtrap_irq
1260         /* Our caller has disabled I-cache and performed membar Sync. */
1261         .globl          cheetah_cee
1262 cheetah_cee:
1263         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1264         andn            %g2, ESTATE_ERROR_CEEN, %g2
1265         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1266         membar          #Sync
1268         /* Fetch and clear AFSR/AFAR */
1269         ldxa            [%g0] ASI_AFSR, %g4
1270         ldxa            [%g0] ASI_AFAR, %g5
1271         stxa            %g4, [%g0] ASI_AFSR
1272         membar          #Sync
1274         CHEETAH_LOG_ERROR
1276         rdpr            %pil, %g2
1277         wrpr            %g0, 15, %pil
1278         ba,pt           %xcc, etrap_irq
1279          rd             %pc, %g7
1280         mov             %l4, %o1
1281         mov             %l5, %o2
1282         call            cheetah_cee_handler
1283          add            %sp, PTREGS_OFF, %o0
1284         ba,a,pt         %xcc, rtrap_irq
1286         /* Our caller has disabled I-cache+D-cache and performed membar Sync. */
1287         .globl          cheetah_deferred_trap
1288 cheetah_deferred_trap:
1289         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1290         andn            %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
1291         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1292         membar          #Sync
1294         /* Fetch and clear AFSR/AFAR */
1295         ldxa            [%g0] ASI_AFSR, %g4
1296         ldxa            [%g0] ASI_AFAR, %g5
1297         stxa            %g4, [%g0] ASI_AFSR
1298         membar          #Sync
1300         CHEETAH_LOG_ERROR
1302         rdpr            %pil, %g2
1303         wrpr            %g0, 15, %pil
1304         ba,pt           %xcc, etrap_irq
1305          rd             %pc, %g7
1306         mov             %l4, %o1
1307         mov             %l5, %o2
1308         call            cheetah_deferred_handler
1309          add            %sp, PTREGS_OFF, %o0
1310         ba,a,pt         %xcc, rtrap_irq
1312         .globl          __do_privact
1313 __do_privact:
1314         mov             TLB_SFSR, %g3
1315         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
1316         membar          #Sync
1317         sethi           %hi(109f), %g7
1318         ba,pt           %xcc, etrap
1319 109:    or              %g7, %lo(109b), %g7
1320         call            do_privact
1321          add            %sp, PTREGS_OFF, %o0
1322         ba,pt           %xcc, rtrap
1323          clr            %l6
1325         .globl          do_mna
1326 do_mna:
1327         rdpr            %tl, %g3
1328         cmp             %g3, 1
1330         /* Setup %g4/%g5 now as they are used in the
1331          * winfixup code.
1332          */
1333         mov             TLB_SFSR, %g3
1334         mov             DMMU_SFAR, %g4
1335         ldxa            [%g4] ASI_DMMU, %g4
1336         ldxa            [%g3] ASI_DMMU, %g5
1337         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
1338         membar          #Sync
1339         bgu,pn          %icc, winfix_mna
1340          rdpr           %tpc, %g3
1342 1:      sethi           %hi(109f), %g7
1343         ba,pt           %xcc, etrap
1344 109:     or             %g7, %lo(109b), %g7
1345         mov             %l4, %o1
1346         mov             %l5, %o2
1347         call            mem_address_unaligned
1348          add            %sp, PTREGS_OFF, %o0
1349         ba,pt           %xcc, rtrap
1350          clr            %l6
1352         .globl          do_lddfmna
1353 do_lddfmna:
1354         sethi           %hi(109f), %g7
1355         mov             TLB_SFSR, %g4
1356         ldxa            [%g4] ASI_DMMU, %g5
1357         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
1358         membar          #Sync
1359         mov             DMMU_SFAR, %g4
1360         ldxa            [%g4] ASI_DMMU, %g4
1361         ba,pt           %xcc, etrap
1362 109:     or             %g7, %lo(109b), %g7
1363         mov             %l4, %o1
1364         mov             %l5, %o2
1365         call            handle_lddfmna
1366          add            %sp, PTREGS_OFF, %o0
1367         ba,pt           %xcc, rtrap
1368          clr            %l6
1370         .globl          do_stdfmna
1371 do_stdfmna:
1372         sethi           %hi(109f), %g7
1373         mov             TLB_SFSR, %g4
1374         ldxa            [%g4] ASI_DMMU, %g5
1375         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
1376         membar          #Sync
1377         mov             DMMU_SFAR, %g4
1378         ldxa            [%g4] ASI_DMMU, %g4
1379         ba,pt           %xcc, etrap
1380 109:     or             %g7, %lo(109b), %g7
1381         mov             %l4, %o1
1382         mov             %l5, %o2
1383         call            handle_stdfmna
1384          add            %sp, PTREGS_OFF, %o0
1385         ba,pt           %xcc, rtrap
1386          clr            %l6
1388         .globl  breakpoint_trap
1389 breakpoint_trap:
1390         call            sparc_breakpoint
1391          add            %sp, PTREGS_OFF, %o0
1392         ba,pt           %xcc, rtrap
1393          nop
1395 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
1396     defined(CONFIG_SOLARIS_EMUL_MODULE)
1397         /* SunOS uses syscall zero as the 'indirect syscall' it looks
1398          * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
1399          * This is complete brain damage.
1400          */
1401         .globl  sunos_indir
1402 sunos_indir:
1403         srl             %o0, 0, %o0
1404         mov             %o7, %l4
1405         cmp             %o0, NR_SYSCALLS
1406         blu,a,pt        %icc, 1f
1407          sll            %o0, 0x2, %o0
1408         sethi           %hi(sunos_nosys), %l6
1409         b,pt            %xcc, 2f
1410          or             %l6, %lo(sunos_nosys), %l6
1411 1:      sethi           %hi(sunos_sys_table), %l7
1412         or              %l7, %lo(sunos_sys_table), %l7
1413         lduw            [%l7 + %o0], %l6
1414 2:      mov             %o1, %o0
1415         mov             %o2, %o1
1416         mov             %o3, %o2
1417         mov             %o4, %o3
1418         mov             %o5, %o4
1419         call            %l6
1420          mov            %l4, %o7
1422         .globl  sunos_getpid
1423 sunos_getpid:
1424         call    sys_getppid
1425          nop
1426         call    sys_getpid
1427          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1428         b,pt    %xcc, ret_sys_call
1429          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1431         /* SunOS getuid() returns uid in %o0 and euid in %o1 */
1432         .globl  sunos_getuid
1433 sunos_getuid:
1434         call    sys32_geteuid16
1435          nop
1436         call    sys32_getuid16
1437          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1438         b,pt    %xcc, ret_sys_call
1439          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1441         /* SunOS getgid() returns gid in %o0 and egid in %o1 */
1442         .globl  sunos_getgid
1443 sunos_getgid:
1444         call    sys32_getegid16
1445          nop
1446         call    sys32_getgid16
1447          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1448         b,pt    %xcc, ret_sys_call
1449          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1450 #endif
1452         /* SunOS's execv() call only specifies the argv argument, the
1453          * environment settings are the same as the calling processes.
1454          */
1455         .globl  sunos_execv
1456 sys_execve:
1457         sethi           %hi(sparc_execve), %g1
1458         ba,pt           %xcc, execve_merge
1459          or             %g1, %lo(sparc_execve), %g1
1460 #ifdef CONFIG_COMPAT
1461         .globl  sys_execve
1462 sunos_execv:
1463         stx             %g0, [%sp + PTREGS_OFF + PT_V9_I2]
1464         .globl  sys32_execve
1465 sys32_execve:
1466         sethi           %hi(sparc32_execve), %g1
1467         or              %g1, %lo(sparc32_execve), %g1
1468 #endif
1469 execve_merge:
1470         flushw
1471         jmpl            %g1, %g0
1472          add            %sp, PTREGS_OFF, %o0
1474         .globl  sys_pipe, sys_sigpause, sys_nis_syscall
1475         .globl  sys_sigsuspend, sys_rt_sigsuspend
1476         .globl  sys_rt_sigreturn
1477         .globl  sys_ptrace
1478         .globl  sys_sigaltstack
1479         .align  32
1480 sys_pipe:       ba,pt           %xcc, sparc_pipe
1481                  add            %sp, PTREGS_OFF, %o0
1482 sys_nis_syscall:ba,pt           %xcc, c_sys_nis_syscall
1483                  add            %sp, PTREGS_OFF, %o0
1484 sys_memory_ordering:
1485                 ba,pt           %xcc, sparc_memory_ordering
1486                  add            %sp, PTREGS_OFF, %o1
1487 sys_sigaltstack:ba,pt           %xcc, do_sigaltstack
1488                  add            %i6, STACK_BIAS, %o2
1489 #ifdef CONFIG_COMPAT
1490         .globl  sys32_sigstack
1491 sys32_sigstack: ba,pt           %xcc, do_sys32_sigstack
1492                  mov            %i6, %o2
1493         .globl  sys32_sigaltstack
1494 sys32_sigaltstack:
1495                 ba,pt           %xcc, do_sys32_sigaltstack
1496                  mov            %i6, %o2
1497 #endif
1498                 .align          32
1499 sys_sigsuspend: add             %sp, PTREGS_OFF, %o0
1500                 call            do_sigsuspend
1501                  add            %o7, 1f-.-4, %o7
1502                 nop
1503 sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
1504                 add             %sp, PTREGS_OFF, %o2
1505                 call            do_rt_sigsuspend
1506                  add            %o7, 1f-.-4, %o7
1507                 nop
1508 #ifdef CONFIG_COMPAT
1509         .globl  sys32_rt_sigsuspend
1510 sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
1511                 srl             %o0, 0, %o0
1512                 add             %sp, PTREGS_OFF, %o2
1513                 call            do_rt_sigsuspend32
1514                  add            %o7, 1f-.-4, %o7
1515 #endif
1516                 /* NOTE: %o0 has a correct value already */
1517 sys_sigpause:   add             %sp, PTREGS_OFF, %o1
1518                 call            do_sigpause
1519                  add            %o7, 1f-.-4, %o7
1520                 nop
1521 #ifdef CONFIG_COMPAT
1522         .globl  sys32_sigreturn
1523 sys32_sigreturn:
1524                 add             %sp, PTREGS_OFF, %o0
1525                 call            do_sigreturn32
1526                  add            %o7, 1f-.-4, %o7
1527                 nop
1528 #endif
1529 sys_rt_sigreturn:
1530                 add             %sp, PTREGS_OFF, %o0
1531                 call            do_rt_sigreturn
1532                  add            %o7, 1f-.-4, %o7
1533                 nop
1534 #ifdef CONFIG_COMPAT
1535         .globl  sys32_rt_sigreturn
1536 sys32_rt_sigreturn:
1537                 add             %sp, PTREGS_OFF, %o0
1538                 call            do_rt_sigreturn32
1539                  add            %o7, 1f-.-4, %o7
1540                 nop
1541 #endif
1542 sys_ptrace:     add             %sp, PTREGS_OFF, %o0
1543                 call            do_ptrace
1544                  add            %o7, 1f-.-4, %o7
1545                 nop
1546                 .align          32
1547 1:              ldx             [%curptr + TI_FLAGS], %l5
1548                 andcc           %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
1549                 be,pt           %icc, rtrap
1550                  clr            %l6
1551                 add             %sp, PTREGS_OFF, %o0
1552                 call            syscall_trace
1553                  mov            1, %o1
1555                 ba,pt           %xcc, rtrap
1556                  clr            %l6
1558         /* This is how fork() was meant to be done, 8 instruction entry.
1559          *
1560          * I questioned the following code briefly, let me clear things
1561          * up so you must not reason on it like I did.
1562          *
1563          * Know the fork_kpsr etc. we use in the sparc32 port?  We don't
1564          * need it here because the only piece of window state we copy to
1565          * the child is the CWP register.  Even if the parent sleeps,
1566          * we are safe because we stuck it into pt_regs of the parent
1567          * so it will not change.
1568          *
1569          * XXX This raises the question, whether we can do the same on
1570          * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim.  The
1571          * XXX answer is yes.  We stick fork_kpsr in UREG_G0 and
1572          * XXX fork_kwim in UREG_G1 (global registers are considered
1573          * XXX volatile across a system call in the sparc ABI I think
1574          * XXX if it isn't we can use regs->y instead, anyone who depends
1575          * XXX upon the Y register being preserved across a fork deserves
1576          * XXX to lose).
1577          *
1578          * In fact we should take advantage of that fact for other things
1579          * during system calls...
1580          */
1581         .globl  sys_fork, sys_vfork, sys_clone, sparc_exit
1582         .globl  ret_from_syscall
1583         .align  32
1584 sys_vfork:      /* Under Linux, vfork and fork are just special cases of clone. */
1585                 sethi           %hi(0x4000 | 0x0100 | SIGCHLD), %o0
1586                 or              %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
1587                 ba,pt           %xcc, sys_clone
1588 sys_fork:        clr            %o1
1589                 mov             SIGCHLD, %o0
1590 sys_clone:      flushw
1591                 movrz           %o1, %fp, %o1
1592                 mov             0, %o3
1593                 ba,pt           %xcc, sparc_do_fork
1594                  add            %sp, PTREGS_OFF, %o2
1595 ret_from_syscall:
1596                 /* Clear current_thread_info()->new_child, and
1597                  * check performance counter stuff too.
1598                  */
1599                 stb             %g0, [%g6 + TI_NEW_CHILD]
1600                 ldx             [%g6 + TI_FLAGS], %l0
1601                 call            schedule_tail
1602                  mov            %g7, %o0
1603                 andcc           %l0, _TIF_PERFCTR, %g0
1604                 be,pt           %icc, 1f
1605                  nop
1606                 ldx             [%g6 + TI_PCR], %o7
1607                 wr              %g0, %o7, %pcr
1609                 /* Blackbird errata workaround.  See commentary in
1610                  * smp.c:smp_percpu_timer_interrupt() for more
1611                  * information.
1612                  */
1613                 ba,pt           %xcc, 99f
1614                  nop
1615                 .align          64
1616 99:             wr              %g0, %g0, %pic
1617                 rd              %pic, %g0
1619 1:              b,pt            %xcc, ret_sys_call
1620                  ldx            [%sp + PTREGS_OFF + PT_V9_I0], %o0
1621 sparc_exit:     wrpr            %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate
1622                 rdpr            %otherwin, %g1
1623                 rdpr            %cansave, %g3
1624                 add             %g3, %g1, %g3
1625                 wrpr            %g3, 0x0, %cansave
1626                 wrpr            %g0, 0x0, %otherwin
1627                 wrpr            %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
1628                 ba,pt           %xcc, sys_exit
1629                  stb            %g0, [%g6 + TI_WSAVED]
1631 linux_sparc_ni_syscall:
1632         sethi           %hi(sys_ni_syscall), %l7
1633         b,pt            %xcc, 4f
1634          or             %l7, %lo(sys_ni_syscall), %l7
1636 linux_syscall_trace32:
1637         add             %sp, PTREGS_OFF, %o0
1638         call            syscall_trace
1639          clr            %o1
1640         srl             %i0, 0, %o0
1641         srl             %i4, 0, %o4
1642         srl             %i1, 0, %o1
1643         srl             %i2, 0, %o2
1644         b,pt            %xcc, 2f
1645          srl            %i3, 0, %o3
1647 linux_syscall_trace:
1648         add             %sp, PTREGS_OFF, %o0
1649         call            syscall_trace
1650          clr            %o1
1651         mov             %i0, %o0
1652         mov             %i1, %o1
1653         mov             %i2, %o2
1654         mov             %i3, %o3
1655         b,pt            %xcc, 2f
1656          mov            %i4, %o4
1659         /* Linux 32-bit and SunOS system calls enter here... */
1660         .align  32
1661         .globl  linux_sparc_syscall32
1662 linux_sparc_syscall32:
1663         /* Direct access to user regs, much faster. */
1664         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
1665         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
1666          srl            %i0, 0, %o0                             ! IEU0
1667         sll             %g1, 2, %l4                             ! IEU0  Group
1668         srl             %i4, 0, %o4                             ! IEU1
1669         lduw            [%l7 + %l4], %l7                        ! Load
1670         srl             %i1, 0, %o1                             ! IEU0  Group
1671         ldx             [%curptr + TI_FLAGS], %l0               ! Load
1673         srl             %i5, 0, %o5                             ! IEU1
1674         srl             %i2, 0, %o2                             ! IEU0  Group
1675         andcc           %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
1676         bne,pn          %icc, linux_syscall_trace32             ! CTI
1677          mov            %i0, %l5                                ! IEU1
1678         call            %l7                                     ! CTI   Group brk forced
1679          srl            %i3, 0, %o3                             ! IEU0
1680         ba,a,pt         %xcc, 3f
1682         /* Linux native and SunOS system calls enter here... */
1683         .align  32
1684         .globl  linux_sparc_syscall, ret_sys_call
1685 linux_sparc_syscall:
1686         /* Direct access to user regs, much faster. */
1687         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
1688         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
1689          mov            %i0, %o0                                ! IEU0
1690         sll             %g1, 2, %l4                             ! IEU0  Group
1691         mov             %i1, %o1                                ! IEU1
1692         lduw            [%l7 + %l4], %l7                        ! Load
1693 4:      mov             %i2, %o2                                ! IEU0  Group
1694         ldx             [%curptr + TI_FLAGS], %l0               ! Load
1696         mov             %i3, %o3                                ! IEU1
1697         mov             %i4, %o4                                ! IEU0  Group
1698         andcc           %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
1699         bne,pn          %icc, linux_syscall_trace               ! CTI   Group
1700          mov            %i0, %l5                                ! IEU0
1701 2:      call            %l7                                     ! CTI   Group brk forced
1702          mov            %i5, %o5                                ! IEU0
1703         nop
1705 3:      stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1706 ret_sys_call:
1707         ldx             [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
1708         ldx             [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
1709         sra             %o0, 0, %o0
1710         mov             %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
1711         sllx            %g2, 32, %g2
1713         /* Check if force_successful_syscall_return()
1714          * was invoked.
1715          */
1716         ldub            [%curptr + TI_SYS_NOERROR], %l0
1717         brz,pt          %l0, 1f
1718          nop
1719         ba,pt           %xcc, 80f
1720          stb            %g0, [%curptr + TI_SYS_NOERROR]
1723         cmp             %o0, -ERESTART_RESTARTBLOCK
1724         bgeu,pn         %xcc, 1f
1725          andcc          %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
1727         /* System call success, clear Carry condition code. */
1728         andn            %g3, %g2, %g3
1729         stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]  
1730         bne,pn          %icc, linux_syscall_trace2
1731          add            %l1, 0x4, %l2                   ! npc = npc+4
1732         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1733         ba,pt           %xcc, rtrap_clr_l6
1734          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1737         /* System call failure, set Carry condition code.
1738          * Also, get abs(errno) to return to the process.
1739          */
1740         andcc           %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6  
1741         sub             %g0, %o0, %o0
1742         or              %g3, %g2, %g3
1743         stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1744         mov             1, %l6
1745         stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
1746         bne,pn          %icc, linux_syscall_trace2
1747          add            %l1, 0x4, %l2                   ! npc = npc+4
1748         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1750         b,pt            %xcc, rtrap
1751          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1752 linux_syscall_trace2:
1753         add             %sp, PTREGS_OFF, %o0
1754         call            syscall_trace
1755          mov            1, %o1
1756         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1757         ba,pt           %xcc, rtrap
1758          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1760         .align          32
1761         .globl          __flushw_user
1762 __flushw_user:
1763         rdpr            %otherwin, %g1
1764         brz,pn          %g1, 2f
1765          clr            %g2
1766 1:      save            %sp, -128, %sp
1767         rdpr            %otherwin, %g1
1768         brnz,pt         %g1, 1b
1769          add            %g2, 1, %g2
1770 1:      sub             %g2, 1, %g2
1771         brnz,pt         %g2, 1b
1772          restore        %g0, %g0, %g0
1773 2:      retl
1774          nop