xref: /qemu/common-user/host/riscv/safe-syscall.inc.S (revision 22b448ccc6611a59d4aa54419f4d88c1f343cb35)
1b8c92c6dSRichard Henderson/*
2b8c92c6dSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment
3b8c92c6dSRichard Henderson * to handle signals occurring at the same time as system calls.
4bbf15aafSRichard Henderson * This is intended to be included by common-user/safe-syscall.S
5b8c92c6dSRichard Henderson *
6b8c92c6dSRichard Henderson * Written by Richard Henderson <rth@twiddle.net>
7b8c92c6dSRichard Henderson * Copyright (C) 2018 Linaro, Inc.
8b8c92c6dSRichard Henderson *
9b8c92c6dSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later.
10b8c92c6dSRichard Henderson * See the COPYING file in the top-level directory.
11b8c92c6dSRichard Henderson */
12b8c92c6dSRichard Henderson
13b8c92c6dSRichard Henderson        .global safe_syscall_base
14b8c92c6dSRichard Henderson        .global safe_syscall_start
15b8c92c6dSRichard Henderson        .global safe_syscall_end
16b8c92c6dSRichard Henderson        .type   safe_syscall_base, @function
17b8c92c6dSRichard Henderson        .type   safe_syscall_start, @function
18b8c92c6dSRichard Henderson        .type   safe_syscall_end, @function
19b8c92c6dSRichard Henderson
20b8c92c6dSRichard Henderson        /*
21b8c92c6dSRichard Henderson         * This is the entry point for making a system call. The calling
22b8c92c6dSRichard Henderson         * convention here is that of a C varargs function with the
23b8c92c6dSRichard Henderson         * first argument an 'int *' to the signal_pending flag, the
24b8c92c6dSRichard Henderson         * second one the system call number (as a 'long'), and all further
25b8c92c6dSRichard Henderson         * arguments being syscall arguments (also 'long').
26b8c92c6dSRichard Henderson         */
27b8c92c6dSRichard Hendersonsafe_syscall_base:
28b8c92c6dSRichard Henderson        .cfi_startproc
29b8c92c6dSRichard Henderson        /*
30b8c92c6dSRichard Henderson         * The syscall calling convention is nearly the same as C:
31a3310c03SRichard Henderson         * we enter with a0 == &signal_pending
32b8c92c6dSRichard Henderson         *               a1 == syscall number
33b8c92c6dSRichard Henderson         *               a2 ... a7 == syscall arguments
34b8c92c6dSRichard Henderson         *               and return the result in a0
35b8c92c6dSRichard Henderson         * and the syscall instruction needs
36b8c92c6dSRichard Henderson         *               a7 == syscall number
37b8c92c6dSRichard Henderson         *               a0 ... a5 == syscall arguments
38b8c92c6dSRichard Henderson         *               and returns the result in a0
39b8c92c6dSRichard Henderson         * Shuffle everything around appropriately.
40b8c92c6dSRichard Henderson         */
41b8c92c6dSRichard Henderson        mv      t0, a0          /* signal_pending pointer */
42b8c92c6dSRichard Henderson        mv      t1, a1          /* syscall number */
43b8c92c6dSRichard Henderson        mv      a0, a2          /* syscall arguments */
44b8c92c6dSRichard Henderson        mv      a1, a3
45b8c92c6dSRichard Henderson        mv      a2, a4
46b8c92c6dSRichard Henderson        mv      a3, a5
47b8c92c6dSRichard Henderson        mv      a4, a6
48b8c92c6dSRichard Henderson        mv      a5, a7
49b8c92c6dSRichard Henderson        mv      a7, t1
50b8c92c6dSRichard Henderson
51b8c92c6dSRichard Henderson        /*
52b8c92c6dSRichard Henderson         * This next sequence of code works in conjunction with the
53b8c92c6dSRichard Henderson         * rewind_if_safe_syscall_function(). If a signal is taken
54b8c92c6dSRichard Henderson         * and the interrupted PC is anywhere between 'safe_syscall_start'
55b8c92c6dSRichard Henderson         * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
56b8c92c6dSRichard Henderson         * The code sequence must therefore be able to cope with this, and
57b8c92c6dSRichard Henderson         * the syscall instruction must be the final one in the sequence.
58b8c92c6dSRichard Henderson         */
59b8c92c6dSRichard Hendersonsafe_syscall_start:
60b8c92c6dSRichard Henderson        /* If signal_pending is non-zero, don't do the call */
61b8c92c6dSRichard Henderson        lw      t1, 0(t0)
62a3310c03SRichard Henderson        bnez    t1, 2f
63b8c92c6dSRichard Henderson        scall
64b8c92c6dSRichard Hendersonsafe_syscall_end:
65b8c92c6dSRichard Henderson        /* code path for having successfully executed the syscall */
66a3310c03SRichard Henderson        li      t2, -4096
67a3310c03SRichard Henderson        bgtu    a0, t2, 0f
68b8c92c6dSRichard Henderson        ret
69b8c92c6dSRichard Henderson
70a3310c03SRichard Henderson        /* code path setting errno */
71a3310c03SRichard Henderson0:      neg     a0, a0
72*22b448ccSIcenowy Zheng        tail    safe_syscall_set_errno_tail
73a3310c03SRichard Henderson
74b8c92c6dSRichard Henderson        /* code path when we didn't execute the syscall */
75af254a27SRichard Henderson2:      li      a0, QEMU_ERESTARTSYS
76*22b448ccSIcenowy Zheng        tail    safe_syscall_set_errno_tail
77b8c92c6dSRichard Henderson
78a3310c03SRichard Henderson        .cfi_endproc
79b8c92c6dSRichard Henderson        .size   safe_syscall_base, .-safe_syscall_base
80