* [PATCH RFC 0/1] linux-user/s390x: save/restore condition code state during signal handling
@ 2021-06-10 18:58 Jonathan Albrecht
2021-06-10 18:58 ` [PATCH RFC 1/1] " Jonathan Albrecht
0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Albrecht @ 2021-06-10 18:58 UTC (permalink / raw)
To: qemu-devel
Cc: ruixin.bao, qemu-s390x, Jonathan Albrecht, Laurent Vivier,
jonathan.albrecht
Peter Bao <ruixin.bao@ibm.com> and I have been looking at some issues with
qemu user mode x86_64 host/s390x guest when running go1.14+ executables.
From the qemu cpu traces, it looks like the condition code is not restored
after a signal handler is run. This affects go1.14+ because it uses signals
heavily to implement the async preempt feature in the goroutine scheduler
that was added in go1.14.
This patch tries save and restore the condition code related fields when
handling a signal. We're submitting it as an RFC since we're new to qemu and
not sure if this is s390x specific. We have some C code (s390x specific)
that reproduces the issue and can try to add it as a unit test.
Jonathan Albrecht (1):
linux-user/s390x: save/restore condition code state during signal
handling
linux-user/s390x/signal.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
--
2.31.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH RFC 1/1] linux-user/s390x: save/restore condition code state during signal handling
2021-06-10 18:58 [PATCH RFC 0/1] linux-user/s390x: save/restore condition code state during signal handling Jonathan Albrecht
@ 2021-06-10 18:58 ` Jonathan Albrecht
2021-06-11 15:18 ` Richard Henderson
0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Albrecht @ 2021-06-10 18:58 UTC (permalink / raw)
To: qemu-devel
Cc: ruixin.bao, qemu-s390x, Jonathan Albrecht, Laurent Vivier,
jonathan.albrecht
When handling a signal, the signal handler may have clobbered the
condition code set by the interrupted thread.
Signed-off-by: Jonathan Albrecht <jonathan.albrecht@linux.vnet.ibm.com>
Buglink: https://bugs.launchpad.net/qemu/+bug/1886793
Buglink: https://bugs.launchpad.net/qemu/+bug/1893040
---
linux-user/s390x/signal.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index ef136dae33..03cacb2829 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -65,6 +65,10 @@ typedef struct {
uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
target_sigcontext sc;
target_sigregs sregs;
+ uint32_t scc_op;
+ uint64_t scc_src;
+ uint64_t scc_dst;
+ uint64_t scc_vr;
int signo;
target_sigregs_ext sregs_ext;
uint16_t retcode;
@@ -86,6 +90,10 @@ typedef struct {
uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
uint16_t retcode;
struct target_siginfo info;
+ uint32_t scc_op;
+ uint64_t scc_src;
+ uint64_t scc_dst;
+ uint64_t scc_vr;
struct target_ucontext uc;
} rt_sigframe;
@@ -224,6 +232,12 @@ void setup_frame(int sig, struct target_sigaction *ka,
env->regs[5] = 0; /* FIXME: regs->int_parm_long */
env->regs[6] = 0; /* FIXME: current->thread.last_break */
+ /* Some programs could clobber the condition code, so save it here */
+ __put_user(env->cc_op, &frame->scc_op);
+ __put_user(env->cc_src, &frame->scc_src);
+ __put_user(env->cc_dst, &frame->scc_dst);
+ __put_user(env->cc_vr, &frame->scc_vr);
+
unlock_user_struct(frame, frame_addr, 1);
}
@@ -273,6 +287,12 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
save_sigregs_ext(env, &frame->uc.tuc_mcontext_ext);
tswap_sigset(&frame->uc.tuc_sigmask, set);
+ /* Some programs could clobber the condition code, so save it here */
+ __put_user(env->cc_op, &frame->scc_op);
+ __put_user(env->cc_src, &frame->scc_src);
+ __put_user(env->cc_dst, &frame->scc_dst);
+ __put_user(env->cc_vr, &frame->scc_vr);
+
/* Set up registers for signal handler */
env->regs[14] = restorer;
env->regs[15] = frame_addr;
@@ -285,6 +305,10 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
env->regs[3] = frame_addr + offsetof(typeof(*frame), info);
env->regs[4] = frame_addr + offsetof(typeof(*frame), uc);
env->regs[5] = 0; /* FIXME: current->thread.last_break */
+
+ /* QUESTION: Was there a missing unlock user struct here? */
+ unlock_user_struct(frame, frame_addr, 1);
+ return;
}
static void restore_sigregs(CPUS390XState *env, target_sigregs *sc)
@@ -350,6 +374,12 @@ long do_sigreturn(CPUS390XState *env)
restore_sigregs(env, &frame->sregs);
restore_sigregs_ext(env, &frame->sregs_ext);
+ /* restore the condition code */
+ __get_user(env->cc_op, &frame->scc_op);
+ __get_user(env->cc_src, &frame->scc_src);
+ __get_user(env->cc_dst, &frame->scc_dst);
+ __get_user(env->cc_vr, &frame->scc_vr);
+
unlock_user_struct(frame, frame_addr, 0);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -372,6 +402,11 @@ long do_rt_sigreturn(CPUS390XState *env)
restore_sigregs(env, &frame->uc.tuc_mcontext);
restore_sigregs_ext(env, &frame->uc.tuc_mcontext_ext);
+ /* restore the condition code */
+ __get_user(env->cc_op, &frame->scc_op);
+ __get_user(env->cc_src, &frame->scc_src);
+ __get_user(env->cc_dst, &frame->scc_dst);
+ __get_user(env->cc_vr, &frame->scc_vr);
target_restore_altstack(&frame->uc.tuc_stack, env);
unlock_user_struct(frame, frame_addr, 0);
--
2.31.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH RFC 1/1] linux-user/s390x: save/restore condition code state during signal handling
2021-06-10 18:58 ` [PATCH RFC 1/1] " Jonathan Albrecht
@ 2021-06-11 15:18 ` Richard Henderson
0 siblings, 0 replies; 3+ messages in thread
From: Richard Henderson @ 2021-06-11 15:18 UTC (permalink / raw)
To: Jonathan Albrecht, qemu-devel
Cc: ruixin.bao, qemu-s390x, Laurent Vivier, jonathan.albrecht
On 6/10/21 11:58 AM, Jonathan Albrecht wrote:
> @@ -65,6 +65,10 @@ typedef struct {
> uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
> target_sigcontext sc;
> target_sigregs sregs;
> + uint32_t scc_op;
> + uint64_t scc_src;
> + uint64_t scc_dst;
> + uint64_t scc_vr;
> int signo;
Nope. The layout of the stack frame is fixed by the kernel. Moreover, all of
these variables are internal to qemu; you should only be exposing architectural
state.
The bug is in save_sigregs:
> __put_user(env->psw.mask, &sregs->regs.psw.mask);
This should use get_psw_mask(), currently declared in target/s390x/internal.h
instead of cpu.h.
and correspondingly, in restore_sigregs:
> __get_user(env->psw.mask, &sc->regs.psw.mask);
> __get_user(env->psw.addr, &sc->regs.psw.addr);
this should use load_psw, and in addition it should not be allowing completely
arbitrary changes to psw.mask. From the kernel:
> /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
> regs->psw.mask = (regs->psw.mask & ~(PSW_MASK_USER | PSW_MASK_RI)) |
> (user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
> /* Check for invalid user address space control. */
> if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
> regs->psw.mask = PSW_ASC_PRIMARY |
> (regs->psw.mask & ~PSW_MASK_ASC);
> /* Check for invalid amode */
> if (regs->psw.mask & PSW_MASK_EA)
> regs->psw.mask |= PSW_MASK_BA;
r~
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-06-11 15:19 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-10 18:58 [PATCH RFC 0/1] linux-user/s390x: save/restore condition code state during signal handling Jonathan Albrecht
2021-06-10 18:58 ` [PATCH RFC 1/1] " Jonathan Albrecht
2021-06-11 15:18 ` 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.