summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-11-27 14:49:45 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-11-27 14:49:45 +0100
commit4f3cf983dcdab2e5443d621894f1c52c1847749e (patch)
tree8cc08075b3615bd9ba2c71cc5775ad53a1bb6f2d /Zend
parent8b281e5b6b0295cab936682134d24bf5bb2d537d (diff)
parent4e30ab33d84232ba2686e7ed5b125861db63142d (diff)
downloadphp-git-4f3cf983dcdab2e5443d621894f1c52c1847749e.tar.gz
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix AVX detection
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_cpuinfo.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/Zend/zend_cpuinfo.c b/Zend/zend_cpuinfo.c
index 81e3f43c51..1b268931ed 100644
--- a/Zend/zend_cpuinfo.c
+++ b/Zend/zend_cpuinfo.c
@@ -73,6 +73,38 @@ static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo
}
#endif
+/* Function based on compiler-rt implementation. */
+static unsigned get_xcr0_eax() {
+#if defined(__GNUC__) || defined(__clang__)
+ // Check xgetbv; this uses a .byte sequence instead of the instruction
+ // directly because older assemblers do not include support for xgetbv and
+ // there is no easy way to conditionally compile based on the assembler used.
+ unsigned eax, edx;
+ __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
+ return eax;
+#elif defined(ZEND_WIN32) && defined(_XCR_XFEATURE_ENABLED_MASK)
+ return _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+#else
+ return 0;
+#endif
+}
+
+static zend_bool is_avx_supported() {
+ if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_AVX)) {
+ /* No support for AVX */
+ return 0;
+ }
+ if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_OSXSAVE)) {
+ /* The operating system does not support XSAVE. */
+ return 0;
+ }
+ if ((get_xcr0_eax() & 0x6) != 0x6) {
+ /* XCR0 SSE and AVX bits must be set. */
+ return 0;
+ }
+ return 1;
+}
+
void zend_cpu_startup(void)
{
if (!cpuinfo.initialized) {
@@ -95,6 +127,11 @@ void zend_cpu_startup(void)
} else {
cpuinfo.ebx = 0;
}
+
+ if (!is_avx_supported()) {
+ cpuinfo.edx &= ~ZEND_CPU_FEATURE_AVX;
+ cpuinfo.ebx &= ~(ZEND_CPU_FEATURE_AVX2 & ~ZEND_CPU_EBX_MASK);
+ }
}
}