safe-syscall.inc.S (3693B)
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 * Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk> 7 * 8 * This work is licensed under the terms of the GNU GPL, version 2 or later. 9 * See the COPYING file in the top-level directory. 10 */ 11 12 .global safe_syscall_base 13 .global safe_syscall_start 14 .global safe_syscall_end 15 .type safe_syscall_base, @function 16 17 /* This is the entry point for making a system call. The calling 18 * convention here is that of a C varargs function with the 19 * first argument an 'int *' to the signal_pending flag, the 20 * second one the system call number (as a 'long'), and all further 21 * arguments being syscall arguments (also 'long'). 22 * We return a long which is the syscall's return value, which 23 * may be negative-errno on failure. Conversion to the 24 * -1-and-errno-set convention is done by the calling wrapper. 25 */ 26safe_syscall_base: 27 .cfi_startproc 28 /* This saves a frame pointer and aligns the stack for the syscall. 29 * (It's unclear if the syscall ABI has the same stack alignment 30 * requirements as the userspace function call ABI, but better safe than 31 * sorry. Appendix A2 of http://www.x86-64.org/documentation/abi.pdf 32 * does not list any ABI differences regarding stack alignment.) 33 */ 34 push %rbp 35 .cfi_adjust_cfa_offset 8 36 .cfi_rel_offset rbp, 0 37 38 /* The syscall calling convention isn't the same as the 39 * C one: 40 * we enter with rdi == *signal_pending 41 * rsi == syscall number 42 * rdx, rcx, r8, r9, (stack), (stack) == syscall arguments 43 * and return the result in rax 44 * and the syscall instruction needs 45 * rax == syscall number 46 * rdi, rsi, rdx, r10, r8, r9 == syscall arguments 47 * and returns the result in rax 48 * Shuffle everything around appropriately. 49 * Note that syscall will trash rcx and r11. 50 */ 51 mov %rsi, %rax /* syscall number */ 52 mov %rdi, %rbp /* signal_pending pointer */ 53 /* and the syscall arguments */ 54 mov %rdx, %rdi 55 mov %rcx, %rsi 56 mov %r8, %rdx 57 mov %r9, %r10 58 mov 16(%rsp), %r8 59 mov 24(%rsp), %r9 60 61 /* This next sequence of code works in conjunction with the 62 * rewind_if_safe_syscall_function(). If a signal is taken 63 * and the interrupted PC is anywhere between 'safe_syscall_start' 64 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 65 * The code sequence must therefore be able to cope with this, and 66 * the syscall instruction must be the final one in the sequence. 67 */ 68safe_syscall_start: 69 /* if signal_pending is non-zero, don't do the call */ 70 cmpl $0, (%rbp) 71 jnz 1f 72 syscall 73safe_syscall_end: 74 /* code path for having successfully executed the syscall */ 75 pop %rbp 76 .cfi_remember_state 77 .cfi_def_cfa_offset 8 78 .cfi_restore rbp 79 ret 80 811: 82 /* code path when we didn't execute the syscall */ 83 .cfi_restore_state 84 mov $-TARGET_ERESTARTSYS, %rax 85 pop %rbp 86 .cfi_def_cfa_offset 8 87 .cfi_restore rbp 88 ret 89 .cfi_endproc 90 91 .size safe_syscall_base, .-safe_syscall_base