Move errno processing from safe_syscall() to safe_syscall_base().
Move safe_syscall() from linux-user to common-user. Add FreeBSD support to safe_syscall_base(). Tidy top-level meson.build wrt {bsd,linux}-user. -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmHA3YMdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+/XggAqZ2kp/xhmhlVKR8X YzxmeAkPPuJSCQZt8v0UFPye2/HQTpXCboi4Lo+IgjI+6tpY4LhcY48071iiI5Ug uWXIW9Y4+GnHPEDbyU3I1Wxg/OtXOj9B0Fy0ULw8ct0vKBjVgPBkiaQqtn+jCzOZ +7SGdIJMz5hsgW+krP60BHyyXypU/NIDPhCEBRwusZ6Vp5UvkVicNmZaQjh4suZt 5gCFNSq43gw/+KhzjDEZvRTG00LteaCHUDY5nAfbyvE0o8hTDuroO16hCWCb7gZ+ 8MH5NMJMOcKupPLk7YCJ+o5NQlWhR86ygZSiTg+WZyHldfXMPBINiLN1b878kNfT NjcGRA== =i5x2 -----END PGP SIGNATURE----- Merge tag 'pull-user-20211220' of https://gitlab.com/rth7680/qemu into staging Move errno processing from safe_syscall() to safe_syscall_base(). Move safe_syscall() from linux-user to common-user. Add FreeBSD support to safe_syscall_base(). Tidy top-level meson.build wrt {bsd,linux}-user. # gpg: Signature made Mon 20 Dec 2021 11:46:11 AM PST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-user-20211220' of https://gitlab.com/rth7680/qemu: meson: Move bsd_user_ss to bsd-user/ meson: Move linux_user_ss to linux-user/ linux-user: Move thunk.c from top-level common-user: Adjust system call return on FreeBSD common-user: Move safe-syscall.* from linux-user bsd-user: Create special-errno.h linux-user: Create special-errno.h linux-user: Rename TARGET_QEMU_ESIGRETURN to QEMU_ESIGRETURN bsd-user: Rename TARGET_ERESTARTSYS to QEMU_ERESTARTSYS linux-user: Rename TARGET_ERESTARTSYS to QEMU_ERESTARTSYS linux-user: Remove HAVE_SAFE_SYSCALL and hostdep.h linux-user/host/sparc64: Add safe-syscall.inc.S linux-user/host/mips: Add safe-syscall.inc.S linux-user: Move syscall error detection into safe_syscall_base linux-user: Untabify all safe-syscall.inc.S Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
2bf40d0841
@ -3077,8 +3077,9 @@ Usermode Emulation
|
||||
Overall usermode emulation
|
||||
M: Riku Voipio <riku.voipio@iki.fi>
|
||||
S: Maintained
|
||||
F: thunk.c
|
||||
F: accel/tcg/user-exec*.c
|
||||
F: include/user/
|
||||
F: common-user/
|
||||
|
||||
BSD user
|
||||
M: Warner Losh <imp@bsdimp.com>
|
||||
|
@ -151,6 +151,10 @@
|
||||
/* Internal errors: */
|
||||
#define TARGET_EJUSTRETURN 254 /* Just return without modifing regs */
|
||||
#define TARGET_ERESTART 255 /* Restart syscall */
|
||||
#define TARGET_ERESTARTSYS TARGET_ERESTART /* Linux compat */
|
||||
|
||||
#include "special-errno.h"
|
||||
|
||||
_Static_assert(TARGET_ERESTART == QEMU_ERESTARTSYS,
|
||||
"TARGET_ERESTART and QEMU_ERESTARTSYS expected to match");
|
||||
|
||||
#endif /* ! _ERRNO_DEFS_H_ */
|
||||
|
@ -2,6 +2,10 @@ if not have_bsd_user
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
bsd_user_ss = ss.source_set()
|
||||
|
||||
common_user_inc += include_directories('.')
|
||||
|
||||
bsd_user_ss.add(files(
|
||||
'bsdload.c',
|
||||
'elfload.c',
|
||||
@ -15,3 +19,5 @@ bsd_user_ss.add(files(
|
||||
|
||||
# Pull in the OS-specific build glue, if any
|
||||
subdir(targetos)
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
|
||||
|
24
bsd-user/special-errno.h
Normal file
24
bsd-user/special-errno.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* QEMU internal errno values for implementing user-only POSIX.
|
||||
*
|
||||
* Copyright (c) 2021 Linaro, Ltd.
|
||||
*/
|
||||
|
||||
#ifndef SPECIAL_ERRNO_H
|
||||
#define SPECIAL_ERRNO_H
|
||||
|
||||
/*
|
||||
* All of these are QEMU internal, not visible to the guest.
|
||||
* They should be chosen so as to not overlap with any host
|
||||
* or guest errno.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is returned when a system call should be restarted, to tell the
|
||||
* main loop that it should wind the guest PC backwards so it will
|
||||
* re-execute the syscall after handling any pending signals.
|
||||
*/
|
||||
#define QEMU_ERESTARTSYS 255
|
||||
|
||||
#endif /* SPECIAL_ERRNO_H */
|
88
common-user/host/aarch64/safe-syscall.inc.S
Normal file
88
common-user/host/aarch64/safe-syscall.inc.S
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 common-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
|
||||
.type safe_syscall_start, #function
|
||||
.type safe_syscall_end, #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').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
/* The syscall calling convention isn't the same as the
|
||||
* C one:
|
||||
* we enter with x0 == &signal_pending
|
||||
* x1 == syscall number
|
||||
* x2 ... x7, (stack) == syscall arguments
|
||||
* and return the result in x0
|
||||
* and the syscall instruction needs
|
||||
* x8 == syscall number
|
||||
* x0 ... x6 == syscall arguments
|
||||
* and returns the result in x0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mov x9, x0 /* signal_pending pointer */
|
||||
mov x8, x1 /* syscall number */
|
||||
mov x0, x2 /* syscall arguments */
|
||||
mov x1, x3
|
||||
mov x2, x4
|
||||
mov x3, x5
|
||||
mov x4, x6
|
||||
mov x5, x7
|
||||
ldr x6, [sp]
|
||||
|
||||
/* 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 w10, [x9]
|
||||
cbnz w10, 2f
|
||||
svc 0x0
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp x0, #-4096
|
||||
b.hi 0f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
b.cs 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
ret
|
||||
|
||||
#if defined(__linux__)
|
||||
/* code path setting errno */
|
||||
0: neg w0, w0
|
||||
b safe_syscall_set_errno_tail
|
||||
#endif
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov w0, #QEMU_ERESTARTSYS
|
||||
1: b safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
108
common-user/host/arm/safe-syscall.inc.S
Normal file
108
common-user/host/arm/safe-syscall.inc.S
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 common-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').
|
||||
*/
|
||||
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 2f
|
||||
swi 0
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp r0, #-4096
|
||||
neghi r0, r0
|
||||
bhi 1f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
bcs 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
pop { r4, r5, r6, r7, r8, pc }
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov r0, #QEMU_ERESTARTSYS
|
||||
|
||||
/* code path setting errno */
|
||||
1: pop { r4, r5, r6, r7, r8, lr }
|
||||
.cfi_adjust_cfa_offset -24
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
.cfi_restore r8
|
||||
.cfi_restore lr
|
||||
b safe_syscall_set_errno_tail
|
||||
|
||||
.fnend
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
126
common-user/host/i386/safe-syscall.inc.S
Normal file
126
common-user/host/i386/safe-syscall.inc.S
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 common-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
|
||||
|
||||
/* 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').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
push %ebp
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebp, 0
|
||||
push %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
push %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
push %ebx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebx, 0
|
||||
|
||||
/* The syscall calling convention isn't the same as the C one:
|
||||
* we enter with 0(%esp) == return address
|
||||
* 4(%esp) == &signal_pending
|
||||
* 8(%esp) == syscall number
|
||||
* 12(%esp) ... 32(%esp) == syscall arguments
|
||||
* and return the result in eax
|
||||
* and the syscall instruction needs
|
||||
* eax == syscall number
|
||||
* ebx, ecx, edx, esi, edi, ebp == syscall arguments
|
||||
* and returns the result in eax
|
||||
* Shuffle everything around appropriately.
|
||||
* Note the 16 bytes that we pushed to save registers.
|
||||
*/
|
||||
mov 12+16(%esp), %ebx /* the syscall arguments */
|
||||
mov 16+16(%esp), %ecx
|
||||
mov 20+16(%esp), %edx
|
||||
mov 24+16(%esp), %esi
|
||||
mov 28+16(%esp), %edi
|
||||
mov 32+16(%esp), %ebp
|
||||
|
||||
/* 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 */
|
||||
mov 4+16(%esp), %eax /* signal_pending */
|
||||
cmpl $0, (%eax)
|
||||
jnz 2f
|
||||
mov 8+16(%esp), %eax /* syscall number */
|
||||
int $0x80
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp $-4095, %eax
|
||||
jae 0f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
jc 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
pop %ebx
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
pop %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
pop %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
pop %ebp
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebp
|
||||
ret
|
||||
.cfi_restore_state
|
||||
|
||||
#if defined(__linux__)
|
||||
0: neg %eax
|
||||
jmp 1f
|
||||
#endif
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov $QEMU_ERESTARTSYS, %eax
|
||||
|
||||
/* code path setting errno */
|
||||
1: pop %ebx
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
pop %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
pop %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
pop %ebp
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebp
|
||||
jmp safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
148
common-user/host/mips/safe-syscall.inc.S
Normal file
148
common-user/host/mips/safe-syscall.inc.S
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <richard.henderson@linaro.org>
|
||||
* Copyright (C) 2021 Linaro, 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.
|
||||
*/
|
||||
|
||||
#include "sys/regdef.h"
|
||||
#include "sys/asm.h"
|
||||
|
||||
.text
|
||||
.set nomips16
|
||||
.set reorder
|
||||
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @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').
|
||||
*/
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
/* 8 * 4 = 32 for outgoing parameters; 1 * 4 for s0 save; 1 * 4 for align. */
|
||||
#define FRAME 40
|
||||
#define OFS_S0 32
|
||||
#else
|
||||
/* 1 * 8 for s0 save; 1 * 8 for align. */
|
||||
#define FRAME 16
|
||||
#define OFS_S0 0
|
||||
#endif
|
||||
|
||||
|
||||
NESTED(safe_syscall_base, FRAME, ra)
|
||||
.cfi_startproc
|
||||
PTR_ADDIU sp, sp, -FRAME
|
||||
.cfi_adjust_cfa_offset FRAME
|
||||
REG_S s0, OFS_S0(sp)
|
||||
.cfi_rel_offset s0, OFS_S0
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2, a3, stack == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* v0 == syscall number
|
||||
* a0 ... a3, stack == syscall arguments
|
||||
* and returns the result in v0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
move s0, a0 /* signal_pending pointer */
|
||||
move v0, a1 /* syscall number */
|
||||
move a0, a2 /* syscall arguments */
|
||||
move a1, a3
|
||||
lw a2, FRAME+16(sp)
|
||||
lw a3, FRAME+20(sp)
|
||||
lw t4, FRAME+24(sp)
|
||||
lw t5, FRAME+28(sp)
|
||||
lw t6, FRAME+32(sp)
|
||||
lw t7, FRAME+40(sp)
|
||||
sw t4, 16(sp)
|
||||
sw t5, 20(sp)
|
||||
sw t6, 24(sp)
|
||||
sw t7, 28(sp)
|
||||
#else
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2 ... a7 == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* v0 == syscall number
|
||||
* a0 ... a5 == syscall arguments
|
||||
* and returns the result in v0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
move s0, a0 /* signal_pending pointer */
|
||||
move v0, a1 /* syscall number */
|
||||
move a0, a2 /* syscall arguments */
|
||||
move a1, a3
|
||||
move a2, a4
|
||||
move a3, a5
|
||||
move a4, a6
|
||||
move a5, a7
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
lw t1, 0(s0)
|
||||
bnez t1, 2f
|
||||
syscall
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
REG_L s0, OFS_S0(sp)
|
||||
PTR_ADDIU sp, sp, FRAME
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -FRAME
|
||||
.cfi_restore s0
|
||||
bnez a3, 1f
|
||||
jr ra
|
||||
.cfi_restore_state
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: REG_L s0, OFS_S0(sp)
|
||||
PTR_ADDIU sp, sp, FRAME
|
||||
.cfi_adjust_cfa_offset -FRAME
|
||||
.cfi_restore s0
|
||||
li v0, QEMU_ERESTARTSYS
|
||||
|
||||
/* code path setting errno */
|
||||
/*
|
||||
* We didn't setup GP on entry, optimistic of the syscall success.
|
||||
* We must do so now to load the address of the helper, as required
|
||||
* by the ABI, into t9.
|
||||
*
|
||||
* Note that SETUP_GPX and SETUP_GPX64 are themselves conditional,
|
||||
* so we can simply let the one that's not empty succeed.
|
||||
*/
|
||||
1: USE_ALT_CP(t0)
|
||||
SETUP_GPX(t1)
|
||||
SETUP_GPX64(t0, t1)
|
||||
PTR_LA t9, safe_syscall_set_errno_tail
|
||||
jr t9
|
||||
|
||||
.cfi_endproc
|
||||
END(safe_syscall_base)
|
94
common-user/host/ppc64/safe-syscall.inc.S
Normal file
94
common-user/host/ppc64/safe-syscall.inc.S
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 common-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
|
||||
|
||||
.text
|
||||
|
||||
/* 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').
|
||||
*/
|
||||
#if _CALL_ELF == 2
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
.localentry safe_syscall_base,0
|
||||
#else
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
safe_syscall_base:
|
||||
.quad .L.safe_syscall_base,.TOC.@tocbase,0
|
||||
.previous
|
||||
.L.safe_syscall_base:
|
||||
.cfi_startproc
|
||||
#endif
|
||||
/* We enter with r3 == &signal_pending
|
||||
* r4 == syscall number
|
||||
* r5 ... r10 == syscall arguments
|
||||
* and return the result in r3
|
||||
* and the syscall instruction needs
|
||||
* r0 == syscall number
|
||||
* r3 ... r8 == syscall arguments
|
||||
* and returns the result in r3
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
std 14, 16(1) /* Preserve r14 in SP+16 */
|
||||
.cfi_offset 14, 16
|
||||
mr 14, 3 /* signal_pending */
|
||||
mr 0, 4 /* syscall number */
|
||||
mr 3, 5 /* syscall arguments */
|
||||
mr 4, 6
|
||||
mr 5, 7
|
||||
mr 6, 8
|
||||
mr 7, 9
|
||||
mr 8, 10
|
||||
|
||||
/* 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 */
|
||||
lwz 12, 0(14)
|
||||
cmpwi 0, 12, 0
|
||||
bne- 2f
|
||||
sc
|
||||
safe_syscall_end:
|
||||
/* code path when we did execute the syscall */
|
||||
ld 14, 16(1) /* restore r14 */
|
||||
bso- 1f
|
||||
blr
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: ld 14, 16(1) /* restore r14 */
|
||||
addi 3, 0, QEMU_ERESTARTSYS
|
||||
|
||||
/* code path setting errno */
|
||||
1: b safe_syscall_set_errno_tail
|
||||
nop /* per abi, for the linker to modify */
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
#if _CALL_ELF == 2
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
#else
|
||||
.size safe_syscall_base, .-.L.safe_syscall_base
|
||||
.size .L.safe_syscall_base, .-.L.safe_syscall_base
|
||||
#endif
|
79
common-user/host/riscv/safe-syscall.inc.S
Normal file
79
common-user/host/riscv/safe-syscall.inc.S
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2018 Linaro, 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
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @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').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == &signal_pending
|
||||
* a1 == syscall number
|
||||
* a2 ... a7 == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* a7 == syscall number
|
||||
* a0 ... a5 == syscall arguments
|
||||
* and returns the result in a0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mv t0, a0 /* signal_pending pointer */
|
||||
mv t1, a1 /* syscall number */
|
||||
mv a0, a2 /* syscall arguments */
|
||||
mv a1, a3
|
||||
mv a2, a4
|
||||
mv a3, a5
|
||||
mv a4, a6
|
||||
mv a5, a7
|
||||
mv a7, t1
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
lw t1, 0(t0)
|
||||
bnez t1, 2f
|
||||
scall
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
li t2, -4096
|
||||
bgtu a0, t2, 0f
|
||||
ret
|
||||
|
||||
/* code path setting errno */
|
||||
0: neg a0, a0
|
||||
j safe_syscall_set_errno_tail
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: li a0, QEMU_ERESTARTSYS
|
||||
j safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
98
common-user/host/s390x/safe-syscall.inc.S
Normal file
98
common-user/host/s390x/safe-syscall.inc.S
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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 common-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
|
||||
|
||||
/* 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').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
stmg %r6,%r15,48(%r15) /* save all call-saved registers */
|
||||
.cfi_offset %r15,-40
|
||||
.cfi_offset %r14,-48
|
||||
.cfi_offset %r13,-56
|
||||
.cfi_offset %r12,-64
|
||||
.cfi_offset %r11,-72
|
||||
.cfi_offset %r10,-80
|
||||
.cfi_offset %r9,-88
|
||||
.cfi_offset %r8,-96
|
||||
.cfi_offset %r7,-104
|
||||
.cfi_offset %r6,-112
|
||||
lgr %r1,%r15
|
||||
lg %r0,8(%r15) /* load eos */
|
||||
aghi %r15,-160
|
||||
.cfi_adjust_cfa_offset 160
|
||||
stg %r1,0(%r15) /* store back chain */
|
||||
stg %r0,8(%r15) /* store eos */
|
||||
|
||||
/*
|
||||
* The syscall calling convention isn't the same as the C one:
|
||||
* we enter with r2 == &signal_pending
|
||||
* r3 == syscall number
|
||||
* r4, r5, r6, (stack) == syscall arguments
|
||||
* and return the result in r2
|
||||
* and the syscall instruction needs
|
||||
* r1 == syscall number
|
||||
* r2 ... r7 == syscall arguments
|
||||
* and returns the result in r2
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
lgr %r8,%r2 /* signal_pending pointer */
|
||||
lgr %r1,%r3 /* syscall number */
|
||||
lgr %r2,%r4 /* syscall args */
|
||||
lgr %r3,%r5
|
||||
lgr %r4,%r6
|
||||
lmg %r5,%r7,320(%r15)
|
||||
|
||||
/* 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 */
|
||||
icm %r0,15,0(%r8)
|
||||
jne 2f
|
||||
svc 0
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
lg %r15,0(%r15) /* load back chain */
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -160
|
||||
lmg %r6,%r15,48(%r15) /* load saved registers */
|
||||
|
||||
lghi %r0, -4095 /* check for syscall error */
|
||||
clgr %r2, %r0
|
||||
blr %r14 /* return on success */
|
||||
lcr %r2, %r2 /* create positive errno */
|
||||
jg safe_syscall_set_errno_tail
|
||||
.cfi_restore_state
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: lg %r15,0(%r15) /* load back chain */
|
||||
.cfi_adjust_cfa_offset -160
|
||||
lmg %r6,%r15,48(%r15) /* load saved registers */
|
||||
lghi %r2, QEMU_ERESTARTSYS
|
||||
jg safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
89
common-user/host/sparc64/safe-syscall.inc.S
Normal file
89
common-user/host/sparc64/safe-syscall.inc.S
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 common-user/safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <richard.henderson@linaro.org>
|
||||
* Copyright (C) 2021 Linaro, 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.
|
||||
*/
|
||||
|
||||
.text
|
||||
.balign 4
|
||||
|
||||
.register %g2, #scratch
|
||||
.register %g3, #scratch
|
||||
|
||||
.global safe_syscall_base
|
||||
.global safe_syscall_start
|
||||
.global safe_syscall_end
|
||||
.type safe_syscall_base, @function
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @function
|
||||
|
||||
#define STACK_BIAS 2047
|
||||
#define PARAM(N) STACK_BIAS + N*8
|
||||
|
||||
/*
|
||||
* 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').
|
||||
*/
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
/*
|
||||
* The syscall calling convention isn't the same as the C one:
|
||||
* we enter with o0 == &signal_pending
|
||||
* o1 == syscall number
|
||||
* o2 ... o5, (stack) == syscall arguments
|
||||
* and return the result in x0
|
||||
* and the syscall instruction needs
|
||||
* g1 == syscall number
|
||||
* o0 ... o5 == syscall arguments
|
||||
* and returns the result in o0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mov %o0, %g2 /* signal_pending pointer */
|
||||
mov %o1, %g1 /* syscall number */
|
||||
mov %o2, %o0 /* syscall arguments */
|
||||
mov %o3, %o1
|
||||
mov %o4, %o2
|
||||
mov %o5, %o3
|
||||
ldx [%sp + PARAM(6)], %o4
|
||||
ldx [%sp + PARAM(7)], %o5
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
lduw [%g2], %g3
|
||||
brnz,pn %g3, 2f
|
||||
nop
|
||||
ta 0x6d
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
bcs,pn %xcc, 1f
|
||||
nop
|
||||
ret
|
||||
nop
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: set QEMU_ERESTARTSYS, %o0
|
||||
|
||||
/* code path setting errno */
|
||||
1: mov %o7, %g1
|
||||
call safe_syscall_set_errno_tail
|
||||
mov %g1, %o7
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* This is intended to be included by common-user/safe-syscall.S
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
|
||||
*
|
||||
@ -19,9 +19,6 @@
|
||||
* 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:
|
||||
.cfi_startproc
|
||||
@ -35,9 +32,9 @@ safe_syscall_base:
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset rbp, 0
|
||||
|
||||
/* The syscall calling convention isn't the same as the
|
||||
* C one:
|
||||
* we enter with rdi == *signal_pending
|
||||
/*
|
||||
* 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
|
||||
@ -67,25 +64,42 @@ safe_syscall_base:
|
||||
*/
|
||||
safe_syscall_start:
|
||||
/* if signal_pending is non-zero, don't do the call */
|
||||
cmpl $0, (%rbp)
|
||||
jnz 1f
|
||||
cmpl $0, (%rbp)
|
||||
jnz 2f
|
||||
syscall
|
||||
safe_syscall_end:
|
||||
|
||||
/* code path for having successfully executed the syscall */
|
||||
#if defined(__linux__)
|
||||
/* Linux kernel returns (small) negative errno. */
|
||||
cmp $-4095, %rax
|
||||
jae 0f
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD kernel returns positive errno and C bit set. */
|
||||
jc 1f
|
||||
#else
|
||||
#error "unsupported os"
|
||||
#endif
|
||||
pop %rbp
|
||||
.cfi_remember_state
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_restore rbp
|
||||
ret
|
||||
|
||||
1:
|
||||
/* code path when we didn't execute the syscall */
|
||||
.cfi_restore_state
|
||||
mov $-TARGET_ERESTARTSYS, %rax
|
||||
pop %rbp
|
||||
|
||||
#if defined(__linux__)
|
||||
0: neg %eax
|
||||
jmp 1f
|
||||
#endif
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: mov $QEMU_ERESTARTSYS, %eax
|
||||
|
||||
/* code path setting errno */
|
||||
1: pop %rbp
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_restore rbp
|
||||
ret
|
||||
jmp safe_syscall_set_errno_tail
|
||||
.cfi_endproc
|
||||
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
6
common-user/meson.build
Normal file
6
common-user/meson.build
Normal file
@ -0,0 +1,6 @@
|
||||
common_user_inc += include_directories('host/' / host_arch)
|
||||
|
||||
common_user_ss.add(files(
|
||||
'safe-syscall.S',
|
||||
'safe-syscall-error.c',
|
||||
))
|
25
common-user/safe-syscall-error.c
Normal file
25
common-user/safe-syscall-error.c
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* safe-syscall-error.c: errno setting fragment
|
||||
* This is intended to be invoked by safe-syscall.S
|
||||
*
|
||||
* Written by Richard Henderson <rth@twiddle.net>
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "user/safe-syscall.h"
|
||||
|
||||
/*
|
||||
* This is intended to be invoked via tail-call on the error path
|
||||
* from the assembly in host/arch/safe-syscall.inc.S. This takes
|
||||
* care of the host specific addressing of errno.
|
||||
* Return -1 to finalize the return value for safe_syscall_base.
|
||||
*/
|
||||
long safe_syscall_set_errno_tail(int value)
|
||||
{
|
||||
errno = value;
|
||||
return -1;
|
||||
}
|
@ -10,15 +10,12 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "hostdep.h"
|
||||
#include "target_errno_defs.h"
|
||||
#include "special-errno.h"
|
||||
|
||||
/* We have the correct host directory on our include path
|
||||
* so that this will pull in the right fragment for the architecture.
|
||||
*/
|
||||
#ifdef HAVE_SAFE_SYSCALL
|
||||
#include "safe-syscall.inc.S"
|
||||
#endif
|
||||
|
||||
/* We must specifically say that we're happy for the stack to not be
|
||||
* executable, otherwise the toolchain will default to assuming our
|
@ -25,10 +25,10 @@
|
||||
*
|
||||
* Call a system call if guest signal not pending.
|
||||
* This has the same API as the libc syscall() function, except that it
|
||||
* may return -1 with errno == TARGET_ERESTARTSYS if a signal was pending.
|
||||
* may return -1 with errno == QEMU_ERESTARTSYS if a signal was pending.
|
||||
*
|
||||
* Returns: the system call result, or -1 with an error code in errno
|
||||
* (Errnos are host errnos; we rely on TARGET_ERESTARTSYS not clashing
|
||||
* (Errnos are host errnos; we rely on QEMU_ERESTARTSYS not clashing
|
||||
* with any of the host errno values.)
|
||||
*/
|
||||
|
||||
@ -81,7 +81,7 @@
|
||||
* which are only technically blocking (ie which we know in practice won't
|
||||
* stay in the host kernel indefinitely) it's OK to use libc if necessary.
|
||||
* You must be able to cope with backing out correctly if some safe_syscall
|
||||
* you make in the implementation returns either -TARGET_ERESTARTSYS or
|
||||
* you make in the implementation returns either -QEMU_ERESTARTSYS or
|
||||
* EINTR though.)
|
||||
*
|
||||
* block_signals() cannot be used for interruptible syscalls.
|
||||
@ -94,7 +94,7 @@
|
||||
* handler checks the interrupted host PC against the addresse of that
|
||||
* known section. If the PC is before or at the address of the syscall
|
||||
* instruction then we change the PC to point at a "return
|
||||
* -TARGET_ERESTARTSYS" code path instead, and then exit the signal handler
|
||||
* -QEMU_ERESTARTSYS" code path instead, and then exit the signal handler
|
||||
* (causing the safe_syscall() call to immediately return that value).
|
||||
* Then in the main.c loop if we see this magic return value we adjust
|
||||
* the guest PC to wind it back to before the system call, and invoke
|
||||
@ -124,34 +124,17 @@
|
||||
* need to check SA_RESTART flags in QEMU or distinguish the various
|
||||
* kinds of restartability.
|
||||
*/
|
||||
#ifdef HAVE_SAFE_SYSCALL
|
||||
|
||||
/* The core part of this function is implemented in assembly */
|
||||
extern long safe_syscall_base(int *pending, long number, ...);
|
||||
extern long safe_syscall_set_errno_tail(int value);
|
||||
|
||||
/* These are defined by the safe-syscall.inc.S file */
|
||||
extern char safe_syscall_start[];
|
||||
extern char safe_syscall_end[];
|
||||
|
||||
#define safe_syscall(...) \
|
||||
({ \
|
||||
long ret_; \
|
||||
int *psp_ = &((TaskState *)thread_cpu->opaque)->signal_pending; \
|
||||
ret_ = safe_syscall_base(psp_, __VA_ARGS__); \
|
||||
if (is_error(ret_)) { \
|
||||
errno = -ret_; \
|
||||
ret_ = -1; \
|
||||
} \
|
||||
ret_; \
|
||||
})
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Fallback for architectures which don't yet provide a safe-syscall assembly
|
||||
* fragment; note that this is racy!
|
||||
* This should go away when all host architectures have been updated.
|
||||
*/
|
||||
#define safe_syscall syscall
|
||||
|
||||
#endif
|
||||
#define safe_syscall(...) \
|
||||
safe_syscall_base(&((TaskState *)thread_cpu->opaque)->signal_pending, \
|
||||
__VA_ARGS__)
|
||||
|
||||
#endif
|
@ -99,9 +99,9 @@ void cpu_loop(CPUARMState *env)
|
||||
env->xregs[4],
|
||||
env->xregs[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->xregs[0] = ret;
|
||||
}
|
||||
break;
|
||||
|
@ -556,12 +556,12 @@ long do_rt_sigreturn(CPUARMState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_sigreturn(CPUARMState *env)
|
||||
|
@ -98,11 +98,11 @@ void cpu_loop(CPUAlphaState *env)
|
||||
env->ir[IR_A2], env->ir[IR_A3],
|
||||
env->ir[IR_A4], env->ir[IR_A5],
|
||||
0, 0);
|
||||
if (sysret == -TARGET_ERESTARTSYS) {
|
||||
if (sysret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
break;
|
||||
}
|
||||
if (sysret == -TARGET_QEMU_ESIGRETURN) {
|
||||
if (sysret == -QEMU_ESIGRETURN) {
|
||||
break;
|
||||
}
|
||||
/* Syscall writes 0 to V0 to bypass error check, similar
|
||||
|
@ -225,11 +225,11 @@ long do_sigreturn(CPUAlphaState *env)
|
||||
|
||||
restore_sigcontext(env, sc);
|
||||
unlock_user_struct(sc, sc_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUAlphaState *env)
|
||||
@ -249,13 +249,13 @@ long do_rt_sigreturn(CPUAlphaState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
@ -407,9 +407,9 @@ void cpu_loop(CPUARMState *env)
|
||||
env->regs[4],
|
||||
env->regs[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->regs[15] -= env->thumb ? 2 : 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[0] = ret;
|
||||
}
|
||||
}
|
||||
|
@ -511,12 +511,12 @@ long do_sigreturn(CPUARMState *env)
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUARMState *env)
|
||||
@ -546,12 +546,12 @@ long do_rt_sigreturn(CPUARMState *env)
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define CPU_LOOP_COMMON_H
|
||||
|
||||
#include "exec/log.h"
|
||||
#include "special-errno.h"
|
||||
|
||||
#define EXCP_DUMP(env, fmt, ...) \
|
||||
do { \
|
||||
|
@ -50,9 +50,9 @@ void cpu_loop(CPUCRISState *env)
|
||||
env->pregs[7],
|
||||
env->pregs[11],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[10] = ret;
|
||||
}
|
||||
break;
|
||||
|
@ -177,10 +177,10 @@ long do_sigreturn(CPUCRISState *env)
|
||||
|
||||
restore_sigcontext(&frame->sc, env);
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUCRISState *env)
|
||||
|
@ -147,21 +147,4 @@
|
||||
#define TARGET_ERFKILL 132 /* Operation not possible due to RF-kill */
|
||||
#define TARGET_EHWPOISON 133 /* Memory page has hardware error */
|
||||
|
||||
/* QEMU internal, not visible to the guest. This is returned when a
|
||||
* system call should be restarted, to tell the main loop that it
|
||||
* should wind the guest PC backwards so it will re-execute the syscall
|
||||
* after handling any pending signals. They match with the ones the guest
|
||||
* kernel uses for the same purpose.
|
||||
*/
|
||||
#define TARGET_ERESTARTSYS 512 /* Restart system call (if SA_RESTART) */
|
||||
|
||||
/* QEMU internal, not visible to the guest. This is returned by the
|
||||
* do_sigreturn() code after a successful sigreturn syscall, to indicate
|
||||
* that it has correctly set the guest registers and so the main loop
|
||||
* should not touch them. We use the value the guest would use for
|
||||
* ERESTART_NOINTR (which is kernel internal) to guarantee that we won't
|
||||
* clash with a valid guest errno now or in the future.
|
||||
*/
|
||||
#define TARGET_QEMU_ESIGRETURN 513 /* Return from signal */
|
||||
|
||||
#endif
|
||||
|
@ -55,9 +55,9 @@ void cpu_loop(CPUHexagonState *env)
|
||||
env->gpr[4],
|
||||
env->gpr[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->gpr[HEX_REG_PC] -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->gpr[0] = ret;
|
||||
}
|
||||
break;
|
||||
|
@ -268,7 +268,7 @@ long do_rt_sigreturn(CPUHexagonState *env)
|
||||
target_restore_altstack(&frame->uc.uc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef AARCH64_HOSTDEP_H
|
||||
#define AARCH64_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
.type safe_syscall_start, #function
|
||||
.type safe_syscall_end, #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:
|
||||
.cfi_startproc
|
||||
/* The syscall calling convention isn't the same as the
|
||||
* C one:
|
||||
* we enter with x0 == *signal_pending
|
||||
* x1 == syscall number
|
||||
* x2 ... x7, (stack) == syscall arguments
|
||||
* and return the result in x0
|
||||
* and the syscall instruction needs
|
||||
* x8 == syscall number
|
||||
* x0 ... x6 == syscall arguments
|
||||
* and returns the result in x0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mov x9, x0 /* signal_pending pointer */
|
||||
mov x8, x1 /* syscall number */
|
||||
mov x0, x2 /* syscall arguments */
|
||||
mov x1, x3
|
||||
mov x2, x4
|
||||
mov x3, x5
|
||||
mov x4, x6
|
||||
mov x5, x7
|
||||
ldr x6, [sp]
|
||||
|
||||
/* 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 w10, [x9]
|
||||
cbnz w10, 0f
|
||||
svc 0x0
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
ret
|
||||
|
||||
0:
|
||||
/* code path when we didn't execute the syscall */
|
||||
mov x0, #-TARGET_ERESTARTSYS
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef ARM_HOSTDEP_H
|
||||
#define ARM_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef I386_HOSTDEP_H
|
||||
#define I386_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* 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:
|
||||
.cfi_startproc
|
||||
push %ebp
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebp, 0
|
||||
push %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
push %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
push %ebx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ebx, 0
|
||||
|
||||
/* The syscall calling convention isn't the same as the C one:
|
||||
* we enter with 0(%esp) == return address
|
||||
* 4(%esp) == *signal_pending
|
||||
* 8(%esp) == syscall number
|
||||
* 12(%esp) ... 32(%esp) == syscall arguments
|
||||
* and return the result in eax
|
||||
* and the syscall instruction needs
|
||||
* eax == syscall number
|
||||
* ebx, ecx, edx, esi, edi, ebp == syscall arguments
|
||||
* and returns the result in eax
|
||||
* Shuffle everything around appropriately.
|
||||
* Note the 16 bytes that we pushed to save registers.
|
||||
*/
|
||||
mov 12+16(%esp), %ebx /* the syscall arguments */
|
||||
mov 16+16(%esp), %ecx
|
||||
mov 20+16(%esp), %edx
|
||||
mov 24+16(%esp), %esi
|
||||
mov 28+16(%esp), %edi
|
||||
mov 32+16(%esp), %ebp
|
||||
|
||||
/* 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 */
|
||||
mov 4+16(%esp), %eax /* signal_pending */
|
||||
cmpl $0, (%eax)
|
||||
jnz 1f
|
||||
mov 8+16(%esp), %eax /* syscall number */
|
||||
int $0x80
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
pop %ebx
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebx
|
||||
pop %edi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore edi
|
||||
pop %esi
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore esi
|
||||
pop %ebp
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore ebp
|
||||
ret
|
||||
|
||||
1:
|
||||
/* code path when we didn't execute the syscall */
|
||||
.cfi_restore_state
|
||||
mov $-TARGET_ERESTARTSYS, %eax
|
||||
jmp safe_syscall_end
|
||||
.cfi_endproc
|
||||
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef IA64_HOSTDEP_H
|
||||
#define IA64_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef MIPS_HOSTDEP_H
|
||||
#define MIPS_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef PPC_HOSTDEP_H
|
||||
#define PPC_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef PPC64_HOSTDEP_H
|
||||
#define PPC64_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
.text
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
#if _CALL_ELF == 2
|
||||
safe_syscall_base:
|
||||
.cfi_startproc
|
||||
.localentry safe_syscall_base,0
|
||||
#else
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
safe_syscall_base:
|
||||
.quad .L.safe_syscall_base,.TOC.@tocbase,0
|
||||
.previous
|
||||
.L.safe_syscall_base:
|
||||
.cfi_startproc
|
||||
#endif
|
||||
/* We enter with r3 == *signal_pending
|
||||
* r4 == syscall number
|
||||
* r5 ... r10 == syscall arguments
|
||||
* and return the result in r3
|
||||
* and the syscall instruction needs
|
||||
* r0 == syscall number
|
||||
* r3 ... r8 == syscall arguments
|
||||
* and returns the result in r3
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
std 14, 16(1) /* Preserve r14 in SP+16 */
|
||||
.cfi_offset 14, 16
|
||||
mr 14, 3 /* signal_pending */
|
||||
mr 0, 4 /* syscall number */
|
||||
mr 3, 5 /* syscall arguments */
|
||||
mr 4, 6
|
||||
mr 5, 7
|
||||
mr 6, 8
|
||||
mr 7, 9
|
||||
mr 8, 10
|
||||
|
||||
/* 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 */
|
||||
lwz 12, 0(14)
|
||||
cmpwi 0, 12, 0
|
||||
bne- 0f
|
||||
sc
|
||||
safe_syscall_end:
|
||||
/* code path when we did execute the syscall */
|
||||
ld 14, 16(1) /* restore r14 to its original value */
|
||||
bnslr+
|
||||
|
||||
/* syscall failed; return negative errno */
|
||||
neg 3, 3
|
||||
blr
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
0: addi 3, 0, -TARGET_ERESTARTSYS
|
||||
ld 14, 16(1) /* restore r14 to its original value */
|
||||
blr
|
||||
.cfi_endproc
|
||||
|
||||
#if _CALL_ELF == 2
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
#else
|
||||
.size safe_syscall_base, .-.L.safe_syscall_base
|
||||
.size .L.safe_syscall_base, .-.L.safe_syscall_base
|
||||
#endif
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef RISCV_HOSTDEP_H
|
||||
#define RISCV_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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) 2018 Linaro, 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
|
||||
.type safe_syscall_start, @function
|
||||
.type safe_syscall_end, @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:
|
||||
.cfi_startproc
|
||||
/*
|
||||
* The syscall calling convention is nearly the same as C:
|
||||
* we enter with a0 == *signal_pending
|
||||
* a1 == syscall number
|
||||
* a2 ... a7 == syscall arguments
|
||||
* and return the result in a0
|
||||
* and the syscall instruction needs
|
||||
* a7 == syscall number
|
||||
* a0 ... a5 == syscall arguments
|
||||
* and returns the result in a0
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
mv t0, a0 /* signal_pending pointer */
|
||||
mv t1, a1 /* syscall number */
|
||||
mv a0, a2 /* syscall arguments */
|
||||
mv a1, a3
|
||||
mv a2, a4
|
||||
mv a3, a5
|
||||
mv a4, a6
|
||||
mv a5, a7
|
||||
mv a7, t1
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
lw t1, 0(t0)
|
||||
bnez t1, 0f
|
||||
scall
|
||||
safe_syscall_end:
|
||||
/* code path for having successfully executed the syscall */
|
||||
ret
|
||||
|
||||
0:
|
||||
/* code path when we didn't execute the syscall */
|
||||
li a0, -TARGET_ERESTARTSYS
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef S390_HOSTDEP_H
|
||||
#define S390_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef S390X_HOSTDEP_H
|
||||
#define S390X_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* 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:
|
||||
.cfi_startproc
|
||||
stmg %r6,%r15,48(%r15) /* save all call-saved registers */
|
||||
.cfi_offset %r15,-40
|
||||
.cfi_offset %r14,-48
|
||||
.cfi_offset %r13,-56
|
||||
.cfi_offset %r12,-64
|
||||
.cfi_offset %r11,-72
|
||||
.cfi_offset %r10,-80
|
||||
.cfi_offset %r9,-88
|
||||
.cfi_offset %r8,-96
|
||||
.cfi_offset %r7,-104
|
||||
.cfi_offset %r6,-112
|
||||
lgr %r1,%r15
|
||||
lg %r0,8(%r15) /* load eos */
|
||||
aghi %r15,-160
|
||||
.cfi_adjust_cfa_offset 160
|
||||
stg %r1,0(%r15) /* store back chain */
|
||||
stg %r0,8(%r15) /* store eos */
|
||||
|
||||
/* The syscall calling convention isn't the same as the
|
||||
* C one:
|
||||
* we enter with r2 == *signal_pending
|
||||
* r3 == syscall number
|
||||
* r4, r5, r6, (stack) == syscall arguments
|
||||
* and return the result in r2
|
||||
* and the syscall instruction needs
|
||||
* r1 == syscall number
|
||||
* r2 ... r7 == syscall arguments
|
||||
* and returns the result in r2
|
||||
* Shuffle everything around appropriately.
|
||||
*/
|
||||
lgr %r8,%r2 /* signal_pending pointer */
|
||||
lgr %r1,%r3 /* syscall number */
|
||||
lgr %r2,%r4 /* syscall args */
|
||||
lgr %r3,%r5
|
||||
lgr %r4,%r6
|
||||
lmg %r5,%r7,320(%r15)
|
||||
|
||||
/* 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 */
|
||||
icm %r0,15,0(%r8)
|
||||
jne 2f
|
||||
svc 0
|
||||
safe_syscall_end:
|
||||
|
||||
1: lg %r15,0(%r15) /* load back chain */
|
||||
.cfi_remember_state
|
||||
.cfi_adjust_cfa_offset -160
|
||||
lmg %r6,%r15,48(%r15) /* load saved registers */
|
||||
br %r14
|
||||
.cfi_restore_state
|
||||
2: lghi %r2, -TARGET_ERESTARTSYS
|
||||
j 1b
|
||||
.cfi_endproc
|
||||
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef SPARC_HOSTDEP_H
|
||||
#define SPARC_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef SPARC64_HOSTDEP_H
|
||||
#define SPARC64_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef X32_HOSTDEP_H
|
||||
#define X32_HOSTDEP_H
|
||||
|
||||
#endif
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* hostdep.h : things which are dependent on the host architecture
|
||||
*
|
||||
* * Written by Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* Copyright (C) 2016 Linaro Limited
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef X86_64_HOSTDEP_H
|
||||
#define X86_64_HOSTDEP_H
|
||||
|
||||
/* We have a safe-syscall.inc.S */
|
||||
#define HAVE_SAFE_SYSCALL
|
||||
|
||||
#endif
|
@ -133,8 +133,8 @@ void cpu_loop(CPUHPPAState *env)
|
||||
env->iaoq_f = env->gr[31];
|
||||
env->iaoq_b = env->gr[31] + 4;
|
||||
break;
|
||||
case -TARGET_ERESTARTSYS:
|
||||
case -TARGET_QEMU_ESIGRETURN:
|
||||
case -QEMU_ERESTARTSYS:
|
||||
case -QEMU_ESIGRETURN:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -191,9 +191,9 @@ long do_rt_sigreturn(CPUArchState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
@ -180,8 +180,8 @@ static void emulate_vsyscall(CPUX86State *env)
|
||||
ret = do_syscall(env, syscall, env->regs[R_EDI], env->regs[R_ESI],
|
||||
env->regs[R_EDX], env->regs[10], env->regs[8],
|
||||
env->regs[9], 0, 0);
|
||||
g_assert(ret != -TARGET_ERESTARTSYS);
|
||||
g_assert(ret != -TARGET_QEMU_ESIGRETURN);
|
||||
g_assert(ret != -QEMU_ERESTARTSYS);
|
||||
g_assert(ret != -QEMU_ESIGRETURN);
|
||||
if (ret == -TARGET_EFAULT) {
|
||||
goto sigsegv;
|
||||
}
|
||||
@ -223,9 +223,9 @@ void cpu_loop(CPUX86State *env)
|
||||
env->regs[R_EDI],
|
||||
env->regs[R_EBP],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->eip -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[R_EAX] = ret;
|
||||
}
|
||||
break;
|
||||
@ -241,9 +241,9 @@ void cpu_loop(CPUX86State *env)
|
||||
env->regs[8],
|
||||
env->regs[9],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->eip -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[R_EAX] = ret;
|
||||
}
|
||||
break;
|
||||
|
@ -559,12 +559,12 @@ long do_sigreturn(CPUX86State *env)
|
||||
if (restore_sigcontext(env, &frame->sc))
|
||||
goto badframe;
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -588,12 +588,12 @@ long do_rt_sigreturn(CPUX86State *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
#ifndef TARGET_X86_64
|
||||
|
@ -80,9 +80,9 @@ void cpu_loop(CPUM68KState *env)
|
||||
env->dregs[5],
|
||||
env->aregs[0],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->dregs[0] = ret;
|
||||
}
|
||||
}
|
||||
|
@ -353,11 +353,11 @@ long do_sigreturn(CPUM68KState *env)
|
||||
restore_sigcontext(env, &frame->sc);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUM68KState *env)
|
||||
@ -381,12 +381,12 @@ long do_rt_sigreturn(CPUM68KState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
@ -2,6 +2,11 @@ if not have_linux_user
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
linux_user_ss = ss.source_set()
|
||||
|
||||
common_user_inc += include_directories('host/' / host_arch)
|
||||
common_user_inc += include_directories('.')
|
||||
|
||||
linux_user_ss.add(files(
|
||||
'elfload.c',
|
||||
'exit.c',
|
||||
@ -9,10 +14,10 @@ linux_user_ss.add(files(
|
||||
'linuxload.c',
|
||||
'main.c',
|
||||
'mmap.c',
|
||||
'safe-syscall.S',
|
||||
'signal.c',
|
||||
'strace.c',
|
||||
'syscall.c',
|
||||
'thunk.c',
|
||||
'uaccess.c',
|
||||
'uname.c',
|
||||
))
|
||||
@ -39,3 +44,5 @@ subdir('sh4')
|
||||
subdir('sparc')
|
||||
subdir('x86_64')
|
||||
subdir('xtensa')
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
|
||||
|
@ -53,10 +53,10 @@ void cpu_loop(CPUMBState *env)
|
||||
env->regs[9],
|
||||
env->regs[10],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
/* Wind back to before the syscall. */
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[3] = ret;
|
||||
}
|
||||
/* All syscall exits result in guest r14 being equal to the
|
||||
|
@ -207,12 +207,12 @@ long do_rt_sigreturn(CPUMBState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
@ -141,11 +141,11 @@ done_syscall:
|
||||
env->active_tc.gpr[8], env->active_tc.gpr[9],
|
||||
env->active_tc.gpr[10], env->active_tc.gpr[11]);
|
||||
# endif /* O32 */
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->active_tc.PC -= 4;
|
||||
break;
|
||||
}
|
||||
if (ret == -TARGET_QEMU_ESIGRETURN) {
|
||||
if (ret == -QEMU_ESIGRETURN) {
|
||||
/* Returning from a successful sigreturn syscall.
|
||||
Avoid clobbering register state. */
|
||||
break;
|
||||
|
@ -281,11 +281,11 @@ long do_sigreturn(CPUMIPSState *regs)
|
||||
/* I am not sure this is right, but it seems to work
|
||||
* maybe a problem with nested signals ? */
|
||||
regs->CP0_EPC = 0;
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
# endif /* O32 */
|
||||
|
||||
@ -371,11 +371,11 @@ long do_rt_sigreturn(CPUMIPSState *env)
|
||||
/* I am not sure this is right, but it seems to work
|
||||
* maybe a problem with nested signals ? */
|
||||
env->CP0_EPC = 0;
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
@ -48,9 +48,9 @@ void cpu_loop(CPUOpenRISCState *env)
|
||||
cpu_get_gpr(env, 6),
|
||||
cpu_get_gpr(env, 7),
|
||||
cpu_get_gpr(env, 8), 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
cpu_set_gpr(env, 11, ret);
|
||||
}
|
||||
break;
|
||||
|
@ -428,11 +428,11 @@ void cpu_loop(CPUPPCState *env)
|
||||
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
|
||||
env->gpr[5], env->gpr[6], env->gpr[7],
|
||||
env->gpr[8], 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->nip -= 4;
|
||||
break;
|
||||
}
|
||||
if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
|
||||
if (ret == (target_ulong)(-QEMU_ESIGRETURN)) {
|
||||
/* Returning from a successful sigreturn syscall.
|
||||
Avoid corrupting register state. */
|
||||
break;
|
||||
|
@ -591,13 +591,13 @@ long do_sigreturn(CPUPPCState *env)
|
||||
|
||||
unlock_user_struct(sr, sr_addr, 1);
|
||||
unlock_user_struct(sc, sc_addr, 1);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
sigsegv:
|
||||
unlock_user_struct(sr, sr_addr, 1);
|
||||
unlock_user_struct(sc, sc_addr, 1);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
#endif /* !defined(TARGET_PPC64) */
|
||||
|
||||
@ -646,12 +646,12 @@ long do_rt_sigreturn(CPUPPCState *env)
|
||||
target_restore_altstack(&rt_sf->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(rt_sf, rt_sf_addr, 1);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
sigsegv:
|
||||
unlock_user_struct(rt_sf, rt_sf_addr, 1);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
/* This syscall implements {get,set,swap}context for userland. */
|
||||
@ -704,7 +704,7 @@ abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
|
||||
/* We cannot return to a partially updated context. */
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
}
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -69,9 +69,9 @@ void cpu_loop(CPURISCVState *env)
|
||||
env->gpr[xA5],
|
||||
0, 0);
|
||||
}
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->gpr[xA0] = ret;
|
||||
}
|
||||
if (cs->singlestep_enabled) {
|
||||
|
@ -188,7 +188,7 @@ long do_rt_sigreturn(CPURISCVState *env)
|
||||
target_restore_altstack(&frame->uc.uc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
|
@ -83,9 +83,9 @@ void cpu_loop(CPUS390XState *env)
|
||||
ret = do_syscall(env, n, env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7], 0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->psw.addr -= env->int_svc_ilen;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->regs[2] = ret;
|
||||
}
|
||||
break;
|
||||
|
@ -359,7 +359,7 @@ long do_sigreturn(CPUS390XState *env)
|
||||
trace_user_do_sigreturn(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
/* Make sure that we're initializing all of target_set. */
|
||||
@ -373,7 +373,7 @@ long do_sigreturn(CPUS390XState *env)
|
||||
restore_sigregs_ext(env, &frame->sregs_ext);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUS390XState *env)
|
||||
@ -385,7 +385,7 @@ long do_rt_sigreturn(CPUS390XState *env)
|
||||
trace_user_do_rt_sigreturn(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
|
||||
|
||||
@ -397,7 +397,7 @@ long do_rt_sigreturn(CPUS390XState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
@ -50,9 +50,9 @@ void cpu_loop(CPUSH4State *env)
|
||||
env->gregs[0],
|
||||
env->gregs[1],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 2;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
} else if (ret != -QEMU_ESIGRETURN) {
|
||||
env->gregs[0] = ret;
|
||||
}
|
||||
break;
|
||||
|
@ -286,12 +286,12 @@ long do_sigreturn(CPUSH4State *regs)
|
||||
restore_sigcontext(regs, &frame->sc);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUSH4State *regs)
|
||||
@ -313,12 +313,12 @@ long do_rt_sigreturn(CPUSH4State *regs)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, regs);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef SIGNAL_COMMON_H
|
||||
#define SIGNAL_COMMON_H
|
||||
|
||||
#include "special-errno.h"
|
||||
|
||||
/* Fallback addresses into sigtramp page. */
|
||||
extern abi_ulong default_sigreturn;
|
||||
extern abi_ulong default_rt_sigreturn;
|
||||
@ -76,7 +78,7 @@ abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
|
||||
* Block all signals, and arrange that the signal mask is returned to
|
||||
* its correct value for the guest before we resume execution of guest code.
|
||||
* If this function returns non-zero, then the caller should immediately
|
||||
* return -TARGET_ERESTARTSYS to the main loop, which will take the pending
|
||||
* return -QEMU_ERESTARTSYS to the main loop, which will take the pending
|
||||
* signal and restart execution of the syscall.
|
||||
* If block_signals() returns zero, then the caller can continue with
|
||||
* emulation of the system call knowing that no signals can be taken
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "trace.h"
|
||||
#include "signal-common.h"
|
||||
#include "host-signal.h"
|
||||
#include "safe-syscall.h"
|
||||
#include "user/safe-syscall.h"
|
||||
|
||||
static struct target_sigaction sigact_table[TARGET_NSIG];
|
||||
|
||||
@ -213,7 +213,7 @@ int block_signals(void)
|
||||
|
||||
/* Wrapper for sigprocmask function
|
||||
* Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
|
||||
* are host signal set, not guest ones. Returns -TARGET_ERESTARTSYS if
|
||||
* are host signal set, not guest ones. Returns -QEMU_ERESTARTSYS if
|
||||
* a signal was already pending and the syscall must be restarted, or
|
||||
* 0 on success.
|
||||
* If set is NULL, this is guaranteed not to fail.
|
||||
@ -230,7 +230,7 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
|
||||
int i;
|
||||
|
||||
if (block_signals()) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
|
||||
switch (how) {
|
||||
@ -798,7 +798,6 @@ int queue_signal(CPUArchState *env, int sig, int si_type,
|
||||
/* Adjust the signal context to rewind out of safe-syscall if we're in it */
|
||||
static inline void rewind_if_in_safe_syscall(void *puc)
|
||||
{
|
||||
#ifdef HAVE_SAFE_SYSCALL
|
||||
ucontext_t *uc = (ucontext_t *)puc;
|
||||
uintptr_t pcreg = host_signal_pc(uc);
|
||||
|
||||
@ -806,7 +805,6 @@ static inline void rewind_if_in_safe_syscall(void *puc)
|
||||
&& pcreg < (uintptr_t)safe_syscall_end) {
|
||||
host_signal_set_pc(uc, (uintptr_t)safe_syscall_start);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
|
||||
@ -987,7 +985,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|
||||
}
|
||||
|
||||
if (block_signals()) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
|
||||
k = &sigact_table[sig - 1];
|
||||
|
@ -181,7 +181,7 @@ void cpu_loop (CPUSPARCState *env)
|
||||
env->regwptr[2], env->regwptr[3],
|
||||
env->regwptr[4], env->regwptr[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) {
|
||||
if (ret == -QEMU_ERESTARTSYS || ret == -QEMU_ESIGRETURN) {
|
||||
break;
|
||||
}
|
||||
if ((abi_ulong)ret >= (abi_ulong)(-515)) {
|
||||
|
@ -431,12 +431,12 @@ long do_sigreturn(CPUSPARCState *env)
|
||||
set_sigmask(&host_set);
|
||||
|
||||
unlock_user_struct(sf, sf_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
segv_and_exit:
|
||||
unlock_user_struct(sf, sf_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
#else
|
||||
return -TARGET_ENOSYS;
|
||||
#endif
|
||||
@ -495,12 +495,12 @@ long do_rt_sigreturn(CPUSPARCState *env)
|
||||
env->npc = tnpc;
|
||||
|
||||
unlock_user_struct(sf, sf_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
segv_and_exit:
|
||||
unlock_user_struct(sf, sf_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
|
32
linux-user/special-errno.h
Normal file
32
linux-user/special-errno.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* QEMU internal errno values for implementing user-only POSIX.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* Copyright (c) 2021 Linaro, Ltd.
|
||||
*/
|
||||
|
||||
#ifndef SPECIAL_ERRNO_H
|
||||
#define SPECIAL_ERRNO_H
|
||||
|
||||
/*
|
||||
* All of these are QEMU internal, not visible to the guest.
|
||||
* They should be chosen so as to not overlap with any host
|
||||
* or guest errno.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is returned when a system call should be restarted, to tell the
|
||||
* main loop that it should wind the guest PC backwards so it will
|
||||
* re-execute the syscall after handling any pending signals.
|
||||
*/
|
||||
#define QEMU_ERESTARTSYS 512
|
||||
|
||||
/*
|
||||
* This is returned after a successful sigreturn syscall, to indicate
|
||||
* that it has correctly set the guest registers and so the main loop
|
||||
* should not touch them.
|
||||
*/
|
||||
#define QEMU_ESIGRETURN 513
|
||||
|
||||
#endif /* SPECIAL_ERRNO_H */
|
@ -132,10 +132,11 @@
|
||||
#include "signal-common.h"
|
||||
#include "loader.h"
|
||||
#include "user-mmap.h"
|
||||
#include "safe-syscall.h"
|
||||
#include "user/safe-syscall.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qemu/selfmap.h"
|
||||
#include "user/syscall-trace.h"
|
||||
#include "special-errno.h"
|
||||
#include "qapi/error.h"
|
||||
#include "fd-trans.h"
|
||||
#include "tcg/tcg.h"
|
||||
@ -547,10 +548,10 @@ static inline abi_long get_errno(abi_long ret)
|
||||
|
||||
const char *target_strerror(int err)
|
||||
{
|
||||
if (err == TARGET_ERESTARTSYS) {
|
||||
if (err == QEMU_ERESTARTSYS) {
|
||||
return "To be restarted";
|
||||
}
|
||||
if (err == TARGET_QEMU_ESIGRETURN) {
|
||||
if (err == QEMU_ESIGRETURN) {
|
||||
return "Successful exit from sigreturn";
|
||||
}
|
||||
|
||||
@ -6458,7 +6459,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
||||
}
|
||||
|
||||
if (block_signals()) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
|
||||
fork_start();
|
||||
@ -8328,7 +8329,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
Do thread termination if we have more then one thread. */
|
||||
|
||||
if (block_signals()) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&clone_lock);
|
||||
@ -9317,7 +9318,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
#endif
|
||||
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
|
||||
SIGSET_T_SIZE));
|
||||
if (ret != -TARGET_ERESTARTSYS) {
|
||||
if (ret != -QEMU_ERESTARTSYS) {
|
||||
ts->in_sigsuspend = 1;
|
||||
}
|
||||
}
|
||||
@ -9336,7 +9337,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
unlock_user(p, arg1, 0);
|
||||
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
|
||||
SIGSET_T_SIZE));
|
||||
if (ret != -TARGET_ERESTARTSYS) {
|
||||
if (ret != -QEMU_ERESTARTSYS) {
|
||||
ts->in_sigsuspend = 1;
|
||||
}
|
||||
}
|
||||
@ -9452,13 +9453,13 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR_sigreturn
|
||||
case TARGET_NR_sigreturn:
|
||||
if (block_signals()) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
return do_sigreturn(cpu_env);
|
||||
#endif
|
||||
case TARGET_NR_rt_sigreturn:
|
||||
if (block_signals()) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
return do_rt_sigreturn(cpu_env);
|
||||
case TARGET_NR_sethostname:
|
||||
@ -13145,7 +13146,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||
static bool flag;
|
||||
flag = !flag;
|
||||
if (flag) {
|
||||
return -TARGET_ERESTARTSYS;
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -18,7 +18,6 @@
|
||||
#ifndef LINUX_USER_USER_INTERNALS_H
|
||||
#define LINUX_USER_USER_INTERNALS_H
|
||||
|
||||
#include "hostdep.h"
|
||||
#include "exec/user/thunk.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/log.h"
|
||||
|
@ -184,11 +184,11 @@ void cpu_loop(CPUXtensaState *env)
|
||||
env->regs[2] = ret;
|
||||
break;
|
||||
|
||||
case -TARGET_ERESTARTSYS:
|
||||
case -QEMU_ERESTARTSYS:
|
||||
env->pc -= 3;
|
||||
break;
|
||||
|
||||
case -TARGET_QEMU_ESIGRETURN:
|
||||
case -QEMU_ESIGRETURN:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -263,12 +263,12 @@ long do_rt_sigreturn(CPUXtensaState *env)
|
||||
target_restore_altstack(&frame->uc.tuc_stack, env);
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
|
23
meson.build
23
meson.build
@ -2375,13 +2375,12 @@ genh += hxdep
|
||||
authz_ss = ss.source_set()
|
||||
blockdev_ss = ss.source_set()
|
||||
block_ss = ss.source_set()
|
||||
bsd_user_ss = ss.source_set()
|
||||
chardev_ss = ss.source_set()
|
||||
common_ss = ss.source_set()
|
||||
common_user_ss = ss.source_set()
|
||||
crypto_ss = ss.source_set()
|
||||
hwcore_ss = ss.source_set()
|
||||
io_ss = ss.source_set()
|
||||
linux_user_ss = ss.source_set()
|
||||
qmp_ss = ss.source_set()
|
||||
qom_ss = ss.source_set()
|
||||
softmmu_ss = ss.source_set()
|
||||
@ -2622,14 +2621,24 @@ subdir('tcg')
|
||||
subdir('fpu')
|
||||
subdir('accel')
|
||||
subdir('plugins')
|
||||
subdir('bsd-user')
|
||||
subdir('linux-user')
|
||||
subdir('ebpf')
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
|
||||
common_user_inc = []
|
||||
|
||||
linux_user_ss.add(files('thunk.c'))
|
||||
specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
|
||||
subdir('common-user')
|
||||
subdir('bsd-user')
|
||||
subdir('linux-user')
|
||||
|
||||
common_user_ss = common_user_ss.apply(config_all, strict: false)
|
||||
common_user = static_library('common-user',
|
||||
sources: common_user_ss.sources(),
|
||||
dependencies: common_user_ss.dependencies(),
|
||||
include_directories: common_user_inc,
|
||||
name_suffix: 'fa',
|
||||
build_by_default: false)
|
||||
common_user = declare_dependency(link_with: common_user)
|
||||
|
||||
user_ss.add(common_user)
|
||||
|
||||
# needed for fuzzing binaries
|
||||
subdir('tests/qtest/libqos')
|
||||
|
Loading…
Reference in New Issue
Block a user