root/arch/sparc/kernel/syscalls.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2         /* SunOS's execv() call only specifies the argv argument, the
   3          * environment settings are the same as the calling processes.
   4          */
   5 sys64_execve:
   6         set     sys_execve, %g1
   7         jmpl    %g1, %g0
   8          flushw
   9 
  10 sys64_execveat:
  11         set     sys_execveat, %g1
  12         jmpl    %g1, %g0
  13          flushw
  14 
  15 #ifdef CONFIG_COMPAT
  16 sunos_execv:
  17         mov     %g0, %o2
  18 sys32_execve:
  19         set     compat_sys_execve, %g1
  20         jmpl    %g1, %g0
  21          flushw
  22 
  23 sys32_execveat:
  24         set     compat_sys_execveat, %g1
  25         jmpl    %g1, %g0
  26          flushw
  27 #endif
  28 
  29         .align  32
  30 #ifdef CONFIG_COMPAT
  31 sys32_sigstack:
  32         ba,pt   %xcc, do_sys32_sigstack
  33          mov    %i6, %o2
  34 #endif
  35         .align  32
  36 #ifdef CONFIG_COMPAT
  37 sys32_sigreturn:
  38         add     %sp, PTREGS_OFF, %o0
  39         call    do_sigreturn32
  40          add    %o7, 1f-.-4, %o7
  41         nop
  42 #endif
  43 sys_rt_sigreturn:
  44         add     %sp, PTREGS_OFF, %o0
  45         call    do_rt_sigreturn
  46          add    %o7, 1f-.-4, %o7
  47         nop
  48 #ifdef CONFIG_COMPAT
  49 sys32_rt_sigreturn:
  50         add     %sp, PTREGS_OFF, %o0
  51         call    do_rt_sigreturn32
  52          add    %o7, 1f-.-4, %o7
  53         nop
  54 #endif
  55         .align  32
  56 1:      ldx     [%g6 + TI_FLAGS], %l5
  57         andcc   %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0
  58         be,pt   %icc, rtrap
  59          nop
  60         call    syscall_trace_leave
  61          add    %sp, PTREGS_OFF, %o0
  62         ba,pt   %xcc, rtrap
  63          nop
  64 
  65         /* This is how fork() was meant to be done, 8 instruction entry.
  66          *
  67          * I questioned the following code briefly, let me clear things
  68          * up so you must not reason on it like I did.
  69          *
  70          * Know the fork_kpsr etc. we use in the sparc32 port?  We don't
  71          * need it here because the only piece of window state we copy to
  72          * the child is the CWP register.  Even if the parent sleeps,
  73          * we are safe because we stuck it into pt_regs of the parent
  74          * so it will not change.
  75          *
  76          * XXX This raises the question, whether we can do the same on
  77          * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim.  The
  78          * XXX answer is yes.  We stick fork_kpsr in UREG_G0 and
  79          * XXX fork_kwim in UREG_G1 (global registers are considered
  80          * XXX volatile across a system call in the sparc ABI I think
  81          * XXX if it isn't we can use regs->y instead, anyone who depends
  82          * XXX upon the Y register being preserved across a fork deserves
  83          * XXX to lose).
  84          *
  85          * In fact we should take advantage of that fact for other things
  86          * during system calls...
  87          */
  88         .align  32
  89 sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */
  90         sethi   %hi(0x4000 | 0x0100 | SIGCHLD), %o0
  91         or      %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
  92         ba,pt   %xcc, sys_clone
  93 sys_fork:
  94          clr    %o1
  95         mov     SIGCHLD, %o0
  96 sys_clone:
  97         flushw
  98         movrz   %o1, %fp, %o1
  99         mov     0, %o3
 100         ba,pt   %xcc, sparc_do_fork
 101          add    %sp, PTREGS_OFF, %o2
 102 
 103         .globl  ret_from_fork
 104 ret_from_fork:
 105         /* Clear current_thread_info()->new_child. */
 106         stb     %g0, [%g6 + TI_NEW_CHILD]
 107         call    schedule_tail
 108          mov    %g7, %o0
 109         ldx     [%sp + PTREGS_OFF + PT_V9_I0], %o0
 110         brnz,pt %o0, ret_sys_call
 111          ldx    [%g6 + TI_FLAGS], %l0
 112         ldx     [%sp + PTREGS_OFF + PT_V9_G1], %l1
 113         call    %l1
 114          ldx    [%sp + PTREGS_OFF + PT_V9_G2], %o0
 115         ba,pt   %xcc, ret_sys_call
 116          mov    0, %o0
 117 
 118         .globl  sparc_exit_group
 119         .type   sparc_exit_group,#function
 120 sparc_exit_group:
 121         sethi   %hi(sys_exit_group), %g7
 122         ba,pt   %xcc, 1f
 123          or     %g7, %lo(sys_exit_group), %g7
 124         .size   sparc_exit_group,.-sparc_exit_group
 125 
 126         .globl  sparc_exit
 127         .type   sparc_exit,#function
 128 sparc_exit:
 129         sethi   %hi(sys_exit), %g7
 130         or      %g7, %lo(sys_exit), %g7
 131 1:      rdpr    %pstate, %g2
 132         wrpr    %g2, PSTATE_IE, %pstate
 133         rdpr    %otherwin, %g1
 134         rdpr    %cansave, %g3
 135         add     %g3, %g1, %g3
 136         wrpr    %g3, 0x0, %cansave
 137         wrpr    %g0, 0x0, %otherwin
 138         wrpr    %g2, 0x0, %pstate
 139         jmpl    %g7, %g0
 140          stb    %g0, [%g6 + TI_WSAVED]
 141         .size   sparc_exit,.-sparc_exit
 142 
 143 linux_sparc_ni_syscall:
 144         sethi   %hi(sys_ni_syscall), %l7
 145         ba,pt   %xcc, 4f
 146          or     %l7, %lo(sys_ni_syscall), %l7
 147 
 148 linux_syscall_trace32:
 149         call    syscall_trace_enter
 150          add    %sp, PTREGS_OFF, %o0
 151         brnz,pn %o0, 3f
 152          mov    -ENOSYS, %o0
 153 
 154         /* Syscall tracing can modify the registers.  */
 155         ldx     [%sp + PTREGS_OFF + PT_V9_G1], %g1
 156         sethi   %hi(sys_call_table32), %l7
 157         ldx     [%sp + PTREGS_OFF + PT_V9_I0], %i0
 158         or      %l7, %lo(sys_call_table32), %l7
 159         ldx     [%sp + PTREGS_OFF + PT_V9_I1], %i1
 160         ldx     [%sp + PTREGS_OFF + PT_V9_I2], %i2
 161         ldx     [%sp + PTREGS_OFF + PT_V9_I3], %i3
 162         ldx     [%sp + PTREGS_OFF + PT_V9_I4], %i4
 163         ldx     [%sp + PTREGS_OFF + PT_V9_I5], %i5
 164 
 165         cmp     %g1, NR_syscalls
 166         bgeu,pn %xcc, 3f
 167          mov    -ENOSYS, %o0
 168 
 169         sll     %g1, 2, %l4
 170         srl     %i0, 0, %o0
 171         lduw    [%l7 + %l4], %l7
 172         srl     %i4, 0, %o4
 173         srl     %i1, 0, %o1
 174         srl     %i2, 0, %o2
 175         ba,pt   %xcc, 5f
 176          srl    %i3, 0, %o3
 177 
 178 linux_syscall_trace:
 179         call    syscall_trace_enter
 180          add    %sp, PTREGS_OFF, %o0
 181         brnz,pn %o0, 3f
 182          mov    -ENOSYS, %o0
 183 
 184         /* Syscall tracing can modify the registers.  */
 185         ldx     [%sp + PTREGS_OFF + PT_V9_G1], %g1
 186         sethi   %hi(sys_call_table64), %l7
 187         ldx     [%sp + PTREGS_OFF + PT_V9_I0], %i0
 188         or      %l7, %lo(sys_call_table64), %l7
 189         ldx     [%sp + PTREGS_OFF + PT_V9_I1], %i1
 190         ldx     [%sp + PTREGS_OFF + PT_V9_I2], %i2
 191         ldx     [%sp + PTREGS_OFF + PT_V9_I3], %i3
 192         ldx     [%sp + PTREGS_OFF + PT_V9_I4], %i4
 193         ldx     [%sp + PTREGS_OFF + PT_V9_I5], %i5
 194 
 195         cmp     %g1, NR_syscalls
 196         bgeu,pn %xcc, 3f
 197          mov    -ENOSYS, %o0
 198 
 199         sll     %g1, 2, %l4
 200         mov     %i0, %o0
 201         lduw    [%l7 + %l4], %l7
 202         mov     %i1, %o1
 203         mov     %i2, %o2
 204         mov     %i3, %o3
 205         b,pt    %xcc, 2f
 206          mov    %i4, %o4
 207 
 208 
 209         /* Linux 32-bit system calls enter here... */
 210         .align  32
 211         .globl  linux_sparc_syscall32
 212 linux_sparc_syscall32:
 213         /* Direct access to user regs, much faster. */
 214         cmp     %g1, NR_syscalls                        ! IEU1  Group
 215         bgeu,pn %xcc, linux_sparc_ni_syscall            ! CTI
 216          srl    %i0, 0, %o0                             ! IEU0
 217         sll     %g1, 2, %l4                             ! IEU0  Group
 218         srl     %i4, 0, %o4                             ! IEU1
 219         lduw    [%l7 + %l4], %l7                        ! Load
 220         srl     %i1, 0, %o1                             ! IEU0  Group
 221         ldx     [%g6 + TI_FLAGS], %l0           ! Load
 222 
 223         srl     %i3, 0, %o3                             ! IEU0
 224         srl     %i2, 0, %o2                             ! IEU0  Group
 225         andcc   %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0
 226         bne,pn  %icc, linux_syscall_trace32             ! CTI
 227          mov    %i0, %l5                                ! IEU1
 228 5:      call    %l7                                     ! CTI   Group brk forced
 229          srl    %i5, 0, %o5                             ! IEU1
 230         ba,pt   %xcc, 3f
 231          sra    %o0, 0, %o0
 232 
 233         /* Linux native system calls enter here... */
 234         .align  32
 235         .globl  linux_sparc_syscall
 236 linux_sparc_syscall:
 237         /* Direct access to user regs, much faster. */
 238         cmp     %g1, NR_syscalls                        ! IEU1  Group
 239         bgeu,pn %xcc, linux_sparc_ni_syscall            ! CTI
 240          mov    %i0, %o0                                ! IEU0
 241         sll     %g1, 2, %l4                             ! IEU0  Group
 242         mov     %i1, %o1                                ! IEU1
 243         lduw    [%l7 + %l4], %l7                        ! Load
 244 4:      mov     %i2, %o2                                ! IEU0  Group
 245         ldx     [%g6 + TI_FLAGS], %l0           ! Load
 246 
 247         mov     %i3, %o3                                ! IEU1
 248         mov     %i4, %o4                                ! IEU0  Group
 249         andcc   %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0
 250         bne,pn  %icc, linux_syscall_trace               ! CTI   Group
 251          mov    %i0, %l5                                ! IEU0
 252 2:      call    %l7                                     ! CTI   Group brk forced
 253          mov    %i5, %o5                                ! IEU0
 254         nop
 255 
 256 3:      stx     %o0, [%sp + PTREGS_OFF + PT_V9_I0]
 257 ret_sys_call:
 258         ldx     [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
 259         mov     %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
 260         sllx    %g2, 32, %g2
 261 
 262         cmp     %o0, -ERESTART_RESTARTBLOCK
 263         bgeu,pn %xcc, 1f
 264          andcc  %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT|_TIF_NOHZ), %g0
 265         ldx     [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 266 
 267 2:
 268         /* System call success, clear Carry condition code. */
 269         andn    %g3, %g2, %g3
 270 3:
 271         stx     %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]  
 272         bne,pn  %icc, linux_syscall_trace2
 273          add    %l1, 0x4, %l2                   ! npc = npc+4
 274         stx     %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
 275         ba,pt   %xcc, rtrap
 276          stx    %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
 277 
 278 1:
 279         /* Check if force_successful_syscall_return()
 280          * was invoked.
 281          */
 282         ldub    [%g6 + TI_SYS_NOERROR], %l2
 283         brnz,pn %l2, 2b
 284          ldx    [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 285         /* System call failure, set Carry condition code.
 286          * Also, get abs(errno) to return to the process.
 287          */
 288         sub     %g0, %o0, %o0
 289         stx     %o0, [%sp + PTREGS_OFF + PT_V9_I0]
 290         ba,pt   %xcc, 3b
 291          or     %g3, %g2, %g3
 292 
 293 linux_syscall_trace2:
 294         call    syscall_trace_leave
 295          add    %sp, PTREGS_OFF, %o0
 296         stx     %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
 297         ba,pt   %xcc, rtrap
 298          stx    %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]

/* [<][>][^][v][top][bottom][index][help] */