]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390: Remove S390_NUM_FACILITY_DW; fix testcase stfle.c (BZ 509562)
authorFlorian Krohm <flo2030@eich-krohm.de>
Sun, 30 Nov 2025 08:33:41 +0000 (08:33 +0000)
committerFlorian Krohm <flo2030@eich-krohm.de>
Sun, 30 Nov 2025 08:34:46 +0000 (08:34 +0000)
Now that the stfle insn is available we can use it to tell uas how
many double words are needed to store all facility bits. Hence,
S390_NUM_FACILITY_DW can go.

none/tests/s390x/stfle.c: The bug is here

  if (bit_to_test < 64)
    return (hoststfle[0] & (1ULL << (63 - bit_to_test)));
  else if (bit_to_test < 128)
    return (hoststfle[1] & (1ULL << (63 - bit_to_test)));
  else if (bit_to_test < 192)
    return (hoststfle[2] & (1ULL << (63 - bit_to_test)));

when bit_to_test >= 64.  Now fixed and test added.

Part of fixing https://bugs.kde.org/show_bug.cgi?id=509562

VEX/pub/libvex_s390x_common.h
coregrind/m_machine.c
none/tests/s390x/stfle.c
none/tests/s390x/stfle.stdout.exp
none/tests/s390x/stfle.stdout.exp-z16
tests/s390x_features.c

index 295e0c29b0433dd1fdef19519c2c049f4a3d7f2d..5fc0be9166d6b79dea0472dd94d065cd2c958b23 100644 (file)
@@ -99,9 +99,6 @@
 /* Number of arguments that can be passed in registers */
 #define S390_NUM_GPRPARMS 5
 
-/* Number of double words needed to store all facility bits. */
-#define S390_NUM_FACILITY_DW 4
-
 #endif /* __LIBVEX_PUB_S390X_H */
 
 /*--------------------------------------------------------------------*/
index 860ce1f9ddbe14eeeb29a98fb19fa4a57bcd9e74..4c65ec6cbc376068ec27f3033721ebcd453e2221 100644 (file)
@@ -1541,15 +1541,24 @@ Bool VG_(machine_get_hwcaps)( void )
         VG_(exit)(1);
      }
 
-     ULong hoststfle[S390_NUM_FACILITY_DW];
+     /* Get number of double words to store all facilities */
+     unsigned long long dummy[1];
 
-     for (i = 0; i < S390_NUM_FACILITY_DW; ++i)
-        hoststfle[i] = 0;
+     register ULong r0 asm("0") = 0;
+     asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
+                  : "=Q" (dummy), "+d"(r0)
+                  :
+                  : "cc", "memory");
+     UInt num_dw = r0 + 1;
+
+     /* Get the facility bits */
+     ULong hoststfle[num_dw];
 
-     register ULong reg0 asm("0") = S390_NUM_FACILITY_DW - 1;
+     for (i = 0; i < num_dw; ++i)
+        hoststfle[i] = 0;
 
      __asm__(".insn s,0xb2b00000,%0" /* stfle */
-                 : "=Q"(hoststfle), "+d"(reg0)
+                 : "=Q"(hoststfle), "+d"(r0)
                  :
                  : "cc");
 
@@ -1582,7 +1591,6 @@ Bool VG_(machine_get_hwcaps)( void )
      UChar dw_number = 0;
      UChar fac_bit = 0;
      for (i=0; i < sizeof fac_hwcaps / sizeof fac_hwcaps[0]; ++i) {
-        vg_assert(fac_hwcaps[i].facility_bit <= 191);  // for now
         dw_number = fac_hwcaps[i].facility_bit / 64;
         fac_bit = fac_hwcaps[i].facility_bit % 64;
         if (hoststfle[dw_number] & (1ULL << (63 - fac_bit))) {
index 5926964c6a32fdeb8f53a0a6faf45ee82c3447a0..db432c6d9b02a56fdce3b9b3ac1e4f0006de4f04 100644 (file)
@@ -1,12 +1,22 @@
 #include <stdio.h>
+#include <assert.h>
 
-/* Number of double words needed to store all facility bits. */
-#define S390_NUM_FACILITY_DW 4
+/* Return the number of double words needed to store all facility bits */
+static unsigned get_num_facility_dw(void)
+{
+   unsigned long long dummy[1];
 
+   register unsigned long long r0 asm("0") = 0;
+   asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
+                : "=Q" (dummy), "+d"(r0)
+                :
+                : "cc", "memory");
+   return r0 + 1;
+}
 
 unsigned long long stfle(unsigned long dw, unsigned bit_to_test)
 {
-  unsigned long long hoststfle[S390_NUM_FACILITY_DW];
+  unsigned long long hoststfle[dw];
   register unsigned long long __nr asm("0") = dw - 1;
   int cc;
 
@@ -16,20 +26,19 @@ unsigned long long stfle(unsigned long dw, unsigned bit_to_test)
                : "=Q" (*hoststfle), "+d" (__nr), "=d" (cc) : : "cc", "memory");
 
   printf("the value of cc is %d and #double words is %llu\n", cc, __nr + 1);
-  if (bit_to_test < 64)
-    return (hoststfle[0] & (1ULL << (63 - bit_to_test)));
-  else if (bit_to_test < 128)
-    return (hoststfle[1] & (1ULL << (63 - bit_to_test)));
-  else if (bit_to_test < 192)
-    return (hoststfle[2] & (1ULL << (63 - bit_to_test)));
-
-  printf("code needs to be updated\n");
-  return 0;
+
+  for (unsigned i = 0; i < dw; ++i) {
+     if (bit_to_test < (i + 1) * 64) {
+        bit_to_test -= i * 64;
+        return (hoststfle[i] & (1ULL << (63 - bit_to_test)));
+     }
+  }
+  assert(0);
 }
 
-int main()
+int main(void)
 {
-  int dw = S390_NUM_FACILITY_DW;
+  int dw = get_num_facility_dw();
 
   /* Test #1: Make sure STFLE returns sensible values. z/Arch facilities
               must be present. */
@@ -44,6 +53,12 @@ int main()
   else
     printf("STFLE facility is not installed\n");
 
+  /* Test #2.1: Test facility 77 which is installed for z196 and later */
+  if (stfle(dw, 77))
+    printf("Facility 77 is installed\n");
+  else
+    printf("Facility 77 is not installed\n");
+
   /* Test #3: Tell STFLE to only write 1 DW of facility bits. Expected condition
               code should be 3 because this test is run on those machines only
               that need 3 do double words to store facility bits. */
index 895551e0719e6343f3ddabfcb3815643575b369f..ff00c06cb5752462b56c8d07c20cdb1deb598add 100644 (file)
@@ -3,6 +3,8 @@ the value of cc is 0 and #double words is 3
 The z/Architecture architectural mode is installed and active
 the value of cc is 0 and #double words is 3
 STFLE facility is installed
+the value of cc is 0 and #double words is 3
+Facility 77 is installed
 the value of cc is 3 and #double words is 3
 the value of cc is 3 and #double words is 3
 The z/Architecture architectural mode is installed and active
index 8b01a2becdddf49b9ed526fe2838bb0f5da6b50b..8c74a068a09c2d0d6f9d8697644cecbbddcb9ea6 100644 (file)
@@ -3,6 +3,8 @@ the value of cc is 0 and #double words is 4
 The z/Architecture architectural mode is installed and active
 the value of cc is 0 and #double words is 4
 STFLE facility is installed
+the value of cc is 0 and #double words is 4
+Facility 77 is installed
 the value of cc is 3 and #double words is 4
 the value of cc is 3 and #double words is 4
 The z/Architecture architectural mode is installed and active
index 2b6af79f8a4ad36cb0e1909b3b765c54e0349dbc..954db9f055a6157d8e3bd12a1604aafb265d1f1f 100644 (file)
 #define GET_HWCAP() 0UL
 #endif
 
-/* Number of double words needed to store all facility bits. */
-#define S390_NUM_FACILITY_DW 3
+/* Return the number of double words needed to store all facility bits */
+static unsigned get_num_facility_dw(void)
+{
+   unsigned long long facilities[1];
 
-static void clear_facilities(unsigned long long *ret)
+   register unsigned long long r0 asm("0") = 0;
+   asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
+                : "=Q" (facilities), "+d"(r0)
+                :
+                : "cc", "memory");
+   return r0 + 1;
+}
+
+static void clear_facilities(unsigned long long *ret, unsigned num_dw)
 {
    unsigned int index;
-   for(index = 0; index < S390_NUM_FACILITY_DW; index++)
+   for(index = 0; index < num_dw; index++)
    {
       ret[index] = 0ULL;
    }
 }
 
-void stfle(unsigned long long *ret)
+void stfle(unsigned long long *ret, unsigned num_dw)
 {
-   register unsigned long long r0 asm("0") = S390_NUM_FACILITY_DW - 1;
+   register unsigned long long r0 asm("0") = num_dw - 1;
    asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
-                : "=m" (*ret), "+d"(r0) :: "cc", "memory");
+                : "=Q" (*ret), "+d"(r0) :: "cc", "memory");
 }
 
 
@@ -217,13 +227,15 @@ static model_info *get_host(void)
 
 static int go(char *feature, char *cpu)
 {
-   unsigned long long facilities[S390_NUM_FACILITY_DW];
    unsigned long long match;
    model_info *host, *from, *to, *p;
    char *colon;
 
-   clear_facilities(facilities);
-   stfle(facilities);
+   unsigned num_dw = get_num_facility_dw();
+   unsigned long long facilities[num_dw];
+
+   clear_facilities(facilities, num_dw);
+   stfle(facilities, num_dw);
 
    if (strcmp(feature, "s390x-vx") == 0 ) {
       /* VX needs kernel support; thus check the appropriate HWCAP bit. */