2 * safe-syscall.inc.S : host-specific assembly fragment
3 * to handle signals occurring at the same time as system calls.
4 * This is intended to be included by common-user/safe-syscall.S
6 * Written by Richard Henderson <richard.henderson@linaro.org>
7 * Copyright (C) 2021 Linaro, Inc.
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
13 #include "sys/regdef.h"
20 .global safe_syscall_start
21 .global safe_syscall_end
22 .type safe_syscall_start, @function
23 .type safe_syscall_end, @function
26 * This is the entry point for making a system call. The calling
27 * convention here is that of a C varargs function with the
28 * first argument an 'int *' to the signal_pending flag, the
29 * second one the system call number (as a 'long'), and all further
30 * arguments being syscall arguments (also 'long').
33 #if _MIPS_SIM == _ABIO32
34 /* 8 * 4 = 32 for outgoing parameters; 1 * 4 for s0 save; 1 * 4 for align. */
38 /* 1 * 8 for s0 save; 1 * 8 for align. */
44 NESTED(safe_syscall_base, FRAME, ra)
46 PTR_ADDIU sp, sp, -FRAME
47 .cfi_adjust_cfa_offset FRAME
49 .cfi_rel_offset s0, OFS_S0
50 #if _MIPS_SIM == _ABIO32
52 * The syscall calling convention is nearly the same as C:
53 * we enter with a0 == &signal_pending
54 * a1 == syscall number
55 * a2, a3, stack == syscall arguments
56 * and return the result in a0
57 * and the syscall instruction needs
58 * v0 == syscall number
59 * a0 ... a3, stack == syscall arguments
60 * and returns the result in v0
61 * Shuffle everything around appropriately.
63 move s0, a0 /* signal_pending pointer */
64 move v0, a1 /* syscall number */
65 move a0, a2 /* syscall arguments */
79 * The syscall calling convention is nearly the same as C:
80 * we enter with a0 == &signal_pending
81 * a1 == syscall number
82 * a2 ... a7 == syscall arguments
83 * and return the result in a0
84 * and the syscall instruction needs
85 * v0 == syscall number
86 * a0 ... a5 == syscall arguments
87 * and returns the result in v0
88 * Shuffle everything around appropriately.
90 move s0, a0 /* signal_pending pointer */
91 move v0, a1 /* syscall number */
92 move a0, a2 /* syscall arguments */
101 * This next sequence of code works in conjunction with the
102 * rewind_if_safe_syscall_function(). If a signal is taken
103 * and the interrupted PC is anywhere between 'safe_syscall_start'
104 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
105 * The code sequence must therefore be able to cope with this, and
106 * the syscall instruction must be the final one in the sequence.
109 /* If signal_pending is non-zero, don't do the call */
115 /* code path for having successfully executed the syscall */
117 PTR_ADDIU sp, sp, FRAME
119 .cfi_adjust_cfa_offset -FRAME
125 /* code path when we didn't execute the syscall */
126 2: REG_L s0, OFS_S0(sp)
127 PTR_ADDIU sp, sp, FRAME
128 .cfi_adjust_cfa_offset -FRAME
130 li v0, QEMU_ERESTARTSYS
132 /* code path setting errno */
134 * We didn't setup GP on entry, optimistic of the syscall success.
135 * We must do so now to load the address of the helper, as required
136 * by the ABI, into t9.
138 * Note that SETUP_GPX and SETUP_GPX64 are themselves conditional,
139 * so we can simply let the one that's not empty succeed.
145 PTR_LA t9, safe_syscall_set_errno_tail
149 END(safe_syscall_base)