This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch overline-textgrid
in repository efl.
View the commit online.
commit 220e09d8390df2dbcf6addc95f40b6bd63f79933
Author: [email protected] <[email protected]>
AuthorDate: Mon Aug 3 14:14:45 2026 -0600
eina: detect AVX2, including the OS YMM-state check
CPUID leaf 7 EBX bit 5 alone is not enough. If the OS has not enabled
XSAVE for the YMM half, AVX2 instructions still execute but the upper
128 bits of each register are not preserved across a context switch, so
the failure looks like rare data corruption rather than a fault. Gate on
OSXSAVE, AVX, and XGETBV(0) reporting both XMM and YMM state.
Also check the CPUID maximum leaf before reading leaf 7, since a CPU
that does not implement it aliases the read to a lower leaf.
---
src/lib/eina/eina_cpu.c | 51 ++++++++++++++++++++++++++++++++++++++++++
src/lib/eina/eina_cpu.h | 3 ++-
src/tests/eina/eina_suite.c | 1 +
src/tests/eina/eina_suite.h | 1 +
src/tests/eina/eina_test_cpu.c | 33 +++++++++++++++++++++++++++
src/tests/eina/meson.build | 1 +
6 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/src/lib/eina/eina_cpu.c b/src/lib/eina/eina_cpu.c
index 119b8d098d..b32c17d9ea 100644
--- a/src/lib/eina/eina_cpu.c
+++ b/src/lib/eina/eina_cpu.c
@@ -83,6 +83,37 @@ static inline void _x86_cpuid(int op, int *a, int *b, int *c, int *d)
: "cc");
}
+static inline void _x86_cpuid_count(int op, int cnt, int *a, int *b, int *c, int *d)
+{
+ __asm__ volatile (
+#if defined(__x86_64__)
+ "pushq %%rbx \n\t"
+#else
+ "pushl %%ebx \n\t"
+#endif
+ "cpuid \n\t"
+ "movl %%ebx, %1 \n\t"
+#if defined(__x86_64__)
+ "popq %%rbx \n\t"
+#else
+ "popl %%ebx \n\t"
+#endif
+ : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d)
+ : "a" (op), "c" (cnt)
+ : "cc");
+}
+
+/* xgetbv without needing -mxsave: 0x0f 0x01 0xd0 is the XGETBV encoding. */
+static inline unsigned long long _x86_xgetbv(unsigned int xcr)
+{
+ unsigned int lo, hi;
+
+ __asm__ volatile (".byte 0x0f, 0x01, 0xd0"
+ : "=a" (lo), "=d" (hi)
+ : "c" (xcr));
+ return ((unsigned long long)hi << 32) | lo;
+}
+
static
void _x86_simd(Eina_Cpu_Features *features)
{
@@ -123,6 +154,26 @@ void _x86_simd(Eina_Cpu_Features *features)
if ((c >> 20) & 1)
*features |= EINA_CPU_SSE42;
+
+ /* AVX2 needs three separate things to be true: the CPU has the
+ * instructions, the OS enabled XSAVE, and the OS actually saves the YMM
+ * half on context switch. Skipping the last check does not fault - it
+ * silently corrupts the upper 128 bits across a switch. */
+ if (((c >> 27) & 1) && ((c >> 28) & 1))
+ {
+ int a7, b7, c7, d7;
+
+ if ((_x86_xgetbv(0) & 0x6) == 0x6)
+ {
+ _x86_cpuid(0, &a7, &b7, &c7, &d7);
+ if (a7 >= 7)
+ {
+ _x86_cpuid_count(7, 0, &a7, &b7, &c7, &d7);
+ if ((b7 >> 5) & 1)
+ *features |= EINA_CPU_AVX2;
+ }
+ }
+ }
}
#endif
diff --git a/src/lib/eina/eina_cpu.h b/src/lib/eina/eina_cpu.h
index c17d46e22b..2fc54669aa 100644
--- a/src/lib/eina/eina_cpu.h
+++ b/src/lib/eina/eina_cpu.h
@@ -56,7 +56,8 @@ typedef enum _Eina_Cpu_Features
EINA_CPU_SSSE3 = 0x00000080, /**< Supplemental Streaming SIMD Extension 3 (Intel) */
EINA_CPU_SSE41 = 0x00000100, /**< Streaming SIMD Extension 4.1 (Intel) */
EINA_CPU_SSE42 = 0x00000200, /**< Streaming SIMD Extension 4.2 (Intel) */
- EINA_CPU_SVE = 0x00000400 /**< Scalable Vector Extension (ARM) */
+ EINA_CPU_SVE = 0x00000400, /**< Scalable Vector Extension (ARM) */
+ EINA_CPU_AVX2 = 0x00000800 /**< Advanced Vector Extensions 2 (Intel) */
} Eina_Cpu_Features;
/**
diff --git a/src/tests/eina/eina_suite.c b/src/tests/eina/eina_suite.c
index 7561878c8b..221e9e8a68 100644
--- a/src/tests/eina/eina_suite.c
+++ b/src/tests/eina/eina_suite.c
@@ -92,6 +92,7 @@ static const Efl_Test_Case etc[] = {
{ "debug", eina_test_debug },
{ "Abstract Content", eina_test_abstract_content },
{ "thread", eina_test_thread },
+ { "Cpu", eina_test_cpu },
{ NULL, NULL }
};
diff --git a/src/tests/eina/eina_suite.h b/src/tests/eina/eina_suite.h
index c9e5476ae7..ac73408c32 100644
--- a/src/tests/eina/eina_suite.h
+++ b/src/tests/eina/eina_suite.h
@@ -80,5 +80,6 @@ void eina_test_vpath(TCase *tc);
void eina_test_debug(TCase *tc);
void eina_test_abstract_content(TCase *tc);
void eina_test_thread(TCase *tc);
+void eina_test_cpu(TCase *tc);
#endif /* EINA_SUITE_H_ */
diff --git a/src/tests/eina/eina_test_cpu.c b/src/tests/eina/eina_test_cpu.c
new file mode 100644
index 0000000000..de318bef0d
--- /dev/null
+++ b/src/tests/eina/eina_test_cpu.c
@@ -0,0 +1,33 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <Eina.h>
+
+#include "eina_suite.h"
+
+EFL_START_TEST(eina_cpu_avx2_implies_sse3)
+{
+ Eina_Cpu_Features f = eina_cpu_features_get();
+
+ /* AVX2 is a strict superset: a CPU reporting AVX2 without SSE3 means the
+ * detection read the wrong CPUID leaf or register. */
+ if (f & EINA_CPU_AVX2)
+ {
+ fail_if(!(f & EINA_CPU_SSE3));
+ fail_if(!(f & EINA_CPU_SSE2));
+ }
+ /* The bit must be distinct from every other feature bit. */
+ fail_if(EINA_CPU_AVX2 & (EINA_CPU_SSE3 | EINA_CPU_SSE41 | EINA_CPU_SSE42 |
+ EINA_CPU_SVE | EINA_CPU_NEON | EINA_CPU_ALTIVEC));
+}
+EFL_END_TEST
+
+void eina_test_cpu(TCase *tc)
+{
+ tcase_add_test(tc, eina_cpu_avx2_implies_sse3);
+}
diff --git a/src/tests/eina/meson.build b/src/tests/eina/meson.build
index 6195515e36..9b1409a357 100644
--- a/src/tests/eina/meson.build
+++ b/src/tests/eina/meson.build
@@ -57,6 +57,7 @@ eina_test_src = files(
'eina_test_vpath.c',
'eina_test_abstract_content.c',
'eina_test_thread.c',
+'eina_test_cpu.c',
)
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.