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-iii@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.albrecht@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
On 7/7/21 6:42 AM, Jonathan Albrecht wrote:
> + 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;
> }
Nearly, but not quite. Replace the ??? Quantum exception with n = 0, otherwise si_code
will be garbage for that case.
The structure of the kernel code is
if (n != 0) {
/* do_fp_trap */
si_code = 0;
if ((n & 3) == 0) {
/* select on bits 6 & 7 */
}
raise sigfpe w/ si_code
} else {
raise sigill
}
The comment for compare-and-trap is misleading, because there are lots of entries in
"Figure 6-2. Data-exception codes (DXC)" which arrive there and are not compare-and-trap.
As a general comment, I think a single switch over DXC would be cleaner for both kernel
and qemu. It seems like giving different si_code for e.g. "0x40 IEEE division by zero"
and "0x43 Simulated IEEE division by zero" is actively incorrect.
r~
On 2021-07-08 1:08 pm, Richard Henderson wrote:
> On 7/7/21 6:42 AM, Jonathan Albrecht wrote:
>> + 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;
>> }
>
Thanks for the review. I should have a v3 ready shortly.
> Nearly, but not quite. Replace the ??? Quantum exception with n = 0,
> otherwise si_code will be garbage for that case.
>
Thx I'll fix that.
> The structure of the kernel code is
>
> if (n != 0) {
> /* do_fp_trap */
> si_code = 0;
> if ((n & 3) == 0) {
> /* select on bits 6 & 7 */
> }
> raise sigfpe w/ si_code
> } else {
> raise sigill
> }
>
> The comment for compare-and-trap is misleading, because there are lots
> of entries in "Figure 6-2. Data-exception codes (DXC)" which arrive
> there and are not compare-and-trap.
>
I'll make the comment less specific.
> As a general comment, I think a single switch over DXC would be
> cleaner for both kernel and qemu. It seems like giving different
> si_code for e.g. "0x40 IEEE division by zero" and "0x43 Simulated IEEE
> division by zero" is actively incorrect.
>
I went over the DXC section and I see what you mean about the si_codes
for simulated IEEE exceptions. I'll plan on handling those the same as
non-simulated IEEE if no objections. Otherwise all non-IEEE will have
si_code == 0 except DXC == 0x00 will still goto do_sigill_opn.
>
> r~
On 7/9/21 7:23 AM, jonathan.albrecht wrote: >> As a general comment, I think a single switch over DXC would be >> cleaner for both kernel and qemu. It seems like giving different >> si_code for e.g. "0x40 IEEE division by zero" and "0x43 Simulated IEEE >> division by zero" is actively incorrect. >> > I went over the DXC section and I see what you mean about the si_codes > for simulated IEEE exceptions. I'll plan on handling those the same as > non-simulated IEEE if no objections. Only if you plan on submitting a similar patch for the kernel. Otherwise, qemu would not match the kernel abi. r~
On 2021-07-09 10:37 am, Richard Henderson wrote: > On 7/9/21 7:23 AM, jonathan.albrecht wrote: >>> As a general comment, I think a single switch over DXC would be >>> cleaner for both kernel and qemu. It seems like giving different >>> si_code for e.g. "0x40 IEEE division by zero" and "0x43 Simulated >>> IEEE >>> division by zero" is actively incorrect. >>> >> I went over the DXC section and I see what you mean about the si_codes >> for simulated IEEE exceptions. I'll plan on handling those the same as >> non-simulated IEEE if no objections. > > Only if you plan on submitting a similar patch for the kernel. > Otherwise, qemu would not match the kernel abi. > Thanks for clarifying. In that case, I'll handle simulated IEEE the same as the current kernel.
© 2016 - 2026 Red Hat, Inc.