s390: Remove S390_NUM_FACILITY_DW; fix testcase stfle.c (BZ 509562)

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
This commit is contained in:
Florian Krohm
2025-11-30 08:33:41 +00:00
parent 34b849de84
commit 502fb19a40
6 changed files with 68 additions and 32 deletions

View 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 */
/*--------------------------------------------------------------------*/

View 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)
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];
for (i = 0; i < num_dw; ++i)
hoststfle[i] = 0;
register ULong reg0 asm("0") = S390_NUM_FACILITY_DW - 1;
__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))) {

View 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. */

View 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

View 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

View File

@@ -51,23 +51,33 @@
#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. */