[libvirt] [PATCH 0/2] cpu_x86: Disable TSX on broken models

This series applies on top of "qemu: Detect host CPU model by asking QEMU on x86_64". https://bugzilla.redhat.com/show_bug.cgi?id=1406791 Jiri Denemark (2): cpu_x86: Disable TSX on broken models cputest: Add CPUID data for Haswell with TSX src/cpu/cpu_x86.c | 72 ++++++++++++++++++++-- tests/cputest.c | 1 + .../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 +- .../x86_64-cpuid-Xeon-E7-8890-guest.xml | 32 ++++++++++ .../cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml | 32 ++++++++++ tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml | 37 +++++++++++ 8 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml -- 2.11.1

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 <jdenemar@redhat.com> --- 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 b3bccd176..bcf50cb9e 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 9c9399562..70d13282b 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 @@ <cpu mode='custom' match='exact'> <arch>x86_64</arch> - <model fallback='forbid'>Haswell</model> + <model fallback='forbid'>Haswell-noTSX</model> <vendor>Intel</vendor> <feature policy='require' name='vme'/> <feature policy='require' name='ds'/> 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 b9f95ad87..d1d0bc716 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 @@ <cpu> <arch>x86_64</arch> - <model>Haswell</model> + <model>Haswell-noTSX</model> <vendor>Intel</vendor> <feature name='vme'/> <feature name='ds'/> 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 cf23f59d7..8d3a0b618 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 @@ <cpu mode='custom' match='exact'> <arch>x86_64</arch> - <model fallback='forbid'>Haswell</model> + <model fallback='forbid'>Haswell-noTSX</model> <vendor>Intel</vendor> <feature policy='require' name='vme'/> <feature policy='require' name='ss'/> -- 2.11.1

All existing Haswell CPUID data were gathered from CPUs with broken TSX. Let's add new data for Haswell with correct TSX implementation. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + .../x86_64-cpuid-Xeon-E7-8890-guest.xml | 32 +++++++++++++++++++ .../cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml | 32 +++++++++++++++++++ tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml | 37 ++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml diff --git a/tests/cputest.c b/tests/cputest.c index b7dd95d84..685aca152 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -842,6 +842,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630", true); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", true); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", true); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890", false); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", true); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", false); diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-guest.xml new file mode 100644 index 000000000..c62e36a3a --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-guest.xml @@ -0,0 +1,32 @@ +<cpu mode='custom' match='exact'> + <arch>x86_64</arch> + <model fallback='forbid'>Haswell</model> + <vendor>Intel</vendor> + <feature policy='require' name='vme'/> + <feature policy='require' name='ds'/> + <feature policy='require' name='acpi'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='ht'/> + <feature policy='require' name='tm'/> + <feature policy='require' name='pbe'/> + <feature policy='require' name='dtes64'/> + <feature policy='require' name='monitor'/> + <feature policy='require' name='ds_cpl'/> + <feature policy='require' name='vmx'/> + <feature policy='require' name='smx'/> + <feature policy='require' name='est'/> + <feature policy='require' name='tm2'/> + <feature policy='require' name='xtpr'/> + <feature policy='require' name='pdcm'/> + <feature policy='require' name='dca'/> + <feature policy='require' name='osxsave'/> + <feature policy='require' name='f16c'/> + <feature policy='require' name='rdrand'/> + <feature policy='require' name='arat'/> + <feature policy='require' name='tsc_adjust'/> + <feature policy='require' name='cmt'/> + <feature policy='require' name='xsaveopt'/> + <feature policy='require' name='pdpe1gb'/> + <feature policy='require' name='abm'/> + <feature policy='require' name='invtsc'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml new file mode 100644 index 000000000..e90598ec6 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-host.xml @@ -0,0 +1,32 @@ +<cpu> + <arch>x86_64</arch> + <model>Haswell</model> + <vendor>Intel</vendor> + <feature name='vme'/> + <feature name='ds'/> + <feature name='acpi'/> + <feature name='ss'/> + <feature name='ht'/> + <feature name='tm'/> + <feature name='pbe'/> + <feature name='dtes64'/> + <feature name='monitor'/> + <feature name='ds_cpl'/> + <feature name='vmx'/> + <feature name='smx'/> + <feature name='est'/> + <feature name='tm2'/> + <feature name='xtpr'/> + <feature name='pdcm'/> + <feature name='dca'/> + <feature name='osxsave'/> + <feature name='f16c'/> + <feature name='rdrand'/> + <feature name='arat'/> + <feature name='tsc_adjust'/> + <feature name='cmt'/> + <feature name='xsaveopt'/> + <feature name='pdpe1gb'/> + <feature name='abm'/> + <feature name='invtsc'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml new file mode 100644 index 000000000..ccdb79219 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890.xml @@ -0,0 +1,37 @@ +<!-- Intel(R) Xeon(R) CPU E7-8890 v3 @ 2.50GHz --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x0000000f' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000306f4' ebx='0x03400800' ecx='0x7ffefbff' edx='0xbfebfbff'/> + <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c10000'/> + <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x7c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x7c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x7c004143' ebx='0x01c0003f' ecx='0x000001ff' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x7c0fc163' ebx='0x04c0003f' ecx='0x00008fff' edx='0x00000006'/> + <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00002120'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000077' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00003fbb' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/> + <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000003'/> + <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000006' ebx='0x00000024' ecx='0x00000201' edx='0x00000003'/> + <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x00000047' ecx='0x00000000' edx='0x00000002'/> + <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x00012000' ecx='0x00000047' edx='0x00000001'/> + <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000021' edx='0x2c100800'/> + <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x6f655820' edx='0x2952286e'/> + <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x55504320' ebx='0x2d374520' ecx='0x30393838' edx='0x20337620'/> + <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x2e322040' ebx='0x48473035' ecx='0x0000007a' edx='0x00000000'/> + <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> + <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000000' ebx='0x00000047' ecx='0x00000000' edx='0x00000002'/> + <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000000' ebx='0x00000047' ecx='0x00000000' edx='0x00000002'/> +</cpudata> -- 2.11.1

On Thu, Feb 16, 2017 at 03:02:17PM +0100, Jiri Denemark wrote:
This series applies on top of "qemu: Detect host CPU model by asking QEMU on x86_64".
https://bugzilla.redhat.com/show_bug.cgi?id=1406791
Jiri Denemark (2): cpu_x86: Disable TSX on broken models cputest: Add CPUID data for Haswell with TSX
ACK series Pavel

On Fri, Feb 24, 2017 at 14:14:10 +0100, Pavel Hrdina wrote:
On Thu, Feb 16, 2017 at 03:02:17PM +0100, Jiri Denemark wrote:
This series applies on top of "qemu: Detect host CPU model by asking QEMU on x86_64".
https://bugzilla.redhat.com/show_bug.cgi?id=1406791
Jiri Denemark (2): cpu_x86: Disable TSX on broken models cputest: Add CPUID data for Haswell with TSX
ACK series
Thanks, pushed. Jirka
participants (2)
-
Jiri Denemark
-
Pavel Hrdina