linux-user/sparc: Implement setup_sigtramp

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

Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
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>
Message-Id: <20210929130553.121567-24-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
master
Richard Henderson 2021-09-29 09:05:50 -04:00 committed by Laurent Vivier
parent b9188f9ccc
commit 3f7685eaf9
2 changed files with 30 additions and 14 deletions

View File

@ -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

View File

@ -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 */