xref: /qemu/common-user/host/riscv/safe-syscall.inc.S (revision b8c92c6d2969e88b252f1d2351237a87981d1e74)
1*b8c92c6dSRichard Henderson/*
2*b8c92c6dSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment
3*b8c92c6dSRichard Henderson * to handle signals occurring at the same time as system calls.
4*b8c92c6dSRichard Henderson * This is intended to be included by linux-user/safe-syscall.S
5*b8c92c6dSRichard Henderson *
6*b8c92c6dSRichard Henderson * Written by Richard Henderson <rth@twiddle.net>
7*b8c92c6dSRichard Henderson * Copyright (C) 2018 Linaro, Inc.
8*b8c92c6dSRichard Henderson *
9*b8c92c6dSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later.
10*b8c92c6dSRichard Henderson * See the COPYING file in the top-level directory.
11*b8c92c6dSRichard Henderson */
12*b8c92c6dSRichard Henderson
13*b8c92c6dSRichard Henderson	.global safe_syscall_base
14*b8c92c6dSRichard Henderson	.global safe_syscall_start
15*b8c92c6dSRichard Henderson	.global safe_syscall_end
16*b8c92c6dSRichard Henderson	.type	safe_syscall_base, @function
17*b8c92c6dSRichard Henderson	.type	safe_syscall_start, @function
18*b8c92c6dSRichard Henderson	.type	safe_syscall_end, @function
19*b8c92c6dSRichard Henderson
20*b8c92c6dSRichard Henderson	/*
21*b8c92c6dSRichard Henderson	 * This is the entry point for making a system call. The calling
22*b8c92c6dSRichard Henderson	 * convention here is that of a C varargs function with the
23*b8c92c6dSRichard Henderson	 * first argument an 'int *' to the signal_pending flag, the
24*b8c92c6dSRichard Henderson	 * second one the system call number (as a 'long'), and all further
25*b8c92c6dSRichard Henderson	 * arguments being syscall arguments (also 'long').
26*b8c92c6dSRichard Henderson	 * We return a long which is the syscall's return value, which
27*b8c92c6dSRichard Henderson	 * may be negative-errno on failure. Conversion to the
28*b8c92c6dSRichard Henderson	 * -1-and-errno-set convention is done by the calling wrapper.
29*b8c92c6dSRichard Henderson	 */
30*b8c92c6dSRichard Hendersonsafe_syscall_base:
31*b8c92c6dSRichard Henderson	.cfi_startproc
32*b8c92c6dSRichard Henderson	/*
33*b8c92c6dSRichard Henderson	 * The syscall calling convention is nearly the same as C:
34*b8c92c6dSRichard Henderson	 * we enter with a0 == *signal_pending
35*b8c92c6dSRichard Henderson	 *               a1 == syscall number
36*b8c92c6dSRichard Henderson	 *               a2 ... a7 == syscall arguments
37*b8c92c6dSRichard Henderson	 *               and return the result in a0
38*b8c92c6dSRichard Henderson	 * and the syscall instruction needs
39*b8c92c6dSRichard Henderson	 *               a7 == syscall number
40*b8c92c6dSRichard Henderson	 *               a0 ... a5 == syscall arguments
41*b8c92c6dSRichard Henderson	 *               and returns the result in a0
42*b8c92c6dSRichard Henderson	 * Shuffle everything around appropriately.
43*b8c92c6dSRichard Henderson	 */
44*b8c92c6dSRichard Henderson	mv	t0, a0		/* signal_pending pointer */
45*b8c92c6dSRichard Henderson	mv	t1, a1		/* syscall number */
46*b8c92c6dSRichard Henderson	mv	a0, a2		/* syscall arguments */
47*b8c92c6dSRichard Henderson	mv	a1, a3
48*b8c92c6dSRichard Henderson	mv	a2, a4
49*b8c92c6dSRichard Henderson	mv	a3, a5
50*b8c92c6dSRichard Henderson	mv	a4, a6
51*b8c92c6dSRichard Henderson	mv	a5, a7
52*b8c92c6dSRichard Henderson	mv	a7, t1
53*b8c92c6dSRichard Henderson
54*b8c92c6dSRichard Henderson	/*
55*b8c92c6dSRichard Henderson	 * This next sequence of code works in conjunction with the
56*b8c92c6dSRichard Henderson	 * rewind_if_safe_syscall_function(). If a signal is taken
57*b8c92c6dSRichard Henderson	 * and the interrupted PC is anywhere between 'safe_syscall_start'
58*b8c92c6dSRichard Henderson	 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
59*b8c92c6dSRichard Henderson	 * The code sequence must therefore be able to cope with this, and
60*b8c92c6dSRichard Henderson	 * the syscall instruction must be the final one in the sequence.
61*b8c92c6dSRichard Henderson	 */
62*b8c92c6dSRichard Hendersonsafe_syscall_start:
63*b8c92c6dSRichard Henderson	/* If signal_pending is non-zero, don't do the call */
64*b8c92c6dSRichard Henderson	lw	t1, 0(t0)
65*b8c92c6dSRichard Henderson	bnez	t1, 0f
66*b8c92c6dSRichard Henderson	scall
67*b8c92c6dSRichard Hendersonsafe_syscall_end:
68*b8c92c6dSRichard Henderson	/* code path for having successfully executed the syscall */
69*b8c92c6dSRichard Henderson	ret
70*b8c92c6dSRichard Henderson
71*b8c92c6dSRichard Henderson0:
72*b8c92c6dSRichard Henderson	/* code path when we didn't execute the syscall */
73*b8c92c6dSRichard Henderson	li	a0, -TARGET_ERESTARTSYS
74*b8c92c6dSRichard Henderson	ret
75*b8c92c6dSRichard Henderson	.cfi_endproc
76*b8c92c6dSRichard Henderson
77*b8c92c6dSRichard Henderson	.size	safe_syscall_base, .-safe_syscall_base
78