diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-12-20 13:20:07 -0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-12-20 13:20:07 -0800 |
commit | 2bf40d0841b942e7ba12953d515e62a436f0af84 (patch) | |
tree | ee6a0c717a8f2a3f42c7846190edc082da548ed8 /linux-user | |
parent | c7d773ae49688463b59ade6989f8d612fecb973d (diff) | |
parent | 3363615a65af8a09d8adbd19ed3ae6b52f26ca7a (diff) | |
download | qemu-2bf40d0841b942e7ba12953d515e62a436f0af84.zip qemu-2bf40d0841b942e7ba12953d515e62a436f0af84.tar.gz qemu-2bf40d0841b942e7ba12953d515e62a436f0af84.tar.bz2 |
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>
Diffstat (limited to 'linux-user')
65 files changed, 626 insertions, 1155 deletions
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c index f9f3473..1737e2e 100644 --- a/linux-user/aarch64/cpu_loop.c +++ b/linux-user/aarch64/cpu_loop.c @@ -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; diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index 29c52db..df9e39a 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -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) diff --git a/linux-user/alpha/cpu_loop.c b/linux-user/alpha/cpu_loop.c index 4029849..37c33f0 100644 --- a/linux-user/alpha/cpu_loop.c +++ b/linux-user/alpha/cpu_loop.c @@ -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 diff --git a/linux-user/alpha/signal.c b/linux-user/alpha/signal.c index bbe3dd1..4ec4299 100644 --- a/linux-user/alpha/signal.c +++ b/linux-user/alpha/signal.c @@ -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) diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 01cb6eb..f153ab5 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -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; } } diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c index df9f8e8..cf99fd7 100644 --- a/linux-user/arm/signal.c +++ b/linux-user/arm/signal.c @@ -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; } /* diff --git a/linux-user/cpu_loop-common.h b/linux-user/cpu_loop-common.h index 8828af2..dc0042e 100644 --- a/linux-user/cpu_loop-common.h +++ b/linux-user/cpu_loop-common.h @@ -21,6 +21,7 @@ #define CPU_LOOP_COMMON_H #include "exec/log.h" +#include "special-errno.h" #define EXCP_DUMP(env, fmt, ...) \ do { \ diff --git a/linux-user/cris/cpu_loop.c b/linux-user/cris/cpu_loop.c index 0d5d268..5213aeb 100644 --- a/linux-user/cris/cpu_loop.c +++ b/linux-user/cris/cpu_loop.c @@ -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; diff --git a/linux-user/cris/signal.c b/linux-user/cris/signal.c index 7f6aca9..4f532b2 100644 --- a/linux-user/cris/signal.c +++ b/linux-user/cris/signal.c @@ -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) diff --git a/linux-user/generic/target_errno_defs.h b/linux-user/generic/target_errno_defs.h index 17d85e0..c2f9d40 100644 --- a/linux-user/generic/target_errno_defs.h +++ b/linux-user/generic/target_errno_defs.h @@ -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 diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c index e47f834..0d73934 100644 --- a/linux-user/hexagon/cpu_loop.c +++ b/linux-user/hexagon/cpu_loop.c @@ -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; diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c index 74e6173..ad4e382 100644 --- a/linux-user/hexagon/signal.c +++ b/linux-user/hexagon/signal.c @@ -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); diff --git a/linux-user/host/aarch64/hostdep.h b/linux-user/host/aarch64/hostdep.h deleted file mode 100644 index 39299d7..0000000 --- a/linux-user/host/aarch64/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/aarch64/safe-syscall.inc.S b/linux-user/host/aarch64/safe-syscall.inc.S deleted file mode 100644 index bc1f5a9..0000000 --- a/linux-user/host/aarch64/safe-syscall.inc.S +++ /dev/null @@ -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 diff --git a/linux-user/host/arm/hostdep.h b/linux-user/host/arm/hostdep.h deleted file mode 100644 index 86b1378..0000000 --- a/linux-user/host/arm/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/arm/safe-syscall.inc.S b/linux-user/host/arm/safe-syscall.inc.S deleted file mode 100644 index 88c4958..0000000 --- a/linux-user/host/arm/safe-syscall.inc.S +++ /dev/null @@ -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 diff --git a/linux-user/host/i386/hostdep.h b/linux-user/host/i386/hostdep.h deleted file mode 100644 index ce71365..0000000 --- a/linux-user/host/i386/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/i386/safe-syscall.inc.S b/linux-user/host/i386/safe-syscall.inc.S deleted file mode 100644 index 9e58fc6..0000000 --- a/linux-user/host/i386/safe-syscall.inc.S +++ /dev/null @@ -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 diff --git a/linux-user/host/ia64/hostdep.h b/linux-user/host/ia64/hostdep.h deleted file mode 100644 index 263bf76..0000000 --- a/linux-user/host/ia64/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/mips/hostdep.h b/linux-user/host/mips/hostdep.h deleted file mode 100644 index ba111d7..0000000 --- a/linux-user/host/mips/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/ppc/hostdep.h b/linux-user/host/ppc/hostdep.h deleted file mode 100644 index 23d8bd9..0000000 --- a/linux-user/host/ppc/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/ppc64/hostdep.h b/linux-user/host/ppc64/hostdep.h deleted file mode 100644 index 0c290dd..0000000 --- a/linux-user/host/ppc64/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/ppc64/safe-syscall.inc.S b/linux-user/host/ppc64/safe-syscall.inc.S deleted file mode 100644 index 8751331..0000000 --- a/linux-user/host/ppc64/safe-syscall.inc.S +++ /dev/null @@ -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 diff --git a/linux-user/host/riscv/hostdep.h b/linux-user/host/riscv/hostdep.h deleted file mode 100644 index 7f67c22..0000000 --- a/linux-user/host/riscv/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/riscv/safe-syscall.inc.S b/linux-user/host/riscv/safe-syscall.inc.S deleted file mode 100644 index 9ca3fbf..0000000 --- a/linux-user/host/riscv/safe-syscall.inc.S +++ /dev/null @@ -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 diff --git a/linux-user/host/s390/hostdep.h b/linux-user/host/s390/hostdep.h deleted file mode 100644 index afcba5a..0000000 --- a/linux-user/host/s390/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/s390x/hostdep.h b/linux-user/host/s390x/hostdep.h deleted file mode 100644 index d801145..0000000 --- a/linux-user/host/s390x/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/s390x/safe-syscall.inc.S b/linux-user/host/s390x/safe-syscall.inc.S deleted file mode 100644 index 414b44a..0000000 --- a/linux-user/host/s390x/safe-syscall.inc.S +++ /dev/null @@ -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 diff --git a/linux-user/host/sparc/hostdep.h b/linux-user/host/sparc/hostdep.h deleted file mode 100644 index 391ad92..0000000 --- a/linux-user/host/sparc/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/sparc64/hostdep.h b/linux-user/host/sparc64/hostdep.h deleted file mode 100644 index ce3968f..0000000 --- a/linux-user/host/sparc64/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/x32/hostdep.h b/linux-user/host/x32/hostdep.h deleted file mode 100644 index 2c2d6d3..0000000 --- a/linux-user/host/x32/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/x86_64/hostdep.h b/linux-user/host/x86_64/hostdep.h deleted file mode 100644 index 9c62bd2..0000000 --- a/linux-user/host/x86_64/hostdep.h +++ /dev/null @@ -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 diff --git a/linux-user/host/x86_64/safe-syscall.inc.S b/linux-user/host/x86_64/safe-syscall.inc.S deleted file mode 100644 index f36992d..0000000 --- a/linux-user/host/x86_64/safe-syscall.inc.S +++ /dev/null @@ -1,91 +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 - * - * Copyright (C) 2015 Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk> - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - - .global safe_syscall_base - .global safe_syscall_start - .global safe_syscall_end - .type safe_syscall_base, @function - - /* This is the entry point for making a system call. The calling - * convention here is that of a C varargs function with the - * first argument an 'int *' to the signal_pending flag, the - * second one the system call number (as a 'long'), and all further - * arguments being syscall arguments (also 'long'). - * We return a long which is the syscall's return value, which - * may be negative-errno on failure. Conversion to the - * -1-and-errno-set convention is done by the calling wrapper. - */ -safe_syscall_base: - .cfi_startproc - /* This saves a frame pointer and aligns the stack for the syscall. - * (It's unclear if the syscall ABI has the same stack alignment - * requirements as the userspace function call ABI, but better safe than - * sorry. Appendix A2 of http://www.x86-64.org/documentation/abi.pdf - * does not list any ABI differences regarding stack alignment.) - */ - push %rbp - .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 - * rsi == syscall number - * rdx, rcx, r8, r9, (stack), (stack) == syscall arguments - * and return the result in rax - * and the syscall instruction needs - * rax == syscall number - * rdi, rsi, rdx, r10, r8, r9 == syscall arguments - * and returns the result in rax - * Shuffle everything around appropriately. - * Note that syscall will trash rcx and r11. - */ - mov %rsi, %rax /* syscall number */ - mov %rdi, %rbp /* signal_pending pointer */ - /* and the syscall arguments */ - mov %rdx, %rdi - mov %rcx, %rsi - mov %r8, %rdx - mov %r9, %r10 - mov 16(%rsp), %r8 - mov 24(%rsp), %r9 - - /* This next sequence of code works in conjunction with the - * rewind_if_safe_syscall_function(). If a signal is taken - * and the interrupted PC is anywhere between 'safe_syscall_start' - * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. - * The code sequence must therefore be able to cope with this, and - * the syscall instruction must be the final one in the sequence. - */ -safe_syscall_start: - /* if signal_pending is non-zero, don't do the call */ - cmpl $0, (%rbp) - jnz 1f - syscall -safe_syscall_end: - /* code path for having successfully executed the syscall */ - 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 - .cfi_def_cfa_offset 8 - .cfi_restore rbp - ret - .cfi_endproc - - .size safe_syscall_base, .-safe_syscall_base diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index 375576c..a47a631 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -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; diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index c2fbc26..962f551 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -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; } diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index f6a1cc6..9aaae93 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -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; diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c index 433efa3..4372621 100644 --- a/linux-user/i386/signal.c +++ b/linux-user/i386/signal.c @@ -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 diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c index 790bd55..3181594 100644 --- a/linux-user/m68k/cpu_loop.c +++ b/linux-user/m68k/cpu_loop.c @@ -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; } } diff --git a/linux-user/m68k/signal.c b/linux-user/m68k/signal.c index ec33482..5f35354 100644 --- a/linux-user/m68k/signal.c +++ b/linux-user/m68k/signal.c @@ -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) diff --git a/linux-user/meson.build b/linux-user/meson.build index bf62c13..b2f4afd 100644 --- a/linux-user/meson.build +++ b/linux-user/meson.build @@ -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) diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index a94467d..ff1fb26 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -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 diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c index 8ebb6a1..5188d74 100644 --- a/linux-user/microblaze/signal.c +++ b/linux-user/microblaze/signal.c @@ -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) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index b735c99..32f9fc1 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -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; diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c index 8f79e40..58a9d7a 100644 --- a/linux-user/mips/signal.c +++ b/linux-user/mips/signal.c @@ -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) diff --git a/linux-user/openrisc/cpu_loop.c b/linux-user/openrisc/cpu_loop.c index 3cfdbbf..592901a 100644 --- a/linux-user/openrisc/cpu_loop.c +++ b/linux-user/openrisc/cpu_loop.c @@ -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; diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c index 483e669..30c82f2 100644 --- a/linux-user/ppc/cpu_loop.c +++ b/linux-user/ppc/cpu_loop.c @@ -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; diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c index 90a0369..176c9d8 100644 --- a/linux-user/ppc/signal.c +++ b/linux-user/ppc/signal.c @@ -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; diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c index b301dac..0cd8985 100644 --- a/linux-user/riscv/cpu_loop.c +++ b/linux-user/riscv/cpu_loop.c @@ -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) { diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index a0f9542..296e39f 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -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); diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c index d089c84..ad0c3cd 100644 --- a/linux-user/s390x/cpu_loop.c +++ b/linux-user/s390x/cpu_loop.c @@ -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; diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 676b948..f47713e 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -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) diff --git a/linux-user/safe-syscall.S b/linux-user/safe-syscall.S deleted file mode 100644 index 42ea7c4..0000000 --- a/linux-user/safe-syscall.S +++ /dev/null @@ -1,30 +0,0 @@ -/* - * safe-syscall.S : include the host-specific assembly fragment - * to handle signals occurring at the same time as system calls. - * - * 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. - */ - -#include "hostdep.h" -#include "target_errno_defs.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 - * assembly needs an executable stack and the whole QEMU binary will - * needlessly end up with one. This should be the last thing in this file. - */ -#if defined(__linux__) && defined(__ELF__) -.section .note.GNU-stack, "", %progbits -#endif diff --git a/linux-user/safe-syscall.h b/linux-user/safe-syscall.h deleted file mode 100644 index aaa9ffc..0000000 --- a/linux-user/safe-syscall.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * safe-syscall.h: prototypes for linux-user signal-race-safe syscalls - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef LINUX_USER_SAFE_SYSCALL_H -#define LINUX_USER_SAFE_SYSCALL_H - -/** - * safe_syscall: - * @int number: number of system call to make - * ...: arguments to the system call - * - * 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. - * - * Returns: the system call result, or -1 with an error code in errno - * (Errnos are host errnos; we rely on TARGET_ERESTARTSYS not clashing - * with any of the host errno values.) - */ - -/* - * A guide to using safe_syscall() to handle interactions between guest - * syscalls and guest signals: - * - * Guest syscalls come in two flavours: - * - * (1) Non-interruptible syscalls - * - * These are guest syscalls that never get interrupted by signals and - * so never return EINTR. They can be implemented straightforwardly in - * QEMU: just make sure that if the implementation code has to make any - * blocking calls that those calls are retried if they return EINTR. - * It's also OK to implement these with safe_syscall, though it will be - * a little less efficient if a signal is delivered at the 'wrong' moment. - * - * Some non-interruptible syscalls need to be handled using block_signals() - * to block signals for the duration of the syscall. This mainly applies - * to code which needs to modify the data structures used by the - * host_signal_handler() function and the functions it calls, including - * all syscalls which change the thread's signal mask. - * - * (2) Interruptible syscalls - * - * These are guest syscalls that can be interrupted by signals and - * for which we need to either return EINTR or arrange for the guest - * syscall to be restarted. This category includes both syscalls which - * always restart (and in the kernel return -ERESTARTNOINTR), ones - * which only restart if there is no handler (kernel returns -ERESTARTNOHAND - * or -ERESTART_RESTARTBLOCK), and the most common kind which restart - * if the handler was registered with SA_RESTART (kernel returns - * -ERESTARTSYS). System calls which are only interruptible in some - * situations (like 'open') also need to be handled this way. - * - * Here it is important that the host syscall is made - * via this safe_syscall() function, and *not* via the host libc. - * If the host libc is used then the implementation will appear to work - * most of the time, but there will be a race condition where a - * signal could arrive just before we make the host syscall inside libc, - * and then then guest syscall will not correctly be interrupted. - * Instead the implementation of the guest syscall can use the safe_syscall - * function but otherwise just return the result or errno in the usual - * way; the main loop code will take care of restarting the syscall - * if appropriate. - * - * (If the implementation needs to make multiple host syscalls this is - * OK; any which might really block must be via safe_syscall(); for those - * 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 - * EINTR though.) - * - * block_signals() cannot be used for interruptible syscalls. - * - * - * How and why the safe_syscall implementation works: - * - * The basic setup is that we make the host syscall via a known - * section of host native assembly. If a signal occurs, our signal - * 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 - * (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 - * the guest signal handler as usual. - * - * This winding-back will happen in two cases: - * (1) signal came in just before we took the host syscall (a race); - * in this case we'll take the guest signal and have another go - * at the syscall afterwards, and this is indistinguishable for the - * guest from the timing having been different such that the guest - * signal really did win the race - * (2) signal came in while the host syscall was blocking, and the - * host kernel decided the syscall should be restarted; - * in this case we want to restart the guest syscall also, and so - * rewinding is the right thing. (Note that "restart" semantics mean - * "first call the signal handler, then reattempt the syscall".) - * The other situation to consider is when a signal came in while the - * host syscall was blocking, and the host kernel decided that the syscall - * should not be restarted; in this case QEMU's host signal handler will - * be invoked with the PC pointing just after the syscall instruction, - * with registers indicating an EINTR return; the special code in the - * handler will not kick in, and we will return EINTR to the guest as - * we should. - * - * Notice that we can leave the host kernel to make the decision for - * us about whether to do a restart of the syscall or not; we do not - * 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, ...); -/* 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 - -#endif diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c index ac9b018..3290f64 100644 --- a/linux-user/sh4/cpu_loop.c +++ b/linux-user/sh4/cpu_loop.c @@ -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; diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c index faa869f..f6a18bc 100644 --- a/linux-user/sh4/signal.c +++ b/linux-user/sh4/signal.c @@ -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) diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 7457f80..42aa479 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -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 diff --git a/linux-user/signal.c b/linux-user/signal.c index 6d5e5b6..510db73 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -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]; diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index 0ba65e4..8765ab6 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -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)) { diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 23e1e76..b501750 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -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) diff --git a/linux-user/special-errno.h b/linux-user/special-errno.h new file mode 100644 index 0000000..4120455 --- /dev/null +++ b/linux-user/special-errno.h @@ -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 */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f1cfcc8..56a3e17 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -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 diff --git a/linux-user/thunk.c b/linux-user/thunk.c new file mode 100644 index 0000000..dac4bf1 --- /dev/null +++ b/linux-user/thunk.c @@ -0,0 +1,481 @@ +/* + * Generic thunking code to convert data between host and target CPU + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" + +#include "qemu.h" +#include "exec/user/thunk.h" + +//#define DEBUG + +static unsigned int max_struct_entries; +StructEntry *struct_entries; + +static const argtype *thunk_type_next_ptr(const argtype *type_ptr); + +static inline const argtype *thunk_type_next(const argtype *type_ptr) +{ + int type; + + type = *type_ptr++; + switch(type) { + case TYPE_CHAR: + case TYPE_SHORT: + case TYPE_INT: + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + case TYPE_OLDDEVT: + return type_ptr; + case TYPE_PTR: + return thunk_type_next_ptr(type_ptr); + case TYPE_ARRAY: + return thunk_type_next_ptr(type_ptr + 1); + case TYPE_STRUCT: + return type_ptr + 1; + default: + return NULL; + } +} + +static const argtype *thunk_type_next_ptr(const argtype *type_ptr) +{ + return thunk_type_next(type_ptr); +} + +void thunk_register_struct(int id, const char *name, const argtype *types) +{ + const argtype *type_ptr; + StructEntry *se; + int nb_fields, offset, max_align, align, size, i, j; + + assert(id < max_struct_entries); + + /* first we count the number of fields */ + type_ptr = types; + nb_fields = 0; + while (*type_ptr != TYPE_NULL) { + type_ptr = thunk_type_next(type_ptr); + nb_fields++; + } + assert(nb_fields > 0); + se = struct_entries + id; + se->field_types = types; + se->nb_fields = nb_fields; + se->name = name; +#ifdef DEBUG + printf("struct %s: id=%d nb_fields=%d\n", + se->name, id, se->nb_fields); +#endif + /* now we can alloc the data */ + + for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) { + offset = 0; + max_align = 1; + se->field_offsets[i] = g_new(int, nb_fields); + type_ptr = se->field_types; + for(j = 0;j < nb_fields; j++) { + size = thunk_type_size(type_ptr, i); + align = thunk_type_align(type_ptr, i); + offset = (offset + align - 1) & ~(align - 1); + se->field_offsets[i][j] = offset; + offset += size; + if (align > max_align) + max_align = align; + type_ptr = thunk_type_next(type_ptr); + } + offset = (offset + max_align - 1) & ~(max_align - 1); + se->size[i] = offset; + se->align[i] = max_align; +#ifdef DEBUG + printf("%s: size=%d align=%d\n", + i == THUNK_HOST ? "host" : "target", offset, max_align); +#endif + } +} + +void thunk_register_struct_direct(int id, const char *name, + const StructEntry *se1) +{ + StructEntry *se; + + assert(id < max_struct_entries); + se = struct_entries + id; + *se = *se1; + se->name = name; +} + + +/* now we can define the main conversion functions */ +const argtype *thunk_convert(void *dst, const void *src, + const argtype *type_ptr, int to_host) +{ + int type; + + type = *type_ptr++; + switch(type) { + case TYPE_CHAR: + *(uint8_t *)dst = *(uint8_t *)src; + break; + case TYPE_SHORT: + *(uint16_t *)dst = tswap16(*(uint16_t *)src); + break; + case TYPE_INT: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + *(uint64_t *)dst = tswap64(*(uint64_t *)src); + break; +#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + if (to_host) { + if (type == TYPE_LONG) { + /* sign extension */ + *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src); + } else { + *(uint64_t *)dst = tswap32(*(uint32_t *)src); + } + } else { + *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff); + } + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + *(uint64_t *)dst = tswap64(*(uint64_t *)src); + break; +#elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + if (to_host) { + *(uint32_t *)dst = tswap64(*(uint64_t *)src); + } else { + if (type == TYPE_LONG) { + /* sign extension */ + *(uint64_t *)dst = tswap64(*(int32_t *)src); + } else { + *(uint64_t *)dst = tswap64(*(uint32_t *)src); + } + } + break; +#else +#warning unsupported conversion +#endif + case TYPE_OLDDEVT: + { + uint64_t val = 0; + switch (thunk_type_size(type_ptr - 1, !to_host)) { + case 2: + val = *(uint16_t *)src; + break; + case 4: + val = *(uint32_t *)src; + break; + case 8: + val = *(uint64_t *)src; + break; + } + switch (thunk_type_size(type_ptr - 1, to_host)) { + case 2: + *(uint16_t *)dst = tswap16(val); + break; + case 4: + *(uint32_t *)dst = tswap32(val); + break; + case 8: + *(uint64_t *)dst = tswap64(val); + break; + } + break; + } + case TYPE_ARRAY: + { + int array_length, i, dst_size, src_size; + const uint8_t *s; + uint8_t *d; + + array_length = *type_ptr++; + dst_size = thunk_type_size(type_ptr, to_host); + src_size = thunk_type_size(type_ptr, 1 - to_host); + d = dst; + s = src; + for(i = 0;i < array_length; i++) { + thunk_convert(d, s, type_ptr, to_host); + d += dst_size; + s += src_size; + } + type_ptr = thunk_type_next(type_ptr); + } + break; + case TYPE_STRUCT: + { + int i; + const StructEntry *se; + const uint8_t *s; + uint8_t *d; + const argtype *field_types; + const int *dst_offsets, *src_offsets; + + assert(*type_ptr < max_struct_entries); + se = struct_entries + *type_ptr++; + if (se->convert[0] != NULL) { + /* specific conversion is needed */ + (*se->convert[to_host])(dst, src); + } else { + /* standard struct conversion */ + field_types = se->field_types; + dst_offsets = se->field_offsets[to_host]; + src_offsets = se->field_offsets[1 - to_host]; + d = dst; + s = src; + for(i = 0;i < se->nb_fields; i++) { + field_types = thunk_convert(d + dst_offsets[i], + s + src_offsets[i], + field_types, to_host); + } + } + } + break; + default: + fprintf(stderr, "Invalid type 0x%x\n", type); + break; + } + return type_ptr; +} + +const argtype *thunk_print(void *arg, const argtype *type_ptr) +{ + int type; + + type = *type_ptr++; + + switch (type) { + case TYPE_CHAR: + qemu_log("%c", *(uint8_t *)arg); + break; + case TYPE_SHORT: + qemu_log("%" PRId16, tswap16(*(uint16_t *)arg)); + break; + case TYPE_INT: + qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_LONGLONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONGLONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg)); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; + case TYPE_LONG: + qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#else + case TYPE_PTRVOID: + qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#endif + case TYPE_OLDDEVT: + { + uint64_t val = 0; + switch (thunk_type_size(type_ptr - 1, 1)) { + case 2: + val = *(uint16_t *)arg; + break; + case 4: + val = *(uint32_t *)arg; + break; + case 8: + val = *(uint64_t *)arg; + break; + } + switch (thunk_type_size(type_ptr - 1, 0)) { + case 2: + qemu_log("%" PRIu16, tswap16(val)); + break; + case 4: + qemu_log("%" PRIu32, tswap32(val)); + break; + case 8: + qemu_log("%" PRIu64, tswap64(val)); + break; + } + } + break; + case TYPE_ARRAY: + { + int i, array_length, arg_size; + uint8_t *a; + int is_string = 0; + + array_length = *type_ptr++; + arg_size = thunk_type_size(type_ptr, 0); + a = arg; + + if (*type_ptr == TYPE_CHAR) { + qemu_log("\""); + is_string = 1; + } else { + qemu_log("["); + } + + for (i = 0; i < array_length; i++) { + if (i > 0 && !is_string) { + qemu_log(","); + } + thunk_print(a, type_ptr); + a += arg_size; + } + + if (is_string) { + qemu_log("\""); + } else { + qemu_log("]"); + } + + type_ptr = thunk_type_next(type_ptr); + } + break; + case TYPE_STRUCT: + { + int i; + const StructEntry *se; + uint8_t *a; + const argtype *field_types; + const int *arg_offsets; + + se = struct_entries + *type_ptr++; + + if (se->print != NULL) { + se->print(arg); + } else { + a = arg; + + field_types = se->field_types; + arg_offsets = se->field_offsets[0]; + + qemu_log("{"); + for (i = 0; i < se->nb_fields; i++) { + if (i > 0) { + qemu_log(","); + } + field_types = thunk_print(a + arg_offsets[i], field_types); + } + qemu_log("}"); + } + } + break; + default: + g_assert_not_reached(); + } + return type_ptr; +} + +/* from em86 */ + +/* Utility function: Table-driven functions to translate bitmasks + * between host and target formats + */ +unsigned int target_to_host_bitmask(unsigned int target_mask, + const bitmask_transtbl * trans_tbl) +{ + const bitmask_transtbl *btp; + unsigned int host_mask = 0; + + for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) { + if ((target_mask & btp->target_mask) == btp->target_bits) { + host_mask |= btp->host_bits; + } + } + return host_mask; +} + +unsigned int host_to_target_bitmask(unsigned int host_mask, + const bitmask_transtbl * trans_tbl) +{ + const bitmask_transtbl *btp; + unsigned int target_mask = 0; + + for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) { + if ((host_mask & btp->host_mask) == btp->host_bits) { + target_mask |= btp->target_bits; + } + } + return target_mask; +} + +int thunk_type_size_array(const argtype *type_ptr, int is_host) +{ + return thunk_type_size(type_ptr, is_host); +} + +int thunk_type_align_array(const argtype *type_ptr, int is_host) +{ + return thunk_type_align(type_ptr, is_host); +} + +void thunk_init(unsigned int max_structs) +{ + max_struct_entries = max_structs; + struct_entries = g_new0(StructEntry, max_structs); +} diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h index 661612a..f71f372 100644 --- a/linux-user/user-internals.h +++ b/linux-user/user-internals.h @@ -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" diff --git a/linux-user/xtensa/cpu_loop.c b/linux-user/xtensa/cpu_loop.c index a83490a..6bc6d6d 100644 --- a/linux-user/xtensa/cpu_loop.c +++ b/linux-user/xtensa/cpu_loop.c @@ -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; diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 81572a5..06d91a3 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -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) |