xref: /qemu/common-user/host/sparc64/safe-syscall.inc.S (revision 620d0b49a40e24465472b667f19b5fb0c63a6f0c)
195c021daSRichard Henderson/*
295c021daSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment
395c021daSRichard 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
595c021daSRichard Henderson *
695c021daSRichard Henderson * Written by Richard Henderson <richard.henderson@linaro.org>
795c021daSRichard Henderson * Copyright (C) 2021 Linaro, Inc.
895c021daSRichard Henderson *
995c021daSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later.
1095c021daSRichard Henderson * See the COPYING file in the top-level directory.
1195c021daSRichard Henderson */
1295c021daSRichard Henderson
1395c021daSRichard Henderson        .text
1495c021daSRichard Henderson        .balign 4
1595c021daSRichard Henderson
1695c021daSRichard Henderson        .register %g2, #scratch
1795c021daSRichard Henderson        .register %g3, #scratch
1895c021daSRichard Henderson
1995c021daSRichard Henderson        .global safe_syscall_base
2095c021daSRichard Henderson        .global safe_syscall_start
2195c021daSRichard Henderson        .global safe_syscall_end
2295c021daSRichard Henderson        .type   safe_syscall_base, @function
2395c021daSRichard Henderson        .type   safe_syscall_start, @function
2495c021daSRichard Henderson        .type   safe_syscall_end, @function
2595c021daSRichard Henderson
2695c021daSRichard Henderson#define STACK_BIAS  2047
27*620d0b49SRichard Henderson#define WINDOW_SIZE 16 * 8
28*620d0b49SRichard Henderson#define PARAM(N)    STACK_BIAS + WINDOW_SIZE + N * 8
2995c021daSRichard Henderson
3095c021daSRichard Henderson        /*
3195c021daSRichard Henderson         * This is the entry point for making a system call. The calling
3295c021daSRichard Henderson         * convention here is that of a C varargs function with the
3395c021daSRichard Henderson         * first argument an 'int *' to the signal_pending flag, the
3495c021daSRichard Henderson         * second one the system call number (as a 'long'), and all further
3595c021daSRichard Henderson         * arguments being syscall arguments (also 'long').
3695c021daSRichard Henderson         */
3795c021daSRichard Hendersonsafe_syscall_base:
3895c021daSRichard Henderson        .cfi_startproc
3995c021daSRichard Henderson        /*
4095c021daSRichard Henderson         * The syscall calling convention isn't the same as the C one:
4195c021daSRichard Henderson         * we enter with o0 == &signal_pending
4295c021daSRichard Henderson         *               o1 == syscall number
4395c021daSRichard Henderson         *               o2 ... o5, (stack) == syscall arguments
4495c021daSRichard Henderson         *               and return the result in x0
4595c021daSRichard Henderson         * and the syscall instruction needs
4695c021daSRichard Henderson         *               g1 == syscall number
4795c021daSRichard Henderson         *               o0 ... o5 == syscall arguments
4895c021daSRichard Henderson         *               and returns the result in o0
4995c021daSRichard Henderson         * Shuffle everything around appropriately.
5095c021daSRichard Henderson         */
5195c021daSRichard Henderson        mov     %o0, %g2                /* signal_pending pointer */
5295c021daSRichard Henderson        mov     %o1, %g1                /* syscall number */
5395c021daSRichard Henderson        mov     %o2, %o0                /* syscall arguments */
5495c021daSRichard Henderson        mov     %o3, %o1
5595c021daSRichard Henderson        mov     %o4, %o2
5695c021daSRichard Henderson        mov     %o5, %o3
5795c021daSRichard Henderson        ldx     [%sp + PARAM(6)], %o4
5895c021daSRichard Henderson        ldx     [%sp + PARAM(7)], %o5
5995c021daSRichard Henderson
6095c021daSRichard Henderson        /*
6195c021daSRichard Henderson         * This next sequence of code works in conjunction with the
6295c021daSRichard Henderson         * rewind_if_safe_syscall_function(). If a signal is taken
6395c021daSRichard Henderson         * and the interrupted PC is anywhere between 'safe_syscall_start'
6495c021daSRichard Henderson         * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
6595c021daSRichard Henderson         * The code sequence must therefore be able to cope with this, and
6695c021daSRichard Henderson         * the syscall instruction must be the final one in the sequence.
6795c021daSRichard Henderson         */
6895c021daSRichard Hendersonsafe_syscall_start:
6995c021daSRichard Henderson        /* if signal_pending is non-zero, don't do the call */
7095c021daSRichard Henderson        lduw    [%g2], %g3
7195c021daSRichard Henderson        brnz,pn %g3, 2f
7295c021daSRichard Henderson         nop
7395c021daSRichard Henderson        ta      0x6d
7495c021daSRichard Hendersonsafe_syscall_end:
7595c021daSRichard Henderson        /* code path for having successfully executed the syscall */
7695c021daSRichard Henderson        bcs,pn  %xcc, 1f
7795c021daSRichard Henderson         nop
78*620d0b49SRichard Henderson        retl
7995c021daSRichard Henderson         nop
8095c021daSRichard Henderson
8195c021daSRichard Henderson        /* code path when we didn't execute the syscall */
82af254a27SRichard Henderson2:      set     QEMU_ERESTARTSYS, %o0
8395c021daSRichard Henderson
8495c021daSRichard Henderson        /* code path setting errno */
8595c021daSRichard Henderson1:      mov     %o7, %g1
8695c021daSRichard Henderson        call    safe_syscall_set_errno_tail
8795c021daSRichard Henderson         mov    %g1, %o7
8895c021daSRichard Henderson
8995c021daSRichard Henderson        .cfi_endproc
9095c021daSRichard Henderson        .size   safe_syscall_base, .-safe_syscall_base
91