[PATCH v2 1/2] linux-user/s390x: signal with SIGFPE on compare-and-trap

Jonathan Albrecht posted 2 patches 4 years, 7 months ago
Maintainers: Laurent Vivier <laurent@vivier.eu>, Cornelia Huck <cohuck@redhat.com>, Thomas Huth <thuth@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, David Hildenbrand <david@redhat.com>
There is a newer version of this series
[PATCH v2 1/2] linux-user/s390x: signal with SIGFPE on compare-and-trap
Posted by Jonathan Albrecht 4 years, 7 months ago
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


Re: [PATCH v2 1/2] linux-user/s390x: signal with SIGFPE on compare-and-trap
Posted by Richard Henderson 4 years, 7 months ago
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~

Re: [PATCH v2 1/2] linux-user/s390x: signal with SIGFPE on compare-and-trap
Posted by jonathan.albrecht 4 years, 7 months ago
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~

Re: [PATCH v2 1/2] linux-user/s390x: signal with SIGFPE on compare-and-trap
Posted by Richard Henderson 4 years, 7 months ago
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~

Re: [PATCH v2 1/2] linux-user/s390x: signal with SIGFPE on compare-and-trap
Posted by jonathan.albrecht 4 years, 7 months ago
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.