qemu

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

safe-syscall.inc.S (3981B)


      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         /* This is the entry point for making a system call. The calling
     19          * convention here is that of a C varargs function with the
     20          * first argument an 'int *' to the signal_pending flag, the
     21          * second one the system call number (as a 'long'), and all further
     22          * arguments being syscall arguments (also 'long').
     23          */
     24 safe_syscall_base:
     25         .cfi_startproc
     26         stmg    %r6,%r15,48(%r15)       /* save all call-saved registers */
     27         .cfi_offset %r15,-40
     28         .cfi_offset %r14,-48
     29         .cfi_offset %r13,-56
     30         .cfi_offset %r12,-64
     31         .cfi_offset %r11,-72
     32         .cfi_offset %r10,-80
     33         .cfi_offset %r9,-88
     34         .cfi_offset %r8,-96
     35         .cfi_offset %r7,-104
     36         .cfi_offset %r6,-112
     37         lgr     %r1,%r15
     38         lg      %r0,8(%r15)             /* load eos */
     39         aghi    %r15,-160
     40         .cfi_adjust_cfa_offset 160
     41         stg     %r1,0(%r15)             /* store back chain */
     42         stg     %r0,8(%r15)             /* store eos */
     43 
     44         /*
     45          * The syscall calling convention isn't the same as the C one:
     46          * we enter with r2 == &signal_pending
     47          *               r3 == syscall number
     48          *               r4, r5, r6, (stack) == syscall arguments
     49          *               and return the result in r2
     50          * and the syscall instruction needs
     51          *               r1 == syscall number
     52          *               r2 ... r7 == syscall arguments
     53          *               and returns the result in r2
     54          * Shuffle everything around appropriately.
     55          */
     56         lgr     %r8,%r2                 /* signal_pending pointer */
     57         lgr     %r1,%r3                 /* syscall number */
     58         lgr     %r2,%r4                 /* syscall args */
     59         lgr     %r3,%r5
     60         lgr     %r4,%r6
     61         lmg     %r5,%r7,320(%r15)
     62 
     63         /* This next sequence of code works in conjunction with the
     64          * rewind_if_safe_syscall_function(). If a signal is taken
     65          * and the interrupted PC is anywhere between 'safe_syscall_start'
     66          * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
     67          * The code sequence must therefore be able to cope with this, and
     68          * the syscall instruction must be the final one in the sequence.
     69          */
     70 safe_syscall_start:
     71         /* if signal_pending is non-zero, don't do the call */
     72         icm     %r0,15,0(%r8)
     73         jne     2f
     74         svc     0
     75 safe_syscall_end:
     76 
     77         /* code path for having successfully executed the syscall */
     78         lg      %r15,0(%r15)            /* load back chain */
     79         .cfi_remember_state
     80         .cfi_adjust_cfa_offset -160
     81         lmg     %r6,%r15,48(%r15)       /* load saved registers */
     82 
     83         lghi    %r0, -4095              /* check for syscall error */
     84         clgr    %r2, %r0
     85         blr     %r14                    /* return on success */
     86         lcr     %r2, %r2                /* create positive errno */
     87         jg      safe_syscall_set_errno_tail
     88         .cfi_restore_state
     89 
     90         /* code path when we didn't execute the syscall */
     91 2:      lg      %r15,0(%r15)            /* load back chain */
     92         .cfi_adjust_cfa_offset -160
     93         lmg     %r6,%r15,48(%r15)       /* load saved registers */
     94         lghi    %r2, QEMU_ERESTARTSYS
     95         jg      safe_syscall_set_errno_tail
     96 
     97         .cfi_endproc
     98         .size   safe_syscall_base, .-safe_syscall_base