Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-04-30' into staging
[qemu/ar7.git] / linux-user / host / x86_64 / safe-syscall.inc.S
blobf36992daa34e0f59c621d506bdda00e281e437be
1 /*
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 linux-user/safe-syscall.S
5  *
6  * Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
7  *
8  * This work is licensed under the terms of the GNU GPL, version 2 or later.
9  * See the COPYING file in the top-level directory.
10  */
12         .global safe_syscall_base
13         .global safe_syscall_start
14         .global safe_syscall_end
15         .type   safe_syscall_base, @function
17         /* This is the entry point for making a system call. The calling
18          * convention here is that of a C varargs function with the
19          * first argument an 'int *' to the signal_pending flag, the
20          * second one the system call number (as a 'long'), and all further
21          * arguments being syscall arguments (also 'long').
22          * We return a long which is the syscall's return value, which
23          * may be negative-errno on failure. Conversion to the
24          * -1-and-errno-set convention is done by the calling wrapper.
25          */
26 safe_syscall_base:
27         .cfi_startproc
28         /* This saves a frame pointer and aligns the stack for the syscall.
29          * (It's unclear if the syscall ABI has the same stack alignment
30          * requirements as the userspace function call ABI, but better safe than
31          * sorry. Appendix A2 of http://www.x86-64.org/documentation/abi.pdf
32          * does not list any ABI differences regarding stack alignment.)
33          */
34         push    %rbp
35         .cfi_adjust_cfa_offset 8
36         .cfi_rel_offset rbp, 0
38         /* The syscall calling convention isn't the same as the
39          * C one:
40          * we enter with rdi == *signal_pending
41          *               rsi == syscall number
42          *               rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
43          *               and return the result in rax
44          * and the syscall instruction needs
45          *               rax == syscall number
46          *               rdi, rsi, rdx, r10, r8, r9 == syscall arguments
47          *               and returns the result in rax
48          * Shuffle everything around appropriately.
49          * Note that syscall will trash rcx and r11.
50          */
51         mov     %rsi, %rax /* syscall number */
52         mov     %rdi, %rbp /* signal_pending pointer */
53         /* and the syscall arguments */
54         mov     %rdx, %rdi
55         mov     %rcx, %rsi
56         mov     %r8,  %rdx
57         mov     %r9,  %r10
58         mov     16(%rsp), %r8
59         mov     24(%rsp), %r9
61         /* This next sequence of code works in conjunction with the
62          * rewind_if_safe_syscall_function(). If a signal is taken
63          * and the interrupted PC is anywhere between 'safe_syscall_start'
64          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
65          * The code sequence must therefore be able to cope with this, and
66          * the syscall instruction must be the final one in the sequence.
67          */
68 safe_syscall_start:
69         /* if signal_pending is non-zero, don't do the call */
70         cmpl    $0, (%rbp)
71         jnz     1f
72         syscall
73 safe_syscall_end:
74         /* code path for having successfully executed the syscall */
75         pop     %rbp
76         .cfi_remember_state
77         .cfi_def_cfa_offset 8
78         .cfi_restore rbp
79         ret
82         /* code path when we didn't execute the syscall */
83         .cfi_restore_state
84         mov     $-TARGET_ERESTARTSYS, %rax
85         pop     %rbp
86         .cfi_def_cfa_offset 8
87         .cfi_restore rbp
88         ret
89         .cfi_endproc
91         .size   safe_syscall_base, .-safe_syscall_base