From d60012b4e77c8c67757847c9a4e4aa924b0ee9a0 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Wed, 15 Feb 2017 15:01:40 +0100 Subject: [PATCH] cpu_x86: Disable TSX on broken models All Intel Haswell processors (except Xeon E7 v3 with stepping >= 4) have TSX disabled by microcode update. As not all CPUs are guaranteed to be patched with microcode updates we need to explicitly disable TSX on affected CPUs to avoid its accidental usage. https://bugzilla.redhat.com/show_bug.cgi?id=1406791 Signed-off-by: Jiri Denemark --- src/cpu/cpu_x86.c | 72 +++++++++++++++++-- .../x86_64-cpuid-Core-i5-4670T-guest.xml | 2 +- .../x86_64-cpuid-Core-i5-4670T-host.xml | 2 +- .../x86_64-cpuid-Core-i5-4670T-json.xml | 2 +- 4 files changed, 70 insertions(+), 8 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index b3bccd1768..bcf50cb9e3 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -547,6 +547,26 @@ x86MakeSignature(unsigned int family, } +static void +x86DataToSignatureFull(const virCPUx86Data *data, + unsigned int *family, + unsigned int *model, + unsigned int *stepping) +{ + virCPUx86CPUID leaf1 = { .eax_in = 0x1 }; + virCPUx86CPUID *cpuid; + + *family = *model = *stepping = 0; + + if (!(cpuid = x86DataCpuid(data, &leaf1))) + return; + + *family = ((cpuid->eax >> 20) & 0xff) + ((cpuid->eax >> 8) & 0xf); + *model = ((cpuid->eax >> 12) & 0xf0) + ((cpuid->eax >> 4) & 0xf); + *stepping = cpuid->eax & 0xf; +} + + /* Mask out irrelevant bits (R and Step) from processor signature. */ #define SIGNATURE_MASK 0x0fff3ff0 @@ -1784,9 +1804,44 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current, } +/** + * Drop broken TSX features. + */ +static void +x86DataFilterTSX(virCPUx86Data *data, + virCPUx86VendorPtr vendor, + virCPUx86MapPtr map) +{ + unsigned int family; + unsigned int model; + unsigned int stepping; + + if (!vendor || STRNEQ(vendor->name, "Intel")) + return; + + x86DataToSignatureFull(data, &family, &model, &stepping); + + if (family == 6 && + ((model == 63 && stepping < 4) || + model == 60 || + model == 69 || + model == 70)) { + virCPUx86FeaturePtr feature; + + VIR_DEBUG("Dropping broken TSX"); + + if ((feature = x86FeatureFind(map, "hle"))) + x86DataSubtract(data, &feature->data); + + if ((feature = x86FeatureFind(map, "rtm"))) + x86DataSubtract(data, &feature->data); + } +} + + static int x86Decode(virCPUDefPtr cpu, - const virCPUx86Data *data, + const virCPUx86Data *cpuData, const char **models, unsigned int nmodels, const char *preferred, @@ -1798,6 +1853,7 @@ x86Decode(virCPUDefPtr cpu, virCPUDefPtr cpuCandidate; virCPUx86ModelPtr model = NULL; virCPUDefPtr cpuModel = NULL; + virCPUx86Data data = VIR_CPU_X86_DATA_INIT; virCPUx86Data copy = VIR_CPU_X86_DATA_INIT; virCPUx86Data features = VIR_CPU_X86_DATA_INIT; virCPUx86VendorPtr vendor; @@ -1808,11 +1864,16 @@ x86Decode(virCPUDefPtr cpu, virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES | VIR_CONNECT_BASELINE_CPU_MIGRATABLE, -1); - if (!data || !(map = virCPUx86GetMap())) + if (!cpuData || x86DataCopy(&data, cpuData) < 0) return -1; - vendor = x86DataToVendor(data, map); - signature = x86DataToSignature(data); + if (!(map = virCPUx86GetMap())) + goto cleanup; + + vendor = x86DataToVendor(&data, map); + signature = x86DataToSignature(&data); + + x86DataFilterTSX(&data, vendor, map); /* Walk through the CPU models in reverse order to check newest * models first. @@ -1847,7 +1908,7 @@ x86Decode(virCPUDefPtr cpu, continue; } - if (!(cpuCandidate = x86DataToCPU(data, candidate, map))) + if (!(cpuCandidate = x86DataToCPU(&data, candidate, map))) goto cleanup; cpuCandidate->type = cpu->type; @@ -1912,6 +1973,7 @@ x86Decode(virCPUDefPtr cpu, cleanup: virCPUDefFree(cpuModel); + virCPUx86DataClear(&data); virCPUx86DataClear(©); virCPUx86DataClear(&features); return ret; diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-guest.xml b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-guest.xml index 9c9399562a..70d13282b3 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-guest.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-guest.xml @@ -1,6 +1,6 @@ x86_64 - Haswell + Haswell-noTSX Intel diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-host.xml b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-host.xml index b9f95ad87c..d1d0bc7168 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-host.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-host.xml @@ -1,6 +1,6 @@ x86_64 - Haswell + Haswell-noTSX Intel diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-json.xml index cf23f59d78..8d3a0b6181 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T-json.xml @@ -1,6 +1,6 @@ x86_64 - Haswell + Haswell-noTSX Intel