All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/27] linux-user: Move signal trampolines to new page
@ 2021-09-24 16:58 Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 01/27] linux-user: Add infrastructure for a signal trampoline page Richard Henderson
                   ` (26 more replies)
  0 siblings, 27 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

Supercedes: 20210706234932.356913-1-richard.henderson@linaro.org
("[PATCH v2 00/36] linux-user: Signal trampolines and vdsos")

Changes for v3:
  * Drop vdsos, reinstate setup_sigtramp for all targets.
  * Incorporate nios2 kuser page emulation, which contains
    the sigtramp for that target.

Changes for v2:
  * Add vdsos for aarch64, arm, i386, riscv.
  * Drop setup_sigtramp for any target with a vdso.
  * Drop arm v1 signal support.
  * Simplify ppc encode_trampoline.


r~


Richard Henderson (27):
  linux-user: Add infrastructure for a signal trampoline page
  linux-user/aarch64: Implement setup_sigtramp
  linux-user/arm: Drop v1 signal frames
  linux-user/arm: Drop "_v2" from symbols in signal.c
  linux-user/arm: Implement setup_sigtramp
  linux-user/alpha: Implement setup_sigtramp
  linux-user/cris: Implement setup_sigtramp
  linux-user/hexagon: Implement setup_sigtramp
  linux-user/hppa: Document non-use of setup_sigtramp
  linux-user/i386: Implement setup_sigtramp
  linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set
  linux-user/m68k: Implement setup_sigtramp
  linux-user/microblaze: Implement setup_sigtramp
  linux-user/mips: Tidy install_sigtramp
  linux-user/mips: Implement setup_sigtramp
  linux-user/nios2: Properly emulate EXCP_TRAP
  linux-user/nios2: Map a real kuser page
  linux-user/nios2: Fixes for signal frame setup
  linux-user/openrisc: Implement setup_sigtramp
  linux-user/ppc: Simplify encode_trampoline
  linux-user/ppc: Implement setup_sigtramp
  linux-user/riscv: Implement setup_sigtramp
  linux-user/s390x: Implement setup_sigtramp
  linux-user/sh4: Implement setup_sigtramp
  linux-user/sparc: Implement setup_sigtramp
  linux-user/xtensa: Implement setup_sigtramp
  linux-user: Remove default for TARGET_ARCH_HAS_SIGTRAMP_PAGE

 linux-user/aarch64/target_signal.h    |   2 +
 linux-user/alpha/target_signal.h      |   1 +
 linux-user/arm/target_signal.h        |   2 +
 linux-user/cris/target_signal.h       |   2 +
 linux-user/hexagon/target_signal.h    |   2 +
 linux-user/hppa/target_signal.h       |  14 +
 linux-user/i386/target_signal.h       |   2 +
 linux-user/m68k/target_signal.h       |   2 +
 linux-user/microblaze/target_signal.h |   2 +
 linux-user/mips/target_signal.h       |   1 +
 linux-user/mips64/target_signal.h     |   2 +
 linux-user/nios2/target_signal.h      |   3 +
 linux-user/openrisc/target_signal.h   |   2 +
 linux-user/ppc/target_signal.h        |   2 +
 linux-user/riscv/target_signal.h      |   2 +
 linux-user/s390x/target_signal.h      |   2 +
 linux-user/sh4/target_signal.h        |   2 +
 linux-user/signal-common.h            |   6 +
 linux-user/sparc/target_signal.h      |   4 +
 linux-user/x86_64/target_signal.h     |   3 +
 linux-user/xtensa/target_signal.h     |   2 +
 target/nios2/cpu.h                    |   5 +-
 linux-user/aarch64/signal.c           |  34 +-
 linux-user/alpha/signal.c             |  34 +-
 linux-user/arm/signal.c               | 590 ++++++++++----------------
 linux-user/cris/signal.c              |  29 +-
 linux-user/elfload.c                  |  49 +++
 linux-user/hexagon/signal.c           |  19 +-
 linux-user/i386/signal.c              |  65 ++-
 linux-user/m68k/signal.c              |  47 +-
 linux-user/microblaze/signal.c        |  24 +-
 linux-user/mips/signal.c              |  39 +-
 linux-user/nios2/cpu_loop.c           |  84 ++--
 linux-user/nios2/signal.c             |  51 +--
 linux-user/openrisc/signal.c          |  22 +-
 linux-user/ppc/signal.c               |  40 +-
 linux-user/riscv/signal.c             |  22 +-
 linux-user/s390x/signal.c             |  24 +-
 linux-user/sh4/signal.c               |  40 +-
 linux-user/signal.c                   |   3 +
 linux-user/sparc/signal.c             |  40 +-
 linux-user/xtensa/signal.c            |  56 ++-
 target/nios2/translate.c              |  26 +-
 43 files changed, 744 insertions(+), 659 deletions(-)

-- 
2.25.1



^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v3 01/27] linux-user: Add infrastructure for a signal trampoline page
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 02/27] linux-user/aarch64: Implement setup_sigtramp Richard Henderson
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Philippe Mathieu-Daudé, laurent, Max Filippov

Allocate a page to hold the signal trampoline(s).
Invoke a guest-specific hook to fill in the contents
of the page before marking it read-execute again.

Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/signal-common.h |  6 ++++++
 linux-user/elfload.c       | 18 ++++++++++++++++++
 linux-user/signal.c        |  3 +++
 3 files changed, 27 insertions(+)

diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h
index 79511becb4..7457f8025c 100644
--- a/linux-user/signal-common.h
+++ b/linux-user/signal-common.h
@@ -20,6 +20,12 @@
 #ifndef SIGNAL_COMMON_H
 #define SIGNAL_COMMON_H
 
+/* Fallback addresses into sigtramp page. */
+extern abi_ulong default_sigreturn;
+extern abi_ulong default_rt_sigreturn;
+
+void setup_sigtramp(abi_ulong tramp_page);
+
 int on_sig_stack(unsigned long sp);
 int sas_ss_flags(unsigned long sp);
 abi_ulong target_sigsp(abi_ulong sp, struct target_sigaction *ka);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5f9e2141ad..459a26ef1d 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -7,6 +7,7 @@
 
 #include "qemu.h"
 #include "user-internals.h"
+#include "signal-common.h"
 #include "loader.h"
 #include "user-mmap.h"
 #include "disas/disas.h"
@@ -17,6 +18,7 @@
 #include "qemu/units.h"
 #include "qemu/selfmap.h"
 #include "qapi/error.h"
+#include "target_signal.h"
 
 #ifdef _ARCH_PPC64
 #undef ARCH_DLINFO
@@ -28,6 +30,10 @@
 #undef ELF_ARCH
 #endif
 
+#ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+#endif
+
 #define ELF_OSABI   ELFOSABI_SYSV
 
 /* from personality.h */
@@ -3249,6 +3255,18 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
 #endif
     }
 
+    /*
+     * TODO: load a vdso, which would also contain the signal trampolines.
+     * Otherwise, allocate a private page to hold them.
+     */
+    if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
+        abi_ulong tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
+                                           PROT_READ | PROT_WRITE,
+                                           MAP_PRIVATE | MAP_ANON, -1, 0);
+        setup_sigtramp(tramp_page);
+        target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
+    }
+
     bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
                                 info, (elf_interpreter ? &interp_info : NULL));
     info->start_stack = bprm->p;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 2038216455..14d8fdfde1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -35,6 +35,9 @@ static struct target_sigaction sigact_table[TARGET_NSIG];
 static void host_signal_handler(int host_signum, siginfo_t *info,
                                 void *puc);
 
+/* Fallback addresses into sigtramp page. */
+abi_ulong default_sigreturn;
+abi_ulong default_rt_sigreturn;
 
 /*
  * System includes define _NSIG as SIGRTMAX + 1,
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 02/27] linux-user/aarch64: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 01/27] linux-user: Add infrastructure for a signal trampoline page Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 03/27] linux-user/arm: Drop v1 signal frames Richard Henderson
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

Create and record the rt signal trampoline.
Use it when the guest does not use SA_RESTORER.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/aarch64/target_signal.h |  2 ++
 linux-user/aarch64/signal.c        | 34 ++++++++++++++++++------------
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h
index 18013e1b23..7580d99403 100644
--- a/linux-user/aarch64/target_signal.h
+++ b/linux-user/aarch64/target_signal.h
@@ -25,4 +25,6 @@ typedef struct target_sigaltstack {
 #define TARGET_SEGV_MTESERR  9  /* Synchronous ARM MTE exception */
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* AARCH64_TARGET_SIGNAL_H */
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 49025648cb..29c52db3f1 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -109,7 +109,6 @@ struct target_rt_sigframe {
 struct target_rt_frame_record {
     uint64_t fp;
     uint64_t lr;
-    uint32_t tramp[2];
 };
 
 static void target_setup_general_frame(struct target_rt_sigframe *sf,
@@ -461,9 +460,9 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
     layout.total_size = MAX(layout.total_size,
                             sizeof(struct target_rt_sigframe));
 
-    /* Reserve space for the return code.  On a real system this would
-     * be within the VDSO.  So, despite the name this is not a "real"
-     * record within the frame.
+    /*
+     * Reserve space for the standard frame unwind pair: fp, lr.
+     * Despite the name this is not a "real" record within the frame.
      */
     fr_ofs = layout.total_size;
     layout.total_size += sizeof(struct target_rt_frame_record);
@@ -496,15 +495,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         return_addr = ka->sa_restorer;
     } else {
-        /*
-         * mov x8,#__NR_rt_sigreturn; svc #0
-         * Since these are instructions they need to be put as little-endian
-         * regardless of target default or current CPU endianness.
-         */
-        __put_user_e(0xd2801168, &fr->tramp[0], le);
-        __put_user_e(0xd4000001, &fr->tramp[1], le);
-        return_addr = frame_addr + fr_ofs
-            + offsetof(struct target_rt_frame_record, tramp);
+        return_addr = default_rt_sigreturn;
     }
     env->xregs[0] = usig;
     env->xregs[29] = frame_addr + fr_ofs;
@@ -577,3 +568,20 @@ long do_sigreturn(CPUARMState *env)
 {
     return do_rt_sigreturn(env);
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
+    assert(tramp != NULL);
+
+    /*
+     * mov x8,#__NR_rt_sigreturn; svc #0
+     * Since these are instructions they need to be put as little-endian
+     * regardless of target default or current CPU endianness.
+     */
+    __put_user_e(0xd2801168, &tramp[0], le);
+    __put_user_e(0xd4000001, &tramp[1], le);
+
+    default_rt_sigreturn = sigtramp_page;
+    unlock_user(tramp, sigtramp_page, 8);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 03/27] linux-user/arm: Drop v1 signal frames
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 01/27] linux-user: Add infrastructure for a signal trampoline page Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 02/27] linux-user/aarch64: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 04/27] linux-user/arm: Drop "_v2" from symbols in signal.c Richard Henderson
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

Version 2 signal frames are used from 2.6.12 and since cbc14e6f286,
we have set UNAME_MINIMUM_RELEASE to 2.6.32.

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/arm/signal.c | 220 +---------------------------------------
 1 file changed, 4 insertions(+), 216 deletions(-)

diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index ed144f9455..d0940bab47 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -46,14 +46,6 @@ struct target_sigcontext {
     abi_ulong fault_address;
 };
 
-struct target_ucontext_v1 {
-    abi_ulong tuc_flags;
-    abi_ulong tuc_link;
-    target_stack_t tuc_stack;
-    struct target_sigcontext tuc_mcontext;
-    target_sigset_t  tuc_sigmask;       /* mask last for extensibility */
-};
-
 struct target_ucontext_v2 {
     abi_ulong tuc_flags;
     abi_ulong tuc_link;
@@ -98,28 +90,12 @@ struct target_iwmmxt_sigframe {
 #define TARGET_VFP_MAGIC 0x56465001
 #define TARGET_IWMMXT_MAGIC 0x12ef842a
 
-struct sigframe_v1
-{
-    struct target_sigcontext sc;
-    abi_ulong extramask[TARGET_NSIG_WORDS-1];
-    abi_ulong retcode[4];
-};
-
 struct sigframe_v2
 {
     struct target_ucontext_v2 uc;
     abi_ulong retcode[4];
 };
 
-struct rt_sigframe_v1
-{
-    abi_ulong pinfo;
-    abi_ulong puc;
-    struct target_siginfo info;
-    struct target_ucontext_v1 uc;
-    abi_ulong retcode[4];
-};
-
 struct rt_sigframe_v2
 {
     struct target_siginfo info;
@@ -363,37 +339,6 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
     }
 }
 
-/* compare linux/arch/arm/kernel/signal.c:setup_frame() */
-static void setup_frame_v1(int usig, struct target_sigaction *ka,
-                           target_sigset_t *set, CPUARMState *regs)
-{
-    struct sigframe_v1 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-    int i;
-
-    trace_user_setup_frame(regs, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    setup_sigcontext(&frame->sc, regs, set->sig[0]);
-
-    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
-        __put_user(set->sig[i], &frame->extramask[i - 1]);
-    }
-
-    if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct sigframe_v1, retcode))) {
-        goto sigsegv;
-    }
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    unlock_user_struct(frame, frame_addr, 1);
-    force_sigsegv(usig);
-}
-
 static void setup_frame_v2(int usig, struct target_sigaction *ka,
                            target_sigset_t *set, CPUARMState *regs)
 {
@@ -422,60 +367,7 @@ sigsegv:
 void setup_frame(int usig, struct target_sigaction *ka,
                  target_sigset_t *set, CPUARMState *regs)
 {
-    if (get_osversion() >= 0x020612) {
-        setup_frame_v2(usig, ka, set, regs);
-    } else {
-        setup_frame_v1(usig, ka, set, regs);
-    }
-}
-
-/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */
-static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
-                              target_siginfo_t *info,
-                              target_sigset_t *set, CPUARMState *env)
-{
-    struct rt_sigframe_v1 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
-    struct target_sigaltstack stack;
-    int i;
-    abi_ulong info_addr, uc_addr;
-
-    trace_user_setup_rt_frame(env, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
-    __put_user(info_addr, &frame->pinfo);
-    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
-    __put_user(uc_addr, &frame->puc);
-    tswap_siginfo(&frame->info, info);
-
-    /* Clear all the bits of the ucontext we don't use.  */
-    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
-
-    memset(&stack, 0, sizeof(stack));
-    target_save_altstack(&stack, env);
-    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
-
-    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
-    }
-
-    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct rt_sigframe_v1, retcode))) {
-        goto sigsegv;
-    }
-
-    env->regs[1] = info_addr;
-    env->regs[2] = uc_addr;
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    unlock_user_struct(frame, frame_addr, 1);
-    force_sigsegv(usig);
+    setup_frame_v2(usig, ka, set, regs);
 }
 
 static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
@@ -516,11 +408,7 @@ void setup_rt_frame(int usig, struct target_sigaction *ka,
                     target_siginfo_t *info,
                     target_sigset_t *set, CPUARMState *env)
 {
-    if (get_osversion() >= 0x020612) {
-        setup_rt_frame_v2(usig, ka, info, set, env);
-    } else {
-        setup_rt_frame_v1(usig, ka, info, set, env);
-    }
+    setup_rt_frame_v2(usig, ka, info, set, env);
 }
 
 static int
@@ -553,54 +441,6 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
     return err;
 }
 
-static long do_sigreturn_v1(CPUARMState *env)
-{
-    abi_ulong frame_addr;
-    struct sigframe_v1 *frame = NULL;
-    target_sigset_t set;
-    sigset_t host_set;
-    int i;
-
-    /*
-     * Since we stacked the signal on a 64-bit boundary,
-     * then 'sp' should be word aligned here.  If it's
-     * not, then the user is trying to mess with us.
-     */
-    frame_addr = env->regs[13];
-    trace_user_do_sigreturn(env, frame_addr);
-    if (frame_addr & 7) {
-        goto badframe;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
-        goto badframe;
-    }
-
-    __get_user(set.sig[0], &frame->sc.oldmask);
-    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
-        __get_user(set.sig[i], &frame->extramask[i - 1]);
-    }
-
-    target_to_host_sigset_internal(&host_set, &set);
-    set_sigmask(&host_set);
-
-    if (restore_sigcontext(env, &frame->sc)) {
-        goto badframe;
-    }
-
-#if 0
-    /* Send SIGTRAP if we're single-stepping */
-    if (ptrace_cancel_bpt(current))
-        send_sig(SIGTRAP, current, 1);
-#endif
-    unlock_user_struct(frame, frame_addr, 0);
-    return -TARGET_QEMU_ESIGRETURN;
-
-badframe:
-    force_sig(TARGET_SIGSEGV);
-    return -TARGET_QEMU_ESIGRETURN;
-}
-
 static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
 {
     int i;
@@ -733,55 +573,7 @@ badframe:
 
 long do_sigreturn(CPUARMState *env)
 {
-    if (get_osversion() >= 0x020612) {
-        return do_sigreturn_v2(env);
-    } else {
-        return do_sigreturn_v1(env);
-    }
-}
-
-static long do_rt_sigreturn_v1(CPUARMState *env)
-{
-    abi_ulong frame_addr;
-    struct rt_sigframe_v1 *frame = NULL;
-    sigset_t host_set;
-
-    /*
-     * Since we stacked the signal on a 64-bit boundary,
-     * then 'sp' should be word aligned here.  If it's
-     * not, then the user is trying to mess with us.
-     */
-    frame_addr = env->regs[13];
-    trace_user_do_rt_sigreturn(env, frame_addr);
-    if (frame_addr & 7) {
-        goto badframe;
-    }
-
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
-        goto badframe;
-    }
-
-    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
-    set_sigmask(&host_set);
-
-    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
-        goto badframe;
-    }
-
-    target_restore_altstack(&frame->uc.tuc_stack, env);
-
-#if 0
-    /* Send SIGTRAP if we're single-stepping */
-    if (ptrace_cancel_bpt(current))
-        send_sig(SIGTRAP, current, 1);
-#endif
-    unlock_user_struct(frame, frame_addr, 0);
-    return -TARGET_QEMU_ESIGRETURN;
-
-badframe:
-    unlock_user_struct(frame, frame_addr, 0);
-    force_sig(TARGET_SIGSEGV);
-    return -TARGET_QEMU_ESIGRETURN;
+    return do_sigreturn_v2(env);
 }
 
 static long do_rt_sigreturn_v2(CPUARMState *env)
@@ -822,9 +614,5 @@ badframe:
 
 long do_rt_sigreturn(CPUARMState *env)
 {
-    if (get_osversion() >= 0x020612) {
-        return do_rt_sigreturn_v2(env);
-    } else {
-        return do_rt_sigreturn_v1(env);
-    }
+    return do_rt_sigreturn_v2(env);
 }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 04/27] linux-user/arm: Drop "_v2" from symbols in signal.c
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (2 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 03/27] linux-user/arm: Drop v1 signal frames Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 05/27] linux-user/arm: Implement setup_sigtramp Richard Henderson
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

Since we no longer support "v1", there's no need to distinguish "v2".

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/arm/signal.c | 155 +++++++++++++++++-----------------------
 1 file changed, 65 insertions(+), 90 deletions(-)

diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index d0940bab47..ed7d1d80bb 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -46,7 +46,7 @@ struct target_sigcontext {
     abi_ulong fault_address;
 };
 
-struct target_ucontext_v2 {
+struct target_ucontext {
     abi_ulong tuc_flags;
     abi_ulong tuc_link;
     target_stack_t tuc_stack;
@@ -90,16 +90,16 @@ struct target_iwmmxt_sigframe {
 #define TARGET_VFP_MAGIC 0x56465001
 #define TARGET_IWMMXT_MAGIC 0x12ef842a
 
-struct sigframe_v2
+struct sigframe
 {
-    struct target_ucontext_v2 uc;
+    struct target_ucontext uc;
     abi_ulong retcode[4];
 };
 
-struct rt_sigframe_v2
+struct rt_sigframe
 {
     struct target_siginfo info;
-    struct target_ucontext_v2 uc;
+    struct target_ucontext uc;
     abi_ulong retcode[4];
 };
 
@@ -270,7 +270,7 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
     return 0;
 }
 
-static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
+static abi_ulong *setup_sigframe_vfp(abi_ulong *regspace, CPUARMState *env)
 {
     int i;
     struct target_vfp_sigframe *vfpframe;
@@ -287,8 +287,7 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
     return (abi_ulong*)(vfpframe+1);
 }
 
-static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
-                                           CPUARMState *env)
+static abi_ulong *setup_sigframe_iwmmxt(abi_ulong *regspace, CPUARMState *env)
 {
     int i;
     struct target_iwmmxt_sigframe *iwmmxtframe;
@@ -307,15 +306,15 @@ static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace,
     return (abi_ulong*)(iwmmxtframe+1);
 }
 
-static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
-                              target_sigset_t *set, CPUARMState *env)
+static void setup_sigframe(struct target_ucontext *uc,
+                           target_sigset_t *set, CPUARMState *env)
 {
     struct target_sigaltstack stack;
     int i;
     abi_ulong *regspace;
 
     /* Clear all the bits of the ucontext we don't use.  */
-    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));
+    memset(uc, 0, offsetof(struct target_ucontext, tuc_mcontext));
 
     memset(&stack, 0, sizeof(stack));
     target_save_altstack(&stack, env);
@@ -325,10 +324,10 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
     /* Save coprocessor signal frame.  */
     regspace = uc->tuc_regspace;
     if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
-        regspace = setup_sigframe_v2_vfp(regspace, env);
+        regspace = setup_sigframe_vfp(regspace, env);
     }
     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-        regspace = setup_sigframe_v2_iwmmxt(regspace, env);
+        regspace = setup_sigframe_iwmmxt(regspace, env);
     }
 
     /* Write terminating magic word */
@@ -339,10 +338,10 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
     }
 }
 
-static void setup_frame_v2(int usig, struct target_sigaction *ka,
-                           target_sigset_t *set, CPUARMState *regs)
+void setup_frame(int usig, struct target_sigaction *ka,
+                 target_sigset_t *set, CPUARMState *regs)
 {
-    struct sigframe_v2 *frame;
+    struct sigframe *frame;
     abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
 
     trace_user_setup_frame(regs, frame_addr);
@@ -350,10 +349,10 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka,
         goto sigsegv;
     }
 
-    setup_sigframe_v2(&frame->uc, set, regs);
+    setup_sigframe(&frame->uc, set, regs);
 
     if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct sigframe_v2, retcode))) {
+                     frame_addr + offsetof(struct sigframe, retcode))) {
         goto sigsegv;
     }
 
@@ -364,51 +363,38 @@ sigsegv:
     force_sigsegv(usig);
 }
 
-void setup_frame(int usig, struct target_sigaction *ka,
-                 target_sigset_t *set, CPUARMState *regs)
-{
-    setup_frame_v2(usig, ka, set, regs);
-}
-
-static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
-                              target_siginfo_t *info,
-                              target_sigset_t *set, CPUARMState *env)
-{
-    struct rt_sigframe_v2 *frame;
-    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
-    abi_ulong info_addr, uc_addr;
-
-    trace_user_setup_rt_frame(env, frame_addr);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-        goto sigsegv;
-    }
-
-    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
-    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
-    tswap_siginfo(&frame->info, info);
-
-    setup_sigframe_v2(&frame->uc, set, env);
-
-    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct rt_sigframe_v2, retcode))) {
-        goto sigsegv;
-    }
-
-    env->regs[1] = info_addr;
-    env->regs[2] = uc_addr;
-
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-sigsegv:
-    unlock_user_struct(frame, frame_addr, 1);
-    force_sigsegv(usig);
-}
-
 void setup_rt_frame(int usig, struct target_sigaction *ka,
                     target_siginfo_t *info,
                     target_sigset_t *set, CPUARMState *env)
 {
-    setup_rt_frame_v2(usig, ka, info, set, env);
+    struct rt_sigframe *frame;
+    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    abi_ulong info_addr, uc_addr;
+
+    trace_user_setup_rt_frame(env, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto sigsegv;
+    }
+
+    info_addr = frame_addr + offsetof(struct rt_sigframe, info);
+    uc_addr = frame_addr + offsetof(struct rt_sigframe, uc);
+    tswap_siginfo(&frame->info, info);
+
+    setup_sigframe(&frame->uc, set, env);
+
+    if (setup_return(env, ka, frame->retcode, frame_addr, usig,
+                     frame_addr + offsetof(struct rt_sigframe, retcode))) {
+        goto sigsegv;
+    }
+
+    env->regs[1] = info_addr;
+    env->regs[2] = uc_addr;
+
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    force_sigsegv(usig);
 }
 
 static int
@@ -441,7 +427,7 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
     return err;
 }
 
-static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
+static abi_ulong *restore_sigframe_vfp(CPUARMState *env, abi_ulong *regspace)
 {
     int i;
     abi_ulong magic, sz;
@@ -471,8 +457,8 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
     return (abi_ulong*)(vfpframe + 1);
 }
 
-static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
-                                             abi_ulong *regspace)
+static abi_ulong *restore_sigframe_iwmmxt(CPUARMState *env,
+                                          abi_ulong *regspace)
 {
     int i;
     abi_ulong magic, sz;
@@ -496,9 +482,9 @@ static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env,
     return (abi_ulong*)(iwmmxtframe + 1);
 }
 
-static int do_sigframe_return_v2(CPUARMState *env,
-                                 target_ulong context_addr,
-                                 struct target_ucontext_v2 *uc)
+static int do_sigframe_return(CPUARMState *env,
+                              target_ulong context_addr,
+                              struct target_ucontext *uc)
 {
     sigset_t host_set;
     abi_ulong *regspace;
@@ -506,19 +492,20 @@ static int do_sigframe_return_v2(CPUARMState *env,
     target_to_host_sigset(&host_set, &uc->tuc_sigmask);
     set_sigmask(&host_set);
 
-    if (restore_sigcontext(env, &uc->tuc_mcontext))
+    if (restore_sigcontext(env, &uc->tuc_mcontext)) {
         return 1;
+    }
 
     /* Restore coprocessor signal frame */
     regspace = uc->tuc_regspace;
     if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
-        regspace = restore_sigframe_v2_vfp(env, regspace);
+        regspace = restore_sigframe_vfp(env, regspace);
         if (!regspace) {
             return 1;
         }
     }
     if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
-        regspace = restore_sigframe_v2_iwmmxt(env, regspace);
+        regspace = restore_sigframe_iwmmxt(env, regspace);
         if (!regspace) {
             return 1;
         }
@@ -535,10 +522,10 @@ static int do_sigframe_return_v2(CPUARMState *env,
     return 0;
 }
 
-static long do_sigreturn_v2(CPUARMState *env)
+long do_sigreturn(CPUARMState *env)
 {
     abi_ulong frame_addr;
-    struct sigframe_v2 *frame = NULL;
+    struct sigframe *frame = NULL;
 
     /*
      * Since we stacked the signal on a 64-bit boundary,
@@ -555,10 +542,9 @@ static long do_sigreturn_v2(CPUARMState *env)
         goto badframe;
     }
 
-    if (do_sigframe_return_v2(env,
-                              frame_addr
-                              + offsetof(struct sigframe_v2, uc),
-                              &frame->uc)) {
+    if (do_sigframe_return(env,
+                           frame_addr + offsetof(struct sigframe, uc),
+                           &frame->uc)) {
         goto badframe;
     }
 
@@ -571,15 +557,10 @@ badframe:
     return -TARGET_QEMU_ESIGRETURN;
 }
 
-long do_sigreturn(CPUARMState *env)
-{
-    return do_sigreturn_v2(env);
-}
-
-static long do_rt_sigreturn_v2(CPUARMState *env)
+long do_rt_sigreturn(CPUARMState *env)
 {
     abi_ulong frame_addr;
-    struct rt_sigframe_v2 *frame = NULL;
+    struct rt_sigframe *frame = NULL;
 
     /*
      * Since we stacked the signal on a 64-bit boundary,
@@ -596,10 +577,9 @@ static long do_rt_sigreturn_v2(CPUARMState *env)
         goto badframe;
     }
 
-    if (do_sigframe_return_v2(env,
-                              frame_addr
-                              + offsetof(struct rt_sigframe_v2, uc),
-                              &frame->uc)) {
+    if (do_sigframe_return(env,
+                           frame_addr + offsetof(struct rt_sigframe, uc),
+                           &frame->uc)) {
         goto badframe;
     }
 
@@ -611,8 +591,3 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
-
-long do_rt_sigreturn(CPUARMState *env)
-{
-    return do_rt_sigreturn_v2(env);
-}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 05/27] linux-user/arm: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (3 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 04/27] linux-user/arm: Drop "_v2" from symbols in signal.c Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 11:06   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 06/27] linux-user/alpha: " Richard Henderson
                   ` (21 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

Update the trampoline code to match the kernel: this uses
sp-relative accesses rather than pc-relative.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/arm/target_signal.h |   2 +
 linux-user/arm/signal.c        | 177 ++++++++++++++++++++++++---------
 2 files changed, 130 insertions(+), 49 deletions(-)

diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h
index 0998dd6dfa..1e7fb0cecb 100644
--- a/linux-user/arm/target_signal.h
+++ b/linux-user/arm/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* ARM_TARGET_SIGNAL_H */
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index ed7d1d80bb..ccfae43028 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -103,39 +103,52 @@ struct rt_sigframe
     abi_ulong retcode[4];
 };
 
-/*
- * For ARM syscalls, we encode the syscall number into the instruction.
- */
-#define SWI_SYS_SIGRETURN       (0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))
-#define SWI_SYS_RT_SIGRETURN    (0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))
+static abi_ptr sigreturn_fdpic_tramp;
 
 /*
- * For Thumb syscalls, we pass the syscall number via r7.  We therefore
- * need two 16-bit instructions.
+ * EABI syscalls pass the number via r7.
+ * Note that the kernel still adds the OABI syscall number to the trap,
+ * presumably for backward ABI compatibility with unwinders.
  */
-#define SWI_THUMB_SIGRETURN     (0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))
-#define SWI_THUMB_RT_SIGRETURN  (0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))
+#define ARM_MOV_R7_IMM(X)       (0xe3a07000 | (X))
+#define ARM_SWI_SYS(X)          (0xef000000 | (X) | ARM_SYSCALL_BASE)
 
-static const abi_ulong retcodes[4] = {
-        SWI_SYS_SIGRETURN,      SWI_THUMB_SIGRETURN,
-        SWI_SYS_RT_SIGRETURN,   SWI_THUMB_RT_SIGRETURN
-};
+#define THUMB_MOVS_R7_IMM(X)    (0x2700 | (X))
+#define THUMB_SWI_SYS           0xdf00
+
+static void write_arm_sigreturn(uint32_t *rc, int syscall)
+{
+    __put_user(ARM_MOV_R7_IMM(syscall), rc);
+    __put_user(ARM_SWI_SYS(syscall), rc + 1);
+}
+
+static void write_thumb_sigreturn(uint32_t *rc, int syscall)
+{
+    __put_user(THUMB_SWI_SYS << 16 | THUMB_MOVS_R7_IMM(syscall), rc);
+}
 
 /*
- * Stub needed to make sure the FD register (r9) contains the right
- * value.
+ * Stub needed to make sure the FD register (r9) contains the right value.
+ * Use the same instruction sequence as the kernel.
  */
-static const unsigned long sigreturn_fdpic_codes[3] = {
-    0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */
-    0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */
-    0xe59cf000  /* ldr pc, [r12] to jump into restorer */
-};
+static void write_arm_fdpic_sigreturn(uint32_t *rc, int ofs)
+{
+    assert(ofs <= 0xfff);
+    __put_user(0xe59d3000 | ofs, rc + 0);   /* ldr r3, [sp, #ofs] */
+    __put_user(0xe8930908, rc + 1);         /* ldm r3, { r3, r9 } */
+    __put_user(0xe12fff13, rc + 2);         /* bx  r3 */
+}
 
-static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
-    0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */
-    0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */
-    0xf000f8dc  /* ldr pc, [r12] to jump into restorer */
-};
+static void write_thumb_fdpic_sigreturn(void *vrc, int ofs)
+{
+    uint16_t *rc = vrc;
+
+    assert((ofs & ~0x3fc) == 0);
+    __put_user(0x9b00 | (ofs >> 2), rc + 0);      /* ldr r3, [sp, #ofs] */
+    __put_user(0xcb0c, rc + 1);                   /* ldm r3, { r2, r3 } */
+    __put_user(0x4699, rc + 2);                   /* mov r9, r3 */
+    __put_user(0x4710, rc + 3);                   /* bx  r2 */
+}
 
 static inline int valid_user_regs(CPUARMState *regs)
 {
@@ -184,13 +197,12 @@ get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 
 static int
 setup_return(CPUARMState *env, struct target_sigaction *ka,
-             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
+             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_ofs)
 {
     abi_ulong handler = 0;
     abi_ulong handler_fdpic_GOT = 0;
     abi_ulong retcode;
-
-    int thumb;
+    int thumb, retcode_idx;
     int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
 
     if (is_fdpic) {
@@ -208,6 +220,7 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
     }
 
     thumb = handler & 1;
+    retcode_idx = thumb + (ka->sa_flags & TARGET_SA_SIGINFO ? 2 : 0);
 
     uint32_t cpsr = cpsr_read(env);
 
@@ -225,37 +238,39 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
 
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         if (is_fdpic) {
-            /* For FDPIC we ensure that the restorer is called with a
-             * correct r9 value.  For that we need to write code on
-             * the stack that sets r9 and jumps back to restorer
-             * value.
+            /*
+             * For FDPIC we ensure that the restorer is called with a
+             * correct r9 value.  For that we need a special trampoline
+             * the reads the function descriptor from the frame,
+             * sets r9 and jumps back to restorer value.
+             *
+             * This on-stack code is unused but retained for ABI compliance.
              */
             if (thumb) {
-                __put_user(sigreturn_fdpic_thumb_codes[0], rc);
-                __put_user(sigreturn_fdpic_thumb_codes[1], rc + 1);
-                __put_user(sigreturn_fdpic_thumb_codes[2], rc + 2);
-                __put_user((abi_ulong)ka->sa_restorer, rc + 3);
+                write_thumb_fdpic_sigreturn(rc, rc_ofs + 12);
             } else {
-                __put_user(sigreturn_fdpic_codes[0], rc);
-                __put_user(sigreturn_fdpic_codes[1], rc + 1);
-                __put_user(sigreturn_fdpic_codes[2], rc + 2);
-                __put_user((abi_ulong)ka->sa_restorer, rc + 3);
+                write_arm_fdpic_sigreturn(rc, rc_ofs + 12);
             }
+            __put_user((abi_ulong)ka->sa_restorer, &rc[3]);
 
-            retcode = rc_addr + thumb;
+            /* Each trampoline variant consumes a 12-byte slot. */
+            retcode = sigreturn_fdpic_tramp + retcode_idx * 12 + thumb;
         } else {
             retcode = ka->sa_restorer;
         }
     } else {
-        unsigned int idx = thumb;
+        int syscall = (ka->sa_flags & TARGET_SA_SIGINFO
+                       ? TARGET_NR_rt_sigreturn : TARGET_NR_sigreturn);
 
-        if (ka->sa_flags & TARGET_SA_SIGINFO) {
-            idx += 2;
+        /* This on-stack code is unused but retained for ABI compliance. */
+        if (thumb) {
+            write_thumb_sigreturn(rc, syscall);
+        } else {
+            write_arm_sigreturn(rc, syscall);
         }
 
-        __put_user(retcodes[idx], rc);
-
-        retcode = rc_addr + thumb;
+        /* Each trampoline variant consumes 8-byte slot. */
+        retcode = default_sigreturn + retcode_idx * 8 + thumb;
     }
 
     env->regs[0] = usig;
@@ -352,7 +367,7 @@ void setup_frame(int usig, struct target_sigaction *ka,
     setup_sigframe(&frame->uc, set, regs);
 
     if (setup_return(regs, ka, frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct sigframe, retcode))) {
+                     offsetof(struct sigframe, retcode))) {
         goto sigsegv;
     }
 
@@ -383,7 +398,7 @@ void setup_rt_frame(int usig, struct target_sigaction *ka,
     setup_sigframe(&frame->uc, set, env);
 
     if (setup_return(env, ka, frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct rt_sigframe, retcode))) {
+                     offsetof(struct rt_sigframe, retcode))) {
         goto sigsegv;
     }
 
@@ -591,3 +606,67 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    enum {
+        SIGFRAME_FDPIC_OFS = offsetof(struct sigframe, retcode[3]),
+        RT_SIGFRAME_FDPIC_OFS = offsetof(struct rt_sigframe, retcode[3]),
+    };
+
+    uint32_t total_size = 4 * 8 + 4 * 12;
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, total_size, 0);
+    uint32_t i = 0;
+
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    write_arm_sigreturn(&tramp[i], TARGET_NR_sigreturn);
+    i += 2;
+    write_thumb_sigreturn(&tramp[i], TARGET_NR_sigreturn);
+    i += 2;
+    write_arm_sigreturn(&tramp[i], TARGET_NR_rt_sigreturn);
+    i += 2;
+    write_thumb_sigreturn(&tramp[i], TARGET_NR_rt_sigreturn);
+    i += 2;
+
+    /*
+     * FDPIC require trampolines to call sa_restorer, and different
+     * from the pc-relative versions we write to the stack.
+     *
+     * ARM versions use:
+     *    ldr   r3, [sp, #ofs]
+     *    ldr   r9, [r3, #4]
+     *    ldr   pc, [r3, #0]
+     *
+     * Thumb versions use:
+     *    ldr   r3, [sp, #ofs]
+     *    ldmia r3, {r2, r3}
+     *    mov   r9, r3
+     *    bx    r2
+     */
+    sigreturn_fdpic_tramp = sigtramp_page + i * 4;
+
+    /* ARM sigframe */
+    write_arm_fdpic_sigreturn(tramp + i,
+                              offsetof(struct sigframe, retcode[3]));
+    i += 3;
+
+    /* Thumb sigframe */
+    write_thumb_fdpic_sigreturn(tramp + i,
+                                offsetof(struct sigframe, retcode[3]));
+    i += 3;
+
+    /* ARM rt_sigframe */
+    write_arm_fdpic_sigreturn(tramp + i,
+                              offsetof(struct rt_sigframe, retcode[3]));
+    i += 3;
+
+    /* Thumb rt_sigframe */
+    write_thumb_fdpic_sigreturn(tramp + i,
+                                offsetof(struct rt_sigframe, retcode[3]));
+    i += 3;
+
+    assert(i * 4 == total_size);
+    unlock_user(tramp, sigtramp_page, total_size);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 06/27] linux-user/alpha: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (4 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 05/27] linux-user/arm: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 07/27] linux-user/cris: " Richard Henderson
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

Create and record the two signal trampolines.
Use them when the guest does not use ka_restorer.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/alpha/target_signal.h |  1 +
 linux-user/alpha/signal.c        | 34 +++++++++++++++++++-------------
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h
index 250642913e..0b6a39de65 100644
--- a/linux-user/alpha/target_signal.h
+++ b/linux-user/alpha/target_signal.h
@@ -93,6 +93,7 @@ typedef struct target_sigaltstack {
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #define TARGET_ARCH_HAS_KA_RESTORER
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
 
 /* bit-flags */
 #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
diff --git a/linux-user/alpha/signal.c b/linux-user/alpha/signal.c
index 3a820f616b..bbe3dd175a 100644
--- a/linux-user/alpha/signal.c
+++ b/linux-user/alpha/signal.c
@@ -55,13 +55,11 @@ struct target_ucontext {
 
 struct target_sigframe {
     struct target_sigcontext sc;
-    unsigned int retcode[3];
 };
 
 struct target_rt_sigframe {
     target_siginfo_t info;
     struct target_ucontext uc;
-    unsigned int retcode[3];
 };
 
 #define INSN_MOV_R30_R16        0x47fe0410
@@ -142,12 +140,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
     if (ka->ka_restorer) {
         r26 = ka->ka_restorer;
     } else {
-        __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
-        __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
-                   &frame->retcode[1]);
-        __put_user(INSN_CALLSYS, &frame->retcode[2]);
-        /* imb() */
-        r26 = frame_addr + offsetof(struct target_sigframe, retcode);
+        r26 = default_sigreturn;
     }
 
     unlock_user_struct(frame, frame_addr, 1);
@@ -196,12 +189,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     if (ka->ka_restorer) {
         r26 = ka->ka_restorer;
     } else {
-        __put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
-        __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
-                   &frame->retcode[1]);
-        __put_user(INSN_CALLSYS, &frame->retcode[2]);
-        /* imb(); */
-        r26 = frame_addr + offsetof(struct target_rt_sigframe, retcode);
+        r26 = default_rt_sigreturn;
     }
 
     if (err) {
@@ -269,3 +257,21 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6 * 4, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    __put_user(INSN_MOV_R30_R16, &tramp[0]);
+    __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, &tramp[1]);
+    __put_user(INSN_CALLSYS, &tramp[2]);
+
+    default_rt_sigreturn = sigtramp_page + 3 * 4;
+    __put_user(INSN_MOV_R30_R16, &tramp[3]);
+    __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, &tramp[4]);
+    __put_user(INSN_CALLSYS, &tramp[5]);
+
+    unlock_user(tramp, sigtramp_page, 6 * 4);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 07/27] linux-user/cris: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (5 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 06/27] linux-user/alpha: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 08/27] linux-user/hexagon: " Richard Henderson
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Philippe Mathieu-Daudé, laurent, Edgar E . Iglesias

Split out setup_sigreturn so that we can continue to
initialize the words on the stack, as documented.
However, use the off-stack trampoline.

Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/cris/target_signal.h |  2 ++
 linux-user/cris/signal.c        | 29 +++++++++++++++++++++--------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/linux-user/cris/target_signal.h b/linux-user/cris/target_signal.h
index 495a142896..83a5155507 100644
--- a/linux-user/cris/target_signal.h
+++ b/linux-user/cris/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* CRIS_TARGET_SIGNAL_H */
diff --git a/linux-user/cris/signal.c b/linux-user/cris/signal.c
index 2c39bdf727..7f6aca934e 100644
--- a/linux-user/cris/signal.c
+++ b/linux-user/cris/signal.c
@@ -97,6 +97,14 @@ static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
     return sp - framesize;
 }
 
+static void setup_sigreturn(uint16_t *retcode)
+{
+    /* This is movu.w __NR_sigreturn, r9; break 13; */
+    __put_user(0x9c5f, retcode + 0);
+    __put_user(TARGET_NR_sigreturn, retcode + 1);
+    __put_user(0xe93d, retcode + 2);
+}
+
 void setup_frame(int sig, struct target_sigaction *ka,
                  target_sigset_t *set, CPUCRISState *env)
 {
@@ -112,14 +120,8 @@ void setup_frame(int sig, struct target_sigaction *ka,
     /*
      * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
      * use this trampoline anymore but it sets it up for GDB.
-     * In QEMU, using the trampoline simplifies things a bit so we use it.
-     *
-     * This is movu.w __NR_sigreturn, r9; break 13;
      */
-    __put_user(0x9c5f, frame->retcode+0);
-    __put_user(TARGET_NR_sigreturn,
-               frame->retcode + 1);
-    __put_user(0xe93d, frame->retcode + 2);
+    setup_sigreturn(frame->retcode);
 
     /* Save the mask.  */
     __put_user(set->sig[0], &frame->sc.oldmask);
@@ -135,7 +137,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
     env->regs[10] = sig;
     env->pc = (unsigned long) ka->_sa_handler;
     /* Link SRP so the guest returns through the trampoline.  */
-    env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
+    env->pregs[PR_SRP] = default_sigreturn;
 
     unlock_user_struct(frame, frame_addr, 1);
     return;
@@ -187,3 +189,14 @@ long do_rt_sigreturn(CPUCRISState *env)
     qemu_log_mask(LOG_UNIMP, "do_rt_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    setup_sigreturn(tramp);
+
+    unlock_user(tramp, sigtramp_page, 6);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (6 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 07/27] linux-user/cris: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 18:49   ` Taylor Simpson
  2021-09-24 16:59 ` [PATCH v3 09/27] linux-user/hppa: Document non-use of setup_sigtramp Richard Henderson
                   ` (18 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Taylor Simpson, laurent, Philippe Mathieu-Daudé

Continue to initialize the words on the stack, as documented.
However, use the off-stack trampoline.

Cc: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/hexagon/target_signal.h |  2 ++
 linux-user/hexagon/signal.c        | 19 +++++++++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/linux-user/hexagon/target_signal.h b/linux-user/hexagon/target_signal.h
index 345cf1cbb8..9e0223d322 100644
--- a/linux-user/hexagon/target_signal.h
+++ b/linux-user/hexagon/target_signal.h
@@ -31,4 +31,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c
index c7f0bf6b92..74e61739a0 100644
--- a/linux-user/hexagon/signal.c
+++ b/linux-user/hexagon/signal.c
@@ -162,6 +162,11 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     setup_ucontext(&frame->uc, env, set);
     tswap_siginfo(&frame->info, info);
+    /*
+     * The on-stack signal trampoline is no longer executed;
+     * however, the libgcc signal frame unwinding code checks
+     * for the presence of these two numeric magic values.
+     */
     install_sigtramp(frame->tramp);
 
     env->gpr[HEX_REG_PC] = ka->_sa_handler;
@@ -171,8 +176,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
         frame_addr + offsetof(struct target_rt_sigframe, info);
     env->gpr[HEX_REG_R02] =
         frame_addr + offsetof(struct target_rt_sigframe, uc);
-    env->gpr[HEX_REG_LR] =
-        frame_addr + offsetof(struct target_rt_sigframe, tramp);
+    env->gpr[HEX_REG_LR] = default_rt_sigreturn;
 
     return;
 
@@ -271,3 +275,14 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return 0;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 4 * 2, 0);
+    assert(tramp != NULL);
+
+    default_rt_sigreturn = sigtramp_page;
+    install_sigtramp(tramp);
+
+    unlock_user(tramp, sigtramp_page, 4 * 2);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 09/27] linux-user/hppa: Document non-use of setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (7 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 08/27] linux-user/hexagon: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp Richard Henderson
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Alex Bennée, laurent, Philippe Mathieu-Daudé

We cannot use a raw sigtramp page for hppa,
but must wait for full vdso support.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/hppa/target_signal.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h
index 7f525362e9..d558119ee7 100644
--- a/linux-user/hppa/target_signal.h
+++ b/linux-user/hppa/target_signal.h
@@ -71,4 +71,18 @@ typedef struct target_sigaltstack {
 /* mask for all SS_xxx flags */
 #define TARGET_SS_FLAG_BITS  TARGET_SS_AUTODISARM
 
+/*
+ * We cannot use a bare sigtramp page for hppa-linux.
+ *
+ * Unlike other guests where we use the instructions at PC to validate
+ * an offset from SP, the hppa libgcc signal frame fallback unwinding uses
+ * the PC address itself to find the frame.  This is due to the fact that
+ * the hppa grows the stack upward, and the frame is of unknown size.
+ *
+ * TODO: We should be able to use a VDSO to address this, by providing
+ * proper unwind info for the sigtramp code, at which point the fallback
+ * unwinder will not be used.
+ */
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
 #endif /* HPPA_TARGET_SIGNAL_H */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (8 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 09/27] linux-user/hppa: Document non-use of setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 18:01   ` Philippe Mathieu-Daudé
  2021-09-24 16:59 ` [PATCH v3 11/27] linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set Richard Henderson
                   ` (16 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.
Note that x86_64 does not use this code.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/i386/target_signal.h   |  2 ++
 linux-user/x86_64/target_signal.h |  3 ++
 linux-user/i386/signal.c          | 56 +++++++++++++++++++++----------
 3 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h
index 50361af874..64d09f2e75 100644
--- a/linux-user/i386/target_signal.h
+++ b/linux-user/i386/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* I386_TARGET_SIGNAL_H */
diff --git a/linux-user/x86_64/target_signal.h b/linux-user/x86_64/target_signal.h
index 4ea74f20dd..4673c5a886 100644
--- a/linux-user/x86_64/target_signal.h
+++ b/linux-user/x86_64/target_signal.h
@@ -21,4 +21,7 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+/* For x86_64, use of SA_RESTORER is mandatory. */
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
 #endif /* X86_64_TARGET_SIGNAL_H */
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 3b4b55fc0a..94ab6396a0 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -310,6 +310,22 @@ get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
 }
 
 #ifndef TARGET_X86_64
+static void install_sigtramp(void *tramp)
+{
+    /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
+    __put_user(0xb858, (uint16_t *)(tramp + 0));
+    __put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));
+    __put_user(0x80cd, (uint16_t *)(tramp + 6));
+}
+
+static void install_rt_sigtramp(void *tramp)
+{
+    /* This is movl $syscall,%eax ; int $0x80 */
+    __put_user(0xb8, (char *)(tramp + 0));
+    __put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));
+    __put_user(0x80cd, (uint16_t *)(tramp + 5));
+}
+
 /* compare linux/arch/i386/kernel/signal.c:setup_frame() */
 void setup_frame(int sig, struct target_sigaction *ka,
                  target_sigset_t *set, CPUX86State *env)
@@ -338,16 +354,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         __put_user(ka->sa_restorer, &frame->pretcode);
     } else {
-        uint16_t val16;
-        abi_ulong retcode_addr;
-        retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
-        __put_user(retcode_addr, &frame->pretcode);
-        /* This is popl %eax ; movl $,%eax ; int $0x80 */
-        val16 = 0xb858;
-        __put_user(val16, (uint16_t *)(frame->retcode+0));
-        __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
-        val16 = 0x80cd;
-        __put_user(val16, (uint16_t *)(frame->retcode+6));
+        /* This is no longer used, but is retained for ABI compatibility. */
+        install_sigtramp(frame->retcode);
+        __put_user(default_sigreturn, &frame->pretcode);
     }
 
     /* Set up registers for signal handler */
@@ -416,14 +425,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         __put_user(ka->sa_restorer, &frame->pretcode);
     } else {
-        uint16_t val16;
-        addr = frame_addr + offsetof(struct rt_sigframe, retcode);
-        __put_user(addr, &frame->pretcode);
-        /* This is movl $,%eax ; int $0x80 */
-        __put_user(0xb8, (char *)(frame->retcode+0));
-        __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
-        val16 = 0x80cd;
-        __put_user(val16, (uint16_t *)(frame->retcode+5));
+        /* This is no longer used, but is retained for ABI compatibility. */
+        install_rt_sigtramp(frame->retcode);
+        __put_user(default_rt_sigreturn, &frame->pretcode);
     }
 #else
     /* XXX: Would be slightly better to return -EFAULT here if test fails
@@ -592,3 +596,19 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+#ifndef TARGET_X86_64
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    install_sigtramp(tramp);
+
+    default_rt_sigreturn = sigtramp_page + 8;
+    install_rt_sigtramp(tramp + 8);
+
+    unlock_user(tramp, sigtramp_page, 2 * 8);
+}
+#endif
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 11/27] linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (9 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 13:01   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 12/27] linux-user/m68k: Implement setup_sigtramp Richard Henderson
                   ` (15 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

This has been a fixme for some time.  The effect of
returning -EFAULT from the kernel code is to raise SIGSEGV.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/i386/signal.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 94ab6396a0..55a36476d1 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -421,19 +421,18 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     /* Set up to return from userspace.  If provided, use a stub
        already in userspace.  */
-#ifndef TARGET_X86_64
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         __put_user(ka->sa_restorer, &frame->pretcode);
     } else {
+#ifdef TARGET_X86_64
+        /* For x86_64, SA_RESTORER is required ABI.  */
+        goto give_sigsegv;
+#else
         /* This is no longer used, but is retained for ABI compatibility. */
         install_rt_sigtramp(frame->retcode);
         __put_user(default_rt_sigreturn, &frame->pretcode);
-    }
-#else
-    /* XXX: Would be slightly better to return -EFAULT here if test fails
-       assert(ka->sa_flags & TARGET_SA_RESTORER); */
-    __put_user(ka->sa_restorer, &frame->pretcode);
 #endif
+    }
 
     /* Set up registers for signal handler */
     env->regs[R_ESP] = frame_addr;
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 12/27] linux-user/m68k: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (10 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 11/27] linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 13/27] linux-user/microblaze: " Richard Henderson
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

Create and record the two signal trampolines.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/m68k/target_signal.h |  2 ++
 linux-user/m68k/signal.c        | 47 +++++++++++++++------------------
 2 files changed, 24 insertions(+), 25 deletions(-)

diff --git a/linux-user/m68k/target_signal.h b/linux-user/m68k/target_signal.h
index d096544ef8..94157bf1f4 100644
--- a/linux-user/m68k/target_signal.h
+++ b/linux-user/m68k/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* M68K_TARGET_SIGNAL_H */
diff --git a/linux-user/m68k/signal.c b/linux-user/m68k/signal.c
index 4f8eb6f727..ec33482e14 100644
--- a/linux-user/m68k/signal.c
+++ b/linux-user/m68k/signal.c
@@ -39,7 +39,6 @@ struct target_sigframe
     int sig;
     int code;
     abi_ulong psc;
-    char retcode[8];
     abi_ulong extramask[TARGET_NSIG_WORDS-1];
     struct target_sigcontext sc;
 };
@@ -76,7 +75,6 @@ struct target_rt_sigframe
     int sig;
     abi_ulong pinfo;
     abi_ulong puc;
-    char retcode[8];
     struct target_siginfo info;
     struct target_ucontext uc;
 };
@@ -130,7 +128,6 @@ void setup_frame(int sig, struct target_sigaction *ka,
 {
     struct target_sigframe *frame;
     abi_ulong frame_addr;
-    abi_ulong retcode_addr;
     abi_ulong sc_addr;
     int i;
 
@@ -152,16 +149,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
     }
 
     /* Set up to return from userspace.  */
-
-    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
-    __put_user(retcode_addr, &frame->pretcode);
-
-    /* moveq #,d0; trap #0 */
-
-    __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
-               (uint32_t *)(frame->retcode));
-
-    /* Set up to return from userspace */
+    __put_user(default_sigreturn, &frame->pretcode);
 
     env->aregs[7] = frame_addr;
     env->pc = ka->_sa_handler;
@@ -288,7 +276,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 {
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
-    abi_ulong retcode_addr;
     abi_ulong info_addr;
     abi_ulong uc_addr;
     int err = 0;
@@ -325,17 +312,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     }
 
     /* Set up to return from userspace.  */
-
-    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode);
-    __put_user(retcode_addr, &frame->pretcode);
-
-    /* moveq #,d0; notb d0; trap #0 */
-
-    __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
-               (uint32_t *)(frame->retcode + 0));
-    __put_user(0x4e40, (uint16_t *)(frame->retcode + 4));
-
-    /* Set up to return from userspace */
+    __put_user(default_rt_sigreturn, &frame->pretcode);
 
     env->aregs[7] = frame_addr;
     env->pc = ka->_sa_handler;
@@ -411,3 +388,23 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    void *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 4 + 6, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+
+    /* moveq #,d0; trap #0 */
+    __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), (uint32_t *)tramp);
+
+    default_rt_sigreturn = sigtramp_page + 4;
+
+    /* moveq #,d0; notb d0; trap #0 */
+    __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16),
+               (uint32_t *)(tramp + 4));
+    __put_user(0x4e40, (uint16_t *)(tramp + 8));
+
+    unlock_user(tramp, sigtramp_page, 4 + 6);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 13/27] linux-user/microblaze: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (11 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 12/27] linux-user/m68k: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 14/27] linux-user/mips: Tidy install_sigtramp Richard Henderson
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Philippe Mathieu-Daudé, laurent, Edgar E . Iglesias

Create and record the rt signal trampoline.

Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/microblaze/target_signal.h |  2 ++
 linux-user/microblaze/signal.c        | 24 +++++++++++++++++-------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/linux-user/microblaze/target_signal.h b/linux-user/microblaze/target_signal.h
index 1c326296de..e8b510f6b1 100644
--- a/linux-user/microblaze/target_signal.h
+++ b/linux-user/microblaze/target_signal.h
@@ -21,4 +21,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* MICROBLAZE_TARGET_SIGNAL_H */
diff --git a/linux-user/microblaze/signal.c b/linux-user/microblaze/signal.c
index b822679d18..8ebb6a1b7d 100644
--- a/linux-user/microblaze/signal.c
+++ b/linux-user/microblaze/signal.c
@@ -161,17 +161,11 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     /* Kernel does not use SA_RESTORER. */
 
-    /* addi r12, r0, __NR_sigreturn */
-    __put_user(0x31800000U | TARGET_NR_rt_sigreturn, frame->tramp + 0);
-    /* brki r14, 0x8 */
-    __put_user(0xb9cc0008U, frame->tramp + 1);
-
     /*
      * Return from sighandler will jump to the tramp.
      * Negative 8 offset because return is rtsd r15, 8
      */
-    env->regs[15] =
-        frame_addr + offsetof(struct target_rt_sigframe, tramp) - 8;
+    env->regs[15] = default_rt_sigreturn - 8;
 
     /* Set up registers for signal handler */
     env->regs[1] = frame_addr;
@@ -220,3 +214,19 @@ long do_rt_sigreturn(CPUMBState *env)
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
+    assert(tramp != NULL);
+
+    /*
+     * addi r12, r0, __NR_rt_sigreturn
+     * brki r14, 0x8
+     */
+    __put_user(0x31800000U | TARGET_NR_rt_sigreturn, tramp);
+    __put_user(0xb9cc0008U, tramp + 1);
+
+    default_rt_sigreturn = sigtramp_page;
+    unlock_user(tramp, sigtramp_page, 8);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 14/27] linux-user/mips: Tidy install_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (12 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 13/27] linux-user/microblaze: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 15/27] linux-user/mips: Implement setup_sigtramp Richard Henderson
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

The return value is constant 0, and unused as well -- change to void.
Drop inline marker.  Change tramp type to uint32_t* for clarity.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/mips/signal.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c
index d174b3453c..64072779b9 100644
--- a/linux-user/mips/signal.c
+++ b/linux-user/mips/signal.c
@@ -87,10 +87,8 @@ struct target_rt_sigframe {
 };
 
 /* Install trampoline to jump back from signal handler */
-static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
+static void install_sigtramp(uint32_t *tramp, unsigned int syscall)
 {
-    int err = 0;
-
     /*
      * Set up the return code ...
      *
@@ -100,7 +98,6 @@ static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
 
     __put_user(0x24020000 + syscall, tramp + 0);
     __put_user(0x0000000c          , tramp + 1);
-    return err;
 }
 
 static inline void setup_sigcontext(CPUMIPSState *regs,
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 15/27] linux-user/mips: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (13 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 14/27] linux-user/mips: Tidy install_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

Create and record the two signal trampolines.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/mips/target_signal.h   |  1 +
 linux-user/mips64/target_signal.h |  2 ++
 linux-user/mips/signal.c          | 34 ++++++++++++++++++++++---------
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h
index d521765f6b..780a4ddf29 100644
--- a/linux-user/mips/target_signal.h
+++ b/linux-user/mips/target_signal.h
@@ -73,6 +73,7 @@ typedef struct target_sigaltstack {
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
 
 /* bit-flags */
 #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h
index d857c55e4c..275e9b7f9a 100644
--- a/linux-user/mips64/target_signal.h
+++ b/linux-user/mips64/target_signal.h
@@ -76,4 +76,6 @@ typedef struct target_sigaltstack {
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* MIPS64_TARGET_SIGNAL_H */
diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c
index 64072779b9..8f79e405ec 100644
--- a/linux-user/mips/signal.c
+++ b/linux-user/mips/signal.c
@@ -209,8 +209,6 @@ void setup_frame(int sig, struct target_sigaction * ka,
         goto give_sigsegv;
     }
 
-    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
-
     setup_sigcontext(regs, &frame->sf_sc);
 
     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
@@ -231,7 +229,7 @@ void setup_frame(int sig, struct target_sigaction * ka,
     regs->active_tc.gpr[ 5] = 0;
     regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
     regs->active_tc.gpr[29] = frame_addr;
-    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
+    regs->active_tc.gpr[31] = default_sigreturn;
     /* The original kernel code sets CP0_EPC to the handler
     * since it returns to userland using eret
     * we cannot do this here, and we must set PC directly */
@@ -305,8 +303,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
         goto give_sigsegv;
     }
 
-    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
-
     tswap_siginfo(&frame->rs_info, info);
 
     __put_user(0, &frame->rs_uc.tuc_flags);
@@ -335,11 +331,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->active_tc.gpr[ 6] = frame_addr
                              + offsetof(struct target_rt_sigframe, rs_uc);
     env->active_tc.gpr[29] = frame_addr;
-    env->active_tc.gpr[31] = frame_addr
-                             + offsetof(struct target_rt_sigframe, rs_code);
-    /* The original kernel code sets CP0_EPC to the handler
-    * since it returns to userland using eret
-    * we cannot do this here, and we must set PC directly */
+    env->active_tc.gpr[31] = default_rt_sigreturn;
+
+    /*
+     * The original kernel code sets CP0_EPC to the handler
+     * since it returns to userland using eret
+     * we cannot do this here, and we must set PC directly
+     */
     env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
     mips_set_hflags_isa_mode_from_pc(env);
     unlock_user_struct(frame, frame_addr, 1);
@@ -379,3 +377,19 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+    assert(tramp != NULL);
+
+#ifdef TARGET_ARCH_HAS_SETUP_FRAME
+    default_sigreturn = sigtramp_page;
+    install_sigtramp(tramp, TARGET_NR_sigreturn);
+#endif
+
+    default_rt_sigreturn = sigtramp_page + 8;
+    install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn);
+
+    unlock_user(tramp, sigtramp_page, 2 * 8);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (14 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 15/27] linux-user/mips: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 13:23   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 17/27] linux-user/nios2: Map a real kuser page Richard Henderson
                   ` (10 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

The real kernel has to load the instruction and extract
the imm5 field; for qemu, modify the translator to do this.

The use of R_AT for this in cpu_loop was a bug.  Handle
the other trap numbers as per the kernel's trap_table.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/nios2/cpu.h          |  5 +++--
 linux-user/nios2/cpu_loop.c | 35 ++++++++++++++++++-----------------
 target/nios2/translate.c    | 17 ++++++++++++++++-
 3 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 2ab82fdc71..395e4d3281 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -158,9 +158,10 @@ struct Nios2CPUClass {
 struct CPUNios2State {
     uint32_t regs[NUM_CORE_REGS];
 
-#if !defined(CONFIG_USER_ONLY)
+#ifdef CONFIG_USER_ONLY
+    int trap_code;
+#else
     Nios2MMU mmu;
-
     uint32_t irq_pending;
 #endif
 };
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 34290fb3b5..246293a501 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -39,9 +39,10 @@ void cpu_loop(CPUNios2State *env)
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
             break;
+
         case EXCP_TRAP:
-            if (env->regs[R_AT] == 0) {
-                abi_long ret;
+            switch (env->trap_code) {
+            case 0:
                 qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
 
                 ret = do_syscall(env, env->regs[2],
@@ -55,26 +56,26 @@ void cpu_loop(CPUNios2State *env)
 
                 env->regs[2] = abs(ret);
                 /* Return value is 0..4096 */
-                env->regs[7] = (ret > 0xfffffffffffff000ULL);
-                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
-                env->regs[CR_STATUS] &= ~0x3;
-                env->regs[R_EA] = env->regs[R_PC] + 4;
+                env->regs[7] = ret > 0xfffff000u;
                 env->regs[R_PC] += 4;
                 break;
-            } else {
-                qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
 
-                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
-                env->regs[CR_STATUS] &= ~0x3;
-                env->regs[R_EA] = env->regs[R_PC] + 4;
-                env->regs[R_PC] = cpu->exception_addr;
-
-                info.si_signo = TARGET_SIGTRAP;
-                info.si_errno = 0;
-                info.si_code = TARGET_TRAP_BRKPT;
-                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+            case 1:
+                qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
+                force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
+                break;
+            case 2:
+                qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
+                force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_PC]);
+                break;
+            default:
+                qemu_log_mask(CPU_LOG_INT, "\nTrap %d\n", env->trap_code);
+                force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
+                                env->regs[R_PC]);
                 break;
             }
+            break;
+
         case EXCP_DEBUG:
             info.si_signo = TARGET_SIGTRAP;
             info.si_errno = 0;
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 08d7ac5398..485b487665 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -636,6 +636,21 @@ static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
     tcg_temp_free(t0);
 }
 
+static void trap(DisasContext *dc, uint32_t code, uint32_t flags)
+{
+#ifdef CONFIG_USER_ONLY
+    /*
+     * The imm5 field is not stored anywhere on real hw; the kernel
+     * has to load the insn and extract the field.  But we can make
+     * things easier for cpu_loop if we pop this into env->trap_code.
+     */
+    R_TYPE(instr, code);
+    tcg_gen_st_i32(tcg_constant_i32(instr.imm5), cpu_env,
+                   offsetof(CPUNios2State, trap_code));
+#endif
+    t_gen_helper_raise_exception(dc, EXCP_TRAP);
+}
+
 static const Nios2Instruction r_type_instructions[] = {
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION(eret),                                /* eret */
@@ -682,7 +697,7 @@ static const Nios2Instruction r_type_instructions[] = {
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION_ILLEGAL(),
-    INSTRUCTION_FLG(gen_excp, EXCP_TRAP),             /* trap */
+    INSTRUCTION(trap),                                /* trap */
     INSTRUCTION(wrctl),                               /* wrctl */
     INSTRUCTION_ILLEGAL(),
     INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU),         /* cmpltu */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 17/27] linux-user/nios2: Map a real kuser page
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (15 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 13:26   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 18/27] linux-user/nios2: Fixes for signal frame setup Richard Henderson
                   ` (9 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

The first word of page1 is data, so the whole thing
can't be implemented with emulation of addresses.

Hijack trap number 31 to implement cmpxchg.

Set default_rt_sigreturn based on the kuser page.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/nios2/target_signal.h |  3 ++
 linux-user/elfload.c             | 35 ++++++++++++++++++++++
 linux-user/nios2/cpu_loop.c      | 51 +++++++++++++++++---------------
 linux-user/nios2/signal.c        |  2 +-
 target/nios2/translate.c         |  9 ------
 5 files changed, 66 insertions(+), 34 deletions(-)

diff --git a/linux-user/nios2/target_signal.h b/linux-user/nios2/target_signal.h
index aebf749f12..fe266c4c51 100644
--- a/linux-user/nios2/target_signal.h
+++ b/linux-user/nios2/target_signal.h
@@ -19,4 +19,7 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+/* Nios2 uses a fixed address on the kuser page for sigreturn. */
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
 #endif /* NIOS2_TARGET_SIGNAL_H */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 459a26ef1d..7b3a91b3ed 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1100,6 +1100,41 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env
 
 static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
+    static const uint8_t kuser_page[4 + 2 * 64] = {
+        /* __kuser_helper_version */
+        [0x00] = 0x02, 0x00, 0x00, 0x00,
+
+        /* __kuser_cmpxchg */
+        [0x04] = 0xfa, 0x6f, 0x3b, 0x00,  /* trap 31 */
+                 0x3a, 0x28, 0x00, 0xf8,  /* ret */
+
+        /* __kuser_sigtramp */
+        [0x44] = 0xc4, 0x22, 0x80, 0x00,  /* movi r2, __NR_rt_sigreturn */
+                 0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
+    };
+
+    abi_ulong pg;
+    uint8_t *ph;
+
+    pg = target_mmap(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE,
+                     PROT_READ | PROT_WRITE,
+                     MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
+
+    /*
+     * If the mmap doesn't give us exactly page 1, there's nothing
+     * we can do, and it's unlikely that the program will be able
+     * to continue.  FIXME: Error out now?
+     */
+    assert(pg == TARGET_PAGE_SIZE);
+
+    ph = lock_user(VERIFY_WRITE, pg, sizeof(kuser_page), 0);
+    memcpy(ph, kuser_page, sizeof(kuser_page));
+    unlock_user(ph, pg, sizeof(kuser_page));
+    target_mprotect(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
+
+    /* Install __kuser_sigtramp */
+    default_rt_sigreturn = TARGET_PAGE_SIZE + 0x44;
+
     regs->ea = infop->entry;
     regs->sp = infop->start_stack;
     regs->estatus = 0x3;
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 246293a501..12070c8a3c 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -26,7 +26,6 @@
 void cpu_loop(CPUNios2State *env)
 {
     CPUState *cs = env_cpu(env);
-    Nios2CPU *cpu = NIOS2_CPU(cs);
     target_siginfo_t info;
     int trapnr, ret;
 
@@ -73,6 +72,32 @@ void cpu_loop(CPUNios2State *env)
                 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
                                 env->regs[R_PC]);
                 break;
+
+            case 31: /* QEMU specific, for __kuser_cmpxchg */
+                {
+                    abi_ptr g = env->regs[4];
+                    uint32_t *h, n, o;
+
+                    if (g & 0x3) {
+                        force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, g);
+                        break;
+                    }
+                    ret = page_get_flags(g);
+                    if (!(ret & PAGE_VALID)) {
+                        force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, g);
+                        break;
+                    }
+                    if (!(ret & PAGE_READ) || !(ret & PAGE_WRITE)) {
+                        force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR, g);
+                        break;
+                    }
+                    h = g2h(cs, g);
+                    o = env->regs[5];
+                    n = env->regs[6];
+                    env->regs[2] = qatomic_cmpxchg(h, o, n) - o;
+                    env->regs[R_PC] += 4;
+                }
+                break;
             }
             break;
 
@@ -83,29 +108,7 @@ void cpu_loop(CPUNios2State *env)
             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
             break;
         case 0xaa:
-            switch (env->regs[R_PC]) {
-            /*case 0x1000:*/  /* TODO:__kuser_helper_version */
-            case 0x1004:      /* __kuser_cmpxchg */
-                start_exclusive();
-                if (env->regs[4] & 0x3) {
-                    goto kuser_fail;
-                }
-                ret = get_user_u32(env->regs[2], env->regs[4]);
-                if (ret) {
-                    end_exclusive();
-                    goto kuser_fail;
-                }
-                env->regs[2] -= env->regs[5];
-                if (env->regs[2] == 0) {
-                    put_user_u32(env->regs[6], env->regs[4]);
-                }
-                end_exclusive();
-                env->regs[R_PC] = env->regs[R_RA];
-                break;
-            /*case 0x1040:*/  /* TODO:__kuser_sigtramp */
-            default:
-                ;
-kuser_fail:
+            {
                 info.si_signo = TARGET_SIGSEGV;
                 info.si_errno = 0;
                 /* TODO: check env->error_code */
diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
index a77e8a40f4..c9a235ded5 100644
--- a/linux-user/nios2/signal.c
+++ b/linux-user/nios2/signal.c
@@ -177,7 +177,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     /* Set up to return from userspace; jump to fixed address sigreturn
        trampoline on kuser page.  */
-    env->regs[R_RA] = (unsigned long) (0x1044);
+    env->regs[R_RA] = default_rt_sigreturn;
 
     /* Set up registers for signal handler */
     env->regs[R_SP] = (unsigned long) frame;
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 485b487665..77706dd805 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -795,15 +795,6 @@ static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
     dc->base.pc_next = pc + 4;
 
     /* Decode an instruction */
-
-#if defined(CONFIG_USER_ONLY)
-    /* FIXME: Is this needed ? */
-    if (pc >= 0x1000 && pc < 0x2000) {
-        t_gen_helper_raise_exception(dc, 0xaa);
-        return;
-    }
-#endif
-
     code = cpu_ldl_code(env, pc);
     op = get_opcode(code);
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 18/27] linux-user/nios2: Fixes for signal frame setup
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (16 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 17/27] linux-user/nios2: Map a real kuser page Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 13:28   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 19/27] linux-user/openrisc: Implement setup_sigtramp Richard Henderson
                   ` (8 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

Do not confuse host and guest addresses.  Lock and unlock
the target_rt_sigframe structure in setup_rt_sigframe.

Since rt_setup_ucontext always returns 0, drop the return
value entirely.  This eliminates the only write to the err
variable in setup_rt_sigframe.

Always copy the siginfo structure.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/nios2/signal.c | 49 ++++++++++++++++-----------------------
 1 file changed, 20 insertions(+), 29 deletions(-)

diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c
index c9a235ded5..95f6d737e1 100644
--- a/linux-user/nios2/signal.c
+++ b/linux-user/nios2/signal.c
@@ -42,7 +42,7 @@ struct target_rt_sigframe {
     struct target_ucontext uc;
 };
 
-static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
+static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
 {
     unsigned long *gregs = uc->tuc_mcontext.gregs;
 
@@ -75,8 +75,6 @@ static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
     __put_user(env->regs[R_GP], &gregs[25]);
     __put_user(env->regs[R_EA], &gregs[27]);
     __put_user(env->regs[R_SP], &gregs[28]);
-
-    return 0;
 }
 
 static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
@@ -135,8 +133,8 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
     return 0;
 }
 
-static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
-                          size_t frame_size)
+static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
+                            size_t frame_size)
 {
     unsigned long usp;
 
@@ -144,7 +142,7 @@ static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
     usp = target_sigsp(get_sp_from_cpustate(env), ka);
 
     /* Verify, is it 32 or 64 bit aligned */
-    return (void *)((usp - frame_size) & -8UL);
+    return (usp - frame_size) & -8;
 }
 
 void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -153,26 +151,25 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
                     CPUNios2State *env)
 {
     struct target_rt_sigframe *frame;
-    int i, err = 0;
+    abi_ptr frame_addr;
+    int i;
 
-    frame = get_sigframe(ka, env, sizeof(*frame));
-
-    if (ka->sa_flags & SA_SIGINFO) {
-        tswap_siginfo(&frame->info, info);
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        force_sigsegv(sig);
+        return;
     }
 
+    tswap_siginfo(&frame->info, info);
+
     /* Create the ucontext.  */
     __put_user(0, &frame->uc.tuc_flags);
     __put_user(0, &frame->uc.tuc_link);
     target_save_altstack(&frame->uc.tuc_stack, env);
-    err |= rt_setup_ucontext(&frame->uc, env);
+    rt_setup_ucontext(&frame->uc, env);
     for (i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user((abi_ulong)set->sig[i],
-            (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
-    }
-
-    if (err) {
-        goto give_sigsegv;
+                   (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
     }
 
     /* Set up to return from userspace; jump to fixed address sigreturn
@@ -180,19 +177,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     env->regs[R_RA] = default_rt_sigreturn;
 
     /* Set up registers for signal handler */
-    env->regs[R_SP] = (unsigned long) frame;
-    env->regs[4] = (unsigned long) sig;
-    env->regs[5] = (unsigned long) &frame->info;
-    env->regs[6] = (unsigned long) &frame->uc;
-    env->regs[R_EA] = (unsigned long) ka->_sa_handler;
-    return;
+    env->regs[R_SP] = frame_addr;
+    env->regs[4] = sig;
+    env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
+    env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
+    env->regs[R_EA] = ka->_sa_handler;
 
-give_sigsegv:
-    if (sig == TARGET_SIGSEGV) {
-        ka->_sa_handler = TARGET_SIG_DFL;
-    }
-    force_sigsegv(sig);
-    return;
+    unlock_user_struct(frame, frame_addr, 1);
 }
 
 long do_sigreturn(CPUNios2State *env)
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 19/27] linux-user/openrisc: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (17 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 18/27] linux-user/nios2: Fixes for signal frame setup Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline Richard Henderson
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Stafford Horne, laurent, Philippe Mathieu-Daudé

Create and record the rt signal trampoline.

Reviewed-by: Stafford Horne <shorne@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/openrisc/target_signal.h |  2 ++
 linux-user/openrisc/signal.c        | 22 ++++++++++++++--------
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h
index 8283eaf544..077ec3d5e8 100644
--- a/linux-user/openrisc/target_signal.h
+++ b/linux-user/openrisc/target_signal.h
@@ -26,4 +26,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* OPENRISC_TARGET_SIGNAL_H */
diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c
index ca2532bf50..be8b68784a 100644
--- a/linux-user/openrisc/signal.c
+++ b/linux-user/openrisc/signal.c
@@ -38,7 +38,6 @@ typedef struct target_ucontext {
 typedef struct target_rt_sigframe {
     struct target_siginfo info;
     target_ucontext uc;
-    uint32_t retcode[4];  /* trampoline code */
 } target_rt_sigframe;
 
 static void restore_sigcontext(CPUOpenRISCState *env, target_sigcontext *sc)
@@ -116,14 +115,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
         __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
     }
 
-    /* This is l.ori r11,r0,__NR_sigreturn; l.sys 1; l.nop; l.nop */
-    __put_user(0xa9600000 | TARGET_NR_rt_sigreturn, frame->retcode + 0);
-    __put_user(0x20000001, frame->retcode + 1);
-    __put_user(0x15000000, frame->retcode + 2);
-    __put_user(0x15000000, frame->retcode + 3);
-
     /* Set up registers for signal handler */
-    cpu_set_gpr(env, 9, frame_addr + offsetof(target_rt_sigframe, retcode));
+    cpu_set_gpr(env, 9, default_rt_sigreturn);
     cpu_set_gpr(env, 3, sig);
     cpu_set_gpr(env, 4, frame_addr + offsetof(target_rt_sigframe, info));
     cpu_set_gpr(env, 5, frame_addr + offsetof(target_rt_sigframe, uc));
@@ -169,3 +162,16 @@ long do_rt_sigreturn(CPUOpenRISCState *env)
     force_sig(TARGET_SIGSEGV);
     return 0;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
+    assert(tramp != NULL);
+
+    /* This is l.ori r11,r0,__NR_sigreturn; l.sys 1 */
+    __put_user(0xa9600000 | TARGET_NR_rt_sigreturn, tramp + 0);
+    __put_user(0x20000001, tramp + 1);
+
+    default_rt_sigreturn = sigtramp_page;
+    unlock_user(tramp, sigtramp_page, 8);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (18 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 19/27] linux-user/openrisc: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 17:55   ` Philippe Mathieu-Daudé
  2021-09-24 16:59 ` [PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp Richard Henderson
                   ` (6 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent

The sigret parameter is never 0, and even if it was the encoding
of the LI instruction would still work.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/ppc/signal.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
index e4d0dfa3bf..77f37b9f01 100644
--- a/linux-user/ppc/signal.c
+++ b/linux-user/ppc/signal.c
@@ -309,10 +309,8 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
 static void encode_trampoline(int sigret, uint32_t *tramp)
 {
     /* Set up the sigreturn trampoline: li r0,sigret; sc.  */
-    if (sigret) {
-        __put_user(0x38000000 | sigret, &tramp[0]);
-        __put_user(0x44000002, &tramp[1]);
-    }
+    __put_user(0x38000000 | sigret, &tramp[0]);
+    __put_user(0x44000002, &tramp[1]);
 }
 
 static void restore_user_regs(CPUPPCState *env,
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (19 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 13:34   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 22/27] linux-user/riscv: " Richard Henderson
                   ` (5 subsequent siblings)
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, qemu-ppc, laurent

Create and record the two signal trampolines.

Cc: qemu-ppc@nongnu.org
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/ppc/target_signal.h |  2 ++
 linux-user/ppc/signal.c        | 34 ++++++++++++++++++----------------
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h
index 72fcdd9bfa..82184ab8f2 100644
--- a/linux-user/ppc/target_signal.h
+++ b/linux-user/ppc/target_signal.h
@@ -24,4 +24,6 @@ typedef struct target_sigaltstack {
 #if !defined(TARGET_PPC64)
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* PPC_TARGET_SIGNAL_H */
diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
index 77f37b9f01..c37744c8fc 100644
--- a/linux-user/ppc/signal.c
+++ b/linux-user/ppc/signal.c
@@ -203,9 +203,6 @@ struct target_func_ptr {
 
 #endif
 
-/* We use the mc_pad field for the signal return trampoline.  */
-#define tramp mc_pad
-
 /* See arch/powerpc/kernel/signal.c.  */
 static target_ulong get_sigframe(struct target_sigaction *ka,
                                  CPUPPCState *env,
@@ -436,12 +433,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
     /* Save user regs.  */
     save_user_regs(env, &frame->mctx);
 
-    /* Construct the trampoline code on the stack. */
-    encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp);
-
-    /* The kernel checks for the presence of a VDSO here.  We don't
-       emulate a vdso, so use a sigreturn system call.  */
-    env->lr = (target_ulong) h2g(frame->mctx.tramp);
+    env->lr = default_sigreturn;
 
     /* Turn off all fp exceptions.  */
     env->fpscr = 0;
@@ -477,7 +469,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
                     target_sigset_t *set, CPUPPCState *env)
 {
     struct target_rt_sigframe *rt_sf;
-    uint32_t *trampptr = 0;
     struct target_mcontext *mctx = 0;
     target_ulong rt_sf_addr, newsp = 0;
     int i, err = 0;
@@ -507,22 +498,17 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
 #if defined(TARGET_PPC64)
     mctx = &rt_sf->uc.tuc_sigcontext.mcontext;
-    trampptr = &rt_sf->trampoline[0];
 
     sc = &rt_sf->uc.tuc_sigcontext;
     __put_user(h2g(mctx), &sc->regs);
     __put_user(sig, &sc->signal);
 #else
     mctx = &rt_sf->uc.tuc_mcontext;
-    trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp;
 #endif
 
     save_user_regs(env, mctx);
-    encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
 
-    /* The kernel checks for the presence of a VDSO here.  We don't
-       emulate a vdso, so use a sigreturn system call.  */
-    env->lr = (target_ulong) h2g(trampptr);
+    env->lr = default_rt_sigreturn;
 
     /* Turn off all fp exceptions.  */
     env->fpscr = 0;
@@ -720,3 +706,19 @@ abi_long do_swapcontext(CPUArchState *env, abi_ulong uold_ctx,
 
     return 0;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+    assert(tramp != NULL);
+
+#ifdef TARGET_ARCH_HAS_SETUP_FRAME
+    default_sigreturn = sigtramp_page;
+    encode_trampoline(TARGET_NR_sigreturn, tramp + 0);
+#endif
+
+    default_rt_sigreturn = sigtramp_page + 8;
+    encode_trampoline(TARGET_NR_rt_sigreturn, tramp + 2);
+
+    unlock_user(tramp, sigtramp_page, 2 * 8);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 22/27] linux-user/riscv: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (20 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 23/27] linux-user/s390x: " Richard Henderson
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Alistair Francis, laurent, Philippe Mathieu-Daudé

Create and record the rt signal trampoline.

This fixes a bug wrt libgcc fallback unwinding.  It expects
the stack pointer to point to the siginfo_t, whereas we had
inexplicably placed our private signal trampoline at the start
of the signal frame instead of the end.  Now moot because we
have removed it from the stack frame entirely.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/riscv/target_signal.h |  2 ++
 linux-user/riscv/signal.c        | 22 +++++++++++++---------
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/linux-user/riscv/target_signal.h b/linux-user/riscv/target_signal.h
index f113ba9a55..3e36fddc9d 100644
--- a/linux-user/riscv/target_signal.h
+++ b/linux-user/riscv/target_signal.h
@@ -15,4 +15,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* RISCV_TARGET_SIGNAL_H */
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index f7f33bc90a..a0f9542ce3 100644
--- a/linux-user/riscv/signal.c
+++ b/linux-user/riscv/signal.c
@@ -47,7 +47,6 @@ struct target_ucontext {
 };
 
 struct target_rt_sigframe {
-    uint32_t tramp[2]; /* not in kernel, which uses VDSO instead */
     struct target_siginfo info;
     struct target_ucontext uc;
 };
@@ -105,12 +104,6 @@ static void setup_ucontext(struct target_ucontext *uc,
     setup_sigcontext(&uc->uc_mcontext, env);
 }
 
-static inline void install_sigtramp(uint32_t *tramp)
-{
-    __put_user(0x08b00893, tramp + 0);  /* li a7, 139 = __NR_rt_sigreturn */
-    __put_user(0x00000073, tramp + 1);  /* ecall */
-}
-
 void setup_rt_frame(int sig, struct target_sigaction *ka,
                     target_siginfo_t *info,
                     target_sigset_t *set, CPURISCVState *env)
@@ -127,14 +120,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
     setup_ucontext(&frame->uc, env, set);
     tswap_siginfo(&frame->info, info);
-    install_sigtramp(frame->tramp);
 
     env->pc = ka->_sa_handler;
     env->gpr[xSP] = frame_addr;
     env->gpr[xA0] = sig;
     env->gpr[xA1] = frame_addr + offsetof(struct target_rt_sigframe, info);
     env->gpr[xA2] = frame_addr + offsetof(struct target_rt_sigframe, uc);
-    env->gpr[xRA] = frame_addr + offsetof(struct target_rt_sigframe, tramp);
+    env->gpr[xRA] = default_rt_sigreturn;
 
     return;
 
@@ -203,3 +195,15 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return 0;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
+    assert(tramp != NULL);
+
+    __put_user(0x08b00893, tramp + 0);  /* li a7, 139 = __NR_rt_sigreturn */
+    __put_user(0x00000073, tramp + 1);  /* ecall */
+
+    default_rt_sigreturn = sigtramp_page;
+    unlock_user(tramp, sigtramp_page, 8);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 23/27] linux-user/s390x: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (21 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 22/27] linux-user/riscv: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 24/27] linux-user/sh4: " Richard Henderson
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, qemu-s390x, Alex Bennée, laurent,
	Philippe Mathieu-Daudé

Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.

Cc: qemu-s390x@nongnu.org
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/s390x/target_signal.h |  2 ++
 linux-user/s390x/signal.c        | 24 ++++++++++++++++--------
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h
index bbfc464d44..64f5f42201 100644
--- a/linux-user/s390x/target_signal.h
+++ b/linux-user/s390x/target_signal.h
@@ -19,4 +19,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* S390X_TARGET_SIGNAL_H */
diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index 80f34086d7..676b948147 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -68,7 +68,6 @@ typedef struct {
     target_sigregs sregs;
     int signo;
     target_sigregs_ext sregs_ext;
-    uint16_t retcode;
 } sigframe;
 
 #define TARGET_UC_VXRS 2
@@ -85,7 +84,6 @@ struct target_ucontext {
 
 typedef struct {
     uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
-    uint16_t retcode;
     struct target_siginfo info;
     struct target_ucontext uc;
 } rt_sigframe;
@@ -209,9 +207,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         restorer = ka->sa_restorer;
     } else {
-        restorer = frame_addr + offsetof(sigframe, retcode);
-        __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
-                   &frame->retcode);
+        restorer = default_sigreturn;
     }
 
     /* Set up registers for signal handler */
@@ -262,9 +258,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         restorer = ka->sa_restorer;
     } else {
-        restorer = frame_addr + offsetof(typeof(*frame), retcode);
-        __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
-                   &frame->retcode);
+        restorer = default_rt_sigreturn;
     }
 
     /* Create siginfo on the signal stack. */
@@ -405,3 +399,17 @@ long do_rt_sigreturn(CPUS390XState *env)
     unlock_user_struct(frame, frame_addr, 0);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 + 2, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, &tramp[0]);
+
+    default_rt_sigreturn = sigtramp_page + 2;
+    __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, &tramp[1]);
+
+    unlock_user(tramp, sigtramp_page, 2 + 2);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 24/27] linux-user/sh4: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (22 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 23/27] linux-user/s390x: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 25/27] linux-user/sparc: " Richard Henderson
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, laurent, Yoshinori Sato, Philippe Mathieu-Daudé

Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.

Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/sh4/target_signal.h |  2 ++
 linux-user/sh4/signal.c        | 40 +++++++++++++++++++---------------
 2 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h
index d7309b7136..04069cba66 100644
--- a/linux-user/sh4/target_signal.h
+++ b/linux-user/sh4/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* SH4_TARGET_SIGNAL_H */
diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
index d70d744bef..faa869fb19 100644
--- a/linux-user/sh4/signal.c
+++ b/linux-user/sh4/signal.c
@@ -52,7 +52,6 @@ struct target_sigframe
 {
     struct target_sigcontext sc;
     target_ulong extramask[TARGET_NSIG_WORDS-1];
-    uint16_t retcode[3];
 };
 
 
@@ -68,7 +67,6 @@ struct target_rt_sigframe
 {
     struct target_siginfo info;
     struct target_ucontext uc;
-    uint16_t retcode[3];
 };
 
 
@@ -190,15 +188,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
     /* Set up to return from userspace.  If provided, use a stub
        already in userspace.  */
     if (ka->sa_flags & TARGET_SA_RESTORER) {
-        regs->pr = (unsigned long) ka->sa_restorer;
+        regs->pr = ka->sa_restorer;
     } else {
-        /* Generate return code (system call to sigreturn) */
-        abi_ulong retcode_addr = frame_addr +
-                                 offsetof(struct target_sigframe, retcode);
-        __put_user(MOVW(2), &frame->retcode[0]);
-        __put_user(TRAP_NOARG, &frame->retcode[1]);
-        __put_user((TARGET_NR_sigreturn), &frame->retcode[2]);
-        regs->pr = (unsigned long) retcode_addr;
+        regs->pr = default_sigreturn;
     }
 
     /* Set up registers for signal handler */
@@ -248,15 +240,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     /* Set up to return from userspace.  If provided, use a stub
        already in userspace.  */
     if (ka->sa_flags & TARGET_SA_RESTORER) {
-        regs->pr = (unsigned long) ka->sa_restorer;
+        regs->pr = ka->sa_restorer;
     } else {
-        /* Generate return code (system call to sigreturn) */
-        abi_ulong retcode_addr = frame_addr +
-                                 offsetof(struct target_rt_sigframe, retcode);
-        __put_user(MOVW(2), &frame->retcode[0]);
-        __put_user(TRAP_NOARG, &frame->retcode[1]);
-        __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]);
-        regs->pr = (unsigned long) retcode_addr;
+        regs->pr = default_rt_sigreturn;
     }
 
     /* Set up registers for signal handler */
@@ -334,3 +320,21 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 6, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    __put_user(MOVW(2), &tramp[0]);
+    __put_user(TRAP_NOARG, &tramp[1]);
+    __put_user(TARGET_NR_sigreturn, &tramp[2]);
+
+    default_rt_sigreturn = sigtramp_page + 6;
+    __put_user(MOVW(2), &tramp[3]);
+    __put_user(TRAP_NOARG, &tramp[4]);
+    __put_user(TARGET_NR_rt_sigreturn, &tramp[5]);
+
+    unlock_user(tramp, sigtramp_page, 2 * 6);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 25/27] linux-user/sparc: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (23 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 24/27] linux-user/sh4: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-27 13:30   ` Peter Maydell
  2021-09-24 16:59 ` [PATCH v3 26/27] linux-user/xtensa: " Richard Henderson
  2021-09-24 16:59 ` [PATCH v3 27/27] linux-user: Remove default for TARGET_ARCH_HAS_SIGTRAMP_PAGE Richard Henderson
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Mark Cave-Ayland, laurent

Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.

Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/sparc/target_signal.h |  4 ++++
 linux-user/sparc/signal.c        | 40 +++++++++++++++++++++-----------
 2 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h
index 34f9a12519..e661ddd6ab 100644
--- a/linux-user/sparc/target_signal.h
+++ b/linux-user/sparc/target_signal.h
@@ -69,6 +69,10 @@ typedef struct target_sigaltstack {
 
 #ifdef TARGET_ABI32
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+#else
+/* For sparc64, use of KA_RESTORER is mandatory. */
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
 #endif
 
 /* bit-flags */
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index 3bc023d281..23e1e761de 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -242,6 +242,12 @@ static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
 }
 
 #ifdef TARGET_ARCH_HAS_SETUP_FRAME
+static void install_sigtramp(uint32_t *tramp, int syscall)
+{
+    __put_user(0x82102000u + syscall, &tramp[0]); /* mov syscall, %g1 */
+    __put_user(0x91d02010u, &tramp[1]);           /* t 0x10 */
+}
+
 void setup_frame(int sig, struct target_sigaction *ka,
                  target_sigset_t *set, CPUSPARCState *env)
 {
@@ -291,13 +297,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
     if (ka->ka_restorer) {
         env->regwptr[WREG_O7] = ka->ka_restorer;
     } else {
-        env->regwptr[WREG_O7] = sf_addr +
-                offsetof(struct target_signal_frame, insns) - 2 * 4;
-
-        /* mov __NR_sigreturn, %g1 */
-        __put_user(0x821020d8u, &sf->insns[0]);
-        /* t 0x10 */
-        __put_user(0x91d02010u, &sf->insns[1]);
+        /* Not used, but retain for ABI compatibility. */
+        install_sigtramp(sf->insns, TARGET_NR_sigreturn);
+        env->regwptr[WREG_O7] = default_sigreturn;
     }
     unlock_user(sf, sf_addr, sf_size);
 }
@@ -358,13 +360,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     if (ka->ka_restorer) {
         env->regwptr[WREG_O7] = ka->ka_restorer;
     } else {
-        env->regwptr[WREG_O7] =
-            sf_addr + offsetof(struct target_rt_signal_frame, insns) - 2 * 4;
-
-        /* mov __NR_rt_sigreturn, %g1 */
-        __put_user(0x82102065u, &sf->insns[0]);
-        /* t 0x10 */
-        __put_user(0x91d02010u, &sf->insns[1]);
+        /* Not used, but retain for ABI compatibility. */
+        install_sigtramp(sf->insns, TARGET_NR_rt_sigreturn);
+        env->regwptr[WREG_O7] = default_rt_sigreturn;
     }
 #else
     env->regwptr[WREG_O7] = ka->ka_restorer;
@@ -775,4 +773,18 @@ do_sigsegv:
     unlock_user_struct(ucp, ucp_addr, 1);
     force_sig(TARGET_SIGSEGV);
 }
+#else
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+    assert(tramp != NULL);
+
+    default_sigreturn = sigtramp_page;
+    install_sigtramp(tramp, TARGET_NR_sigreturn);
+
+    default_rt_sigreturn = sigtramp_page + 8;
+    install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn);
+
+    unlock_user(tramp, sigtramp_page, 2 * 8);
+}
 #endif
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 26/27] linux-user/xtensa: Implement setup_sigtramp
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (24 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 25/27] linux-user/sparc: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  2021-09-24 17:53   ` Philippe Mathieu-Daudé
  2021-09-24 16:59 ` [PATCH v3 27/27] linux-user: Remove default for TARGET_ARCH_HAS_SIGTRAMP_PAGE Richard Henderson
  26 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Max Filippov

Create and record the rt signal trampoline.
Use it when the guest does not use SA_RESTORER.

Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/xtensa/target_signal.h |  2 ++
 linux-user/xtensa/signal.c        | 56 ++++++++++++++++++++-----------
 2 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/linux-user/xtensa/target_signal.h b/linux-user/xtensa/target_signal.h
index c60bf656f6..1c7ee73154 100644
--- a/linux-user/xtensa/target_signal.h
+++ b/linux-user/xtensa/target_signal.h
@@ -20,4 +20,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index 7a3bfb92ca..81572a5fc7 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -128,6 +128,29 @@ static int setup_sigcontext(struct target_rt_sigframe *frame,
     return 1;
 }
 
+static void install_sigtramp(uint8_t *tramp)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    /* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
+    __put_user(0x22, &tramp[0]);
+    __put_user(0x0a, &tramp[1]);
+    __put_user(TARGET_NR_rt_sigreturn, &tramp[2]);
+    /* Generate instruction:  SYSCALL */
+    __put_user(0x00, &tramp[3]);
+    __put_user(0x05, &tramp[4]);
+    __put_user(0x00, &tramp[5]);
+#else
+    /* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
+    __put_user(0x22, &tramp[0]);
+    __put_user(0xa0, &tramp[1]);
+    __put_user(TARGET_NR_rt_sigreturn, &tramp[2]);
+    /* Generate instruction:  SYSCALL */
+    __put_user(0x00, &tramp[3]);
+    __put_user(0x50, &tramp[4]);
+    __put_user(0x00, &tramp[5]);
+#endif
+}
+
 void setup_rt_frame(int sig, struct target_sigaction *ka,
                     target_siginfo_t *info,
                     target_sigset_t *set, CPUXtensaState *env)
@@ -164,26 +187,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         ra = ka->sa_restorer;
     } else {
-        ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
-#ifdef TARGET_WORDS_BIGENDIAN
-        /* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
-        __put_user(0x22, &frame->retcode[0]);
-        __put_user(0x0a, &frame->retcode[1]);
-        __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
-        /* Generate instruction:  SYSCALL */
-        __put_user(0x00, &frame->retcode[3]);
-        __put_user(0x05, &frame->retcode[4]);
-        __put_user(0x00, &frame->retcode[5]);
-#else
-        /* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
-        __put_user(0x22, &frame->retcode[0]);
-        __put_user(0xa0, &frame->retcode[1]);
-        __put_user(TARGET_NR_rt_sigreturn, &frame->retcode[2]);
-        /* Generate instruction:  SYSCALL */
-        __put_user(0x00, &frame->retcode[3]);
-        __put_user(0x50, &frame->retcode[4]);
-        __put_user(0x00, &frame->retcode[5]);
-#endif
+        /* Not used, but retain for ABI compatibility. */
+        install_sigtramp(frame->retcode);
+        ra = default_rt_sigreturn;
     }
     memset(env->regs, 0, sizeof(env->regs));
     env->pc = ka->_sa_handler;
@@ -264,3 +270,13 @@ badframe:
     force_sig(TARGET_SIGSEGV);
     return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+    uint8_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6, 0);
+    assert(tramp != NULL);
+
+    default_rt_sigreturn = sigtramp_page;
+    install_sigtramp(tramp);
+    unlock_user(tramp, sigtramp_page, 6);
+}
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH v3 27/27] linux-user: Remove default for TARGET_ARCH_HAS_SIGTRAMP_PAGE
  2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
                   ` (25 preceding siblings ...)
  2021-09-24 16:59 ` [PATCH v3 26/27] linux-user/xtensa: " Richard Henderson
@ 2021-09-24 16:59 ` Richard Henderson
  26 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-24 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, laurent, Philippe Mathieu-Daudé

All targets now define TARGET_ARCH_HAS_SIGTRAMP_PAGE.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7b3a91b3ed..f6a4f8f489 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -30,10 +30,6 @@
 #undef ELF_ARCH
 #endif
 
-#ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE
-#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
-#endif
-
 #define ELF_OSABI   ELFOSABI_SYSV
 
 /* from personality.h */
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 26/27] linux-user/xtensa: Implement setup_sigtramp
  2021-09-24 16:59 ` [PATCH v3 26/27] linux-user/xtensa: " Richard Henderson
@ 2021-09-24 17:53   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-09-24 17:53 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, laurent, Max Filippov

On 9/24/21 18:59, Richard Henderson wrote:
> Create and record the rt signal trampoline.
> Use it when the guest does not use SA_RESTORER.
> 
> Reviewed-by: Max Filippov <jcmvbkbc@gmail.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/xtensa/target_signal.h |  2 ++
>   linux-user/xtensa/signal.c        | 56 ++++++++++++++++++++-----------
>   2 files changed, 38 insertions(+), 20 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline
  2021-09-24 16:59 ` [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline Richard Henderson
@ 2021-09-24 17:55   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-09-24 17:55 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, laurent

On 9/24/21 18:59, Richard Henderson wrote:
> The sigret parameter is never 0, and even if it was the encoding
> of the LI instruction would still work.
> 
> Reported-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/ppc/signal.c | 6 ++----
>   1 file changed, 2 insertions(+), 4 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp
  2021-09-24 16:59 ` [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp Richard Henderson
@ 2021-09-24 18:01   ` Philippe Mathieu-Daudé
  2021-09-28  1:42     ` Richard Henderson
  0 siblings, 1 reply; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-09-24 18:01 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: peter.maydell, laurent

On 9/24/21 18:59, Richard Henderson wrote:
> Create and record the two signal trampolines.
> Use them when the guest does not use SA_RESTORER.
> Note that x86_64 does not use this code.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/i386/target_signal.h   |  2 ++
>   linux-user/x86_64/target_signal.h |  3 ++
>   linux-user/i386/signal.c          | 56 +++++++++++++++++++++----------
>   3 files changed, 43 insertions(+), 18 deletions(-)
> 
> diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h
> index 50361af874..64d09f2e75 100644
> --- a/linux-user/i386/target_signal.h
> +++ b/linux-user/i386/target_signal.h
> @@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
>   #include "../generic/signal.h"
>   
>   #define TARGET_ARCH_HAS_SETUP_FRAME
> +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
> +
>   #endif /* I386_TARGET_SIGNAL_H */
> diff --git a/linux-user/x86_64/target_signal.h b/linux-user/x86_64/target_signal.h
> index 4ea74f20dd..4673c5a886 100644
> --- a/linux-user/x86_64/target_signal.h
> +++ b/linux-user/x86_64/target_signal.h
> @@ -21,4 +21,7 @@ typedef struct target_sigaltstack {
>   
>   #include "../generic/signal.h"
>   
> +/* For x86_64, use of SA_RESTORER is mandatory. */
> +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
> +
>   #endif /* X86_64_TARGET_SIGNAL_H */
> diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
> index 3b4b55fc0a..94ab6396a0 100644
> --- a/linux-user/i386/signal.c
> +++ b/linux-user/i386/signal.c
> @@ -310,6 +310,22 @@ get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
>   }
>   
>   #ifndef TARGET_X86_64
> +static void install_sigtramp(void *tramp)
> +{
> +    /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
> +    __put_user(0xb858, (uint16_t *)(tramp + 0));
> +    __put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));

I know this is mostly code movement, but using uint32_t would
make it easier to read.

> +    __put_user(0x80cd, (uint16_t *)(tramp + 6));
> +}
> +
> +static void install_rt_sigtramp(void *tramp)
> +{
> +    /* This is movl $syscall,%eax ; int $0x80 */
> +    __put_user(0xb8, (char *)(tramp + 0));

Ditto uint8_t,

> +    __put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));

and uint32_t.

> +    __put_user(0x80cd, (uint16_t *)(tramp + 5));
> +}
> +
>   /* compare linux/arch/i386/kernel/signal.c:setup_frame() */
>   void setup_frame(int sig, struct target_sigaction *ka,
>                    target_sigset_t *set, CPUX86State *env)
> @@ -338,16 +354,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
>       if (ka->sa_flags & TARGET_SA_RESTORER) {
>           __put_user(ka->sa_restorer, &frame->pretcode);
>       } else {
> -        uint16_t val16;
> -        abi_ulong retcode_addr;
> -        retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
> -        __put_user(retcode_addr, &frame->pretcode);
> -        /* This is popl %eax ; movl $,%eax ; int $0x80 */
> -        val16 = 0xb858;
> -        __put_user(val16, (uint16_t *)(frame->retcode+0));
> -        __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
> -        val16 = 0x80cd;
> -        __put_user(val16, (uint16_t *)(frame->retcode+6));
> +        /* This is no longer used, but is retained for ABI compatibility. */
> +        install_sigtramp(frame->retcode);
> +        __put_user(default_sigreturn, &frame->pretcode);
>       }
>   
>       /* Set up registers for signal handler */
> @@ -416,14 +425,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
>       if (ka->sa_flags & TARGET_SA_RESTORER) {
>           __put_user(ka->sa_restorer, &frame->pretcode);
>       } else {
> -        uint16_t val16;
> -        addr = frame_addr + offsetof(struct rt_sigframe, retcode);
> -        __put_user(addr, &frame->pretcode);
> -        /* This is movl $,%eax ; int $0x80 */
> -        __put_user(0xb8, (char *)(frame->retcode+0));
> -        __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
> -        val16 = 0x80cd;
> -        __put_user(val16, (uint16_t *)(frame->retcode+5));
> +        /* This is no longer used, but is retained for ABI compatibility. */
> +        install_rt_sigtramp(frame->retcode);
> +        __put_user(default_rt_sigreturn, &frame->pretcode);
>       }
>   #else
>       /* XXX: Would be slightly better to return -EFAULT here if test fails
> @@ -592,3 +596,19 @@ badframe:
>       force_sig(TARGET_SIGSEGV);
>       return -TARGET_QEMU_ESIGRETURN;
>   }
> +
> +#ifndef TARGET_X86_64
> +void setup_sigtramp(abi_ulong sigtramp_page)
> +{
> +    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);

Shouldn't this be 8 + 7?

> +    assert(tramp != NULL);
> +
> +    default_sigreturn = sigtramp_page;
> +    install_sigtramp(tramp);
> +
> +    default_rt_sigreturn = sigtramp_page + 8;
> +    install_rt_sigtramp(tramp + 8);
> +
> +    unlock_user(tramp, sigtramp_page, 2 * 8);
> +}
> +#endif
> 



^ permalink raw reply	[flat|nested] 43+ messages in thread

* RE: [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp
  2021-09-24 16:59 ` [PATCH v3 08/27] linux-user/hexagon: " Richard Henderson
@ 2021-09-24 18:49   ` Taylor Simpson
  0 siblings, 0 replies; 43+ messages in thread
From: Taylor Simpson @ 2021-09-24 18:49 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, laurent, Philippe Mathieu-Daudé



> -----Original Message-----
> From: Richard Henderson <richard.henderson@linaro.org>
> Sent: Friday, September 24, 2021 11:59 AM
> To: qemu-devel@nongnu.org
> Cc: laurent@vivier.eu; peter.maydell@linaro.org; Taylor Simpson
> <tsimpson@quicinc.com>; Philippe Mathieu-Daudé <f4bug@amsat.org>
> Subject: [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp
> 
> Continue to initialize the words on the stack, as documented.
> However, use the off-stack trampoline.
> 
> Cc: Taylor Simpson <tsimpson@quicinc.com>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/hexagon/target_signal.h |  2 ++
>  linux-user/hexagon/signal.c        | 19 +++++++++++++++++--
>  2 files changed, 19 insertions(+), 2 deletions(-)

Reviewed-by: Taylor Simpson <tsimpson@quicinc.com>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 05/27] linux-user/arm: Implement setup_sigtramp
  2021-09-24 16:59 ` [PATCH v3 05/27] linux-user/arm: Implement setup_sigtramp Richard Henderson
@ 2021-09-27 11:06   ` Peter Maydell
  0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 11:06 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Update the trampoline code to match the kernel: this uses
> sp-relative accesses rather than pc-relative.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

These functions must write at most 8 bytes:

> +static void write_arm_sigreturn(uint32_t *rc, int syscall)
> +{
> +    __put_user(ARM_MOV_R7_IMM(syscall), rc);
> +    __put_user(ARM_SWI_SYS(syscall), rc + 1);
> +}
> +
> +static void write_thumb_sigreturn(uint32_t *rc, int syscall)
> +{
> +    __put_user(THUMB_SWI_SYS << 16 | THUMB_MOVS_R7_IMM(syscall), rc);
> +}
>
>  /*
> - * Stub needed to make sure the FD register (r9) contains the right
> - * value.
> + * Stub needed to make sure the FD register (r9) contains the right value.
> + * Use the same instruction sequence as the kernel.
>   */
> -static const unsigned long sigreturn_fdpic_codes[3] = {
> -    0xe59fc004, /* ldr r12, [pc, #4] to read function descriptor */
> -    0xe59c9004, /* ldr r9, [r12, #4] to setup GOT */
> -    0xe59cf000  /* ldr pc, [r12] to jump into restorer */
> -};

...and these must write at most 12 bytes. But nothing states
or asserts that.

> +static void write_arm_fdpic_sigreturn(uint32_t *rc, int ofs)
> +{
> +    assert(ofs <= 0xfff);
> +    __put_user(0xe59d3000 | ofs, rc + 0);   /* ldr r3, [sp, #ofs] */
> +    __put_user(0xe8930908, rc + 1);         /* ldm r3, { r3, r9 } */
> +    __put_user(0xe12fff13, rc + 2);         /* bx  r3 */
> +}
>
> -static const unsigned long sigreturn_fdpic_thumb_codes[3] = {
> -    0xc008f8df, /* ldr r12, [pc, #8] to read function descriptor */
> -    0x9004f8dc, /* ldr r9, [r12, #4] to setup GOT */
> -    0xf000f8dc  /* ldr pc, [r12] to jump into restorer */
> -};
> +static void write_thumb_fdpic_sigreturn(void *vrc, int ofs)
> +{
> +    uint16_t *rc = vrc;
> +
> +    assert((ofs & ~0x3fc) == 0);
> +    __put_user(0x9b00 | (ofs >> 2), rc + 0);      /* ldr r3, [sp, #ofs] */
> +    __put_user(0xcb0c, rc + 1);                   /* ldm r3, { r2, r3 } */
> +    __put_user(0x4699, rc + 2);                   /* mov r9, r3 */
> +    __put_user(0x4710, rc + 3);                   /* bx  r2 */
> +}
>

> -            retcode = rc_addr + thumb;
> +            /* Each trampoline variant consumes a 12-byte slot. */
> +            retcode = sigreturn_fdpic_tramp + retcode_idx * 12 + thumb;
>          } else {
>              retcode = ka->sa_restorer;
>          }
>      } else {

> -
> -        retcode = rc_addr + thumb;
> +        /* Each trampoline variant consumes 8-byte slot. */
> +        retcode = default_sigreturn + retcode_idx * 8 + thumb;

These 12 and 8 magic numbers correspond to the maximum sequence sizes
above...

> +void setup_sigtramp(abi_ulong sigtramp_page)
> +{
> +    enum {
> +        SIGFRAME_FDPIC_OFS = offsetof(struct sigframe, retcode[3]),
> +        RT_SIGFRAME_FDPIC_OFS = offsetof(struct rt_sigframe, retcode[3]),
> +    };
> +
> +    uint32_t total_size = 4 * 8 + 4 * 12;
> +    uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, total_size, 0);
> +    uint32_t i = 0;
> +
> +    assert(tramp != NULL);
> +
> +    default_sigreturn = sigtramp_page;
> +    write_arm_sigreturn(&tramp[i], TARGET_NR_sigreturn);
> +    i += 2;
> +    write_thumb_sigreturn(&tramp[i], TARGET_NR_sigreturn);
> +    i += 2;
> +    write_arm_sigreturn(&tramp[i], TARGET_NR_rt_sigreturn);
> +    i += 2;
> +    write_thumb_sigreturn(&tramp[i], TARGET_NR_rt_sigreturn);
> +    i += 2;

...and these "+=2" and the "+=3" later do as well, but with
a count of 32-bit words rather than bytes. I think it would be
useful to at least have some defined constants for the lengths
rather than hard-coded 8,12,2,3, and comments that the write_
functions must not write more than however-many bytes.

> +
> +    /*
> +     * FDPIC require trampolines to call sa_restorer, and different
> +     * from the pc-relative versions we write to the stack.
> +     *
> +     * ARM versions use:
> +     *    ldr   r3, [sp, #ofs]
> +     *    ldr   r9, [r3, #4]
> +     *    ldr   pc, [r3, #0]

This comment doesn't match the code that write_arm_fdpic_sigreturn()
now generates. The "different from the pc-relative versions we
write from the stack" bit doesn't seem to be right either, given
we call the same functions in both places to write the code.

> +     *
> +     * Thumb versions use:
> +     *    ldr   r3, [sp, #ofs]
> +     *    ldmia r3, {r2, r3}
> +     *    mov   r9, r3
> +     *    bx    r2
> +     */
> +    sigreturn_fdpic_tramp = sigtramp_page + i * 4;
> +
> +    /* ARM sigframe */
> +    write_arm_fdpic_sigreturn(tramp + i,
> +                              offsetof(struct sigframe, retcode[3]));
> +    i += 3;
> +
> +    /* Thumb sigframe */
> +    write_thumb_fdpic_sigreturn(tramp + i,
> +                                offsetof(struct sigframe, retcode[3]));
> +    i += 3;
> +
> +    /* ARM rt_sigframe */
> +    write_arm_fdpic_sigreturn(tramp + i,
> +                              offsetof(struct rt_sigframe, retcode[3]));
> +    i += 3;
> +
> +    /* Thumb rt_sigframe */
> +    write_thumb_fdpic_sigreturn(tramp + i,
> +                                offsetof(struct rt_sigframe, retcode[3]));
> +    i += 3;
> +
> +    assert(i * 4 == total_size);
> +    unlock_user(tramp, sigtramp_page, total_size);
> +}
> --
> 2.25.1

thanks
-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 11/27] linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set
  2021-09-24 16:59 ` [PATCH v3 11/27] linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set Richard Henderson
@ 2021-09-27 13:01   ` Peter Maydell
  0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 13:01 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This has been a fixme for some time.  The effect of
> returning -EFAULT from the kernel code is to raise SIGSEGV.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP
  2021-09-24 16:59 ` [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
@ 2021-09-27 13:23   ` Peter Maydell
  2021-09-27 14:30     ` Richard Henderson
  0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 13:23 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The real kernel has to load the instruction and extract
> the imm5 field; for qemu, modify the translator to do this.
>
> The use of R_AT for this in cpu_loop was a bug.  Handle
> the other trap numbers as per the kernel's trap_table.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/nios2/cpu.h          |  5 +++--
>  linux-user/nios2/cpu_loop.c | 35 ++++++++++++++++++-----------------
>  target/nios2/translate.c    | 17 ++++++++++++++++-
>  3 files changed, 37 insertions(+), 20 deletions(-)
>
> diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
> index 2ab82fdc71..395e4d3281 100644
> --- a/target/nios2/cpu.h
> +++ b/target/nios2/cpu.h
> @@ -158,9 +158,10 @@ struct Nios2CPUClass {
>  struct CPUNios2State {
>      uint32_t regs[NUM_CORE_REGS];
>
> -#if !defined(CONFIG_USER_ONLY)
> +#ifdef CONFIG_USER_ONLY
> +    int trap_code;
> +#else
>      Nios2MMU mmu;
> -
>      uint32_t irq_pending;
>  #endif
>  };

Loading the insn and fishing out the imm5 field is about 2
lines of code, isn't it ? It's how we handle similar cases
for other targets. I think I prefer that over putting
linux-user specific fields and handling into the target/nios2
code.

> diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
> index 34290fb3b5..246293a501 100644
> --- a/linux-user/nios2/cpu_loop.c
> +++ b/linux-user/nios2/cpu_loop.c
> @@ -39,9 +39,10 @@ void cpu_loop(CPUNios2State *env)
>          case EXCP_INTERRUPT:
>              /* just indicate that signals should be handled asap */
>              break;
> +
>          case EXCP_TRAP:
> -            if (env->regs[R_AT] == 0) {
> -                abi_long ret;
> +            switch (env->trap_code) {
> +            case 0:
>                  qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
>
>                  ret = do_syscall(env, env->regs[2],
> @@ -55,26 +56,26 @@ void cpu_loop(CPUNios2State *env)
>
>                  env->regs[2] = abs(ret);
>                  /* Return value is 0..4096 */
> -                env->regs[7] = (ret > 0xfffffffffffff000ULL);
> -                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
> -                env->regs[CR_STATUS] &= ~0x3;
> -                env->regs[R_EA] = env->regs[R_PC] + 4;
> +                env->regs[7] = ret > 0xfffff000u;
>                  env->regs[R_PC] += 4;
>                  break;
> -            } else {
> -                qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
>
> -                env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
> -                env->regs[CR_STATUS] &= ~0x3;
> -                env->regs[R_EA] = env->regs[R_PC] + 4;
> -                env->regs[R_PC] = cpu->exception_addr;
> -
> -                info.si_signo = TARGET_SIGTRAP;
> -                info.si_errno = 0;
> -                info.si_code = TARGET_TRAP_BRKPT;
> -                queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
> +            case 1:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
> +                force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
> +                break;
> +            case 2:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
> +                force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_PC]);
> +                break;
> +            default:
> +                qemu_log_mask(CPU_LOG_INT, "\nTrap %d\n", env->trap_code);
> +                force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
> +                                env->regs[R_PC]);
>                  break;
>              }

The kernel also defines:
 * trap 31 ("breakpoint"), which should wind PC back by 4 and
   send a SIGTRAP/TRAP_BRKPT
 * trap 30 ("KGDB breakpoint"), which we should treat the same
   as the "default" case since we should be acting like "kernel
   with CONFIG_KGDB not defined"

Side note: the kernel code for the "CONFIG_KGDB not defined" case
of trap 30 seems buggy to me. It points the trap at 'instruction_trap',
but that is the "emulate multiply and divide insns" entry point, and
that emulation code assumes that it really is getting a mul or div,
not a trap, so I think it will do something bogus. This seems to
be an error introduced in kernel commit  baa54ab93c2e1, which refactored
trap handling and changed the reserved-trap-number handling from
"instruction_trap" to "handle_trap_reserved" but forgot this one entry.

> +            break;
> +
>          case EXCP_DEBUG:
>              info.si_signo = TARGET_SIGTRAP;
>              info.si_errno = 0;

thanks
-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 17/27] linux-user/nios2: Map a real kuser page
  2021-09-24 16:59 ` [PATCH v3 17/27] linux-user/nios2: Map a real kuser page Richard Henderson
@ 2021-09-27 13:26   ` Peter Maydell
  2021-09-27 13:59     ` Richard Henderson
  0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 13:26 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The first word of page1 is data, so the whole thing
> can't be implemented with emulation of addresses.
>
> Hijack trap number 31 to implement cmpxchg.

31 is used -- it's "breakpoint". We need to pick something else...

>
> Set default_rt_sigreturn based on the kuser page.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/nios2/target_signal.h |  3 ++
>  linux-user/elfload.c             | 35 ++++++++++++++++++++++
>  linux-user/nios2/cpu_loop.c      | 51 +++++++++++++++++---------------
>  linux-user/nios2/signal.c        |  2 +-
>  target/nios2/translate.c         |  9 ------
>  5 files changed, 66 insertions(+), 34 deletions(-)
>
> diff --git a/linux-user/nios2/target_signal.h b/linux-user/nios2/target_signal.h
> index aebf749f12..fe266c4c51 100644
> --- a/linux-user/nios2/target_signal.h
> +++ b/linux-user/nios2/target_signal.h
> @@ -19,4 +19,7 @@ typedef struct target_sigaltstack {
>
>  #include "../generic/signal.h"
>
> +/* Nios2 uses a fixed address on the kuser page for sigreturn. */
> +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
> +
>  #endif /* NIOS2_TARGET_SIGNAL_H */
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 459a26ef1d..7b3a91b3ed 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1100,6 +1100,41 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env
>
>  static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
>  {
> +    static const uint8_t kuser_page[4 + 2 * 64] = {
> +        /* __kuser_helper_version */
> +        [0x00] = 0x02, 0x00, 0x00, 0x00,
> +
> +        /* __kuser_cmpxchg */
> +        [0x04] = 0xfa, 0x6f, 0x3b, 0x00,  /* trap 31 */
> +                 0x3a, 0x28, 0x00, 0xf8,  /* ret */
> +
> +        /* __kuser_sigtramp */
> +        [0x44] = 0xc4, 0x22, 0x80, 0x00,  /* movi r2, __NR_rt_sigreturn */
> +                 0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
> +    };
> +
> +    abi_ulong pg;
> +    uint8_t *ph;
> +
> +    pg = target_mmap(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE,
> +                     PROT_READ | PROT_WRITE,
> +                     MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
> +
> +    /*
> +     * If the mmap doesn't give us exactly page 1, there's nothing
> +     * we can do, and it's unlikely that the program will be able
> +     * to continue.  FIXME: Error out now?
> +     */
> +    assert(pg == TARGET_PAGE_SIZE);

Shouldn't we be doing this via the probe_guest_base machinery
the way we do for the Arm commpage ?

> +
> +    ph = lock_user(VERIFY_WRITE, pg, sizeof(kuser_page), 0);
> +    memcpy(ph, kuser_page, sizeof(kuser_page));
> +    unlock_user(ph, pg, sizeof(kuser_page));
> +    target_mprotect(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
> +
> +    /* Install __kuser_sigtramp */
> +    default_rt_sigreturn = TARGET_PAGE_SIZE + 0x44;
> +
>      regs->ea = infop->entry;
>      regs->sp = infop->start_stack;
>      regs->estatus = 0x3;

-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 18/27] linux-user/nios2: Fixes for signal frame setup
  2021-09-24 16:59 ` [PATCH v3 18/27] linux-user/nios2: Fixes for signal frame setup Richard Henderson
@ 2021-09-27 13:28   ` Peter Maydell
  0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 13:28 UTC (permalink / raw)
  To: Richard Henderson; +Cc: QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Do not confuse host and guest addresses.  Lock and unlock
> the target_rt_sigframe structure in setup_rt_sigframe.
>
> Since rt_setup_ucontext always returns 0, drop the return
> value entirely.  This eliminates the only write to the err
> variable in setup_rt_sigframe.
>
> Always copy the siginfo structure.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 25/27] linux-user/sparc: Implement setup_sigtramp
  2021-09-24 16:59 ` [PATCH v3 25/27] linux-user/sparc: " Richard Henderson
@ 2021-09-27 13:30   ` Peter Maydell
  0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 13:30 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Mark Cave-Ayland, QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Create and record the two signal trampolines.
> Use them when the guest does not use SA_RESTORER.
>
> Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp
  2021-09-24 16:59 ` [PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp Richard Henderson
@ 2021-09-27 13:34   ` Peter Maydell
  0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2021-09-27 13:34 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-ppc, QEMU Developers, Laurent Vivier

On Fri, 24 Sept 2021 at 17:59, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Create and record the two signal trampolines.
>
> Cc: qemu-ppc@nongnu.org
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/ppc/target_signal.h |  2 ++
>  linux-user/ppc/signal.c        | 34 ++++++++++++++++++----------------
>  2 files changed, 20 insertions(+), 16 deletions(-)


Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 17/27] linux-user/nios2: Map a real kuser page
  2021-09-27 13:26   ` Peter Maydell
@ 2021-09-27 13:59     ` Richard Henderson
  0 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-27 13:59 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Laurent Vivier

On 9/27/21 9:26 AM, Peter Maydell wrote:
>> +    /*
>> +     * If the mmap doesn't give us exactly page 1, there's nothing
>> +     * we can do, and it's unlikely that the program will be able
>> +     * to continue.  FIXME: Error out now?
>> +     */
>> +    assert(pg == TARGET_PAGE_SIZE);
> 
> Shouldn't we be doing this via the probe_guest_base machinery
> the way we do for the Arm commpage ?

Well, maybe.  Though the Arm commpage continues to not work.

https://gitlab.com/qemu-project/qemu/-/issues/633
https://gitlab.com/qemu-project/qemu/-/issues/447

But you're right, this could just as easily error out on a 32-bit host.


r~


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP
  2021-09-27 13:23   ` Peter Maydell
@ 2021-09-27 14:30     ` Richard Henderson
  0 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2021-09-27 14:30 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers, Laurent Vivier

On 9/27/21 9:23 AM, Peter Maydell wrote:
> Loading the insn and fishing out the imm5 field is about 2
> lines of code, isn't it?
> It's how we handle similar cases for other targets.

And we actively get it wrong, e.g. mips.
So I have patches to move that code *out* of linux-user.

We have macros in target/nios2/ to do the field decode, and not in linux-user/.

> I think I prefer that over putting
> linux-user specific fields and handling into the target/nios2
> code.

Would you prefer a generic-y named field like error_code, which we include in other targets?

> The kernel also defines:
>   * trap 31 ("breakpoint"), which should wind PC back by 4 and
>     send a SIGTRAP/TRAP_BRKPT
>   * trap 30 ("KGDB breakpoint"), which we should treat the same
>     as the "default" case since we should be acting like "kernel
>     with CONFIG_KGDB not defined"

Dang it, how did I miss those?


r~


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp
  2021-09-24 18:01   ` Philippe Mathieu-Daudé
@ 2021-09-28  1:42     ` Richard Henderson
  2021-09-28  6:50       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2021-09-28  1:42 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: peter.maydell, laurent

On 9/24/21 2:01 PM, Philippe Mathieu-Daudé wrote:
>> +static void install_sigtramp(void *tramp)
>> +{
>> +    /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
>> +    __put_user(0xb858, (uint16_t *)(tramp + 0));
>> +    __put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));
> 
> I know this is mostly code movement, but using uint32_t would
> make it easier to read.

I'll give you int32_t here, since the value is signed.

>> +    __put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));
> 
> and uint32_t.

Likewise.

>> +    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
> 
> Shouldn't this be 8 + 7?

Does it really matter if we write 15 or 16 bytes of this page?


r~


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp
  2021-09-28  1:42     ` Richard Henderson
@ 2021-09-28  6:50       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-09-28  6:50 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers, Laurent Vivier

On Tue, Sep 28, 2021 at 3:42 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
> On 9/24/21 2:01 PM, Philippe Mathieu-Daudé wrote:
> >> +static void install_sigtramp(void *tramp)
> >> +{
> >> +    /* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
> >> +    __put_user(0xb858, (uint16_t *)(tramp + 0));
> >> +    __put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));
> >
> > I know this is mostly code movement, but using uint32_t would
> > make it easier to read.
>
> I'll give you int32_t here, since the value is signed.

Better, thanks.

>
> >> +    __put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));
> >
> > and uint32_t.
>
> Likewise.
>
> >> +    uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
> >
> > Shouldn't this be 8 + 7?
>
> Does it really matter if we write 15 or 16 bytes of this page?

Certainly not :)


^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2021-09-28  6:52 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-24 16:58 [PATCH v3 00/27] linux-user: Move signal trampolines to new page Richard Henderson
2021-09-24 16:59 ` [PATCH v3 01/27] linux-user: Add infrastructure for a signal trampoline page Richard Henderson
2021-09-24 16:59 ` [PATCH v3 02/27] linux-user/aarch64: Implement setup_sigtramp Richard Henderson
2021-09-24 16:59 ` [PATCH v3 03/27] linux-user/arm: Drop v1 signal frames Richard Henderson
2021-09-24 16:59 ` [PATCH v3 04/27] linux-user/arm: Drop "_v2" from symbols in signal.c Richard Henderson
2021-09-24 16:59 ` [PATCH v3 05/27] linux-user/arm: Implement setup_sigtramp Richard Henderson
2021-09-27 11:06   ` Peter Maydell
2021-09-24 16:59 ` [PATCH v3 06/27] linux-user/alpha: " Richard Henderson
2021-09-24 16:59 ` [PATCH v3 07/27] linux-user/cris: " Richard Henderson
2021-09-24 16:59 ` [PATCH v3 08/27] linux-user/hexagon: " Richard Henderson
2021-09-24 18:49   ` Taylor Simpson
2021-09-24 16:59 ` [PATCH v3 09/27] linux-user/hppa: Document non-use of setup_sigtramp Richard Henderson
2021-09-24 16:59 ` [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp Richard Henderson
2021-09-24 18:01   ` Philippe Mathieu-Daudé
2021-09-28  1:42     ` Richard Henderson
2021-09-28  6:50       ` Philippe Mathieu-Daudé
2021-09-24 16:59 ` [PATCH v3 11/27] linux-user/x86_64: Raise SIGSEGV if SA_RESTORER not set Richard Henderson
2021-09-27 13:01   ` Peter Maydell
2021-09-24 16:59 ` [PATCH v3 12/27] linux-user/m68k: Implement setup_sigtramp Richard Henderson
2021-09-24 16:59 ` [PATCH v3 13/27] linux-user/microblaze: " Richard Henderson
2021-09-24 16:59 ` [PATCH v3 14/27] linux-user/mips: Tidy install_sigtramp Richard Henderson
2021-09-24 16:59 ` [PATCH v3 15/27] linux-user/mips: Implement setup_sigtramp Richard Henderson
2021-09-24 16:59 ` [PATCH v3 16/27] linux-user/nios2: Properly emulate EXCP_TRAP Richard Henderson
2021-09-27 13:23   ` Peter Maydell
2021-09-27 14:30     ` Richard Henderson
2021-09-24 16:59 ` [PATCH v3 17/27] linux-user/nios2: Map a real kuser page Richard Henderson
2021-09-27 13:26   ` Peter Maydell
2021-09-27 13:59     ` Richard Henderson
2021-09-24 16:59 ` [PATCH v3 18/27] linux-user/nios2: Fixes for signal frame setup Richard Henderson
2021-09-27 13:28   ` Peter Maydell
2021-09-24 16:59 ` [PATCH v3 19/27] linux-user/openrisc: Implement setup_sigtramp Richard Henderson
2021-09-24 16:59 ` [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline Richard Henderson
2021-09-24 17:55   ` Philippe Mathieu-Daudé
2021-09-24 16:59 ` [PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp Richard Henderson
2021-09-27 13:34   ` Peter Maydell
2021-09-24 16:59 ` [PATCH v3 22/27] linux-user/riscv: " Richard Henderson
2021-09-24 16:59 ` [PATCH v3 23/27] linux-user/s390x: " Richard Henderson
2021-09-24 16:59 ` [PATCH v3 24/27] linux-user/sh4: " Richard Henderson
2021-09-24 16:59 ` [PATCH v3 25/27] linux-user/sparc: " Richard Henderson
2021-09-27 13:30   ` Peter Maydell
2021-09-24 16:59 ` [PATCH v3 26/27] linux-user/xtensa: " Richard Henderson
2021-09-24 17:53   ` Philippe Mathieu-Daudé
2021-09-24 16:59 ` [PATCH v3 27/27] linux-user: Remove default for TARGET_ARCH_HAS_SIGTRAMP_PAGE Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.