03904a
From 300c6315d2e644ae81b43fa2dd7bbf68b3afb5b2 Mon Sep 17 00:00:00 2001
03904a
From: Daiki Ueno <ueno@gnu.org>
03904a
Date: Thu, 18 Nov 2021 19:02:03 +0100
03904a
Subject: [PATCH 1/2] accelerated: fix CPU feature detection for Intel CPUs
03904a
03904a
This fixes read_cpuid_vals to correctly read the CPUID quadruple, as
03904a
well as to set the bit the ustream CRYPTOGAMS uses to identify Intel
03904a
CPUs.
03904a
03904a
Suggested by Rafael Gieschke in:
03904a
https://gitlab.com/gnutls/gnutls/-/issues/1282
03904a
03904a
Signed-off-by: Daiki Ueno <ueno@gnu.org>
03904a
---
03904a
 lib/accelerated/x86/x86-common.c | 91 +++++++++++++++++++++++++-------
03904a
 1 file changed, 71 insertions(+), 20 deletions(-)
03904a
03904a
diff --git a/lib/accelerated/x86/x86-common.c b/lib/accelerated/x86/x86-common.c
03904a
index 3845c6b4c9..cf615ef24f 100644
03904a
--- a/lib/accelerated/x86/x86-common.c
03904a
+++ b/lib/accelerated/x86/x86-common.c
03904a
@@ -81,15 +81,38 @@ unsigned int _gnutls_x86_cpuid_s[4];
03904a
 # define bit_AVX 0x10000000
03904a
 #endif
03904a
 
03904a
-#ifndef OSXSAVE_MASK
03904a
-/* OSXSAVE|FMA|MOVBE */
03904a
-# define OSXSAVE_MASK (0x8000000|0x1000|0x400000)
03904a
+#ifndef bit_AVX2
03904a
+# define bit_AVX2 0x00000020
03904a
+#endif
03904a
+
03904a
+#ifndef bit_AVX512F
03904a
+# define bit_AVX512F 0x00010000
03904a
+#endif
03904a
+
03904a
+#ifndef bit_AVX512IFMA
03904a
+# define bit_AVX512IFMA 0x00200000
03904a
+#endif
03904a
+
03904a
+#ifndef bit_AVX512BW
03904a
+# define bit_AVX512BW 0x40000000
03904a
+#endif
03904a
+
03904a
+#ifndef bit_AVX512VL
03904a
+# define bit_AVX512VL 0x80000000
03904a
+#endif
03904a
+
03904a
+#ifndef bit_OSXSAVE
03904a
+# define bit_OSXSAVE 0x8000000
03904a
 #endif
03904a
 
03904a
 #ifndef bit_MOVBE
03904a
 # define bit_MOVBE 0x00400000
03904a
 #endif
03904a
 
03904a
+#ifndef OSXSAVE_MASK
03904a
+# define OSXSAVE_MASK (bit_OSXSAVE|bit_MOVBE)
03904a
+#endif
03904a
+
03904a
 #define via_bit_PADLOCK (0x3 << 6)
03904a
 #define via_bit_PADLOCK_PHE (0x3 << 10)
03904a
 #define via_bit_PADLOCK_PHE_SHA512 (0x3 << 25)
03904a
@@ -127,7 +150,7 @@ static unsigned read_cpuid_vals(unsigned int vals[4])
03904a
 	unsigned t1, t2, t3;
03904a
 	vals[0] = vals[1] = vals[2] = vals[3] = 0;
03904a
 
03904a
-	if (!__get_cpuid(1, &t1, &vals[0], &vals[1], &t2))
03904a
+	if (!__get_cpuid(1, &t1, &t2, &vals[1], &vals[0]))
03904a
 		return 0;
03904a
 	/* suppress AVX512; it works conditionally on certain CPUs on the original code */
03904a
 	vals[1] &= 0xfffff7ff;
03904a
@@ -145,7 +168,7 @@ static unsigned check_4th_gen_intel_features(unsigned ecx)
03904a
 {
03904a
 	uint32_t xcr0;
03904a
 
03904a
-	if ((ecx & OSXSAVE_MASK) != OSXSAVE_MASK)
03904a
+	if ((ecx & bit_OSXSAVE) != bit_OSXSAVE)
03904a
 		return 0;
03904a
 
03904a
 #if defined(_MSC_VER) && !defined(__clang__)
03904a
@@ -233,10 +256,7 @@ static unsigned check_sha(void)
03904a
 #ifdef ASM_X86_64
03904a
 static unsigned check_avx_movbe(void)
03904a
 {
03904a
-	if (check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1]) == 0)
03904a
-		return 0;
03904a
-
03904a
-	return ((_gnutls_x86_cpuid_s[1] & bit_AVX));
03904a
+	return (_gnutls_x86_cpuid_s[1] & bit_AVX);
03904a
 }
03904a
 
03904a
 static unsigned check_pclmul(void)
03904a
@@ -514,33 +534,47 @@ void register_x86_padlock_crypto(unsigned capabilities)
03904a
 }
03904a
 #endif
03904a
 
03904a
-static unsigned check_intel_or_amd(void)
03904a
+enum x86_cpu_vendor {
03904a
+	X86_CPU_VENDOR_OTHER,
03904a
+	X86_CPU_VENDOR_INTEL,
03904a
+	X86_CPU_VENDOR_AMD,
03904a
+};
03904a
+
03904a
+static enum x86_cpu_vendor check_x86_cpu_vendor(void)
03904a
 {
03904a
 	unsigned int a, b, c, d;
03904a
 
03904a
-	if (!__get_cpuid(0, &a, &b, &c, &d))
03904a
-		return 0;
03904a
+	if (!__get_cpuid(0, &a, &b, &c, &d)) {
03904a
+		return X86_CPU_VENDOR_OTHER;
03904a
+	}
03904a
 
03904a
-	if ((memcmp(&b, "Genu", 4) == 0 &&
03904a
-	     memcmp(&d, "ineI", 4) == 0 &&
03904a
-	     memcmp(&c, "ntel", 4) == 0) ||
03904a
-	    (memcmp(&b, "Auth", 4) == 0 &&
03904a
-	     memcmp(&d, "enti", 4) == 0 && memcmp(&c, "cAMD", 4) == 0)) {
03904a
-		return 1;
03904a
+	if (memcmp(&b, "Genu", 4) == 0 &&
03904a
+	    memcmp(&d, "ineI", 4) == 0 &&
03904a
+	    memcmp(&c, "ntel", 4) == 0) {
03904a
+		return X86_CPU_VENDOR_INTEL;
03904a
 	}
03904a
 
03904a
-	return 0;
03904a
+	if (memcmp(&b, "Auth", 4) == 0 &&
03904a
+	    memcmp(&d, "enti", 4) == 0 &&
03904a
+	    memcmp(&c, "cAMD", 4) == 0) {
03904a
+		return X86_CPU_VENDOR_AMD;
03904a
+	}
03904a
+
03904a
+	return X86_CPU_VENDOR_OTHER;
03904a
 }
03904a
 
03904a
 static
03904a
 void register_x86_intel_crypto(unsigned capabilities)
03904a
 {
03904a
 	int ret;
03904a
+	enum x86_cpu_vendor vendor;
03904a
 
03904a
 	memset(_gnutls_x86_cpuid_s, 0, sizeof(_gnutls_x86_cpuid_s));
03904a
 
03904a
-	if (check_intel_or_amd() == 0)
03904a
+	vendor = check_x86_cpu_vendor();
03904a
+	if (vendor == X86_CPU_VENDOR_OTHER) {
03904a
 		return;
03904a
+	}
03904a
 
03904a
 	if (capabilities == 0) {
03904a
 		if (!read_cpuid_vals(_gnutls_x86_cpuid_s))
03904a
@@ -549,6 +583,23 @@ void register_x86_intel_crypto(unsigned capabilities)
03904a
 		capabilities_to_intel_cpuid(capabilities);
03904a
 	}
03904a
 
03904a
+	/* CRYPTOGAMS uses the (1 << 30) bit as an indicator of Intel CPUs */
03904a
+	if (vendor == X86_CPU_VENDOR_INTEL) {
03904a
+		_gnutls_x86_cpuid_s[0] |= 1 << 30;
03904a
+	} else {
03904a
+		_gnutls_x86_cpuid_s[0] &= ~(1 << 30);
03904a
+	}
03904a
+
03904a
+	if (!check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1])) {
03904a
+		_gnutls_x86_cpuid_s[1] &= ~bit_AVX;
03904a
+
03904a
+		/* Clear AVX2 bits as well, according to what OpenSSL does.
03904a
+		 * Should we clear bit_AVX512DQ, bit_AVX512PF, bit_AVX512ER, and
03904a
+		 * bit_AVX512CD? */
03904a
+		_gnutls_x86_cpuid_s[2] &= ~(bit_AVX2|bit_AVX512F|bit_AVX512IFMA|
03904a
+					    bit_AVX512BW|bit_AVX512BW);
03904a
+	}
03904a
+
03904a
 	if (check_ssse3()) {
03904a
 		_gnutls_debug_log("Intel SSSE3 was detected\n");
03904a
 
03904a
-- 
03904a
2.37.3
03904a
03904a
03904a
From cd509dac9e6d1bf76fd12c72c1fd61f1708c254a Mon Sep 17 00:00:00 2001
03904a
From: Daiki Ueno <ueno@gnu.org>
03904a
Date: Mon, 15 Aug 2022 09:39:18 +0900
03904a
Subject: [PATCH 2/2] accelerated: clear AVX bits if it cannot be queried
03904a
 through XSAVE
03904a
MIME-Version: 1.0
03904a
Content-Type: text/plain; charset=UTF-8
03904a
Content-Transfer-Encoding: 8bit
03904a
03904a
The algorithm to detect AVX is described in 14.3 of "Intel® 64 and IA-32
03904a
Architectures Software Developer’s Manual".
03904a
03904a
GnuTLS previously only followed that algorithm when registering the
03904a
crypto backend, while the CRYPTOGAMS derived SHA code assembly expects
03904a
that the extension bits are propagated to _gnutls_x86_cpuid_s.
03904a
03904a
Signed-off-by: Daiki Ueno <ueno@gnu.org>
03904a
---
03904a
 lib/accelerated/x86/x86-common.c | 18 ++++++++++++++++--
03904a
 1 file changed, 16 insertions(+), 2 deletions(-)
03904a
03904a
diff --git a/lib/accelerated/x86/x86-common.c b/lib/accelerated/x86/x86-common.c
03904a
index cf615ef24f..655d0c65f2 100644
03904a
--- a/lib/accelerated/x86/x86-common.c
03904a
+++ b/lib/accelerated/x86/x86-common.c
03904a
@@ -210,7 +210,8 @@ static void capabilities_to_intel_cpuid(unsigned capabilities)
03904a
 	}
03904a
 
03904a
 	if (capabilities & INTEL_AVX) {
03904a
-		if ((a[1] & bit_AVX) && check_4th_gen_intel_features(a[1])) {
03904a
+		if ((a[1] & bit_AVX) && (a[1] & bit_MOVBE) &&
03904a
+		    check_4th_gen_intel_features(a[1])) {
03904a
 			_gnutls_x86_cpuid_s[1] |= bit_AVX|bit_MOVBE;
03904a
 		} else {
03904a
 			_gnutls_debug_log
03904a
@@ -256,7 +257,7 @@ static unsigned check_sha(void)
03904a
 #ifdef ASM_X86_64
03904a
 static unsigned check_avx_movbe(void)
03904a
 {
03904a
-	return (_gnutls_x86_cpuid_s[1] & bit_AVX);
03904a
+	return (_gnutls_x86_cpuid_s[1] & (bit_AVX|bit_MOVBE)) == (bit_AVX|bit_MOVBE);
03904a
 }
03904a
 
03904a
 static unsigned check_pclmul(void)
03904a
@@ -579,6 +580,19 @@ void register_x86_intel_crypto(unsigned capabilities)
03904a
 	if (capabilities == 0) {
03904a
 		if (!read_cpuid_vals(_gnutls_x86_cpuid_s))
03904a
 			return;
03904a
+		if (!check_4th_gen_intel_features(_gnutls_x86_cpuid_s[1])) {
03904a
+			_gnutls_x86_cpuid_s[1] &= ~bit_AVX;
03904a
+
03904a
+			/* Clear AVX2 bits as well, according to what
03904a
+			 * OpenSSL does.  Should we clear
03904a
+			 * bit_AVX512DQ, bit_AVX512PF, bit_AVX512ER,
03904a
+			 * and bit_AVX512CD? */
03904a
+			_gnutls_x86_cpuid_s[2] &= ~(bit_AVX2|
03904a
+						    bit_AVX512F|
03904a
+						    bit_AVX512IFMA|
03904a
+						    bit_AVX512BW|
03904a
+						    bit_AVX512BW);
03904a
+		}
03904a
 	} else {
03904a
 		capabilities_to_intel_cpuid(capabilities);
03904a
 	}
03904a
-- 
03904a
2.37.3
03904a