This fix follows the same approach that glibc uses to disable TSX on
processors on which it is broken.  TSX can also be disabled through a
microcode update on these processors, but glibc consensus is that it
cannot be detected reliably whether the microcode update has been
applied.  Thus, we just look for affected models/steppings.

Tested on x86_64-linux (but I don't have a machine with broken TSX
available).

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

commit ff5b36bbb136d73e673d8cbe234a4c070c3d72ee
Author: torvald <torvald@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Wed Jan 18 20:22:02 2017 +0000

    libitm: Disable TSX on processors on which it may be broken.
    
    	libitm/ChangeLog
    
    	* config/x86/target.h (htm_available): Add check for some processors
    	on which TSX is broken.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244594 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libitm/config/x86/target.h b/libitm/config/x86/target.h
index 8d0a0da..665c7d6 100644
--- a/libitm/config/x86/target.h
+++ b/libitm/config/x86/target.h
@@ -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;

Reply via email to