diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-05-27 14:05:48 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-05-27 14:05:48 +0100 |
commit | d6550e9ed2e1a60d889dfb721de00d9a4e3bafbe (patch) | |
tree | 3ab1161c8e63c202cbd207cfb10e1e37ec206951 /linux-user/host/x86_64/safe-syscall.inc.S | |
parent | 34c99d7b93c9181aa8c426300beca130b2b19e39 (diff) | |
parent | 49e55cbacf4ad08f831b9f3f9cb0f3082883a3a1 (diff) | |
download | qemu-d6550e9ed2e1a60d889dfb721de00d9a4e3bafbe.zip qemu-d6550e9ed2e1a60d889dfb721de00d9a4e3bafbe.tar.gz qemu-d6550e9ed2e1a60d889dfb721de00d9a4e3bafbe.tar.bz2 |
Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20160527' into staging
linux-user pull request v2 for may 2016
# gpg: Signature made Fri 27 May 2016 12:51:10 BST using RSA key ID DE3C9BC0
# gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>"
# gpg: aka "Riku Voipio <riku.voipio@linaro.org>"
* remotes/riku/tags/pull-linux-user-20160527: (38 commits)
linux-user,target-ppc: fix use of MSR_LE
linux-user/signal.c: Use s390 target space address instead of host space
linux-user/signal.c: Use target address instead of host address for microblaze restorer
linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame
linux-user: arm: Remove ARM_cpsr and similar #defines
linux-user: Use direct syscalls for setuid(), etc
linux-user: x86_64: Don't use 16-bit UIDs
linux-user: Use g_try_malloc() in do_msgrcv()
linux-user: Handle msgrcv error case correctly
linux-user: Handle negative values in timespec conversion
linux-user: Use safe_syscall for futex syscall
linux-user: Use safe_syscall for pselect, select syscalls
linux-user: Use safe_syscall for execve syscall
linux-user: Use safe_syscall for wait system calls
linux-user: Use safe_syscall for open and openat system calls
linux-user: Use safe_syscall for read and write system calls
linux-user: Provide safe_syscall for fixing races between signals and syscalls
linux-user: Add debug code to exercise restarting system calls
linux-user: Support for restarting system calls for Microblaze targets
linux-user: Set r14 on exit from microblaze syscall
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/host/x86_64/safe-syscall.inc.S')
-rw-r--r-- | linux-user/host/x86_64/safe-syscall.inc.S | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/linux-user/host/x86_64/safe-syscall.inc.S b/linux-user/host/x86_64/safe-syscall.inc.S new file mode 100644 index 0000000..dde434c --- /dev/null +++ b/linux-user/host/x86_64/safe-syscall.inc.S @@ -0,0 +1,81 @@ +/* + * safe-syscall.inc.S : host-specific assembly fragment + * to handle signals occurring at the same time as system calls. + * This is intended to be included by linux-user/safe-syscall.S + * + * Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + + .global safe_syscall_base + .global safe_syscall_start + .global safe_syscall_end + .type safe_syscall_base, @function + + /* This is the entry point for making a system call. The calling + * convention here is that of a C varargs function with the + * first argument an 'int *' to the signal_pending flag, the + * second one the system call number (as a 'long'), and all further + * arguments being syscall arguments (also 'long'). + * We return a long which is the syscall's return value, which + * may be negative-errno on failure. Conversion to the + * -1-and-errno-set convention is done by the calling wrapper. + */ +safe_syscall_base: + /* This saves a frame pointer and aligns the stack for the syscall. + * (It's unclear if the syscall ABI has the same stack alignment + * requirements as the userspace function call ABI, but better safe than + * sorry. Appendix A2 of http://www.x86-64.org/documentation/abi.pdf + * does not list any ABI differences regarding stack alignment.) + */ + push %rbp + + /* The syscall calling convention isn't the same as the + * C one: + * we enter with rdi == *signal_pending + * rsi == syscall number + * rdx, rcx, r8, r9, (stack), (stack) == syscall arguments + * and return the result in rax + * and the syscall instruction needs + * rax == syscall number + * rdi, rsi, rdx, r10, r8, r9 == syscall arguments + * and returns the result in rax + * Shuffle everything around appropriately. + * Note that syscall will trash rcx and r11. + */ + mov %rsi, %rax /* syscall number */ + mov %rdi, %rbp /* signal_pending pointer */ + /* and the syscall arguments */ + mov %rdx, %rdi + mov %rcx, %rsi + mov %r8, %rdx + mov %r9, %r10 + mov 16(%rsp), %r8 + mov 24(%rsp), %r9 + + /* This next sequence of code works in conjunction with the + * rewind_if_safe_syscall_function(). If a signal is taken + * and the interrupted PC is anywhere between 'safe_syscall_start' + * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. + * The code sequence must therefore be able to cope with this, and + * the syscall instruction must be the final one in the sequence. + */ +safe_syscall_start: + /* if signal_pending is non-zero, don't do the call */ + testl $1, (%rbp) + jnz return_ERESTARTSYS + syscall +safe_syscall_end: + /* code path for having successfully executed the syscall */ + pop %rbp + ret + +return_ERESTARTSYS: + /* code path when we didn't execute the syscall */ + mov $-TARGET_ERESTARTSYS, %rax + pop %rbp + ret + + .size safe_syscall_base, .-safe_syscall_base |