Skip to content

Commit

Permalink
linux-user/signal.c: Create a common rewind_if_in_safe_syscall
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bsdimp authored and rth7680 committed Nov 23, 2021
1 parent c6cda6a commit 0763788
Show file tree
Hide file tree
Showing 9 changed files with 15 additions and 143 deletions.
20 changes: 0 additions & 20 deletions linux-user/host/aarch64/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions linux-user/host/arm/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions linux-user/host/i386/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions linux-user/host/ppc64/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions linux-user/host/riscv/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions linux-user/host/s390x/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions linux-user/host/x86_64/hostdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions linux-user/safe-syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(...) \
({ \
Expand Down
15 changes: 12 additions & 3 deletions linux-user/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit 0763788

Please sign in to comment.