Intel TSX is broken on Haswell based processors (erratum HSD136/HSW136)
and a microcode update is available to simply disable the corresponding
instructions.

A live microcode update will disable the TSX instructions causing
already started binaries to segfault. This patch simply disable Intel
TSX (HLE and RTM) on processors which might receive a microcode update,
so that it doesn't happen.  We might expect newer steppings to fix the
issue (e.g. as Haswell-EX did).

Intel TSX-NI is also broken on Broadwell systems, and documented as
being unavailable in their specification updates errata list.  However,
some end-user systems were shipped with old microcode that left Intel
TSX-NI still enabled in CPUID on these processors.  We must not allow
RTM to be used by glibc on these systems, due to runtime system
misbehavior and live-update of microcode hazards.

Author: Henrique de Moraes Holschuh <hmh@debian.org>

--- a/sysdeps/x86_64/multiarch/init-arch.c
+++ b/sysdeps/x86_64/multiarch/init-arch.c
@@ -26,7 +26,7 @@
 
 
 static void
-get_common_indeces (unsigned int *family, unsigned int *model)
+get_common_indeces (unsigned int *family, unsigned int *model, unsigned int *stepping)
 {
   __cpuid (1, __cpu_features.cpuid[COMMON_CPUID_INDEX_1].eax,
 	   __cpu_features.cpuid[COMMON_CPUID_INDEX_1].ebx,
@@ -36,6 +36,7 @@
   unsigned int eax = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].eax;
   *family = (eax >> 8) & 0x0f;
   *model = (eax >> 4) & 0x0f;
+  *stepping = eax & 0x0f;
 }
 
 
@@ -47,6 +48,7 @@
   unsigned int edx;
   unsigned int family = 0;
   unsigned int model = 0;
+  unsigned int stepping = 0;
   enum cpu_features_kind kind;
 
   __cpuid (0, __cpu_features.max_cpuid, ebx, ecx, edx);
@@ -56,7 +58,7 @@
     {
       kind = arch_kind_intel;
 
-      get_common_indeces (&family, &model);
+      get_common_indeces (&family, &model, &stepping);
 
       unsigned int eax = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].eax;
       unsigned int extended_family = (eax >> 20) & 0xff;
@@ -131,7 +133,7 @@
     {
       kind = arch_kind_amd;
 
-      get_common_indeces (&family, &model);
+      get_common_indeces (&family, &model, &stepping);
 
       ecx = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx;
 
@@ -176,6 +178,24 @@
 	}
     }
 
+  /* Disable Intel TSX (HLE and RTM) due to erratum HSD136/HSW136
+     on all Haswell processors, except Haswell-EX/Xeon E7-v3 (306F4),
+     to work around outdated microcode that doesn't disable the
+     broken feature by default.
+
+     Disable TSX on Broadwell, due to errata BDM53/BDW51/BDD51/
+     BDE42.  The errata documentation states that RTM is unusable,
+     and that it should not be advertised by CPUID at all on any
+     such processors.  Unfortunately, it _is_ advertised in some
+     (older) microcode versions.  Exceptions: Broadwell-E (406Fx),
+     likely already fixed at launch */
+  if (kind == arch_kind_intel && family == 6 &&
+      ((model == 63 && stepping <= 2) || (model == 60 && stepping <= 3) ||
+       (model == 69 && stepping <= 1) || (model == 70 && stepping <= 1) ||
+       (model == 61 && stepping <= 4) || (model == 71 && stepping <= 1) ||
+       (model == 86 && stepping <= 2) ))
+    __cpu_features.cpuid[COMMON_CPUID_INDEX_7].ebx &= ~(bit_RTM | bit_HLE);
+
   __cpu_features.family = family;
   __cpu_features.model = model;
   atomic_write_barrier ();
--- a/sysdeps/x86_64/multiarch/init-arch.h
+++ b/sysdeps/x86_64/multiarch/init-arch.h
@@ -40,6 +40,7 @@
 
 /* COMMON_CPUID_INDEX_7.  */
 #define bit_RTM		(1 << 11)
+#define bit_HLE		(1 << 4)
 
 /* XCR0 Feature flags.  */
 #define bit_XMM_state  (1 << 1)
