From 595e0d66f455e31e1cfd762527b978c0309d6cbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Mon, 5 Feb 2018 18:28:24 +0100
Subject: [PATCH] Check for x86_64 sha_ni extension.

---
 ChangeLog            |  6 ++++++
 fat-x86_64.c         | 17 +++++++++++++----
 x86_64/fat/cpuid.asm |  3 ++-
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5643343a..88d93844 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2018-02-05  Niels Möller  <nisse@lysator.liu.se>
+
+	* fat-x86_64.c (get_x86_features): Check for sha_ni extension.
+
+	* x86_64/fat/cpuid.asm: Clear %ecx input to cpuid instruction.
+
 2018-02-01  Nikos Mavrogiannopoulos  <nmav@redhat.com>
 
 	* gcm.c (gcm_fill): New function, for use with _ctr_crypt16.
diff --git a/fat-x86_64.c b/fat-x86_64.c
index 2e97d1e5..b2328b90 100644
--- a/fat-x86_64.c
+++ b/fat-x86_64.c
@@ -52,6 +52,7 @@ struct x86_features
 {
   enum x86_vendor { X86_OTHER, X86_INTEL, X86_AMD } vendor;
   int have_aesni;
+  int have_sha_ni;
 };
 
 #define SKIP(s, slen, literal, llen)				\
@@ -66,6 +67,7 @@ get_x86_features (struct x86_features *features)
   const char *s;
   features->vendor = X86_OTHER;
   features->have_aesni = 0;
+  features->have_sha_ni = 0;
 
   s = secure_getenv (ENV_OVERRIDE);
   if (s)
@@ -84,9 +86,11 @@ get_x86_features (struct x86_features *features)
 	  }
 	else if (MATCH (s, length, "aesni", 5))
 	  features->have_aesni = 1;
+	else if (MATCH (s, length, "sha_ni", 6))
+	  features->have_sha_ni = 1;
 	if (!sep)
 	  break;
-	s = sep + 1;	
+	s = sep + 1;
       }
   else
     {
@@ -99,7 +103,11 @@ get_x86_features (struct x86_features *features)
 
       _nettle_cpuid (1, cpuid_data);
       if (cpuid_data[2] & 0x02000000)
-	features->have_aesni = 1;      
+       features->have_aesni = 1;
+
+      _nettle_cpuid (7, cpuid_data);
+      if (cpuid_data[1] & 0x20000000)
+       features->have_sha_ni = 1;
     }
 }
 
@@ -135,9 +143,10 @@ fat_init (void)
     {
       const char * const vendor_names[3] =
 	{ "other", "intel", "amd" };
-      fprintf (stderr, "libnettle: cpu features: vendor:%s%s\n",
+      fprintf (stderr, "libnettle: cpu features: vendor:%s%s%s\n",
 	       vendor_names[features.vendor],
-	       features.have_aesni ? ",aesni" : "");
+	       features.have_aesni ? ",aesni" : "",
+	       features.have_sha_ni ? ",sha_ni" : "");
     }
   if (features.have_aesni)
     {
diff --git a/x86_64/fat/cpuid.asm b/x86_64/fat/cpuid.asm
index 16a66d57..f317d56e 100644
--- a/x86_64/fat/cpuid.asm
+++ b/x86_64/fat/cpuid.asm
@@ -43,8 +43,9 @@ C output pointer: %rsi
 PROLOGUE(_nettle_cpuid)
 	W64_ENTRY(2)
 	push	%rbx
-	
+
 	movl	%edi, %eax
+	xorl	%ecx, %ecx      C Information we need use ecx = 0
 	cpuid
 	mov	%eax, (%rsi)
 	mov	%ebx, 4(%rsi)
-- 
GitLab