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