Import 2.3.18pre1
[davej-history.git] / arch / sparc64 / kernel / entry.S
blobfbd64a5073f17051138415ad4ad30204ca0fbbdb
1 /* $Id: entry.S,v 1.107 1999/08/31 19:25:29 davem Exp $
2  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
3  *
4  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
5  * Copyright (C) 1996 Eddie C. Dost        (ecd@skynet.be)
6  * Copyright (C) 1996 Miguel de Icaza      (miguel@nuclecu.unam.mx)
7  * Copyright (C) 1996,98,99 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
8  */
10 #include <linux/config.h>
11 #include <linux/errno.h>
13 #include <asm/head.h>
14 #include <asm/asi.h>
15 #include <asm/smp.h>
16 #include <asm/ptrace.h>
17 #include <asm/page.h>
18 #include <asm/signal.h>
19 #include <asm/pgtable.h>
20 #include <asm/processor.h>
21 #include <asm/visasm.h>
23 /* #define SYSCALL_TRACING */
25 #define curptr      g6
27 #define NR_SYSCALLS 256      /* Each OS is different... */
29         .text
30         .align          32
32         .globl          sparc64_vpte_patchme1
33         .globl          sparc64_vpte_patchme2
34 sparc64_vpte_nucleus:
35 sparc64_vpte_patchme1:
36         sethi           %hi(0), %g5                     ! This has to be patched
37 sparc64_vpte_patchme2:
38         or              %g5, %lo(0), %g5                ! This is patched too
39         ba,pt           %xcc, sparc64_kpte_continue     ! Part of dtlb_backend
40          add            %g1, %g1, %g1                   ! Finish PMD offset adjustment
42         /* This is trivial with the new code... */
43         .globl          do_fpdis
44 do_fpdis:
45         ldub            [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g5     ! Load  Group
46         sethi           %hi(TSTATE_PEF), %g4                                    ! IEU0
47         wr              %g0, FPRS_FEF, %fprs                                    ! LSU   Group+4bubbles
48         andcc           %g5, FPRS_FEF, %g0                                      ! IEU1  Group
49         be,a,pt         %icc, 1f                                                ! CTI
50          clr            %g7                                                     ! IEU0
51         ldub            [%g6 + AOFF_task_thread + AOFF_thread_gsr], %g7         ! Load  Group
52 1:      andcc           %g5, FPRS_DL, %g0                                       ! IEU1
53         bne,pn          %icc, 2f                                                ! CTI
54          fzero          %f0                                                     ! FPA
55         andcc           %g5, FPRS_DU, %g0                                       ! IEU1  Group
56         bne,pn          %icc, 1f                                                ! CTI
57          fzero          %f2                                                     ! FPA
58         faddd           %f0, %f2, %f4
59         fmuld           %f0, %f2, %f6
60         faddd           %f0, %f2, %f8
61         fmuld           %f0, %f2, %f10
62         faddd           %f0, %f2, %f12
63         fmuld           %f0, %f2, %f14
64         faddd           %f0, %f2, %f16
65         fmuld           %f0, %f2, %f18
66         faddd           %f0, %f2, %f20
67         fmuld           %f0, %f2, %f22
68         faddd           %f0, %f2, %f24
69         fmuld           %f0, %f2, %f26
70         faddd           %f0, %f2, %f28
71         fmuld           %f0, %f2, %f30
72         faddd           %f0, %f2, %f32
73         fmuld           %f0, %f2, %f34
74         faddd           %f0, %f2, %f36
75         fmuld           %f0, %f2, %f38
76         faddd           %f0, %f2, %f40
77         fmuld           %f0, %f2, %f42
78         faddd           %f0, %f2, %f44
79         fmuld           %f0, %f2, %f46
80         faddd           %f0, %f2, %f48
81         fmuld           %f0, %f2, %f50
82         faddd           %f0, %f2, %f52
83         fmuld           %f0, %f2, %f54
84         faddd           %f0, %f2, %f56
85         fmuld           %f0, %f2, %f58
86         b,pt            %xcc, fpdis_exit2
87          faddd          %f0, %f2, %f60
88 1:      mov             SECONDARY_CONTEXT, %g3
89         add             %g6, AOFF_task_fpregs + 0x80, %g1
90         faddd           %f0, %f2, %f4
91         fmuld           %f0, %f2, %f6
92         ldxa            [%g3] ASI_DMMU, %g5
93         add             %g6, AOFF_task_fpregs + 0xc0, %g2
94         stxa            %g0, [%g3] ASI_DMMU
95         faddd           %f0, %f2, %f8
96         fmuld           %f0, %f2, %f10
97         flush           %g6
98         membar          #StoreLoad | #LoadLoad
99         ldda            [%g1] ASI_BLK_S, %f32   ! grrr, where is ASI_BLK_NUCLEUS 8-(
100         ldda            [%g2] ASI_BLK_S, %f48
101         faddd           %f0, %f2, %f12
102         fmuld           %f0, %f2, %f14
103         faddd           %f0, %f2, %f16
104         fmuld           %f0, %f2, %f18
105         faddd           %f0, %f2, %f20
106         fmuld           %f0, %f2, %f22
107         faddd           %f0, %f2, %f24
108         fmuld           %f0, %f2, %f26
109         faddd           %f0, %f2, %f28
110         fmuld           %f0, %f2, %f30
111         b,pt            %xcc, fpdis_exit
112          membar         #Sync
113 2:      andcc           %g5, FPRS_DU, %g0
114         bne,pt          %icc, 3f
115          fzero          %f32
116         mov             SECONDARY_CONTEXT, %g3
117         fzero           %f34
118         ldxa            [%g3] ASI_DMMU, %g5
119         add             %g6, AOFF_task_fpregs, %g1
120         stxa            %g0, [%g3] ASI_DMMU
121         add             %g6, AOFF_task_fpregs + 0x40, %g2
122         faddd           %f32, %f34, %f36
123         fmuld           %f32, %f34, %f38
124         flush           %g6
125         membar          #StoreLoad | #LoadLoad
126         ldda            [%g1] ASI_BLK_S, %f0    ! grrr, where is ASI_BLK_NUCLEUS 8-(
127         ldda            [%g2] ASI_BLK_S, %f16
128         faddd           %f32, %f34, %f40
129         fmuld           %f32, %f34, %f42
130         faddd           %f32, %f34, %f44
131         fmuld           %f32, %f34, %f46
132         faddd           %f32, %f34, %f48
133         fmuld           %f32, %f34, %f50
134         faddd           %f32, %f34, %f52
135         fmuld           %f32, %f34, %f54
136         faddd           %f32, %f34, %f56
137         fmuld           %f32, %f34, %f58
138         faddd           %f32, %f34, %f60
139         fmuld           %f32, %f34, %f62
140         b,pt            %xcc, fpdis_exit
141          membar         #Sync
142 3:      mov             SECONDARY_CONTEXT, %g3
143         add             %g6, AOFF_task_fpregs, %g1
144         ldxa            [%g3] ASI_DMMU, %g5
145         mov             0x40, %g2
146         stxa            %g0, [%g3] ASI_DMMU
147         flush           %g6
148         membar          #StoreLoad | #LoadLoad
149         ldda            [%g1] ASI_BLK_S, %f0            ! grrr, where is ASI_BLK_NUCLEUS 8-(
150         ldda            [%g1 + %g2] ASI_BLK_S, %f16
151         add             %g1, 0x80, %g1
152         ldda            [%g1] ASI_BLK_S, %f32
153         ldda            [%g1 + %g2] ASI_BLK_S, %f48
154         membar          #Sync
155 fpdis_exit:
156         stxa            %g5, [%g3] ASI_DMMU
157         flush           %g6
158 fpdis_exit2:
159         wr              %g7, 0, %gsr
160         ldx             [%g6 + AOFF_task_thread + AOFF_thread_xfsr], %fsr
161         rdpr            %tstate, %g3
162         or              %g3, %g4, %g3           ! anal...
163         wrpr            %g3, %tstate
164         wr              %g0, FPRS_FEF, %fprs    ! clean DU/DL bits
165         retry
167         .globl          do_fptrap
168         .align          32
169 do_fptrap:
170         ldub            [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3
171         stx             %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
172         rd              %fprs, %g1
173         or              %g3, %g1, %g3
174         stb             %g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
175         rd              %gsr, %g3
176         stb             %g3, [%g6 + AOFF_task_thread + AOFF_thread_gsr]
177         mov             SECONDARY_CONTEXT, %g3
178         add             %g6, AOFF_task_fpregs, %g2
179         ldxa            [%g3] ASI_DMMU, %g5
180         stxa            %g0, [%g3] ASI_DMMU
181         flush           %g6
182         membar          #StoreStore | #LoadStore
183         andcc           %g1, FPRS_DL, %g0
184         be,pn           %icc, 4f
185          mov            0x40, %g3
186         stda            %f0, [%g2] ASI_BLK_S
187         stda            %f16, [%g2 + %g3] ASI_BLK_S
188         andcc           %g1, FPRS_DU, %g0
189         be,pn           %icc, 5f
190 4:       add            %g2, 128, %g2
191         stda            %f32, [%g2] ASI_BLK_S
192         stda            %f48, [%g2 + %g3] ASI_BLK_S
193 5:      mov             SECONDARY_CONTEXT, %g1
194         membar          #Sync
195         stxa            %g5, [%g1] ASI_DMMU
196         flush           %g6
197         ba,pt           %xcc, etrap
198          wr             %g0, 0, %fprs
200         /* The registers for cross calls will be:
201          *
202          * DATA 0: [low 32-bits]  Address of function to call, jmp to this
203          *         [high 32-bits] MMU Context Argument 0, place in %g5
204          * DATA 1: Address Argument 1, place in %g6
205          * DATA 2: Address Argument 2, place in %g7
206          *
207          * With this method we can do most of the cross-call tlb/cache
208          * flushing very quickly.
209          *
210          * Current CPU's IRQ worklist table is locked into %g1,
211          * don't touch.
212          */
213         .text
214         .align          32
215         .globl          do_ivec
216 do_ivec:
217         wr              %g0, ASI_UDB_INTR_R, %asi
218         ldxa            [%g0 + 0x40] %asi, %g3
219         sethi           %hi(KERNBASE), %g4
220         cmp             %g3, %g4
221         bgeu,pn         %xcc, do_ivec_xcall
222          srlx           %g3, 32, %g5
223         stxa            %g0, [%g0] ASI_INTR_RECEIVE
224         membar          #Sync
226         sethi           %hi(ivector_table), %g2
227         sllx            %g3, 5, %g3
228         or              %g2, %lo(ivector_table), %g2
229         add             %g2, %g3, %g3
230         ldx             [%g3 + 0x08], %g2       /* irq_info */
231         ldub            [%g3 + 0x04], %g4       /* pil */
232         brz,pn          %g2, do_ivec_spurious
233          mov            1, %g2
235         sllx            %g2, %g4, %g2
236         sllx            %g4, 2, %g4
237         lduw            [%g1 + %g4], %g5        /* g5 = irq_work(cpu, pil) */
238         stw             %g5, [%g3 + 0x00]       /* bucket->irq_chain = g5 */
239         stw             %g3, [%g1 + %g4]        /* irq_work(cpu, pil) = bucket */
240         wr              %g2, 0x0, %set_softint
241         retry
242 do_ivec_xcall:
243         ldxa            [%g0 + 0x50] %asi, %g6
245         srl             %g3, 0, %g3
246         ldxa            [%g0 + 0x60] %asi, %g7
247         stxa            %g0, [%g0] ASI_INTR_RECEIVE
248         membar          #Sync
249         jmpl            %g3, %g0
250          nop
251 do_ivec_spurious:
252         stw             %g3, [%g1 + 0x00]       /* irq_work(cpu, 0) = bucket */
253         rdpr            %pstate, %g5
255         wrpr            %g5, PSTATE_IG | PSTATE_AG, %pstate
256         sethi           %hi(109f), %g7
257         ba,pt           %xcc, etrap
258 109:     or             %g7, %lo(109b), %g7
259         call            catch_disabled_ivec
260          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
261         ba,pt           %xcc, rtrap
262          clr            %l6
264         .globl          getcc, setcc
265 getcc:
266         ldx             [%o0 + PT_V9_TSTATE], %o1
267         srlx            %o1, 32, %o1
268         and             %o1, 0xf, %o1
269         retl
270          stx            %o1, [%o0 + PT_V9_G1]
271 setcc:
272         ldx             [%o0 + PT_V9_TSTATE], %o1
273         ldx             [%o0 + PT_V9_G1], %o2
274         or              %g0, %ulo(TSTATE_ICC), %o3
275         sllx            %o3, 32, %o3
276         andn            %o1, %o3, %o1
277         sllx            %o2, 32, %o2
278         and             %o2, %o3, %o2
279         or              %o1, %o2, %o1
280         retl
281          stx            %o1, [%o0 + PT_V9_TSTATE]
283         .globl          utrap, utrap_ill
284 utrap:  brz,pn          %g1, etrap
285          nop
286         save            %sp, -128, %sp
287         rdpr            %tstate, %l6
288         rdpr            %cwp, %l7
289         andn            %l6, TSTATE_CWP, %l6
290         wrpr            %l6, %l7, %tstate
291         rdpr            %tpc, %l6
292         rdpr            %tnpc, %l7
293         wrpr            %g1, 0, %tnpc
294         done
295 utrap_ill:
296         call            bad_trap
297          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
298         ba,pt           %xcc, rtrap
299          clr            %l6
301 #ifdef CONFIG_BLK_DEV_FD
302         .globl          floppy_hardint
303 floppy_hardint:
304         wr              %g0, (1 << 11), %clear_softint
305         sethi           %hi(doing_pdma), %g1
306         ld              [%g1 + %lo(doing_pdma)], %g2
307         brz,pn          %g2, floppy_dosoftint
308          sethi          %hi(fdc_status), %g3
309         ldx             [%g3 + %lo(fdc_status)], %g3
310         sethi           %hi(pdma_vaddr), %g5
311         ldx             [%g5 + %lo(pdma_vaddr)], %g4
312         sethi           %hi(pdma_size), %g5
313         ldx             [%g5 + %lo(pdma_size)], %g5
315 next_byte:
316         ldub            [%g3], %g7
317         andcc           %g7, 0x80, %g0
318         be,pn           %icc, floppy_fifo_emptied
319          andcc          %g7, 0x20, %g0
320         be,pn           %icc, floppy_overrun
321          andcc          %g7, 0x40, %g0
322         be,pn           %icc, floppy_write
323          sub            %g5, 1, %g5
325         ldub            [%g3 + 1], %g7
326         orcc            %g0, %g5, %g0
327         stb             %g7, [%g4]
328         bne,pn          %xcc, next_byte
329          add            %g4, 1, %g4
331         b,pt            %xcc, floppy_tdone
332          nop
334 floppy_write:
335         ldub            [%g4], %g7
336         orcc            %g0, %g5, %g0
337         stb             %g7, [%g3 + 1]
338         bne,pn          %xcc, next_byte
339          add            %g4, 1, %g4
341 floppy_tdone:
342         sethi           %hi(pdma_vaddr), %g1
343         stx             %g4, [%g1 + %lo(pdma_vaddr)]
344         sethi           %hi(pdma_size), %g1
345         stx             %g5, [%g1 + %lo(pdma_size)]
346         sethi           %hi(auxio_register), %g1
347         ldx             [%g1 + %lo(auxio_register)], %g7
348         ldub            [%g7], %g5
349         or              %g5, 0xc2, %g5
350         stb             %g5, [%g7]
351         andn            %g5, 0x02, %g5
353         nop; nop;  nop; nop;  nop; nop;
354         nop; nop;  nop; nop;  nop; nop;
356         stb             %g5, [%g7]
357         sethi           %hi(doing_pdma), %g1
358         b,pt            %xcc, floppy_dosoftint
359          st             %g0, [%g1 + %lo(doing_pdma)]
361 floppy_fifo_emptied:
362         sethi           %hi(pdma_vaddr), %g1
363         stx             %g4, [%g1 + %lo(pdma_vaddr)]
364         sethi           %hi(pdma_size), %g1
365         stx             %g5, [%g1 + %lo(pdma_size)]
366         sethi           %hi(irq_action), %g1
367         or              %g1, %lo(irq_action), %g1
368         ldx             [%g1 + (11 << 3)], %g3          ! irqaction[floppy_irq]
369         ldx             [%g3 + 0x10], %g4               ! action->mask == ino_bucket ptr
370         ldx             [%g4 + 0x10], %g4               ! bucket->iclr
371         stw             %g0, [%g4]                      ! SYSIO_ICLR_IDLE
372         membar          #Sync                           ! probably not needed...
373         retry
375 floppy_overrun:
376         sethi           %hi(pdma_vaddr), %g1
377         stx             %g4, [%g1 + %lo(pdma_vaddr)]
378         sethi           %hi(pdma_size), %g1
379         stx             %g5, [%g1 + %lo(pdma_size)]
380         sethi           %hi(doing_pdma), %g1
381         st              %g0, [%g1 + %lo(doing_pdma)]
383 floppy_dosoftint:
384         rdpr            %pil, %g2
385         wrpr            %g0, 15, %pil
386         sethi           %hi(109f), %g7
387         b,pt            %xcc, etrap_irq
388 109:     or             %g7, %lo(109b), %g7
390         mov             11, %o0
391         mov             0, %o1
392         call            sparc_floppy_irq
393          add            %sp, STACK_BIAS + REGWIN_SZ, %o2
395         b,pt            %xcc, rtrap
396          clr            %l6
398 #endif /* CONFIG_BLK_DEV_FD */
400         /* XXX Here is stuff we still need to write... -DaveM XXX */
401         .globl          netbsd_syscall
402 netbsd_syscall:
403         retl
404          nop
406         /* These next few routines must be sure to clear the
407          * SFSR FaultValid bit so that the fast tlb data protection
408          * handler does not flush the wrong context and lock up the
409          * box.
410          */
411         .globl          __do_data_access_exception
412         .globl          __do_data_access_exception_tl1
413 __do_data_access_exception_tl1:
414         rdpr            %pstate, %g4
415         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
416         rdpr            %tl, %g3
417         cmp             %g3, 1
418         mov             TLB_SFSR, %g3
419         mov             DMMU_SFAR, %g5
420         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
421         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
422         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
423         membar          #Sync
424         bgu,pn          %icc, winfix_dax
425          rdpr           %tpc, %g3
426         sethi           %hi(109f), %g7
427         ba,pt           %xcc, etraptl1
428          or             %g7, %lo(109f), %g7     ! Merge in below
429 __do_data_access_exception:
430         rdpr            %pstate, %g4
431         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
432         mov             TLB_SFSR, %g3
433         mov             DMMU_SFAR, %g5
434         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
435         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
436         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
437         membar          #Sync
438         sethi           %hi(109f), %g7
439         ba,pt           %xcc, etrap
440 109:     or             %g7, %lo(109b), %g7
441         mov             %l4, %o1
442         mov             %l5, %o2
443         call            data_access_exception
444          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
445         ba,pt           %xcc, rtrap
446          clr            %l6
448         .globl          __do_instruction_access_exception
449         .globl          __do_instruction_access_exception_tl1
450 __do_instruction_access_exception_tl1:
451         rdpr            %pstate, %g4
452         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
453         mov             TLB_SFSR, %g3
454         mov             DMMU_SFAR, %g5
455         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
456         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
457         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
458         membar          #Sync
459         sethi           %hi(109f), %g7
460         ba,pt           %xcc, etraptl1
461          or             %g7, %lo(109f), %g7     ! Merge in below
462 __do_instruction_access_exception:
463         rdpr            %pstate, %g4
464         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
465         mov             TLB_SFSR, %g3
466         mov             DMMU_SFAR, %g5
467         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
468         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
469         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
470         membar          #Sync
471         sethi           %hi(109f), %g7
472         ba,pt           %xcc, etrap
473 109:     or             %g7, %lo(109b), %g7
474         mov             %l4, %o1
475         mov             %l5, %o2
476         call            instruction_access_exception
477          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
478         ba,pt           %xcc, rtrap
479          clr            %l6
481         /* This is the trap handler entry point for ECC correctable
482          * errors.  They are corrected, but we listen for the trap
483          * so that the event can be logged.
484          *
485          * Disrupting errors are either:
486          * 1) single-bit ECC errors during UDB reads to system
487          *    memory
488          * 2) data parity errors during write-back events
489          *
490          * As far as I can make out from the manual, the CEE trap
491          * is only for correctable errors during memory read
492          * accesses by the front-end of the processor.
493          *
494          * The code below is only for trap level 1 CEE events,
495          * as it is the only situation where we can safely record
496          * and log.  For trap level >1 we just clear the CE bit
497          * in the AFSR and return.
498          */
500         /* Our trap handling infrastructure allows us to preserve
501          * two 64-bit values during etrap for arguments to
502          * subsequent C code.  Therefore we encode the information
503          * as follows:
504          *
505          * value 1) Full 64-bits of AFAR
506          * value 2) Low 33-bits of AFSR, then bits 33-->42
507          *          are UDBL error status and bits 43-->52
508          *          are UDBH error status
509          */
510         .align  64
511         .globl  cee_trap
512 cee_trap:
513         ldxa    [%g0] ASI_AFSR, %g1             ! Read AFSR
514         ldxa    [%g0] ASI_AFAR, %g2             ! Read AFAR
515         sllx    %g1, 31, %g1                    ! Clear reserved bits
516         srlx    %g1, 31, %g1                    ! in AFSR
518         /* NOTE: UltraSparc-I/II have high and low UDB error
519          *       registers, corresponding to the two UDB units
520          *       present on those chips.  UltraSparc-IIi only
521          *       has a single UDB, called "SDB" in the manual.
522          *       For IIi the upper UDB register always reads
523          *       as zero so for our purposes things will just
524          *       work with the checks below.
525          */
526         ldxa    [%g0] ASI_UDBL_ERROR_R, %g3     ! Read UDB-Low error status
527         andcc   %g3, (1 << 8), %g4              ! Check CE bit
528         sllx    %g3, (64 - 10), %g3             ! Clear reserved bits
529         srlx    %g3, (64 - 10), %g3             ! in UDB-Low error status
531         sllx    %g3, (33 + 0), %g3              ! Shift up to encoding area
532         or      %g1, %g3, %g1                   ! Or it in
533         be,pn   %xcc, 1f                        ! Branch if CE bit was clear
534          nop
535         stxa    %g4, [%g0] ASI_UDB_ERROR_W      ! Clear CE sticky bit in UDBL
536         membar  #Sync                           ! Synchronize ASI stores
537 1:      mov     0x18, %g5                       ! Addr of UDB-High error status
538         ldxa    [%g5] ASI_UDBH_ERROR_R, %g3     ! Read it
540         andcc   %g3, (1 << 8), %g4              ! Check CE bit
541         sllx    %g3, (64 - 10), %g3             ! Clear reserved bits
542         srlx    %g3, (64 - 10), %g3             ! in UDB-High error status
543         sllx    %g3, (33 + 10), %g3             ! Shift up to encoding area
544         or      %g1, %g3, %g1                   ! Or it in
545         be,pn   %xcc, 1f                        ! Branch if CE bit was clear
546          nop
547         nop
549         stxa    %g4, [%g5] ASI_UDB_ERROR_W      ! Clear CE sticky bit in UDBH
550         membar  #Sync                           ! Synchronize ASI stores
551 1:      mov     1, %g5                          ! AFSR CE bit is
552         sllx    %g5, 20, %g5                    ! bit 20
553         stxa    %g5, [%g0] ASI_AFSR             ! Clear CE sticky bit in AFSR
554         membar  #Sync                           ! Synchronize ASI stores
555         sllx    %g2, (64 - 41), %g2             ! Clear reserved bits
556         srlx    %g2, (64 - 41), %g2             ! in latched AFAR
558         andn    %g2, 0x0f, %g2                  ! Finish resv bit clearing
559         mov     %g1, %g4                        ! Move AFSR+UDB* into save reg
560         mov     %g2, %g5                        ! Move AFAR into save reg
561         rdpr    %pil, %g2
562         wrpr    %g0, 15, %pil
563         ba,pt   %xcc, etrap_irq
564          rd     %pc, %g7
565         mov     %l4, %o0
567         mov     %l5, %o1
568         call    cee_log
569          add    %sp, STACK_BIAS + REGWIN_SZ, %o2
570         ba,a,pt %xcc, rtrap_clr_l6
572         .globl          __do_privact
573 __do_privact:
574         mov             TLB_SFSR, %g3
575         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
576         membar          #Sync
577         sethi           %hi(109f), %g7
578         ba,pt           %xcc, etrap
579 109:    or              %g7, %lo(109b), %g7
580         call            do_privact
581          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
582         ba,pt           %xcc, rtrap
583          clr            %l6
585         .globl          do_mna
586 do_mna:
587         rdpr            %tl, %g3
588         cmp             %g3, 1
590         /* Setup %g4/%g5 now as they are used in the
591          * winfixup code.
592          */
593         mov             TLB_SFSR, %g3
594         mov             DMMU_SFAR, %g4
595         ldxa            [%g4] ASI_DMMU, %g4
596         ldxa            [%g3] ASI_DMMU, %g5
597         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
598         membar          #Sync
599         bgu,pn          %icc, winfix_dax
600          rdpr           %tpc, %g3
602 1:      sethi           %hi(109f), %g7
603         ba,pt           %xcc, etrap
604 109:     or             %g7, %lo(109b), %g7
605         mov             %l4, %o1
606         mov             %l5, %o2
607         call            mem_address_unaligned
608          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
609         ba,pt           %xcc, rtrap
610          clr            %l6
612         .globl          do_lddfmna
613 do_lddfmna:
614         sethi           %hi(109f), %g7
615         mov             TLB_SFSR, %g4
616         ldxa            [%g4] ASI_DMMU, %g5
617         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
618         membar          #Sync
619         mov             DMMU_SFAR, %g4
620         ldxa            [%g4] ASI_DMMU, %g4
621         ba,pt           %xcc, etrap
622 109:     or             %g7, %lo(109b), %g7
623         mov             %l4, %o1
624         mov             %l5, %o2
625         call            handle_lddfmna
626          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
627         ba,pt           %xcc, rtrap
628          clr            %l6
630         .globl          do_stdfmna
631 do_stdfmna:
632         sethi           %hi(109f), %g7
633         mov             TLB_SFSR, %g4
634         ldxa            [%g4] ASI_DMMU, %g5
635         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
636         membar          #Sync
637         mov             DMMU_SFAR, %g4
638         ldxa            [%g4] ASI_DMMU, %g4
639         ba,pt           %xcc, etrap
640 109:     or             %g7, %lo(109b), %g7
641         mov             %l4, %o1
642         mov             %l5, %o2
643         call            handle_stdfmna
644          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
645         ba,pt           %xcc, rtrap
646          clr            %l6
648         .globl  breakpoint_trap
649 breakpoint_trap:
650         call            sparc_breakpoint
651          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
652         ba,pt           %xcc, rtrap
653          nop
655         /* SunOS uses syscall zero as the 'indirect syscall' it looks
656          * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
657          * This is complete brain damage.
658          */
659         .globl  sunos_indir
660 sunos_indir:
661         srl             %o0, 0, %o0
662         mov             %o7, %l4
663         cmp             %o0, NR_SYSCALLS
664         blu,a,pt        %icc, 1f
665          sll            %o0, 0x2, %o0
666         sethi           %hi(sunos_nosys), %l6
667         b,pt            %xcc, 2f
668          or             %l6, %lo(sunos_nosys), %l6
669 1:      sethi           %hi(sunos_sys_table), %l7
670         or              %l7, %lo(sunos_sys_table), %l7
671         lduw            [%l7 + %o0], %l6
672 2:      mov             %o1, %o0
673         mov             %o2, %o1
674         mov             %o3, %o2
675         mov             %o4, %o3
676         mov             %o5, %o4
677         call            %l6
678          mov            %l4, %o7
680         .globl  sunos_getpid
681 sunos_getpid:
682         call    sys_getppid
683          nop
684         call    sys_getpid
685          stx    %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
686         b,pt    %xcc, ret_sys_call
687          stx    %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
689         /* SunOS getuid() returns uid in %o0 and euid in %o1 */
690         .globl  sunos_getuid
691 sunos_getuid:
692         call    sys_geteuid
693          nop
694         call    sys_getuid
695          stx    %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
696         b,pt    %xcc, ret_sys_call
697          stx    %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
699         /* SunOS getgid() returns gid in %o0 and egid in %o1 */
700         .globl  sunos_getgid
701 sunos_getgid:
702         call    sys_getegid
703          nop
704         call    sys_getgid
705          stx    %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
706         b,pt    %xcc, ret_sys_call
707          stx    %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
709         /* SunOS's execv() call only specifies the argv argument, the
710          * environment settings are the same as the calling processes.
711          */
712         .globl  sunos_execv, sys_execve, sys32_execve
713 sys_execve:
714         sethi           %hi(sparc_execve), %g1
715         ba,pt           %xcc, execve_merge
716          or             %g1, %lo(sparc_execve), %g1
717 sunos_execv:
718         stx             %g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
719 sys32_execve:
720         sethi           %hi(sparc32_execve), %g1
721         or              %g1, %lo(sparc32_execve), %g1
722 execve_merge:
723         flushw
724         jmpl            %g1, %g0
725          add            %sp, STACK_BIAS + REGWIN_SZ, %o0
727         .globl  sys_pipe, sys_sigpause, sys_nis_syscall
728         .globl  sys_sigsuspend, sys_rt_sigsuspend, sys32_rt_sigsuspend
729         .globl  sys_rt_sigreturn
730         .globl  sys32_sigreturn, sys32_rt_sigreturn
731         .globl  sys32_execve, sys_ptrace
732         .globl  sys_sigaltstack, sys32_sigaltstack
733         .globl  sys32_sigstack
734         .align  32
735 sys_pipe:       ba,pt           %xcc, sparc_pipe
736                  add            %sp, STACK_BIAS + REGWIN_SZ, %o0
737 sys_nis_syscall:ba,pt           %xcc, c_sys_nis_syscall
738                  add            %sp, STACK_BIAS + REGWIN_SZ, %o0
739 sys_memory_ordering:
740                 ba,pt           %xcc, sparc_memory_ordering
741                  add            %sp, STACK_BIAS + REGWIN_SZ, %o1
742 sys_sigaltstack:ba,pt           %xcc, do_sigaltstack
743                  add            %i6, STACK_BIAS, %o2
744 sys32_sigstack: ba,pt           %xcc, do_sys32_sigstack
745                  mov            %i6, %o2
746 sys32_sigaltstack:
747                 ba,pt           %xcc, do_sys32_sigaltstack
748                  mov            %i6, %o2
750                 .align          32
751 sys_sigsuspend: add             %sp, STACK_BIAS + REGWIN_SZ, %o0
752                 call            do_sigsuspend
753                  add            %o7, 1f-.-4, %o7
754                 nop
755 sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
756                 add             %sp, STACK_BIAS + REGWIN_SZ, %o2
757                 call            do_rt_sigsuspend
758                  add            %o7, 1f-.-4, %o7
759                 nop
760 sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
761                 srl             %o0, 0, %o0
762                 add             %sp, STACK_BIAS + REGWIN_SZ, %o2
763                 call            do_rt_sigsuspend32
764                  add            %o7, 1f-.-4, %o7
765                 /* NOTE: %o0 has a correct value already */
766 sys_sigpause:   add             %sp, STACK_BIAS + REGWIN_SZ, %o1
767                 call            do_sigpause
768                  add            %o7, 1f-.-4, %o7
769                 nop
770 sys32_sigreturn:
771                 add             %sp, STACK_BIAS + REGWIN_SZ, %o0
772                 call            do_sigreturn32
773                  add            %o7, 1f-.-4, %o7
774                 nop
775 sys_rt_sigreturn:
776                 add             %sp, STACK_BIAS + REGWIN_SZ, %o0
777                 call            do_rt_sigreturn
778                  add            %o7, 1f-.-4, %o7
779                 nop
780 sys32_rt_sigreturn:
781                 add             %sp, STACK_BIAS + REGWIN_SZ, %o0
782                 call            do_rt_sigreturn32
783                  add            %o7, 1f-.-4, %o7
784                 nop
785 sys_ptrace:     add             %sp, STACK_BIAS + REGWIN_SZ, %o0
786                 call            do_ptrace
787                  add            %o7, 1f-.-4, %o7
788                 nop
789                 .align          32
790 1:              ldx             [%curptr + AOFF_task_flags], %l5
791                 andcc           %l5, 0x20, %g0
792                 be,pt           %icc, rtrap
793                  clr            %l6
794                 call            syscall_trace
795                  nop
797                 ba,pt           %xcc, rtrap
798                  clr            %l6
800         /* This is how fork() was meant to be done, 8 instruction entry.
801          *
802          * I questioned the following code briefly, let me clear things
803          * up so you must not reason on it like I did.
804          *
805          * Know the fork_kpsr etc. we use in the sparc32 port?  We don't
806          * need it here because the only piece of window state we copy to
807          * the child is the CWP register.  Even if the parent sleeps,
808          * we are safe because we stuck it into pt_regs of the parent
809          * so it will not change.
810          *
811          * XXX This raises the question, whether we can do the same on
812          * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim.  The
813          * XXX answer is yes.  We stick fork_kpsr in UREG_G0 and
814          * XXX fork_kwim in UREG_G1 (global registers are considered
815          * XXX volatile across a system call in the sparc ABI I think
816          * XXX if it isn't we can use regs->y instead, anyone who depends
817          * XXX upon the Y register being preserved across a fork deserves
818          * XXX to lose).
819          *
820          * In fact we should take advantage of that fact for other things
821          * during system calls...
822          */
823         .globl  sys_fork, sys_vfork, sys_clone, sparc_exit
824         .globl  ret_from_syscall
825         .align  32
826 sys_vfork:      /* Under Linux, vfork and fork are just special cases of clone. */
827                 sethi           %hi(0x4000 | 0x0100 | SIGCHLD), %o0
828                 or              %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
829                 ba,pt           %xcc, sys_clone
830 sys_fork:        clr            %o1
831                 mov             SIGCHLD, %o0
832 sys_clone:      flushw
833                 movrz           %o1, %fp, %o1
834                 nop
835                 ba,pt           %xcc, do_fork
836                  add            %sp, STACK_BIAS + REGWIN_SZ, %o2
837 ret_from_syscall:
838                 /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in
839                  * %o7 for us.  Check performance counter stuff too.
840                  */
841                 andn            %o7, SPARC_FLAG_NEWCHILD, %l0
842                 mov             %g5, %o0        /* 'prev' */
843                 call            schedule_tail
844                  stb            %l0, [%g6 + AOFF_task_thread + AOFF_thread_flags]
845                 andcc           %l0, SPARC_FLAG_PERFCTR, %g0
846                 be,pt           %icc, 1f
847                  nop
848                 ldx             [%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7
849                 wr              %g0, %o7, %pcr
850                 wr              %g0, %g0, %pic
851 1:              b,pt            %xcc, ret_sys_call
852                  ldx            [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
853 sparc_exit:     rdpr            %otherwin, %g1
854                 wrpr            %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate
855                 rdpr            %cansave, %g3
856                 add             %g3, %g1, %g3
857                 wrpr            %g3, 0x0, %cansave
858                 wrpr            %g0, 0x0, %otherwin
859                 wrpr            %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
860                 ba,pt           %xcc, sys_exit
861                  stb            %g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
863 linux_sparc_ni_syscall:
864         sethi           %hi(sys_ni_syscall), %l7
865         b,pt            %xcc, 4f
866          or             %l7, %lo(sys_ni_syscall), %l7
868 linux_syscall_trace32:
869         call            syscall_trace
870          nop
871         srl             %i0, 0, %o0
872         mov             %i4, %o4
873         srl             %i1, 0, %o1
874         srl             %i2, 0, %o2
875         b,pt            %xcc, 2f
876          srl            %i3, 0, %o3
878 linux_syscall_trace:
879         call            syscall_trace
880          nop
881         mov             %i0, %o0
882         mov             %i1, %o1
883         mov             %i2, %o2
884         mov             %i3, %o3
885         b,pt            %xcc, 2f
886          mov            %i4, %o4
889         /* Linux 32-bit and SunOS system calls enter here... */
890         .align  32
891         .globl  linux_sparc_syscall32
892 linux_sparc_syscall32:
893         /* Direct access to user regs, must faster. */
894         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
895         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
896          srl            %i0, 0, %o0                             ! IEU0
897         sll             %g1, 2, %l4                             ! IEU0  Group
898 #ifdef SYSCALL_TRACING
899         add             %sp, STACK_BIAS + REGWIN_SZ, %o1
900         call            syscall_trace_entry
901          mov            %g1, %o0
902         srl             %i0, 0, %o0
903 #endif
904         mov             %i4, %o4                                ! IEU1
905         lduw            [%l7 + %l4], %l7                        ! Load
906         srl             %i1, 0, %o1                             ! IEU0  Group
907         ldx             [%curptr + AOFF_task_flags], %l0        ! Load
909         mov             %i5, %o5                                ! IEU1
910         srl             %i2, 0, %o2                             ! IEU0  Group
911         mov             %i0, %l5                                ! IEU1
912         andcc           %l0, 0x20, %g0                          ! IEU1  Group
913         bne,pn          %icc, linux_syscall_trace32             ! CTI
914          srl            %i3, 0, %o3                             ! IEU0
915         call            %l7                                     ! CTI   Group brk forced
916          add            %o7, 3f-.-4, %o7                        ! IEU0
918         /* Linux native and SunOS system calls enter here... */
919         .align  32
920         .globl  linux_sparc_syscall, ret_sys_call
921 linux_sparc_syscall:
922         /* Direct access to user regs, must faster. */
923         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
924         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
925          mov            %i0, %o0                                ! IEU0
926         sll             %g1, 2, %l4                             ! IEU0  Group
927 #ifdef SYSCALL_TRACING
928         add             %sp, STACK_BIAS + REGWIN_SZ, %o1
929         call            syscall_trace_entry
930          mov            %g1, %o0
931         mov             %i0, %o0
932 #endif
933         mov             %i1, %o1                                ! IEU1
934         lduw            [%l7 + %l4], %l7                        ! Load
935 4:      mov             %i2, %o2                                ! IEU0  Group
936         ldx             [%curptr + AOFF_task_flags], %l0        ! Load
938         mov             %i3, %o3                                ! IEU1
939         mov             %i4, %o4                                ! IEU0  Group
940         andcc           %l0, 0x20, %g0                          ! IEU1  Group+1 bubble
941         bne,pn          %icc, linux_syscall_trace               ! CTI   Group
942          mov            %i0, %l5                                ! IEU0
943 2:      call            %l7                                     ! CTI   Group brk forced
944          mov            %i5, %o5                                ! IEU0
945 3:      stx             %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
946 ret_sys_call:
947 #ifdef SYSCALL_TRACING
948         call            syscall_trace_exit
949          add            %sp, STACK_BIAS + REGWIN_SZ, %o1
950 #endif
951         ldx             [%curptr + AOFF_task_flags], %l6
952         sra             %o0, 0, %o0
953         mov             %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
954         ldx             [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
955         cmp             %o0, -ENOIOCTLCMD
956         sllx            %g2, 32, %g2
957         bgeu,pn         %xcc, 1f
958          andcc          %l6, 0x20, %l6  
960         /* System call success, clear Carry condition code. */
961         andn            %g3, %g2, %g3
962         stx             %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]      
963         bne,pn          %icc, linux_syscall_trace2
964          ldx            [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
965         add             %l1, 0x4, %l2                                    !npc = npc+4
966         stx             %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
967         b,pt            %xcc, rtrap_clr_l6
968          stx            %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
970         /* System call failure, set Carry condition code.
971          * Also, get abs(errno) to return to the process.
972          */
973         sub             %g0, %o0, %o0
974         or              %g3, %g2, %g3
975         stx             %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
976         mov             1, %l6
977         stx             %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
978         bne,pn          %icc, linux_syscall_trace2
979          ldx            [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
980         add             %l1, 0x4, %l2                                    !npc = npc+4
982         stx             %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
983         b,pt            %xcc, rtrap
984          stx            %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
985 linux_syscall_trace2:
986         call            syscall_trace
987          add            %l1, 0x4, %l2                   /* npc = npc+4 */
988         stx             %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
989         ba,pt           %xcc, rtrap
990          stx            %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
992         .align          32
993         .globl          __flushw_user
994 __flushw_user:
995 1:      save            %sp, -128, %sp
996         rdpr            %otherwin, %g1
997         brnz,pt         %g1, 1b
998          add            %g2, 1, %g2
999 1:      sub             %g2, 1, %g2
1000         brnz,pt         %g2, 1b
1001          restore        %g0, %g0, %g0
1002 2:      retl
1003          mov            %g3, %o7