Bug 447991 - s390x: Valgrind indicates illegal instruction on wflrx
Summary: s390x: Valgrind indicates illegal instruction on wflrx
Status: RESOLVED FIXED
Alias: None
Product: valgrind
Classification: Developer tools
Component: vex (show other bugs)
Version: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Andreas Arnez
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-01-05 19:14 UTC by Andreas Arnez
Modified: 2022-02-08 16:57 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Fix VFLRX instruction (1.29 KB, patch)
2022-01-05 19:20 UTC, Andreas Arnez
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Arnez 2022-01-05 19:14:13 UTC
In a Fedora build, it has been seen that Valgrind crashes with illegal instruction when trying to execute the WFLRX instruction:

    vex s390->IR: specification exception: E700 0008 40C5
    ==4036598== valgrind: Unrecognised instruction at address ...

See the original bug report: https://bugzilla.redhat.com/show_bug.cgi?id=2035807

WFLRX is a variant of VFLR (vector FP load rounded); it rounds the source vector's first element down from extended format to long format. This variant was introduced with z14.
Comment 1 Andreas Arnez 2022-01-05 19:20:11 UTC
Created attachment 145141 [details]
Fix VFLRX instruction

The problem was due to a typo in s390_irgen_VFLR. This fixes the typo.
Comment 2 Jesus Checa 2022-01-14 13:45:16 UTC
I've tested this patch with the following source:
-----
int main(){
    asm("wflrx %v0,%v0,0,0");
    return 0 ;
}
-----
Built with "gcc -march=z14 main.c -o main" and tested with a valgrind build that contains this patch. Now valgrind works correctly and doesn't report "IR: specification exception" anymore.

I wanted to do a bit more in-depth testing and I moved to another instruction, so I changed my program to this one:
-----
int main(){
    asm("vflr %v0,%v0,0,0,0");
    return 0 ;
}
-----
Building and running the same way as the aforementioned, this executable will make that valgrind prints again a specification exception message such as this:
    vex s390->IR: specification exception: E700 0000 00C5
    ==52001== valgrind: Unrecognised instruction at address 0x1000558.

Checking s390x opcodes, it feels like s390_irgen_VFLR  is missing the case for when m3 == 0 (provided my inline asm is right).

I did the same test with VFLL (e700 xxxx xxc4) opcodes with the same result, VFLL instruction makes valgrind report a specification exception, whereas VFLLS/WFLLS/WFLLD instructions work correctly.

FTR, this is the link where I checked the opcodes: https://fossies.org/linux/binutils/opcodes/s390-opc.txt
Comment 3 Andreas Arnez 2022-01-14 14:09:13 UTC
(In reply to Jesus Checa from comment #2)
> ...
> Checking s390x opcodes, it feels like s390_irgen_VFLR  is missing the case
> for when m3 == 0 (provided my inline asm is right).
Right, m3 == 0 is not a valid format code.  The z/Architecture Principle of
Operation states:

  The M3 field specifies the floating-point format.  The floating-point
  format determines the size of the elements within the second operand.
  If a reserved value is specified, a specification exception is
  recognized.

And then declares the values 3 and 4 as representing the long and extended
formats, respectively, and all other values as reserved.

So I'd say that Valgrind is correct in raising a SIGILL for m3 == 0.
Comment 4 Mark Wielaard 2022-01-14 16:47:36 UTC
(In reply to Andreas Arnez from comment #3)
> (In reply to Jesus Checa from comment #2)
> > ...
> > Checking s390x opcodes, it feels like s390_irgen_VFLR  is missing the case
> > for when m3 == 0 (provided my inline asm is right).
> Right, m3 == 0 is not a valid format code.  The z/Architecture Principle of
> Operation states:
> 
>   The M3 field specifies the floating-point format.  The floating-point
>   format determines the size of the elements within the second operand.
>   If a reserved value is specified, a specification exception is
>   recognized.
> 
> And then declares the values 3 and 4 as representing the long and extended
> formats, respectively, and all other values as reserved.
> 
> So I'd say that Valgrind is correct in raising a SIGILL for m3 == 0.

OK, but does that mean that "vflr" isn't a real opcode because it doesn't define on what format it operates?
Only "vflrd", "wflrd", which operate on longs, and "wflrx", which operate on extended long, are valid opcodes?

If so, then it is slightly surprising gcc/binutils accepts asm("vflr %v0,%v0,0,0,0");
Comment 5 Andreas Arnez 2022-01-14 19:36:37 UTC
(In reply to Mark Wielaard from comment #4)
> OK, but does that mean that "vflr" isn't a real opcode because it doesn't
> define on what format it operates?
Basically yes.  Well, strictly speaking, the opcode only consists of the
encoded instruction's (E700000000C5) first and last bytes in this case.
So while this byte sequence correctly specifies the vflr instruction, it
violates the instruction's specification -- hence the specification
exception.  On Linux this raises SIGILL, same as if the opcode itself was
unrecognized.
> Only "vflrd", "wflrd", which operate on longs, and "wflrx", which operate on
> extended long, are valid opcodes?
> 
> If so, then it is slightly surprising gcc/binutils accepts asm("vflr
> %v0,%v0,0,0,0");
Yeah, it's arguable that it shouldn't.  The advantage is that future
extensions can be used even without explicit binutils support.  Sometimes
this comes in handy, and the risk of misuse is fairly low.  For instance,
if a future extension supported rounding down from long to short format,
you could already express this by specifying m3 = 2.
Comment 6 Jesus Checa 2022-01-17 16:16:19 UTC
(In reply to Andreas Arnez from comment #3)
> Right, m3 == 0 is not a valid format code.  The z/Architecture Principle of
> Operation states:
> 
>   The M3 field specifies the floating-point format.  The floating-point
>   format determines the size of the elements within the second operand.
>   If a reserved value is specified, a specification exception is
>   recognized.
> 
> And then declares the values 3 and 4 as representing the long and extended
> formats, respectively, and all other values as reserved.
> 
> So I'd say that Valgrind is correct in raising a SIGILL for m3 == 0.

Oh, I understand now. Thanks for the clarification!
Comment 7 Andreas Arnez 2022-02-08 16:57:37 UTC
Since this is a fairly trivial fix and there haven't been any more comments, I've pushed this as
   8229569cb8b1d564a -- s390: Fix VFLRX and WFLRX instructions