syscalls.S 6.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
	/* SunOS's execv() call only specifies the argv argument, the
	 * environment settings are the same as the calling processes.
	 */
sys_execve:
	sethi	%hi(sparc_execve), %g1
	ba,pt	%xcc, execve_merge
	 or	%g1, %lo(sparc_execve), %g1

#ifdef CONFIG_COMPAT
sunos_execv:
	stx	%g0, [%sp + PTREGS_OFF + PT_V9_I2]
sys32_execve:
	sethi	%hi(sparc32_execve), %g1
	or	%g1, %lo(sparc32_execve), %g1
#endif

execve_merge:
	flushw
	jmpl	%g1, %g0
	 add	%sp, PTREGS_OFF, %o0

	.align	32
23
sys_sparc_pipe:
24
	ba,pt	%xcc, sys_sparc_pipe_real
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
	 add	%sp, PTREGS_OFF, %o0
sys_nis_syscall:
	ba,pt	%xcc, c_sys_nis_syscall
	 add	%sp, PTREGS_OFF, %o0
sys_memory_ordering:
	ba,pt	%xcc, sparc_memory_ordering
	 add	%sp, PTREGS_OFF, %o1
sys_sigaltstack:
	ba,pt	%xcc, do_sigaltstack
	 add	%i6, STACK_BIAS, %o2
#ifdef CONFIG_COMPAT
sys32_sigstack:
	ba,pt	%xcc, do_sys32_sigstack
	 mov	%i6, %o2
sys32_sigaltstack:
	ba,pt	%xcc, do_sys32_sigaltstack
	 mov	%i6, %o2
#endif
	.align	32
#ifdef CONFIG_COMPAT
sys32_sigreturn:
	add	%sp, PTREGS_OFF, %o0
	call	do_sigreturn32
	 add	%o7, 1f-.-4, %o7
	nop
#endif
sys_rt_sigreturn:
	add	%sp, PTREGS_OFF, %o0
	call	do_rt_sigreturn
	 add	%o7, 1f-.-4, %o7
	nop
#ifdef CONFIG_COMPAT
sys32_rt_sigreturn:
	add	%sp, PTREGS_OFF, %o0
	call	do_rt_sigreturn32
	 add	%o7, 1f-.-4, %o7
	nop
#endif
	.align	32
1:	ldx	[%g6 + TI_FLAGS], %l5
65
	andcc	%l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
66 67
	be,pt	%icc, rtrap
	 nop
68 69
	call	syscall_trace_leave
	 add	%sp, PTREGS_OFF, %o0
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	ba,pt	%xcc, rtrap
	 nop

	/* This is how fork() was meant to be done, 8 instruction entry.
	 *
	 * I questioned the following code briefly, let me clear things
	 * up so you must not reason on it like I did.
	 *
	 * Know the fork_kpsr etc. we use in the sparc32 port?  We don't
	 * need it here because the only piece of window state we copy to
	 * the child is the CWP register.  Even if the parent sleeps,
	 * we are safe because we stuck it into pt_regs of the parent
	 * so it will not change.
	 *
	 * XXX This raises the question, whether we can do the same on
	 * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim.  The
	 * XXX answer is yes.  We stick fork_kpsr in UREG_G0 and
	 * XXX fork_kwim in UREG_G1 (global registers are considered
	 * XXX volatile across a system call in the sparc ABI I think
	 * XXX if it isn't we can use regs->y instead, anyone who depends
	 * XXX upon the Y register being preserved across a fork deserves
	 * XXX to lose).
	 *
	 * In fact we should take advantage of that fact for other things
	 * during system calls...
	 */
	.align	32
sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */
	sethi	%hi(0x4000 | 0x0100 | SIGCHLD), %o0
	or	%o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
	ba,pt	%xcc, sys_clone
sys_fork:
	 clr	%o1
	mov	SIGCHLD, %o0
sys_clone:
	flushw
	movrz	%o1, %fp, %o1
	mov	0, %o3
	ba,pt	%xcc, sparc_do_fork
	 add	%sp, PTREGS_OFF, %o2

	.globl	ret_from_syscall
ret_from_syscall:
113
	/* Clear current_thread_info()->new_child. */
114 115 116 117
	stb	%g0, [%g6 + TI_NEW_CHILD]
	ldx	[%g6 + TI_FLAGS], %l0
	call	schedule_tail
	 mov	%g7, %o0
118
	ba,pt	%xcc, ret_sys_call
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
	 ldx	[%sp + PTREGS_OFF + PT_V9_I0], %o0

	.globl	sparc_exit
	.type	sparc_exit,#function
sparc_exit:
	rdpr	%pstate, %g2
	wrpr	%g2, PSTATE_IE, %pstate
	rdpr	%otherwin, %g1
	rdpr	%cansave, %g3
	add	%g3, %g1, %g3
	wrpr	%g3, 0x0, %cansave
	wrpr	%g0, 0x0, %otherwin
	wrpr	%g2, 0x0, %pstate
	ba,pt	%xcc, sys_exit
	 stb	%g0, [%g6 + TI_WSAVED]
	.size	sparc_exit,.-sparc_exit

linux_sparc_ni_syscall:
	sethi	%hi(sys_ni_syscall), %l7
	ba,pt	%xcc, 4f
	 or	%l7, %lo(sys_ni_syscall), %l7

linux_syscall_trace32:
142 143
	call	syscall_trace_enter
	 add	%sp, PTREGS_OFF, %o0
R
Roland McGrath 已提交
144 145
	brnz,pn	%o0, 3f
	 mov	-ENOSYS, %o0
146 147 148 149 150 151 152 153
	srl	%i0, 0, %o0
	srl	%i4, 0, %o4
	srl	%i1, 0, %o1
	srl	%i2, 0, %o2
	ba,pt	%xcc, 2f
	 srl	%i3, 0, %o3

linux_syscall_trace:
154 155
	call	syscall_trace_enter
	 add	%sp, PTREGS_OFF, %o0
R
Roland McGrath 已提交
156 157
	brnz,pn	%o0, 3f
	 mov	-ENOSYS, %o0
158 159 160 161 162 163 164 165 166 167 168 169 170
	mov	%i0, %o0
	mov	%i1, %o1
	mov	%i2, %o2
	mov	%i3, %o3
	b,pt	%xcc, 2f
	 mov	%i4, %o4


	/* Linux 32-bit system calls enter here... */
	.align	32
	.globl	linux_sparc_syscall32
linux_sparc_syscall32:
	/* Direct access to user regs, much faster. */
171
	cmp	%g1, NR_syscalls			! IEU1	Group
172 173 174 175 176 177 178 179 180 181
	bgeu,pn	%xcc, linux_sparc_ni_syscall		! CTI
	 srl	%i0, 0, %o0				! IEU0
	sll	%g1, 2, %l4				! IEU0	Group
	srl	%i4, 0, %o4				! IEU1
	lduw	[%l7 + %l4], %l7			! Load
	srl	%i1, 0, %o1				! IEU0	Group
	ldx	[%g6 + TI_FLAGS], %l0		! Load

	srl	%i5, 0, %o5				! IEU1
	srl	%i2, 0, %o2				! IEU0	Group
182
	andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
183 184 185 186 187 188 189 190 191 192 193
	bne,pn	%icc, linux_syscall_trace32		! CTI
	 mov	%i0, %l5				! IEU1
	call	%l7					! CTI	Group brk forced
	 srl	%i3, 0, %o3				! IEU0
	ba,a,pt	%xcc, 3f

	/* Linux native system calls enter here... */
	.align	32
	.globl	linux_sparc_syscall
linux_sparc_syscall:
	/* Direct access to user regs, much faster. */
194
	cmp	%g1, NR_syscalls			! IEU1	Group
195 196 197 198 199 200 201 202 203 204
	bgeu,pn	%xcc, linux_sparc_ni_syscall		! CTI
	 mov	%i0, %o0				! IEU0
	sll	%g1, 2, %l4				! IEU0	Group
	mov	%i1, %o1				! IEU1
	lduw	[%l7 + %l4], %l7			! Load
4:	mov	%i2, %o2				! IEU0	Group
	ldx	[%g6 + TI_FLAGS], %l0		! Load

	mov	%i3, %o3				! IEU1
	mov	%i4, %o4				! IEU0	Group
205
	andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
	bne,pn	%icc, linux_syscall_trace		! CTI	Group
	 mov	%i0, %l5				! IEU0
2:	call	%l7					! CTI	Group brk forced
	 mov	%i5, %o5				! IEU0
	nop

3:	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
ret_sys_call:
	ldx	[%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
	sra	%o0, 0, %o0
	mov	%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
	sllx	%g2, 32, %g2

	cmp	%o0, -ERESTART_RESTARTBLOCK
	bgeu,pn	%xcc, 1f
221 222 223 224
	 andcc	%l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc

2:
225 226
	/* System call success, clear Carry condition code. */
	andn	%g3, %g2, %g3
227
3:
228 229 230 231 232 233 234 235
	stx	%g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]	
	bne,pn	%icc, linux_syscall_trace2
	 add	%l1, 0x4, %l2			! npc = npc+4
	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
	ba,pt	%xcc, rtrap
	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]

1:
236 237 238 239 240 241
	/* Check if force_successful_syscall_return()
	 * was invoked.
	 */
	ldub	[%g6 + TI_SYS_NOERROR], %l2
	brnz,pn %l2, 2b
	 ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
242 243 244 245 246
	/* System call failure, set Carry condition code.
	 * Also, get abs(errno) to return to the process.
	 */
	sub	%g0, %o0, %o0
	stx	%o0, [%sp + PTREGS_OFF + PT_V9_I0]
247 248
	ba,pt	%xcc, 3b
	 or	%g3, %g2, %g3
249 250

linux_syscall_trace2:
251 252
	call	syscall_trace_leave
	 add	%sp, PTREGS_OFF, %o0
253 254 255
	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC]
	ba,pt	%xcc, rtrap
	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC]