safe-syscall.inc.S (2949B)
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 linux-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 * We return a long which is the syscall's return value, which 24 * may be negative-errno on failure. Conversion to the 25 * -1-and-errno-set convention is done by the calling wrapper. 26 */ 27safe_syscall_base: 28 .cfi_startproc 29 stmg %r6,%r15,48(%r15) /* save all call-saved registers */ 30 .cfi_offset %r15,-40 31 .cfi_offset %r14,-48 32 .cfi_offset %r13,-56 33 .cfi_offset %r12,-64 34 .cfi_offset %r11,-72 35 .cfi_offset %r10,-80 36 .cfi_offset %r9,-88 37 .cfi_offset %r8,-96 38 .cfi_offset %r7,-104 39 .cfi_offset %r6,-112 40 lgr %r1,%r15 41 lg %r0,8(%r15) /* load eos */ 42 aghi %r15,-160 43 .cfi_adjust_cfa_offset 160 44 stg %r1,0(%r15) /* store back chain */ 45 stg %r0,8(%r15) /* store eos */ 46 47 /* The syscall calling convention isn't the same as the 48 * C one: 49 * we enter with r2 == *signal_pending 50 * r3 == syscall number 51 * r4, r5, r6, (stack) == syscall arguments 52 * and return the result in r2 53 * and the syscall instruction needs 54 * r1 == syscall number 55 * r2 ... r7 == syscall arguments 56 * and returns the result in r2 57 * Shuffle everything around appropriately. 58 */ 59 lgr %r8,%r2 /* signal_pending pointer */ 60 lgr %r1,%r3 /* syscall number */ 61 lgr %r2,%r4 /* syscall args */ 62 lgr %r3,%r5 63 lgr %r4,%r6 64 lmg %r5,%r7,320(%r15) 65 66 /* This next sequence of code works in conjunction with the 67 * rewind_if_safe_syscall_function(). If a signal is taken 68 * and the interrupted PC is anywhere between 'safe_syscall_start' 69 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 70 * The code sequence must therefore be able to cope with this, and 71 * the syscall instruction must be the final one in the sequence. 72 */ 73safe_syscall_start: 74 /* if signal_pending is non-zero, don't do the call */ 75 icm %r0,15,0(%r8) 76 jne 2f 77 svc 0 78safe_syscall_end: 79 801: lg %r15,0(%r15) /* load back chain */ 81 .cfi_remember_state 82 .cfi_adjust_cfa_offset -160 83 lmg %r6,%r15,48(%r15) /* load saved registers */ 84 br %r14 85 .cfi_restore_state 862: lghi %r2, -TARGET_ERESTARTSYS 87 j 1b 88 .cfi_endproc 89 90 .size safe_syscall_base, .-safe_syscall_base