|
- #include "common.h"
- #include <stdbool.h>
-
- // Guard the use of getauxval() on glibc version >= 2.16
- #ifdef __GLIBC__
- #include <features.h>
- #if __GLIBC_PREREQ(2, 16)
- #include <sys/auxv.h>
- #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
- extern gotoblas_t gotoblas_Z13;
- #endif
- #ifdef DYN_Z14
- extern gotoblas_t gotoblas_Z14;
- #endif
-
- #define NUM_CORETYPES 4
-
- 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];
- #endif
- #ifdef DYN_Z14
- if (gotoblas == &gotoblas_Z14) return corename[2];
- #endif
- if (gotoblas == &gotoblas_ZARCH_GENERIC) return corename[3];
-
- return corename[0];
- }
-
- #ifndef HWCAP_S390_VXE
- #define HWCAP_S390_VXE 8192
- #endif
-
- /**
- * Detect the fitting set of kernels by retrieving the CPU features supported by
- * OS from the auxiliary value AT_HWCAP and choosing the set of kernels
- * ("coretype") that exploits most of the features and can be compiled with the
- * available gcc version.
- * Note that we cannot use vector registers on a z13 or newer unless supported
- * by the OS kernel (which needs to handle them properly during context switch).
- */
- static gotoblas_t* get_coretype(void) {
-
- unsigned long hwcap __attribute__((unused)) = get_hwcap();
-
- #ifdef DYN_Z14
- // 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))
- return &gotoblas_Z14;
- #endif
-
- #ifdef DYN_Z13
- // z13: Vector Facility (SIMD for double)
- if (hwcap & HWCAP_S390_VX)
- return &gotoblas_Z13;
- #endif
-
- // 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;
- }
-
- static gotoblas_t* force_coretype(char* coretype) {
-
- int i;
- int found = -1;
- char message[128];
-
- for (i = 0; i < NUM_CORETYPES; i++)
- {
- if (!strncasecmp(coretype, corename[i], 20))
- {
- found = i;
- break;
- }
- }
-
- if (found == 1) {
- #ifdef DYN_Z13
- return &gotoblas_Z13;
- #else
- openblas_warning(1, "Z13 support not compiled in");
- return NULL;
- #endif
- } else if (found == 2) {
- #ifdef DYN_Z14
- return &gotoblas_Z14;
- #else
- openblas_warning(1, "Z14 support not compiled in");
- return NULL;
- #endif
- } else if (found == 3) {
- return &gotoblas_ZARCH_GENERIC;
- }
-
- snprintf(message, 128, "Core not found: %s\n", coretype);
- openblas_warning(1, message);
- return NULL;
- }
-
- void gotoblas_dynamic_init(void) {
-
- char coremsg[128];
- char coren[22];
- char* p;
-
-
- if (gotoblas) return;
-
- p = getenv("OPENBLAS_CORETYPE");
- if (p)
- {
- gotoblas = force_coretype(p);
- }
- else
- {
- gotoblas = get_coretype();
- }
-
- if (gotoblas == NULL)
- {
- snprintf(coremsg, 128, "Failed to detect system, falling back to generic z support.\n");
- openblas_warning(1, coremsg);
- gotoblas = &gotoblas_ZARCH_GENERIC;
- }
-
- if (gotoblas && gotoblas->init) {
- strncpy(coren, gotoblas_corename(), 20);
- sprintf(coremsg, "Core: %s\n", coren);
- openblas_warning(2, coremsg);
- gotoblas->init();
- }
- else {
- openblas_warning(0, "OpenBLAS : Architecture Initialization failed. No initialization function found.\n");
- exit(1);
- }
- }
-
- void gotoblas_dynamic_quit(void) {
- gotoblas = NULL;
- }
|