On Mon, May 25, 2026 at 11:26 AM Matt Turner <[email protected]> wrote:
>
> QEMU keeps the SH4 T, M and Q status-register bits outside env->sr, in
> the dedicated env->sr_t, env->sr_m and env->sr_q fields; cpu_read_sr()
> folds them back into the architectural SR value and cpu_write_sr()
> splits them back out.
>
> setup_sigcontext() saved the bare env->sr (so the T/M/Q bits were always
> zero in the signal frame) and restore_sigcontext() wrote the value
> straight back into env->sr without updating sr_t/sr_m/sr_q. As a result
> the T bit was never preserved across signal delivery: on sigreturn the
> interrupted code resumed with whatever T value the signal handler last
> left behind. Any conditional branch (or addc/subc/rotcl/div1, etc.)
> immediately following the interrupted instruction could then take the
> wrong path.
>
> This is the cause of the long-standing intermittent failures of the
> tests/tcg/multiarch/signals.c test on sh4, which was marked BROKEN. With
> a SIGRTMIN timer firing every millisecond across many threads, the race
> was hit a few percent of the time and corrupted the guest heap, surfacing
> as a SIGSEGV in memset, a malloc assertion, or an rseq registration abort.
>
> Traced on a deterministic rr recording: a cmp/hi set T=0, the timer
> signal interrupted the very next instruction (a bf), the handler left
> T=1, and the resumed bf took glibc calloc's MORECORE_CLEARS branch,
> using the old top-chunk size as the clear length for a freshly split
> small chunk and running memset off the end of the heap.
>
> Fix setup_sigcontext()/restore_sigcontext() to use cpu_read_sr() and
> cpu_write_sr() so the T, M and Q bits round-trip correctly, and drop the
> BROKEN annotation on the sh4 signals test.
>
> Fixes: c3b5bc8ab3 ("SH4: Signal handling for the user space emulator, by 
> Magnus Damm.")
> Cc: [email protected]
> ---

Signed-off-by: Matt Turner <[email protected]>

Reply via email to