qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

safe-syscall.inc.S (2998B)


      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  * Written by Richard Henderson <rth@twiddle.net>
      7  * Copyright (C) 2018 Linaro, 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  */
     12 
     13         .global safe_syscall_base
     14         .global safe_syscall_start
     15         .global safe_syscall_end
     16         .type   safe_syscall_base, @function
     17         .type   safe_syscall_start, @function
     18         .type   safe_syscall_end, @function
     19 
     20         /*
     21          * This is the entry point for making a system call. The calling
     22          * convention here is that of a C varargs function with the
     23          * first argument an 'int *' to the signal_pending flag, the
     24          * second one the system call number (as a 'long'), and all further
     25          * arguments being syscall arguments (also 'long').
     26          */
     27 safe_syscall_base:
     28         .cfi_startproc
     29         /*
     30          * The syscall calling convention is nearly the same as C:
     31          * we enter with a0 == &signal_pending
     32          *               a1 == syscall number
     33          *               a2 ... a7 == syscall arguments
     34          *               and return the result in a0
     35          * and the syscall instruction needs
     36          *               a7 == syscall number
     37          *               a0 ... a5 == syscall arguments
     38          *               and returns the result in a0
     39          * Shuffle everything around appropriately.
     40          */
     41         mv      t0, a0          /* signal_pending pointer */
     42         mv      t1, a1          /* syscall number */
     43         mv      a0, a2          /* syscall arguments */
     44         mv      a1, a3
     45         mv      a2, a4
     46         mv      a3, a5
     47         mv      a4, a6
     48         mv      a5, a7
     49         mv      a7, t1
     50 
     51         /*
     52          * This next sequence of code works in conjunction with the
     53          * rewind_if_safe_syscall_function(). If a signal is taken
     54          * and the interrupted PC is anywhere between 'safe_syscall_start'
     55          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
     56          * The code sequence must therefore be able to cope with this, and
     57          * the syscall instruction must be the final one in the sequence.
     58          */
     59 safe_syscall_start:
     60         /* If signal_pending is non-zero, don't do the call */
     61         lw      t1, 0(t0)
     62         bnez    t1, 2f
     63         scall
     64 safe_syscall_end:
     65         /* code path for having successfully executed the syscall */
     66         li      t2, -4096
     67         bgtu    a0, t2, 0f
     68         ret
     69 
     70         /* code path setting errno */
     71 0:      neg     a0, a0
     72         j       safe_syscall_set_errno_tail
     73 
     74         /* code path when we didn't execute the syscall */
     75 2:      li      a0, QEMU_ERESTARTSYS
     76         j       safe_syscall_set_errno_tail
     77 
     78         .cfi_endproc
     79         .size   safe_syscall_base, .-safe_syscall_base