diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | src/hwf-x86.c | 46 |
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*/ } |