Currently when a compare-and-trap instruction is executed, qemu will always raise a SIGILL signal. On real hardware, a SIGFPE is raised.
Change the PGM_DATA case in cpu_loop to follow the behavior in linux kernel /arch/s390/kernel/traps.c. * Only raise SIGILL if DXC == 0 * If DXC matches an IEEE exception, raise SIGFPE with correct si_code * Raise SIGFPE with si_code == 0 for everything else When applied on 20210705210434.45824-2-...@linux.ibm.com, this fixes crashes in the java jdk such as the linked bug. Buglink: https://bugs.launchpad.net/qemu/+bug/1920913 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/319 Signed-off-by: Jonathan Albrecht <jonathan.albre...@linux.vnet.ibm.com> --- linux-user/s390x/cpu_loop.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c index 22f2e89c62..6e7dfb290a 100644 --- a/linux-user/s390x/cpu_loop.c +++ b/linux-user/s390x/cpu_loop.c @@ -106,11 +106,13 @@ void cpu_loop(CPUS390XState *env) case PGM_DATA: n = (env->fpc >> 8) & 0xff; - if (n == 0xff) { - /* compare-and-trap */ + if (n == 0) { goto do_sigill_opn; - } else { - /* An IEEE exception, simulated or otherwise. */ + } + + sig = TARGET_SIGFPE; + if ((n & 0x03) == 0) { + /* An IEEE exception, simulated or otherwise. */ if (n & 0x80) { n = TARGET_FPE_FLTINV; } else if (n & 0x40) { @@ -121,13 +123,12 @@ void cpu_loop(CPUS390XState *env) n = TARGET_FPE_FLTUND; } else if (n & 0x08) { n = TARGET_FPE_FLTRES; - } else { - /* ??? Quantum exception; BFP, DFP error. */ - goto do_sigill_opn; } - sig = TARGET_SIGFPE; - goto do_signal_pc; + } else { + /* compare-and-trap */ + n = 0; } + goto do_signal_pc; default: fprintf(stderr, "Unhandled program exception: %#x\n", n); -- 2.31.1