libitm: Disable TSX on processors on which it may be broken.
authorTorvald Riegel <triegel@redhat.com>
Wed, 18 Jan 2017 20:22:02 +0000 (20:22 +0000)
committerTorvald Riegel <torvald@gcc.gnu.org>
Wed, 18 Jan 2017 20:22:02 +0000 (20:22 +0000)
libitm/ChangeLog

* config/x86/target.h (htm_available): Add check for some processors
on which TSX is broken.

From-SVN: r244594

libitm/ChangeLog
libitm/config/x86/target.h

index 13e5e91a54eee90ce75bf2fc8c92ffa5bfe64117..d50005f4d910009f8375e5a5620b1e3eb9be763a 100644 (file)
@@ -1,3 +1,8 @@
+2017-01-18  Torvald Riegel  <triegel@redhat.com>
+
+       * config/x86/target.h (htm_available): Add check for some processors
+       on which TSX is broken.
+
 2017-01-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR other/79046
index 8d0a0da58aa3b144c52f985d58e9bb7c6f0701f5..665c7d6e986bd5a1899a613918de9e97ee99fe95 100644 (file)
@@ -78,6 +78,28 @@ htm_available ()
   if (__get_cpuid_max (0, NULL) >= 7)
     {
       unsigned a, b, c, d;
+      /* TSX is broken on some processors.  This can be fixed by microcode,
+        but we cannot reliably detect whether the microcode has been
+        updated.  Therefore, do not report availability of TSX on these
+        processors.  We use the same approach here as in glibc (see
+        https://sourceware.org/ml/libc-alpha/2016-12/msg00470.html).  */
+      __cpuid (0, a, b, c, d);
+      if (b == 0x756e6547 && c == 0x6c65746e && d == 0x49656e69)
+       {
+         __cpuid (1, a, b, c, d);
+         if (((a >> 8) & 0x0f) == 0x06) // Family.
+           {
+             unsigned model = ((a >> 4) & 0x0f) // Model.
+                 + ((a >> 12) & 0xf0); // Extended model.
+             unsigned stepping = a & 0x0f;
+             if ((model == 0x3c)
+                 || (model == 0x45)
+                 || (model == 0x46)
+                 /* Xeon E7 v3 has correct TSX if stepping >= 4.  */
+                 || ((model == 0x3f) && (stepping < 4)))
+               return false;
+           }
+       }
       __cpuid_count (7, 0, a, b, c, d);
       if (b & cpuid_rtm)
        return true;