1
-
2
1
#include "common.h"
2
+ #include <stdbool.h>
3
+
4
+ // Gate kernels for z13 and z14 on gcc version
5
+ #if (__GNUC__ == 5 && __GNUC_MINOR__ >= 2 ) || __GNUC__ >= 6 || \
6
+ /* RHEL 7 since 7.3: */ \
7
+ (__GNUC__ == 4 && __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ == 5 && \
8
+ __GNUC_RH_RELEASE__ >= 11 )
9
+ #define HAVE_Z13_SUPPORT
10
+ #endif
11
+
12
+ #if __GNUC__ >= 7
13
+ #define HAVE_Z14_SUPPORT
14
+ #endif
15
+
16
+ // Guard the use of getauxval() on glibc version >= 2.16
17
+ #ifdef __GLIBC__
18
+ #include <features.h>
19
+ #if __GLIBC_PREREQ (2 , 16 )
20
+ #include <sys/auxv.h>
21
+ #define HAVE_GETAUXVAL 1
22
+
23
+ static unsigned long get_hwcap (void )
24
+ {
25
+ unsigned long hwcap = getauxval (AT_HWCAP );
26
+ char * maskenv ;
27
+
28
+ // honor requests for not using specific CPU features in LD_HWCAP_MASK
29
+ maskenv = getenv ("LD_HWCAP_MASK" );
30
+ if (maskenv )
31
+ hwcap &= strtoul (maskenv , NULL , 0 );
32
+
33
+ return hwcap ;
34
+ // note that a missing auxval is interpreted as no capabilities
35
+ // available, which is safe.
36
+ }
3
37
38
+ #else // __GLIBC_PREREQ(2, 16)
39
+ #warn "Cannot detect SIMD support in Z13 or newer architectures since glibc is older than 2.16"
40
+
41
+ static unsigned long get_hwcap (void ) {
42
+ // treat missing support for getauxval() as no capabilities available,
43
+ // which is safe.
44
+ return 0 ;
45
+ }
46
+ #endif // __GLIBC_PREREQ(2, 16)
47
+ #endif // __GLIBC
48
+
49
+ extern gotoblas_t gotoblas_ZARCH_GENERIC ;
50
+ #ifdef HAVE_Z13_SUPPORT
4
51
extern gotoblas_t gotoblas_Z13 ;
52
+ #endif
53
+ #ifdef HAVE_Z14_SUPPORT
5
54
extern gotoblas_t gotoblas_Z14 ;
6
- //extern gotoblas_t gotoblas_Z15;
7
- //#if (!defined C_GCC) || (GCC_VERSION >= 60000)
8
- //extern gotoblas_t gotoblas_Z14;
9
- //#endif
55
+ #endif
10
56
11
57
#define NUM_CORETYPES 4
12
58
@@ -16,47 +62,50 @@ static char* corename[] = {
16
62
"unknown" ,
17
63
"Z13" ,
18
64
"Z14" ,
19
- // "Z15",
20
65
"ZARCH_GENERIC" ,
21
66
};
22
67
23
68
char * gotoblas_corename (void ) {
69
+ #ifdef HAVE_Z13_SUPPORT
24
70
if (gotoblas == & gotoblas_Z13 ) return corename [1 ];
71
+ #endif
72
+ #ifdef HAVE_Z14_SUPPORT
25
73
if (gotoblas == & gotoblas_Z14 ) return corename [2 ];
26
- // if (gotoblas == &gotoblas_Z15) return corename[3];
27
- //#if (!defined C_GCC) || (GCC_VERSION >= 60000)
28
- // if (gotoblas == &gotoblas_POWER9) return corename[3];
29
- //#endif
30
- return corename [0 ]; // try generic?
74
+ #endif
75
+ if (gotoblas == & gotoblas_ZARCH_GENERIC ) return corename [3 ];
76
+
77
+ return corename [0 ];
31
78
}
32
79
33
- // __builtin_cpu_is is not supported by zarch
80
+ /**
81
+ * Detect the fitting set of kernels by retrieving the CPU features supported by
82
+ * OS from the auxiliary value AT_HWCAP and choosing the set of kernels
83
+ * ("coretype") that exploits most of the features and can be compiled with the
84
+ * available gcc version.
85
+ * Note that we cannot use vector registers on a z13 or newer unless supported
86
+ * by the OS kernel (which needs to handle them properly during context switch).
87
+ */
34
88
static gotoblas_t * get_coretype (void ) {
35
- FILE * infile ;
36
- char buffer [512 ], * p ;
37
-
38
- p = (char * )NULL ;
39
- infile = fopen ("/proc/sysinfo" , "r" );
40
- while (fgets (buffer , sizeof (buffer ), infile )) {
41
- if (!strncmp ("Type" , buffer , 4 )) {
42
- p = strchr (buffer , ':' ) + 2 ;
43
- #if 0
44
- fprintf (stderr , "%s\n" , p );
45
- #endif
46
- break ;
47
- }
48
- }
49
89
50
- fclose ( infile );
90
+ unsigned long hwcap __attribute__(( unused )) = get_hwcap ( );
51
91
52
- if (strstr (p , "2964" )) return & gotoblas_Z13 ;
53
- if (strstr (p , "2965" )) return & gotoblas_Z13 ;
54
- if (strstr (p , "3906" )) return & gotoblas_Z14 ;
55
- if (strstr (p , "3907" )) return & gotoblas_Z14 ;
56
- if (strstr (p , "8561" )) return & gotoblas_Z14 ; // fallback z15 to z14
57
- if (strstr (p , "8562" )) return & gotoblas_Z14 ; // fallback z15 to z14
92
+ // z14 and z15 systems: exploit Vector Facility (SIMD) and
93
+ // Vector-Enhancements Facility 1 (float SIMD instructions), if present.
94
+ #ifdef HAVE_Z14_SUPPORT
95
+ if ((hwcap & HWCAP_S390_VX ) && (hwcap & HWCAP_S390_VXE ))
96
+ return & gotoblas_Z14 ;
97
+ #endif
98
+
99
+ // z13: Vector Facility (SIMD for double)
100
+ #ifdef HAVE_Z13_SUPPORT
101
+ if (hwcap & HWCAP_S390_VX )
102
+ return & gotoblas_Z13 ;
103
+ #endif
58
104
59
- return NULL ; // should be ZARCH_GENERIC
105
+ // fallback in case of missing compiler support, systems before z13, or
106
+ // when the OS does not advertise support for the Vector Facility (e.g.,
107
+ // missing support in the OS kernel)
108
+ return & gotoblas_ZARCH_GENERIC ;
60
109
}
61
110
62
111
static gotoblas_t * force_coretype (char * coretype ) {
@@ -76,12 +125,13 @@ static gotoblas_t* force_coretype(char* coretype) {
76
125
77
126
switch (found )
78
127
{
128
+ #ifdef HAVE_Z13_SUPPORT
79
129
case 1 : return (& gotoblas_Z13 );
130
+ #endif
131
+ #ifdef HAVE_Z14_SUPPORT
80
132
case 2 : return (& gotoblas_Z14 );
81
- // case 3: return (&gotoblas_Z15);
82
- //#if (!defined C_GCC) || (GCC_VERSION >= 60000)
83
- // case 3: return (&gotoblas_POWER9);
84
- //#endif
133
+ #endif
134
+ case 3 : return (& gotoblas_ZARCH_GENERIC );
85
135
default : return NULL ;
86
136
}
87
137
snprintf (message , 128 , "Core not found: %s\n" , coretype );
@@ -109,9 +159,9 @@ void gotoblas_dynamic_init(void) {
109
159
110
160
if (gotoblas == NULL )
111
161
{
112
- snprintf (coremsg , 128 , "Falling back to Z14 core \n" );
162
+ snprintf (coremsg , 128 , "Failed to detect system, falling back to generic z support. \n" );
113
163
openblas_warning (1 , coremsg );
114
- gotoblas = & gotoblas_Z14 ;
164
+ gotoblas = & gotoblas_ZARCH_GENERIC ;
115
165
}
116
166
117
167
if (gotoblas && gotoblas -> init ) {
0 commit comments