From 1b0cd162cf5afcfbfe1eec2035ce245585c8767c Mon Sep 17 00:00:00 2001 From: GNU Libc Maintainers Date: Tue, 18 Oct 2016 21:10:46 +0000 Subject: [PATCH] local-blacklist-for-Intel-TSX 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 Gbp-Pq: Topic amd64 Gbp-Pq: Name local-blacklist-for-Intel-TSX.diff --- sysdeps/x86/cpu-features.c | 31 +++++++++++++++++++++++++++---- sysdeps/x86/cpu-features.h | 1 + 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c index 9ce4b495a..618160a23 100644 --- a/sysdeps/x86/cpu-features.c +++ b/sysdeps/x86/cpu-features.c @@ -22,7 +22,8 @@ static void get_common_indeces (struct cpu_features *cpu_features, unsigned int *family, unsigned int *model, - unsigned int *extended_model) + unsigned int *extended_model, + unsigned int *stepping) { if (family) { @@ -34,6 +35,7 @@ get_common_indeces (struct cpu_features *cpu_features, *family = (eax >> 8) & 0x0f; *model = (eax >> 4) & 0x0f; *extended_model = (eax >> 12) & 0xf0; + *stepping = eax & 0x0f; if (*family == 0x0f) { *family += (eax >> 20) & 0xff; @@ -97,6 +99,7 @@ init_cpu_features (struct cpu_features *cpu_features) unsigned int ebx, ecx, edx; unsigned int family = 0; unsigned int model = 0; + unsigned int stepping = 0; enum cpu_features_kind kind; #if !HAS_CPUID @@ -116,7 +119,8 @@ init_cpu_features (struct cpu_features *cpu_features) kind = arch_kind_intel; - get_common_indeces (cpu_features, &family, &model, &extended_model); + get_common_indeces (cpu_features, &family, &model, + &extended_model, &stepping); if (family == 0x06) { @@ -213,7 +217,8 @@ init_cpu_features (struct cpu_features *cpu_features) kind = arch_kind_amd; - get_common_indeces (cpu_features, &family, &model, &extended_model); + get_common_indeces (cpu_features, &family, &model, + &extended_model, &stepping); ecx = cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx; @@ -250,7 +255,7 @@ init_cpu_features (struct cpu_features *cpu_features) else { kind = arch_kind_other; - get_common_indeces (cpu_features, NULL, NULL, NULL); + get_common_indeces (cpu_features, NULL, NULL, NULL, NULL); } /* Support i586 if CX8 is available. */ @@ -261,6 +266,24 @@ init_cpu_features (struct cpu_features *cpu_features) if (CPU_FEATURES_CPU_P (cpu_features, CMOV)) cpu_features->feature[index_arch_I686] |= bit_arch_I686; + /* 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_cpu_RTM | bit_cpu_HLE); + #if !HAS_CPUID no_cpuid: #endif diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h index 97ffe765f..12820a046 100644 --- a/sysdeps/x86/cpu-features.h +++ b/sysdeps/x86/cpu-features.h @@ -55,6 +55,7 @@ #define bit_cpu_HTT (1 << 28) /* COMMON_CPUID_INDEX_7. */ +#define bit_cpu_HLE (1 << 4) #define bit_cpu_ERMS (1 << 9) #define bit_cpu_RTM (1 << 11) #define bit_cpu_AVX2 (1 << 5) -- 2.30.2