diff mbox series

[RFC,2/4] linux-user/signal.c: Create a common rewind_if_in_safe_syscall

Message ID 20211108023738.42125-3-imp@bsdimp.com
State New
Headers show
Series linux-user: simplify safe signal handling | expand

Commit Message

Warner Losh Nov. 8, 2021, 2:37 a.m. UTC
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.

Signed-off-by: Warner Losh <imp@bsdimp.com>
---
 linux-user/host/aarch64/hostdep.h | 20 --------------------
 linux-user/host/arm/hostdep.h     | 20 --------------------
 linux-user/host/i386/hostdep.h    | 20 --------------------
 linux-user/host/ppc64/hostdep.h   | 20 --------------------
 linux-user/host/riscv/hostdep.h   | 20 --------------------
 linux-user/host/s390x/hostdep.h   | 20 --------------------
 linux-user/host/x86_64/hostdep.h  | 20 --------------------
 linux-user/signal.c               | 18 +++++++++++++++++-
 8 files changed, 17 insertions(+), 141 deletions(-)

Comments

Richard Henderson Nov. 8, 2021, 3:07 p.m. UTC | #1
On 11/8/21 3:37 AM, Warner Losh wrote:
> 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.
> 
> Signed-off-by: Warner Losh<imp@bsdimp.com>
> ---
>   linux-user/host/aarch64/hostdep.h | 20 --------------------
>   linux-user/host/arm/hostdep.h     | 20 --------------------
>   linux-user/host/i386/hostdep.h    | 20 --------------------
>   linux-user/host/ppc64/hostdep.h   | 20 --------------------
>   linux-user/host/riscv/hostdep.h   | 20 --------------------
>   linux-user/host/s390x/hostdep.h   | 20 --------------------
>   linux-user/host/x86_64/hostdep.h  | 20 --------------------
>   linux-user/signal.c               | 18 +++++++++++++++++-
>   8 files changed, 17 insertions(+), 141 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

Although I think we can fairly safely drop HAVE_SAFE_SYSCALL.  It is required for proper 
operation.  As with host-signal.h, really.


r~
Warner Losh Nov. 8, 2021, 4:39 p.m. UTC | #2
On Mon, Nov 8, 2021 at 8:07 AM Richard Henderson <
richard.henderson@linaro.org> wrote:

> On 11/8/21 3:37 AM, Warner Losh wrote:
> > 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.
> >
> > Signed-off-by: Warner Losh<imp@bsdimp.com>
> > ---
> >   linux-user/host/aarch64/hostdep.h | 20 --------------------
> >   linux-user/host/arm/hostdep.h     | 20 --------------------
> >   linux-user/host/i386/hostdep.h    | 20 --------------------
> >   linux-user/host/ppc64/hostdep.h   | 20 --------------------
> >   linux-user/host/riscv/hostdep.h   | 20 --------------------
> >   linux-user/host/s390x/hostdep.h   | 20 --------------------
> >   linux-user/host/x86_64/hostdep.h  | 20 --------------------
> >   linux-user/signal.c               | 18 +++++++++++++++++-
> >   8 files changed, 17 insertions(+), 141 deletions(-)
>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>
> Although I think we can fairly safely drop HAVE_SAFE_SYSCALL.  It is
> required for proper
> operation.  As with host-signal.h, really.
>

Yes. The only possible use I can see for it is to allow people to bring up
new platforms more easily by deferring the signal-safe system call details
until later in that process.

Warner
Philippe Mathieu-Daudé Nov. 10, 2021, 3:44 p.m. UTC | #3
On 11/8/21 03:37, Warner Losh wrote:
> 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.
> 
> Signed-off-by: Warner Losh <imp@bsdimp.com>
> ---
>  linux-user/host/aarch64/hostdep.h | 20 --------------------
>  linux-user/host/arm/hostdep.h     | 20 --------------------
>  linux-user/host/i386/hostdep.h    | 20 --------------------
>  linux-user/host/ppc64/hostdep.h   | 20 --------------------
>  linux-user/host/riscv/hostdep.h   | 20 --------------------
>  linux-user/host/s390x/hostdep.h   | 20 --------------------
>  linux-user/host/x86_64/hostdep.h  | 20 --------------------
>  linux-user/signal.c               | 18 +++++++++++++++++-
>  8 files changed, 17 insertions(+), 141 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Warner Losh Nov. 10, 2021, 4:20 p.m. UTC | #4
On Mon, Nov 8, 2021 at 9:39 AM Warner Losh <imp@bsdimp.com> wrote:

>
>
> On Mon, Nov 8, 2021 at 8:07 AM Richard Henderson <
> richard.henderson@linaro.org> wrote:
>
>> On 11/8/21 3:37 AM, Warner Losh wrote:
>> > 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.
>> >
>> > Signed-off-by: Warner Losh<imp@bsdimp.com>
>> > ---
>> >   linux-user/host/aarch64/hostdep.h | 20 --------------------
>> >   linux-user/host/arm/hostdep.h     | 20 --------------------
>> >   linux-user/host/i386/hostdep.h    | 20 --------------------
>> >   linux-user/host/ppc64/hostdep.h   | 20 --------------------
>> >   linux-user/host/riscv/hostdep.h   | 20 --------------------
>> >   linux-user/host/s390x/hostdep.h   | 20 --------------------
>> >   linux-user/host/x86_64/hostdep.h  | 20 --------------------
>> >   linux-user/signal.c               | 18 +++++++++++++++++-
>> >   8 files changed, 17 insertions(+), 141 deletions(-)
>>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>
>> Although I think we can fairly safely drop HAVE_SAFE_SYSCALL.  It is
>> required for proper
>> operation.  As with host-signal.h, really.
>>
>
> Yes. The only possible use I can see for it is to allow people to bring up
> new platforms more easily by deferring the signal-safe system call details
> until later in that process.
>

If we do, we'd need to remove the linux-user on a mips host tests from the
CI pipeline. Those are the only ones left that don't use this that we test.

Warner
Richard Henderson Nov. 10, 2021, 4:31 p.m. UTC | #5
On 11/10/21 5:20 PM, Warner Losh wrote:
>         Although I think we can fairly safely drop HAVE_SAFE_SYSCALL.  It is required for
>         proper
>         operation.  As with host-signal.h, really.
> 
>     Yes. The only possible use I can see for it is to allow people to bring up new
>     platforms more easily by deferring the signal-safe system call details until later in
>     that process.
> 
> If we do, we'd need to remove the linux-user on a mips host tests from the CI pipeline. 
> Those are the only ones left that don't use this that we test.

Ack, thanks.  I'll take care of this next release.


r~
diff mbox series

Patch

diff --git a/linux-user/host/aarch64/hostdep.h b/linux-user/host/aarch64/hostdep.h
index a8d41a21ad..39299d798a 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 9276fe6ceb..86b137875a 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 073be74d87..ce7136501f 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 98979ad917..0c290dd904 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 2ba07456ae..7f67c22868 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 4f0171f36f..d801145854 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 a4fefb5114..9c62bd26bd 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/signal.c b/linux-user/signal.c
index 81c45bfce9..dafdf46b93 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -793,7 +793,23 @@  int queue_signal(CPUArchState *env, int sig, int si_type,
     return 1; /* indicates that the signal was queued */
 }
 
-#ifndef HAVE_SAFE_SYSCALL
+#ifdef HAVE_SAFE_SYSCALL
+/* 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 = (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);
+    }
+}
+#else
 static inline void rewind_if_in_safe_syscall(void *puc)
 {
     /* Default version: never rewind */