qemu

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

safe-syscall.inc.S (3543B)


      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  * Ported to LoongArch by WANG Xuerui <git@xen0n.name>
      7  *
      8  * Based on safe-syscall.inc.S code for RISC-V,
      9  * originally written by Richard Henderson <rth@twiddle.net>
     10  * Copyright (C) 2018 Linaro, Inc.
     11  *
     12  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     13  * See the COPYING file in the top-level directory.
     14  */
     15 
     16         .global safe_syscall_base
     17         .global safe_syscall_start
     18         .global safe_syscall_end
     19         .type   safe_syscall_base, @function
     20         .type   safe_syscall_start, @function
     21         .type   safe_syscall_end, @function
     22 
     23         /*
     24          * This is the entry point for making a system call. The calling
     25          * convention here is that of a C varargs function with the
     26          * first argument an 'int *' to the signal_pending flag, the
     27          * second one the system call number (as a 'long'), and all further
     28          * arguments being syscall arguments (also 'long').
     29          */
     30 safe_syscall_base:
     31         .cfi_startproc
     32         /*
     33          * The syscall calling convention is nearly the same as C:
     34          * we enter with a0 == &signal_pending
     35          *               a1 == syscall number
     36          *               a2 ... a7 == syscall arguments
     37          *               and return the result in a0
     38          * and the syscall instruction needs
     39          *               a7 == syscall number
     40          *               a0 ... a5 == syscall arguments
     41          *               and returns the result in a0
     42          * Shuffle everything around appropriately.
     43          */
     44         move    $t0, $a0        /* signal_pending pointer */
     45         move    $t1, $a1        /* syscall number */
     46         move    $a0, $a2        /* syscall arguments */
     47         move    $a1, $a3
     48         move    $a2, $a4
     49         move    $a3, $a5
     50         move    $a4, $a6
     51         move    $a5, $a7
     52         move    $a7, $t1
     53 
     54         /*
     55          * We need to preserve the signal_pending pointer but t0 is
     56          * clobbered by syscalls on LoongArch, so we need to move it
     57          * somewhere else, ideally both preserved across syscalls and
     58          * clobbered by procedure calls so we don't have to allocate a
     59          * stack frame; a6 is just the register we want here.
     60          */
     61         move    $a6, $t0
     62 
     63         /*
     64          * This next sequence of code works in conjunction with the
     65          * rewind_if_safe_syscall_function(). If a signal is taken
     66          * and the interrupted PC is anywhere between 'safe_syscall_start'
     67          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
     68          * The code sequence must therefore be able to cope with this, and
     69          * the syscall instruction must be the final one in the sequence.
     70          */
     71 safe_syscall_start:
     72         /* If signal_pending is non-zero, don't do the call */
     73         ld.w    $t1, $a6, 0
     74         bnez    $t1, 2f
     75         syscall 0
     76 safe_syscall_end:
     77         /* code path for having successfully executed the syscall */
     78         li.w    $t2, -4096
     79         bgtu    $a0, $t2, 0f
     80         jr      $ra
     81 
     82         /* code path setting errno */
     83 0:      sub.d   $a0, $zero, $a0
     84         b       safe_syscall_set_errno_tail
     85 
     86         /* code path when we didn't execute the syscall */
     87 2:      li.w    $a0, QEMU_ERESTARTSYS
     88         b       safe_syscall_set_errno_tail
     89         .cfi_endproc
     90         .size   safe_syscall_base, .-safe_syscall_base