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.
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)
10 #include <linux/config.h>
11 #include <linux/errno.h>
16 #include <asm/ptrace.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 */
27 #define NR_SYSCALLS 256 /* Each OS is different... */
32 .globl sparc64_vpte_patchme1
33 .globl sparc64_vpte_patchme2
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... */
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
51 ldub [%g6 + AOFF_task_thread + AOFF_thread_gsr], %g7 ! Load Group
52 1: andcc %g5, FPRS_DL, %g0 ! IEU1
55 andcc %g5, FPRS_DU, %g0 ! IEU1 Group
86 b,pt %xcc, fpdis_exit2
88 1: mov SECONDARY_CONTEXT, %g3
89 add %g6, AOFF_task_fpregs + 0x80, %g1
92 ldxa [%g3] ASI_DMMU, %g5
93 add %g6, AOFF_task_fpregs + 0xc0, %g2
94 stxa %g0, [%g3] ASI_DMMU
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
111 b,pt %xcc, fpdis_exit
113 2: andcc %g5, FPRS_DU, %g0
116 mov SECONDARY_CONTEXT, %g3
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
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
142 3: mov SECONDARY_CONTEXT, %g3
143 add %g6, AOFF_task_fpregs, %g1
144 ldxa [%g3] ASI_DMMU, %g5
146 stxa %g0, [%g3] ASI_DMMU
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
152 ldda [%g1] ASI_BLK_S, %f32
153 ldda [%g1 + %g2] ASI_BLK_S, %f48
156 stxa %g5, [%g3] ASI_DMMU
160 ldx [%g6 + AOFF_task_thread + AOFF_thread_xfsr], %fsr
162 or %g3, %g4, %g3 ! anal...
164 wr %g0, FPRS_FEF, %fprs ! clean DU/DL bits
170 ldub [%g6 + AOFF_task_thread + AOFF_thread_fpsaved], %g3
171 stx %fsr, [%g6 + AOFF_task_thread + AOFF_thread_xfsr]
174 stb %g3, [%g6 + AOFF_task_thread + AOFF_thread_fpsaved]
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
182 membar #StoreStore | #LoadStore
183 andcc %g1, FPRS_DL, %g0
186 stda %f0, [%g2] ASI_BLK_S
187 stda %f16, [%g2 + %g3] ASI_BLK_S
188 andcc %g1, FPRS_DU, %g0
191 stda %f32, [%g2] ASI_BLK_S
192 stda %f48, [%g2 + %g3] ASI_BLK_S
193 5: mov SECONDARY_CONTEXT, %g1
195 stxa %g5, [%g1] ASI_DMMU
200 /* The registers for cross calls will be:
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
207 * With this method we can do most of the cross-call tlb/cache
208 * flushing very quickly.
210 * Current CPU's IRQ worklist table is locked into %g1,
217 wr %g0, ASI_UDB_INTR_R, %asi
218 ldxa [%g0 + 0x40] %asi, %g3
219 sethi %hi(KERNBASE), %g4
221 bgeu,pn %xcc, do_ivec_xcall
223 stxa %g0, [%g0] ASI_INTR_RECEIVE
226 sethi %hi(ivector_table), %g2
228 or %g2, %lo(ivector_table), %g2
230 ldx [%g3 + 0x08], %g2 /* irq_info */
231 ldub [%g3 + 0x04], %g4 /* pil */
232 brz,pn %g2, do_ivec_spurious
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
243 ldxa [%g0 + 0x50] %asi, %g6
246 ldxa [%g0 + 0x60] %asi, %g7
247 stxa %g0, [%g0] ASI_INTR_RECEIVE
252 stw %g3, [%g1 + 0x00] /* irq_work(cpu, 0) = bucket */
255 wrpr %g5, PSTATE_IG | PSTATE_AG, %pstate
258 109: or %g7, %lo(109b), %g7
259 call catch_disabled_ivec
260 add %sp, STACK_BIAS + REGWIN_SZ, %o0
266 ldx [%o0 + PT_V9_TSTATE], %o1
270 stx %o1, [%o0 + PT_V9_G1]
272 ldx [%o0 + PT_V9_TSTATE], %o1
273 ldx [%o0 + PT_V9_G1], %o2
274 or %g0, %ulo(TSTATE_ICC), %o3
281 stx %o1, [%o0 + PT_V9_TSTATE]
283 .globl utrap, utrap_ill
284 utrap: brz,pn %g1, etrap
289 andn %l6, TSTATE_CWP, %l6
290 wrpr %l6, %l7, %tstate
297 add %sp, STACK_BIAS + REGWIN_SZ, %o0
301 #ifdef CONFIG_BLK_DEV_FD
302 .globl 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
318 be,pn %icc, floppy_fifo_emptied
320 be,pn %icc, floppy_overrun
322 be,pn %icc, floppy_write
328 bne,pn %xcc, next_byte
331 b,pt %xcc, floppy_tdone
338 bne,pn %xcc, next_byte
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
353 nop; nop; nop; nop; nop; nop;
354 nop; nop; nop; nop; nop; nop;
357 sethi %hi(doing_pdma), %g1
358 b,pt %xcc, floppy_dosoftint
359 st %g0, [%g1 + %lo(doing_pdma)]
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...
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)]
388 109: or %g7, %lo(109b), %g7
392 call sparc_floppy_irq
393 add %sp, STACK_BIAS + REGWIN_SZ, %o2
398 #endif /* CONFIG_BLK_DEV_FD */
400 /* XXX Here is stuff we still need to write... -DaveM XXX */
401 .globl netbsd_syscall
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
411 .globl __do_data_access_exception
412 .globl __do_data_access_exception_tl1
413 __do_data_access_exception_tl1:
415 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
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
424 bgu,pn %icc, winfix_dax
428 or %g7, %lo(109f), %g7 ! Merge in below
429 __do_data_access_exception:
431 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
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
440 109: or %g7, %lo(109b), %g7
443 call data_access_exception
444 add %sp, STACK_BIAS + REGWIN_SZ, %o0
448 .globl __do_instruction_access_exception
449 .globl __do_instruction_access_exception_tl1
450 __do_instruction_access_exception_tl1:
452 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
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
461 or %g7, %lo(109f), %g7 ! Merge in below
462 __do_instruction_access_exception:
464 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
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
473 109: or %g7, %lo(109b), %g7
476 call instruction_access_exception
477 add %sp, STACK_BIAS + REGWIN_SZ, %o0
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.
485 * Disrupting errors are either:
486 * 1) single-bit ECC errors during UDB reads to system
488 * 2) data parity errors during write-back events
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.
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.
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
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
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.
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
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
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
563 ba,pt %xcc, etrap_irq
569 add %sp, STACK_BIAS + REGWIN_SZ, %o2
570 ba,a,pt %xcc, rtrap_clr_l6
575 stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
579 109: or %g7, %lo(109b), %g7
581 add %sp, STACK_BIAS + REGWIN_SZ, %o0
590 /* Setup %g4/%g5 now as they are used in the
595 ldxa [%g4] ASI_DMMU, %g4
596 ldxa [%g3] ASI_DMMU, %g5
597 stxa %g0, [%g3] ASI_DMMU ! Clear FaultValid bit
599 bgu,pn %icc, winfix_dax
602 1: sethi %hi(109f), %g7
604 109: or %g7, %lo(109b), %g7
607 call mem_address_unaligned
608 add %sp, STACK_BIAS + REGWIN_SZ, %o0
616 ldxa [%g4] ASI_DMMU, %g5
617 stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
620 ldxa [%g4] ASI_DMMU, %g4
622 109: or %g7, %lo(109b), %g7
626 add %sp, STACK_BIAS + REGWIN_SZ, %o0
634 ldxa [%g4] ASI_DMMU, %g5
635 stxa %g0, [%g4] ASI_DMMU ! Clear FaultValid bit
638 ldxa [%g4] ASI_DMMU, %g4
640 109: or %g7, %lo(109b), %g7
644 add %sp, STACK_BIAS + REGWIN_SZ, %o0
648 .globl breakpoint_trap
650 call sparc_breakpoint
651 add %sp, STACK_BIAS + REGWIN_SZ, %o0
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.
666 sethi %hi(sunos_nosys), %l6
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
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 */
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 */
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.
712 .globl sunos_execv, sys_execve, sys32_execve
714 sethi %hi(sparc_execve), %g1
715 ba,pt %xcc, execve_merge
716 or %g1, %lo(sparc_execve), %g1
718 stx %g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
720 sethi %hi(sparc32_execve), %g1
721 or %g1, %lo(sparc32_execve), %g1
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
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
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
747 ba,pt %xcc, do_sys32_sigaltstack
751 sys_sigsuspend: add %sp, STACK_BIAS + REGWIN_SZ, %o0
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
760 sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
762 add %sp, STACK_BIAS + REGWIN_SZ, %o2
763 call do_rt_sigsuspend32
765 /* NOTE: %o0 has a correct value already */
766 sys_sigpause: add %sp, STACK_BIAS + REGWIN_SZ, %o1
771 add %sp, STACK_BIAS + REGWIN_SZ, %o0
776 add %sp, STACK_BIAS + REGWIN_SZ, %o0
781 add %sp, STACK_BIAS + REGWIN_SZ, %o0
782 call do_rt_sigreturn32
785 sys_ptrace: add %sp, STACK_BIAS + REGWIN_SZ, %o0
790 1: ldx [%curptr + AOFF_task_flags], %l5
800 /* This is how fork() was meant to be done, 8 instruction entry.
802 * I questioned the following code briefly, let me clear things
803 * up so you must not reason on it like I did.
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.
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
820 * In fact we should take advantage of that fact for other things
821 * during system calls...
823 .globl sys_fork, sys_vfork, sys_clone, sparc_exit
824 .globl ret_from_syscall
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
836 add %sp, STACK_BIAS + REGWIN_SZ, %o2
838 /* Clear SPARC_FLAG_NEWCHILD, switch_to leaves thread.flags in
839 * %o7 for us. Check performance counter stuff too.
841 andn %o7, SPARC_FLAG_NEWCHILD, %l0
842 mov %g5, %o0 /* 'prev' */
844 stb %l0, [%g6 + AOFF_task_thread + AOFF_thread_flags]
845 andcc %l0, SPARC_FLAG_PERFCTR, %g0
848 ldx [%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7
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
857 wrpr %g3, 0x0, %cansave
858 wrpr %g0, 0x0, %otherwin
859 wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
861 stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]
863 linux_sparc_ni_syscall:
864 sethi %hi(sys_ni_syscall), %l7
866 or %l7, %lo(sys_ni_syscall), %l7
868 linux_syscall_trace32:
889 /* Linux 32-bit and SunOS system calls enter here... */
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
905 lduw [%l7 + %l4], %l7 ! Load
906 srl %i1, 0, %o1 ! IEU0 Group
907 ldx [%curptr + AOFF_task_flags], %l0 ! Load
910 srl %i2, 0, %o2 ! IEU0 Group
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... */
920 .globl linux_sparc_syscall, ret_sys_call
922 /* Direct access to user regs, must faster. */
923 cmp %g1, NR_SYSCALLS ! IEU1 Group
924 bgeu,pn %xcc, linux_sparc_ni_syscall ! CTI
926 sll %g1, 2, %l4 ! IEU0 Group
927 #ifdef SYSCALL_TRACING
928 add %sp, STACK_BIAS + REGWIN_SZ, %o1
929 call syscall_trace_entry
934 lduw [%l7 + %l4], %l7 ! Load
935 4: mov %i2, %o2 ! IEU0 Group
936 ldx [%curptr + AOFF_task_flags], %l0 ! Load
939 mov %i4, %o4 ! IEU0 Group
940 andcc %l0, 0x20, %g0 ! IEU1 Group+1 bubble
941 bne,pn %icc, linux_syscall_trace ! CTI Group
943 2: call %l7 ! CTI Group brk forced
945 3: stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
947 #ifdef SYSCALL_TRACING
948 call syscall_trace_exit
949 add %sp, STACK_BIAS + REGWIN_SZ, %o1
951 ldx [%curptr + AOFF_task_flags], %l6
953 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
954 ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
955 cmp %o0, -ENOIOCTLCMD
960 /* System call success, clear Carry condition code. */
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.
975 stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
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]
984 stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
985 linux_syscall_trace2:
987 add %l1, 0x4, %l2 /* npc = npc+4 */
988 stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
990 stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
995 1: save %sp, -128, %sp
1001 restore %g0, %g0, %g0