MAINTAINERS: Cover docs/igd-assign.txt in VFIO section
[qemu/ar7.git] / linux-user / host / i386 / safe-syscall.inc.S
blob9e58fc650455f452972007af9eb25d2851c0f3dd
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  * Written by Richard Henderson <rth@twiddle.net>
7  * Copyright (C) 2016 Red Hat, Inc.
8  *
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.
11  */
13         .global safe_syscall_base
14         .global safe_syscall_start
15         .global safe_syscall_end
16         .type   safe_syscall_base, @function
18         /* This is the entry point for making a system call. The calling
19          * convention here is that of a C varargs function with the
20          * first argument an 'int *' to the signal_pending flag, the
21          * second one the system call number (as a 'long'), and all further
22          * arguments being syscall arguments (also 'long').
23          * We return a long which is the syscall's return value, which
24          * may be negative-errno on failure. Conversion to the
25          * -1-and-errno-set convention is done by the calling wrapper.
26          */
27 safe_syscall_base:
28         .cfi_startproc
29         push    %ebp
30         .cfi_adjust_cfa_offset 4
31         .cfi_rel_offset ebp, 0
32         push    %esi
33         .cfi_adjust_cfa_offset 4
34         .cfi_rel_offset esi, 0
35         push    %edi
36         .cfi_adjust_cfa_offset 4
37         .cfi_rel_offset edi, 0
38         push    %ebx
39         .cfi_adjust_cfa_offset 4
40         .cfi_rel_offset ebx, 0
42         /* The syscall calling convention isn't the same as the C one:
43          * we enter with 0(%esp) == return address
44          *               4(%esp) == *signal_pending
45          *               8(%esp) == syscall number
46          *               12(%esp) ... 32(%esp) == syscall arguments
47          *               and return the result in eax
48          * and the syscall instruction needs
49          *               eax == syscall number
50          *               ebx, ecx, edx, esi, edi, ebp == syscall arguments
51          *               and returns the result in eax
52          * Shuffle everything around appropriately.
53          * Note the 16 bytes that we pushed to save registers.
54          */
55         mov     12+16(%esp), %ebx       /* the syscall arguments */
56         mov     16+16(%esp), %ecx
57         mov     20+16(%esp), %edx
58         mov     24+16(%esp), %esi
59         mov     28+16(%esp), %edi
60         mov     32+16(%esp), %ebp
62         /* This next sequence of code works in conjunction with the
63          * rewind_if_safe_syscall_function(). If a signal is taken
64          * and the interrupted PC is anywhere between 'safe_syscall_start'
65          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
66          * The code sequence must therefore be able to cope with this, and
67          * the syscall instruction must be the final one in the sequence.
68          */
69 safe_syscall_start:
70         /* if signal_pending is non-zero, don't do the call */
71         mov     4+16(%esp), %eax        /* signal_pending */
72         cmpl    $0, (%eax)
73         jnz     1f
74         mov     8+16(%esp), %eax        /* syscall number */
75         int     $0x80
76 safe_syscall_end:
77         /* code path for having successfully executed the syscall */
78         pop     %ebx
79         .cfi_remember_state
80         .cfi_adjust_cfa_offset -4
81         .cfi_restore ebx
82         pop     %edi
83         .cfi_adjust_cfa_offset -4
84         .cfi_restore edi
85         pop     %esi
86         .cfi_adjust_cfa_offset -4
87         .cfi_restore esi
88         pop     %ebp
89         .cfi_adjust_cfa_offset -4
90         .cfi_restore ebp
91         ret
94         /* code path when we didn't execute the syscall */
95         .cfi_restore_state
96         mov     $-TARGET_ERESTARTSYS, %eax
97         jmp     safe_syscall_end
98         .cfi_endproc
100         .size   safe_syscall_base, .-safe_syscall_base