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;