]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
accelerated: fix CPU feature detection for Intel CPUs
authorDaiki Ueno <ueno@gnu.org>
Thu, 18 Nov 2021 18:02:03 +0000 (19:02 +0100)
committerDaiki Ueno <ueno@gnu.org>
Wed, 22 Dec 2021 16:01:41 +0000 (17:01 +0100)
This fixes read_cpuid_vals to correctly read the CPUID quadruple, as
well as to set the bit the ustream CRYPTOGAMS uses to identify Intel
CPUs.

Suggested by Rafael Gieschke in:
https://gitlab.com/gnutls/gnutls/-/issues/1282

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/accelerated/x86/x86-common.c

index 264ae8f1a0463c9e2574899d8f6834b5daf4f136..7ddaa594e652e10259459a0dc057e33e7d01c6df 100644 (file)
@@ -81,15 +81,18 @@ unsigned int _gnutls_x86_cpuid_s[4];
 # define bit_AVX 0x10000000
 #endif
 
-#ifndef OSXSAVE_MASK
-/* OSXSAVE|MOVBE */
-# define OSXSAVE_MASK (0x8000000|0x400000)
+#ifndef bit_OSXSAVE
+# define bit_OSXSAVE 0x8000000
 #endif
 
 #ifndef bit_MOVBE
 # define bit_MOVBE 0x00400000
 #endif
 
+#ifndef OSXSAVE_MASK
+# define OSXSAVE_MASK (bit_OSXSAVE|bit_MOVBE)
+#endif
+
 #define bit_PADLOCK (0x3 << 6)
 #define bit_PADLOCK_PHE (0x3 << 10)
 #define bit_PADLOCK_PHE_SHA512 (0x3 << 25)
@@ -127,7 +130,7 @@ static unsigned read_cpuid_vals(unsigned int vals[4])
        unsigned t1, t2, t3;
        vals[0] = vals[1] = vals[2] = vals[3] = 0;
 
-       if (!__get_cpuid(1, &t1, &vals[0], &vals[1], &t2))
+       if (!__get_cpuid(1, &t1, &t2, &vals[1], &vals[0]))
                return 0;
        /* suppress AVX512; it works conditionally on certain CPUs on the original code */
        vals[1] &= 0xfffff7ff;
@@ -836,33 +839,47 @@ void register_x86_padlock_crypto(unsigned capabilities)
 }
 #endif
 
-static unsigned check_intel_or_amd(void)
+enum x86_cpu_vendor {
+       X86_CPU_VENDOR_OTHER,
+       X86_CPU_VENDOR_INTEL,
+       X86_CPU_VENDOR_AMD,
+};
+
+static enum x86_cpu_vendor check_x86_cpu_vendor(void)
 {
        unsigned int a, b, c, d;
 
-       if (!__get_cpuid(0, &a, &b, &c, &d))
-               return 0;
+       if (!__get_cpuid(0, &a, &b, &c, &d)) {
+               return X86_CPU_VENDOR_OTHER;
+       }
 
-       if ((memcmp(&b, "Genu", 4) == 0 &&
-            memcmp(&d, "ineI", 4) == 0 &&
-            memcmp(&c, "ntel", 4) == 0) ||
-           (memcmp(&b, "Auth", 4) == 0 &&
-            memcmp(&d, "enti", 4) == 0 && memcmp(&c, "cAMD", 4) == 0)) {
-               return 1;
+       if (memcmp(&b, "Genu", 4) == 0 &&
+           memcmp(&d, "ineI", 4) == 0 &&
+           memcmp(&c, "ntel", 4) == 0) {
+               return X86_CPU_VENDOR_INTEL;
        }
 
-       return 0;
+       if (memcmp(&b, "Auth", 4) == 0 &&
+           memcmp(&d, "enti", 4) == 0 &&
+           memcmp(&c, "cAMD", 4) == 0) {
+               return X86_CPU_VENDOR_AMD;
+       }
+
+       return X86_CPU_VENDOR_OTHER;
 }
 
 static
 void register_x86_intel_crypto(unsigned capabilities)
 {
        int ret;
+       enum x86_cpu_vendor vendor;
 
        memset(_gnutls_x86_cpuid_s, 0, sizeof(_gnutls_x86_cpuid_s));
 
-       if (check_intel_or_amd() == 0)
+       vendor = check_x86_cpu_vendor();
+       if (vendor == X86_CPU_VENDOR_OTHER) {
                return;
+       }
 
        if (capabilities == 0) {
                if (!read_cpuid_vals(_gnutls_x86_cpuid_s))
@@ -871,6 +888,13 @@ void register_x86_intel_crypto(unsigned capabilities)
                capabilities_to_intel_cpuid(capabilities);
        }
 
+       /* CRYPTOGAMS uses the (1 << 30) bit as an indicator of Intel CPUs */
+       if (vendor == X86_CPU_VENDOR_INTEL) {
+               _gnutls_x86_cpuid_s[0] |= 1 << 30;
+       } else {
+               _gnutls_x86_cpuid_s[0] &= ~(1 << 30);
+       }
+
        if (check_ssse3()) {
                _gnutls_debug_log("Intel SSSE3 was detected\n");