summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--src/hwf-x86.c46
2 files changed, 47 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 27de850e..8b43d9a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1033,7 +1033,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions],
[gcry_cv_gcc_inline_asm_avx=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
- __asm__("vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
+ __asm__("xgetbv; vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
}]])],
[gcry_cv_gcc_inline_asm_avx=yes])])
if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
@@ -1050,7 +1050,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions],
[gcry_cv_gcc_inline_asm_avx2=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
- __asm__("vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
+ __asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
}]])],
[gcry_cv_gcc_inline_asm_avx2=yes])])
if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
diff --git a/src/hwf-x86.c b/src/hwf-x86.c
index 4e825588..0591b4fd 100644
--- a/src/hwf-x86.c
+++ b/src/hwf-x86.c
@@ -95,6 +95,21 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
if (edx)
*edx = regs[3];
}
+
+static unsigned int
+get_xgetbv(void)
+{
+ unsigned int t_eax;
+
+ asm volatile
+ ("xgetbv\n\t"
+ : "=a" (t_eax)
+ : "c" (0)
+ );
+
+ return t_eax;
+}
+
#endif /* i386 && GNUC */
@@ -129,6 +144,21 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
if (edx)
*edx = regs[3];
}
+
+static unsigned int
+get_xgetbv(void)
+{
+ unsigned int t_eax;
+
+ asm volatile
+ ("xgetbv\n\t"
+ : "=a" (t_eax)
+ : "c" (0)
+ );
+
+ return t_eax;
+}
+
#endif /* x86-64 && GNUC */
@@ -138,9 +168,12 @@ detect_x86_gnuc (void)
{
char vendor_id[12+1];
unsigned int features;
+ unsigned int os_supports_avx_avx2_registers = 0;
unsigned int max_cpuid_level;
unsigned int result = 0;
+ (void)os_supports_avx_avx2_registers;
+
if (!is_cpuid_available())
return 0;
@@ -215,10 +248,20 @@ detect_x86_gnuc (void)
if (features & 0x02000000)
result |= HWF_INTEL_AESNI;
#endif /*ENABLE_AESNI_SUPPORT*/
+#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT)
+ /* Test bit 27 for OSXSAVE (required for AVX/AVX2). */
+ if (features & 0x08000000)
+ {
+ /* Check that OS has enabled both XMM and YMM state support. */
+ if ((get_xgetbv() & 0x6) == 0x6)
+ os_supports_avx_avx2_registers = 1;
+ }
+#endif
#ifdef ENABLE_AVX_SUPPORT
/* Test bit 28 for AVX. */
if (features & 0x10000000)
- result |= HWF_INTEL_AVX;
+ if (os_supports_avx_avx2_registers)
+ result |= HWF_INTEL_AVX;
#endif /*ENABLE_AVX_SUPPORT*/
#ifdef ENABLE_DRNG_SUPPORT
/* Test bit 30 for RDRAND. */
@@ -242,6 +285,7 @@ detect_x86_gnuc (void)
#ifdef ENABLE_AVX2_SUPPORT
/* Test bit 5 for AVX2. */
if (features & 0x00000020)
+ if (os_supports_avx_avx2_registers)
result |= HWF_INTEL_AVX2;
#endif /*ENABLE_AVX_SUPPORT*/
}