Skip to content

Commit 4e30ab3

Browse files
committed
Fix AVX detection
Our CPU detection code currently only checks whether hardware support for AVX exists. However, we also need to check for operating system support for XSAVE, as well as whether XCR0 has the SSE and AVX bits set. If this is not the case, unset the AVX and AVX2 bits in the cpuinfo structure. Hopefully this resolves our issues with CPU support detection. Closes GH-6460.
1 parent 07c5efb commit 4e30ab3

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

Zend/zend_cpuinfo.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,38 @@ static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo
7373
}
7474
#endif
7575

76+
/* Function based on compiler-rt implementation. */
77+
static unsigned get_xcr0_eax() {
78+
#if defined(__GNUC__) || defined(__clang__)
79+
// Check xgetbv; this uses a .byte sequence instead of the instruction
80+
// directly because older assemblers do not include support for xgetbv and
81+
// there is no easy way to conditionally compile based on the assembler used.
82+
unsigned eax, edx;
83+
__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
84+
return eax;
85+
#elif defined(ZEND_WIN32) && defined(_XCR_XFEATURE_ENABLED_MASK)
86+
return _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
87+
#else
88+
return 0;
89+
#endif
90+
}
91+
92+
static zend_bool is_avx_supported() {
93+
if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_AVX)) {
94+
/* No support for AVX */
95+
return 0;
96+
}
97+
if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_OSXSAVE)) {
98+
/* The operating system does not support XSAVE. */
99+
return 0;
100+
}
101+
if ((get_xcr0_eax() & 0x6) != 0x6) {
102+
/* XCR0 SSE and AVX bits must be set. */
103+
return 0;
104+
}
105+
return 1;
106+
}
107+
76108
void zend_cpu_startup(void)
77109
{
78110
if (!cpuinfo.initialized) {
@@ -95,6 +127,11 @@ void zend_cpu_startup(void)
95127
} else {
96128
cpuinfo.ebx = 0;
97129
}
130+
131+
if (!is_avx_supported()) {
132+
cpuinfo.edx &= ~ZEND_CPU_FEATURE_AVX;
133+
cpuinfo.ebx &= ~(ZEND_CPU_FEATURE_AVX2 & ~ZEND_CPU_EBX_MASK);
134+
}
98135
}
99136
}
100137

0 commit comments

Comments
 (0)