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:
Richard Henderson 2021-12-20 13:20:07 -08:00
commit 2bf40d0841
80 changed files with 1099 additions and 932 deletions

View File

@ -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>

View File

@ -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_ */

View File

@ -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
View 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 */

View 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

View 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

View 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

View 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)

View 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

View 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

View 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

View 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

View File

@ -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
@ -68,24 +65,41 @@ safe_syscall_base:
safe_syscall_start:
/* if signal_pending is non-zero, don't do the call */
cmpl $0, (%rbp)
jnz 1f
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
View 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',
))

View 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;
}

View File

@ -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

View File

@ -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
safe_syscall_base(&((TaskState *)thread_cpu->opaque)->signal_pending, \
__VA_ARGS__)
#endif

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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;
}
/*

View File

@ -21,6 +21,7 @@
#define CPU_LOOP_COMMON_H
#include "exec/log.h"
#include "special-errno.h"
#define EXCP_DUMP(env, fmt, ...) \
do { \

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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];

View File

@ -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)) {

View File

@ -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)

View 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 */

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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)

View File

@ -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')