aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-09-29 09:05:47 -0400
committerLaurent Vivier <laurent@vivier.eu>2021-10-01 12:03:48 +0200
commit3c62b5d2015b8292d4453f8174abf5fadbc6cc0f (patch)
treebd484c82528a07167180dfc3d0e13ad2cc67be50
parentc790e4ebfed8174f65d685f5a4f3262873c237a5 (diff)
downloadqemu-3c62b5d2015b8292d4453f8174abf5fadbc6cc0f.zip
qemu-3c62b5d2015b8292d4453f8174abf5fadbc6cc0f.tar.gz
qemu-3c62b5d2015b8292d4453f8174abf5fadbc6cc0f.tar.bz2
linux-user/riscv: Implement setup_sigtramp
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> Message-Id: <20210929130553.121567-21-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
-rw-r--r--linux-user/riscv/signal.c22
-rw-r--r--linux-user/riscv/target_signal.h2
2 files changed, 15 insertions, 9 deletions
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index f7f33bc..a0f9542 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);
+}
diff --git a/linux-user/riscv/target_signal.h b/linux-user/riscv/target_signal.h
index f113ba9..3e36fdd 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 */