diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-06-29 10:43:07 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-06-29 10:43:08 +0100 |
commit | 3e904d6ade7f363c64b3c54c5d14372b8a9e6892 (patch) | |
tree | 6cffcbf0eac7b0894a39002ae8b76cc8813d248d /linux-user/host/arm/safe-syscall.inc.S | |
parent | d7f30403576f04f1f3a5fb5a1d18cba8dfa7a6d2 (diff) | |
parent | 4ba92cd736a9ce0dc83c9b16a75d24d385e1cdf3 (diff) | |
download | qemu-3e904d6ade7f363c64b3c54c5d14372b8a9e6892.zip qemu-3e904d6ade7f363c64b3c54c5d14372b8a9e6892.tar.gz qemu-3e904d6ade7f363c64b3c54c5d14372b8a9e6892.tar.bz2 |
Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20160628' into staging
Drop building linux-user targets on HPPA or m68k host systems
and add safe_syscall support for i386, aarch64, arm, ppc64 and
s390x.
# gpg: Signature made Tue 28 Jun 2016 19:31:16 BST
# gpg: using RSA key 0xB44890DEDE3C9BC0
# gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>"
# gpg: aka "Riku Voipio <riku.voipio@linaro.org>"
# Primary key fingerprint: FF82 03C8 C391 98AE 0581 41EF B448 90DE DE3C 9BC0
* remotes/riku/tags/pull-linux-user-20160628: (24 commits)
linux-user: Provide safe_syscall for ppc64
linux-user: Provide safe_syscall for s390x
linux-user: Provide safe_syscall for aarch64
linux-user: Provide safe_syscall for arm
linux-user: Provide safe_syscall for i386
linux-user: fix x86_64 safe_syscall
linux-user: don't swap NLMSG_DATA() fields
linux-user: fd_trans_host_to_target_data() must process only received data
linux-user: add missing return in netlink switch statement
linux-user: update get_thread_area/set_thread_area strace
linux-user: fix clone() strace
linux-user: add socket() strace
linux-user: add socketcall() strace
linux-user: Support F_GETPIPE_SZ and F_SETPIPE_SZ fcntls
linux-user: Fix wrong type used for argument to rt_sigqueueinfo
linux-user: Create a hostdep.h for each host architecture
user-exec: Remove unused code for OSX hosts
user-exec: Delete now-unused hppa and m68k cpu_signal_handler() code
configure: Don't allow user-only targets for unknown CPU architectures
configure: Don't override ARCH=unknown if enabling TCI
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/host/arm/safe-syscall.inc.S')
-rw-r--r-- | linux-user/host/arm/safe-syscall.inc.S | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/linux-user/host/arm/safe-syscall.inc.S b/linux-user/host/arm/safe-syscall.inc.S new file mode 100644 index 0000000..88c4958 --- /dev/null +++ b/linux-user/host/arm/safe-syscall.inc.S @@ -0,0 +1,90 @@ +/* + * 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 + * + * Written by Richard Henderson <rth@twiddle.net> + * Copyright (C) 2016 Red Hat, Inc. + * + * 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 + + .cfi_sections .debug_frame + + .text + .syntax unified + .arm + .align 2 + + /* 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: + .fnstart + .cfi_startproc + mov r12, sp /* save entry stack */ + push { r4, r5, r6, r7, r8, lr } + .save { r4, r5, r6, r7, r8, lr } + .cfi_adjust_cfa_offset 24 + .cfi_rel_offset r4, 0 + .cfi_rel_offset r5, 4 + .cfi_rel_offset r6, 8 + .cfi_rel_offset r7, 12 + .cfi_rel_offset r8, 16 + .cfi_rel_offset lr, 20 + + /* The syscall calling convention isn't the same as the C one: + * we enter with r0 == *signal_pending + * r1 == syscall number + * r2, r3, [sp+0] ... [sp+12] == syscall arguments + * and return the result in r0 + * and the syscall instruction needs + * r7 == syscall number + * r0 ... r6 == syscall arguments + * and returns the result in r0 + * Shuffle everything around appropriately. + * Note the 16 bytes that we pushed to save registers. + */ + mov r8, r0 /* copy signal_pending */ + mov r7, r1 /* syscall number */ + mov r0, r2 /* syscall args */ + mov r1, r3 + ldm r12, { r2, r3, r4, r5, r6 } + + /* 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 */ + ldr r12, [r8] /* signal_pending */ + tst r12, r12 + bne 1f + swi 0 +safe_syscall_end: + /* code path for having successfully executed the syscall */ + pop { r4, r5, r6, r7, r8, pc } + +1: + /* code path when we didn't execute the syscall */ + ldr r0, =-TARGET_ERESTARTSYS + pop { r4, r5, r6, r7, r8, pc } + .fnend + .cfi_endproc + + .size safe_syscall_base, .-safe_syscall_base |