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