From 44950ca173176d696f0c6e952a0b4aa7876dbd36 Mon Sep 17 00:00:00 2001 From: Marius Hillenbrand Date: Tue, 26 Oct 2021 15:19:49 +0200 Subject: [PATCH] s390x: use DYNAMIC_ARCH's cpu detection for compile-time choice On s390x, the run-time detection for DYNAMIC_ARCH and the compile-time choice in cpuid_zarch use different methods for identifying the supported CPU features. To make cpuid_zarch future-proof and both easier to maintain, switch cpuid_zarch to the same mechanism as DYNAMIC_ZARCH (i.e., derive the supported CPU features from hwcap flags) and share code between both (in a new header cpuid_zarch.h). Signed-off-by: Marius Hillenbrand --- cpuid_zarch.c | 48 +---------------------- cpuid_zarch.h | 67 +++++++++++++++++++++++++++++++++ driver/others/dynamic_zarch.c | 71 +++++++++-------------------------- 3 files changed, 86 insertions(+), 100 deletions(-) create mode 100644 cpuid_zarch.h diff --git a/cpuid_zarch.c b/cpuid_zarch.c index df3b7898f..a6b953dd9 100644 --- a/cpuid_zarch.c +++ b/cpuid_zarch.c @@ -27,57 +27,11 @@ #include -#define CPU_GENERIC 0 -#define CPU_Z13 1 -#define CPU_Z14 2 -#define CPU_Z15 3 +#include "cpuid_zarch.h" -static char *cpuname[] = { - "ZARCH_GENERIC", - "Z13", - "Z14", - "Z15" -}; - -static char *cpuname_lower[] = { - "zarch_generic", - "z13", - "z14", - "z15" -}; - -int detect(void) -{ - FILE *infile; - char buffer[512], *p; - - p = (char *)NULL; - infile = fopen("/proc/sysinfo", "r"); - while (fgets(buffer, sizeof(buffer), infile)){ - if (!strncmp("Type", buffer, 4)){ - p = strchr(buffer, ':') + 2; -#if 0 - fprintf(stderr, "%s\n", p); -#endif - break; - } - } - - fclose(infile); - - if (strstr(p, "2964")) return CPU_Z13; - if (strstr(p, "2965")) return CPU_Z13; - if (strstr(p, "3906")) return CPU_Z14; - if (strstr(p, "3907")) return CPU_Z14; - if (strstr(p, "8561")) return CPU_Z14; // fallback z15 to z14 - if (strstr(p, "8562")) return CPU_Z14; // fallback z15 to z14 - - return CPU_GENERIC; -} void get_libname(void) { - int d = detect(); printf("%s", cpuname_lower[d]); } diff --git a/cpuid_zarch.h b/cpuid_zarch.h new file mode 100644 index 000000000..404d90e86 --- /dev/null +++ b/cpuid_zarch.h @@ -0,0 +1,67 @@ +#include + +#define CPU_GENERIC 0 +#define CPU_Z13 1 +#define CPU_Z14 2 +#define CPU_Z15 3 + +static char *cpuname[] = { + "ZARCH_GENERIC", + "Z13", + "Z14", + "Z15" +}; + +static char *cpuname_lower[] = { + "zarch_generic", + "z13", + "z14", + "z15" +}; + +// Guard the use of getauxval() on glibc version >= 2.16 +#ifdef __GLIBC__ +#include +#if __GLIBC_PREREQ(2, 16) +#include +#define HAVE_GETAUXVAL 1 + +static unsigned long get_hwcap(void) +{ + unsigned long hwcap = getauxval(AT_HWCAP); + char *maskenv; + + // honor requests for not using specific CPU features in LD_HWCAP_MASK + maskenv = getenv("LD_HWCAP_MASK"); + if (maskenv) + hwcap &= strtoul(maskenv, NULL, 0); + + return hwcap; + // note that a missing auxval is interpreted as no capabilities + // available, which is safe. +} + +#else // __GLIBC_PREREQ(2, 16) +#warn "Cannot detect SIMD support in Z13 or newer architectures since glibc is older than 2.16" + +static unsigned long get_hwcap(void) { + // treat missing support for getauxval() as no capabilities available, + // which is safe. + return 0; +} +#endif // __GLIBC_PREREQ(2, 16) +#endif // __GLIBC + +static int detect(void) +{ + unsigned long hwcap = get_hwcap(); + + if ((hwcap & HWCAP_S390_VX) && (hwcap & HWCAP_S390_VXE)) + return CPU_Z14; + + if (hwcap & HWCAP_S390_VX) + return CPU_Z13; + + return CPU_GENERIC; +} + diff --git a/driver/others/dynamic_zarch.c b/driver/others/dynamic_zarch.c index bf5eab9b2..ad748f14c 100644 --- a/driver/others/dynamic_zarch.c +++ b/driver/others/dynamic_zarch.c @@ -1,38 +1,7 @@ #include "common.h" +#include "cpuid_zarch.h" #include -// Guard the use of getauxval() on glibc version >= 2.16 -#ifdef __GLIBC__ -#include -#if __GLIBC_PREREQ(2, 16) -#include -#define HAVE_GETAUXVAL 1 - -static unsigned long get_hwcap(void) -{ - unsigned long hwcap = getauxval(AT_HWCAP); - char *maskenv; - - // honor requests for not using specific CPU features in LD_HWCAP_MASK - maskenv = getenv("LD_HWCAP_MASK"); - if (maskenv) - hwcap &= strtoul(maskenv, NULL, 0); - - return hwcap; - // note that a missing auxval is interpreted as no capabilities - // available, which is safe. -} - -#else // __GLIBC_PREREQ(2, 16) -#warn "Cannot detect SIMD support in Z13 or newer architectures since glibc is older than 2.16" - -static unsigned long get_hwcap(void) { - // treat missing support for getauxval() as no capabilities available, - // which is safe. - return 0; -} -#endif // __GLIBC_PREREQ(2, 16) -#endif // __GLIBC extern gotoblas_t gotoblas_ZARCH_GENERIC; #ifdef DYN_Z13 @@ -46,23 +15,16 @@ extern gotoblas_t gotoblas_Z14; extern void openblas_warning(int verbose, const char* msg); -static char* corename[] = { - "unknown", - "Z13", - "Z14", - "ZARCH_GENERIC", -}; - char* gotoblas_corename(void) { #ifdef DYN_Z13 - if (gotoblas == &gotoblas_Z13) return corename[1]; + if (gotoblas == &gotoblas_Z13) return cpuname[CPU_Z13]; #endif #ifdef DYN_Z14 - if (gotoblas == &gotoblas_Z14) return corename[2]; + if (gotoblas == &gotoblas_Z14) return cpuname[CPU_Z14]; #endif - if (gotoblas == &gotoblas_ZARCH_GENERIC) return corename[3]; + if (gotoblas == &gotoblas_ZARCH_GENERIC) return cpuname[CPU_GENERIC]; - return corename[0]; + return "unknown"; } #ifndef HWCAP_S390_VXE @@ -79,25 +41,28 @@ char* gotoblas_corename(void) { */ static gotoblas_t* get_coretype(void) { - unsigned long hwcap __attribute__((unused)) = get_hwcap(); + int cpu = detect(); -#ifdef DYN_Z14 + switch(cpu) { // z14 and z15 systems: exploit Vector Facility (SIMD) and // Vector-Enhancements Facility 1 (float SIMD instructions), if present. - if ((hwcap & HWCAP_S390_VX) && (hwcap & HWCAP_S390_VXE)) + case CPU_Z14: +#ifdef DYN_Z14 return &gotoblas_Z14; #endif -#ifdef DYN_Z13 // z13: Vector Facility (SIMD for double) - if (hwcap & HWCAP_S390_VX) + case CPU_Z13: +#ifdef DYN_Z13 return &gotoblas_Z13; #endif + default: // fallback in case of missing compiler support, systems before z13, or // when the OS does not advertise support for the Vector Facility (e.g., // missing support in the OS kernel) - return &gotoblas_ZARCH_GENERIC; + return &gotoblas_ZARCH_GENERIC; + } } static gotoblas_t* force_coretype(char* coretype) { @@ -108,28 +73,28 @@ static gotoblas_t* force_coretype(char* coretype) { for (i = 0; i < NUM_CORETYPES; i++) { - if (!strncasecmp(coretype, corename[i], 20)) + if (!strncasecmp(coretype, cpuname[i], 20)) { found = i; break; } } - if (found == 1) { + if (found == CPU_Z13) { #ifdef DYN_Z13 return &gotoblas_Z13; #else openblas_warning(1, "Z13 support not compiled in"); return NULL; #endif - } else if (found == 2) { + } else if (found == CPU_Z14) { #ifdef DYN_Z14 return &gotoblas_Z14; #else openblas_warning(1, "Z14 support not compiled in"); return NULL; #endif - } else if (found == 3) { + } else if (found == CPU_GENERIC) { return &gotoblas_ZARCH_GENERIC; }