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