Message ID | 20210928020039.184412-24-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | linux-user: Move signal trampolines to new page | expand |
On 9/28/21 04:00, Richard Henderson 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> > Reviewed-by: Peter Maydell <peter.maydell@linaro.org> > 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(-) Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
On 28/09/2021 03:00, Richard Henderson 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> > Reviewed-by: Peter Maydell <peter.maydell@linaro.org> > 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 This is certainly outside of my knowledge domain, however if it works in your tests then happy to give: Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> ATB, Mark.
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