Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210107' into staging
[qemu/ar7.git] / linux-user / host / s390x / safe-syscall.inc.S
blob414b44ad38c0758ca72e1ffeccb6d7339e5fcfdd
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         stmg    %r6,%r15,48(%r15)       /* save all call-saved registers */
30         .cfi_offset %r15,-40
31         .cfi_offset %r14,-48
32         .cfi_offset %r13,-56
33         .cfi_offset %r12,-64
34         .cfi_offset %r11,-72
35         .cfi_offset %r10,-80
36         .cfi_offset %r9,-88
37         .cfi_offset %r8,-96
38         .cfi_offset %r7,-104
39         .cfi_offset %r6,-112
40         lgr     %r1,%r15
41         lg      %r0,8(%r15)             /* load eos */
42         aghi    %r15,-160
43         .cfi_adjust_cfa_offset 160
44         stg     %r1,0(%r15)             /* store back chain */
45         stg     %r0,8(%r15)             /* store eos */
47         /* The syscall calling convention isn't the same as the
48          * C one:
49          * we enter with r2 == *signal_pending
50          *               r3 == syscall number
51          *               r4, r5, r6, (stack) == syscall arguments
52          *               and return the result in r2
53          * and the syscall instruction needs
54          *               r1 == syscall number
55          *               r2 ... r7 == syscall arguments
56          *               and returns the result in r2
57          * Shuffle everything around appropriately.
58          */
59         lgr     %r8,%r2                 /* signal_pending pointer */
60         lgr     %r1,%r3                 /* syscall number */
61         lgr     %r2,%r4                 /* syscall args */
62         lgr     %r3,%r5
63         lgr     %r4,%r6
64         lmg     %r5,%r7,320(%r15)
66         /* This next sequence of code works in conjunction with the
67          * rewind_if_safe_syscall_function(). If a signal is taken
68          * and the interrupted PC is anywhere between 'safe_syscall_start'
69          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
70          * The code sequence must therefore be able to cope with this, and
71          * the syscall instruction must be the final one in the sequence.
72          */
73 safe_syscall_start:
74         /* if signal_pending is non-zero, don't do the call */
75         icm     %r0,15,0(%r8)
76         jne     2f
77         svc     0
78 safe_syscall_end:
80 1:      lg      %r15,0(%r15)            /* load back chain */
81         .cfi_remember_state
82         .cfi_adjust_cfa_offset -160
83         lmg     %r6,%r15,48(%r15)       /* load saved registers */
84         br      %r14
85         .cfi_restore_state
86 2:      lghi    %r2, -TARGET_ERESTARTSYS
87         j       1b
88         .cfi_endproc
90         .size   safe_syscall_base, .-safe_syscall_base