[Gmp-commit] /var/hg/gmp: Work around skylake cpuid bug.

mercurial at gmplib.org mercurial at gmplib.org
Thu Dec 3 22:07:06 UTC 2015


details:   /var/hg/gmp/rev/a0d7048910a7
changeset: 16983:a0d7048910a7
user:      Torbjorn Granlund <torbjorng at google.com>
date:      Thu Dec 03 22:30:25 2015 +0100
description:
Work around skylake cpuid bug.
Fix spelling of kabylake.

diffstat:

 config.guess |  58 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 52 insertions(+), 6 deletions(-)

diffs (79 lines):

diff -r e0a73902edef -r a0d7048910a7 config.guess
--- a/config.guess	Tue Dec 01 21:29:32 2015 +0100
+++ b/config.guess	Thu Dec 03 22:30:25 2015 +0100
@@ -762,6 +762,49 @@
 extern "C"
 #endif
 unsigned int cpuid (int, char *, char *, int);
+
+int
+workaround_intel_skylake_bugs ()
+{
+  char feature_string[49];
+  char processor_name_string[49];
+  const char *bad_cpus[] = {" G44", " G45", " G39" /* , "6600" */ };
+  int i;
+
+  /* Example strings:                                   */
+  /* "Intel(R) Pentium(R) CPU G4400 @ 3.30GHz"          */
+  /* "Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz"         */
+  /*                  ^               ^               ^ */
+  /*     0x80000002       0x80000003      0x80000004    */
+
+  /* We match out just the 0x80000003 part here. */
+
+  /* In there infinitive wisdom, Intel decided to use one register
+     order for the vendor string, and another for the processor
+     name string.  We shuffle things about, rather than write a new
+     variant of our assembly cpuid.  */
+
+  unsigned int eax, ebx, ecx, edx;
+  eax = CPUID (feature_string, 0x80000003);
+  ebx = ((unsigned int *)feature_string)[0];
+  edx = ((unsigned int *)feature_string)[1];
+  ecx = ((unsigned int *)feature_string)[2];
+
+  ((unsigned int *) (processor_name_string))[0] = eax;
+  ((unsigned int *) (processor_name_string))[1] = ebx;
+  ((unsigned int *) (processor_name_string))[2] = ecx;
+  ((unsigned int *) (processor_name_string))[3] = edx;
+
+  processor_name_string[16] = 0;
+
+  for (i = 0; i < sizeof (bad_cpus) / sizeof (char *); i++)
+    {
+      if (strstr (processor_name_string, bad_cpus[i]) != 0)
+	return 1;
+    }
+  return 0;
+}
+
 int
 main ()
 {
@@ -839,16 +882,19 @@
           else if (model == 0x5c) cpu_64bit = 1,            modelstr = "goldmont";   /* Goldmont */
           else if (model == 0x5e) cpu_64bit = 1, cpu_avx=1, modelstr = "skylake";    /* Skylake */
           else if (model == 0x5f) cpu_64bit = 1,            modelstr = "goldmont";   /* Goldmont */
-          else if (model == 0x8e) cpu_64bit = 1, cpu_avx=1, modelstr = "cabylake";   /* Capylake Y/U */
-          else if (model == 0x9e) cpu_64bit = 1, cpu_avx=1, modelstr = "cabylake";   /* Capylake desktop */
+          else if (model == 0x8e) cpu_64bit = 1, cpu_avx=1, modelstr = "kabylake";   /* Kabylake Y/U */
+          else if (model == 0x9e) cpu_64bit = 1, cpu_avx=1, modelstr = "kabylake";   /* Kabylake desktop */
           else                    cpu_64bit = 1,            modelstr = "nehalem";    /* default */
 
-	  if (strcmp (modelstr, "haswell") == 0)
+	  if (strcmp (modelstr, "haswell") == 0 ||
+	      strcmp (modelstr, "broadwell") == 0 ||
+	      strcmp (modelstr, "skylake") == 0)
 	    {
-	      /* Some Haswells lack BMI2.  Let them appear as Sandybridges for
-		 now.  */
+	      /* Some haswell, broadwell, skylake lack BMI2.  Let them appear
+		 as sandybridge for now.  */
 	      CPUID (feature_string, 7);
-	      if ((feature_string[0 + 8 / 8] & (1 << (8 % 8))) == 0)
+	      if ((feature_string[0 + 8 / 8] & (1 << (8 % 8))) == 0
+		  || workaround_intel_skylake_bugs())
 		modelstr = "sandybridge";
 	    }
 


More information about the gmp-commit mailing list