|
From: Florian K. <fk...@so...> - 2025-11-30 08:35:03
|
https://sourceware.org/cgit/valgrind/commit/?id=502fb19a40194c52f051c603c311c0dd2d5c29b2 commit 502fb19a40194c52f051c603c311c0dd2d5c29b2 Author: Florian Krohm <fl...@ei...> Date: Sun Nov 30 08:33:41 2025 +0000 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 Diff: --- VEX/pub/libvex_s390x_common.h | 3 --- coregrind/m_machine.c | 20 +++++++++++----- none/tests/s390x/stfle.c | 43 +++++++++++++++++++++++------------ none/tests/s390x/stfle.stdout.exp | 2 ++ none/tests/s390x/stfle.stdout.exp-z16 | 2 ++ tests/s390x_features.c | 32 ++++++++++++++++++-------- 6 files changed, 69 insertions(+), 33 deletions(-) diff --git a/VEX/pub/libvex_s390x_common.h b/VEX/pub/libvex_s390x_common.h index 295e0c29b0..5fc0be9166 100644 --- a/VEX/pub/libvex_s390x_common.h +++ b/VEX/pub/libvex_s390x_common.h @@ -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 */ /*--------------------------------------------------------------------*/ diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 860ce1f9dd..4c65ec6cbc 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -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))) { diff --git a/none/tests/s390x/stfle.c b/none/tests/s390x/stfle.c index 5926964c6a..db432c6d9b 100644 --- a/none/tests/s390x/stfle.c +++ b/none/tests/s390x/stfle.c @@ -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. */ diff --git a/none/tests/s390x/stfle.stdout.exp b/none/tests/s390x/stfle.stdout.exp index 895551e071..ff00c06cb5 100644 --- a/none/tests/s390x/stfle.stdout.exp +++ b/none/tests/s390x/stfle.stdout.exp @@ -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 diff --git a/none/tests/s390x/stfle.stdout.exp-z16 b/none/tests/s390x/stfle.stdout.exp-z16 index 8b01a2becd..8c74a068a0 100644 --- a/none/tests/s390x/stfle.stdout.exp-z16 +++ b/none/tests/s390x/stfle.stdout.exp-z16 @@ -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 diff --git a/tests/s390x_features.c b/tests/s390x_features.c index 2b6af79f8a..954db9f055 100644 --- a/tests/s390x_features.c +++ b/tests/s390x_features.c @@ -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. */ |