qemu

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

safe-syscall.inc.S (3298B)


      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) 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  */
     12 
     13         .global safe_syscall_base
     14         .global safe_syscall_start
     15         .global safe_syscall_end
     16         .type   safe_syscall_base, @function
     17 
     18         .text
     19 
     20         /* This is the entry point for making a system call. The calling
     21          * convention here is that of a C varargs function with the
     22          * first argument an 'int *' to the signal_pending flag, the
     23          * second one the system call number (as a 'long'), and all further
     24          * arguments being syscall arguments (also 'long').
     25          */
     26 #if _CALL_ELF == 2
     27 safe_syscall_base:
     28         .cfi_startproc
     29         .localentry safe_syscall_base,0
     30 #else
     31         .section ".opd","aw"
     32         .align  3
     33 safe_syscall_base:
     34         .quad   .L.safe_syscall_base,.TOC.@tocbase,0
     35         .previous
     36 .L.safe_syscall_base:
     37         .cfi_startproc
     38 #endif
     39         /* We enter with r3 == &signal_pending
     40          *               r4 == syscall number
     41          *               r5 ... r10 == syscall arguments
     42          *               and return the result in r3
     43          * and the syscall instruction needs
     44          *               r0 == syscall number
     45          *               r3 ... r8 == syscall arguments
     46          *               and returns the result in r3
     47          * Shuffle everything around appropriately.
     48          */
     49         std     14, 16(1) /* Preserve r14 in SP+16 */
     50         .cfi_offset 14, 16
     51         mr      14, 3   /* signal_pending */
     52         mr      0, 4    /* syscall number */
     53         mr      3, 5    /* syscall arguments */
     54         mr      4, 6
     55         mr      5, 7
     56         mr      6, 8
     57         mr      7, 9
     58         mr      8, 10
     59 
     60         /* This next sequence of code works in conjunction with the
     61          * rewind_if_safe_syscall_function(). If a signal is taken
     62          * and the interrupted PC is anywhere between 'safe_syscall_start'
     63          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
     64          * The code sequence must therefore be able to cope with this, and
     65          * the syscall instruction must be the final one in the sequence.
     66          */
     67 safe_syscall_start:
     68         /* if signal_pending is non-zero, don't do the call */
     69         lwz     12, 0(14)
     70         cmpwi   0, 12, 0
     71         bne-    2f
     72         sc
     73 safe_syscall_end:
     74         /* code path when we did execute the syscall */
     75         ld      14, 16(1) /* restore r14 */
     76         bso-    1f
     77         blr
     78 
     79         /* code path when we didn't execute the syscall */
     80 2:      ld      14, 16(1) /* restore r14 */
     81         addi    3, 0, QEMU_ERESTARTSYS
     82 
     83         /* code path setting errno */
     84 1:      b       safe_syscall_set_errno_tail
     85         nop     /* per abi, for the linker to modify */
     86 
     87         .cfi_endproc
     88 
     89 #if _CALL_ELF == 2
     90         .size   safe_syscall_base, .-safe_syscall_base
     91 #else
     92         .size   safe_syscall_base, .-.L.safe_syscall_base
     93         .size   .L.safe_syscall_base, .-.L.safe_syscall_base
     94 #endif