Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / common-user / host / x86_64 / safe-syscall.inc.S
blobd1a67a303a9f3e021f536e6a7d73ccd16d79cd18
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 common-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          */
23 safe_syscall_base:
24         .cfi_startproc
25         /* This saves a frame pointer and aligns the stack for the syscall.
26          * (It's unclear if the syscall ABI has the same stack alignment
27          * requirements as the userspace function call ABI, but better safe than
28          * sorry. Appendix A2 of http://www.x86-64.org/documentation/abi.pdf
29          * does not list any ABI differences regarding stack alignment.)
30          */
31         push    %rbp
32         .cfi_adjust_cfa_offset 8
33         .cfi_rel_offset rbp, 0
35         /*
36          * The syscall calling convention isn't the same as the C one:
37          * we enter with rdi == &signal_pending
38          *               rsi == syscall number
39          *               rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
40          *               and return the result in rax
41          * and the syscall instruction needs
42          *               rax == syscall number
43          *               rdi, rsi, rdx, r10, r8, r9 == syscall arguments
44          *               and returns the result in rax
45          * Shuffle everything around appropriately.
46          * Note that syscall will trash rcx and r11.
47          */
48         mov     %rsi, %rax /* syscall number */
49         mov     %rdi, %rbp /* signal_pending pointer */
50         /* and the syscall arguments */
51         mov     %rdx, %rdi
52         mov     %rcx, %rsi
53         mov     %r8,  %rdx
54         mov     %r9,  %r10
55         mov     16(%rsp), %r8
56         mov     24(%rsp), %r9
58         /* This next sequence of code works in conjunction with the
59          * rewind_if_safe_syscall_function(). If a signal is taken
60          * and the interrupted PC is anywhere between 'safe_syscall_start'
61          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
62          * The code sequence must therefore be able to cope with this, and
63          * the syscall instruction must be the final one in the sequence.
64          */
65 safe_syscall_start:
66         /* if signal_pending is non-zero, don't do the call */
67         cmpl    $0, (%rbp)
68         jnz     2f
69         syscall
70 safe_syscall_end:
72         /* code path for having successfully executed the syscall */
73 #if defined(__linux__)
74         /* Linux kernel returns (small) negative errno. */
75         cmp     $-4095, %rax
76         jae     0f
77 #elif defined(__FreeBSD__)
78         /* FreeBSD kernel returns positive errno and C bit set. */
79         jc      1f
80 #else
81 #error "unsupported os"
82 #endif
83         pop     %rbp
84         .cfi_remember_state
85         .cfi_def_cfa_offset 8
86         .cfi_restore rbp
87         ret
88         .cfi_restore_state
90 #if defined(__linux__)
91 0:      neg     %eax
92         jmp     1f
93 #endif
95         /* code path when we didn't execute the syscall */
96 2:      mov     $QEMU_ERESTARTSYS, %eax
98         /* code path setting errno */
99 1:      pop     %rbp
100         .cfi_def_cfa_offset 8
101         .cfi_restore rbp
102         mov     %eax, %edi
103         jmp     safe_syscall_set_errno_tail
104         .cfi_endproc
106         .size   safe_syscall_base, .-safe_syscall_base