diff options
author | Warner Losh <imp@bsdimp.com> | 2021-11-12 21:56:00 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-11-23 01:47:20 +0100 |
commit | 07637888687bfecf3c0cc8351c5c24f29a611691 (patch) | |
tree | 516c155aa936626c6d3dbe0494b1e950974f2ad7 /linux-user | |
parent | c6cda6a44a8adaeb30bd6dc185f021809625433d (diff) | |
download | qemu-07637888687bfecf3c0cc8351c5c24f29a611691.zip qemu-07637888687bfecf3c0cc8351c5c24f29a611691.tar.gz qemu-07637888687bfecf3c0cc8351c5c24f29a611691.tar.bz2 |
linux-user/signal.c: Create a common rewind_if_in_safe_syscall
All instances of rewind_if_in_safe_syscall are the same, differing only
in how the instruction point is fetched from the ucontext and the size
of the registers. Use host_signal_pc and new host_signal_set_pc
interfaces to fetch the pointer to the PC and adjust if needed. Delete
all the old copies of rewind_if_in_safe_syscall.
Acked-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20211113045603.60391-3-imp@bsdimp.com>
[rth: include safe-syscall.h, simplify ifdefs]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/host/aarch64/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/host/arm/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/host/i386/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/host/ppc64/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/host/riscv/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/host/s390x/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/host/x86_64/hostdep.h | 20 | ||||
-rw-r--r-- | linux-user/safe-syscall.h | 3 | ||||
-rw-r--r-- | linux-user/signal.c | 15 |
9 files changed, 15 insertions, 143 deletions
diff --git a/linux-user/host/aarch64/hostdep.h b/linux-user/host/aarch64/hostdep.h index a8d41a2..39299d7 100644 --- a/linux-user/host/aarch64/hostdep.h +++ b/linux-user/host/aarch64/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - __u64 *pcreg = &uc->uc_mcontext.pc; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/arm/hostdep.h b/linux-user/host/arm/hostdep.h index 9276fe6..86b1378 100644 --- a/linux-user/host/arm/hostdep.h +++ b/linux-user/host/arm/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.arm_pc; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/i386/hostdep.h b/linux-user/host/i386/hostdep.h index 073be74..ce71365 100644 --- a/linux-user/host/i386/hostdep.h +++ b/linux-user/host/i386/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - greg_t *pcreg = &uc->uc_mcontext.gregs[REG_EIP]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/ppc64/hostdep.h b/linux-user/host/ppc64/hostdep.h index 98979ad..0c290dd 100644 --- a/linux-user/host/ppc64/hostdep.h +++ b/linux-user/host/ppc64/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.gp_regs[PT_NIP]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/riscv/hostdep.h b/linux-user/host/riscv/hostdep.h index 2ba0745..7f67c22 100644 --- a/linux-user/host/riscv/hostdep.h +++ b/linux-user/host/riscv/hostdep.h @@ -11,24 +11,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.__gregs[REG_PC]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/s390x/hostdep.h b/linux-user/host/s390x/hostdep.h index 4f0171f..d801145 100644 --- a/linux-user/host/s390x/hostdep.h +++ b/linux-user/host/s390x/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.psw.addr; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/x86_64/hostdep.h b/linux-user/host/x86_64/hostdep.h index a4fefb5..9c62bd2 100644 --- a/linux-user/host/x86_64/hostdep.h +++ b/linux-user/host/x86_64/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* 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) -{ - ucontext_t *uc = puc; - greg_t *pcreg = &uc->uc_mcontext.gregs[REG_RIP]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/safe-syscall.h b/linux-user/safe-syscall.h index 6bc0390..aaa9ffc 100644 --- a/linux-user/safe-syscall.h +++ b/linux-user/safe-syscall.h @@ -127,6 +127,9 @@ #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(...) \ ({ \ diff --git a/linux-user/signal.c b/linux-user/signal.c index 81c45bf..6d5e5b6 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -31,6 +31,7 @@ #include "trace.h" #include "signal-common.h" #include "host-signal.h" +#include "safe-syscall.h" static struct target_sigaction sigact_table[TARGET_NSIG]; @@ -793,12 +794,20 @@ int queue_signal(CPUArchState *env, int sig, int si_type, return 1; /* indicates that the signal was queued */ } -#ifndef HAVE_SAFE_SYSCALL + +/* 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) { - /* Default version: never rewind */ -} +#ifdef HAVE_SAFE_SYSCALL + ucontext_t *uc = (ucontext_t *)puc; + uintptr_t pcreg = host_signal_pc(uc); + + if (pcreg > (uintptr_t)safe_syscall_start + && 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) { |