From c1a63a5f7bb17f88fea34bc647a0eee7024d05ea Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Tue, 10 Oct 2017 13:34:28 +0200 Subject: [PATCH] qemu: Parse CPU stepping from query-cpu-model-expansion Even though only family and model are used for matching CPUID data with CPU models from cpu_map.xml, stepping is used by x86DataFilterTSX which is supposed to disable TSX on CPU models with broken TSX support. Thus we need to start parsing stepping from QEMU to make sure we don't disable TSX on CPUs which provide working TSX implementation. See the following patch for a real world example of such CPU. Signed-off-by: Jiri Denemark Reviewed-by: John Ferlan --- src/cpu/cpu_x86.c | 16 +++++++++------- src/cpu/cpu_x86.h | 3 ++- src/qemu/qemu_capabilities.c | 5 ++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index b177885f5e..a6cbd45766 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -531,7 +531,8 @@ virCPUx86VendorToCPUID(const char *vendor, static uint32_t x86MakeSignature(unsigned int family, - unsigned int model) + unsigned int model, + unsigned int stepping) { uint32_t sig = 0; @@ -551,6 +552,7 @@ x86MakeSignature(unsigned int family, * * family = eax[27:20] + eax[11:8] * model = eax[19:16] << 4 + eax[7:4] + * stepping = eax[3:0] */ /* extFam */ @@ -570,9 +572,8 @@ x86MakeSignature(unsigned int family, /* Mod */ sig |= (model & 0xf) << 4; - /* Step is irrelevant, it is used to distinguish different revisions - * of the same CPU model - */ + /* Step */ + sig |= stepping & 0xf; return sig; } @@ -1248,7 +1249,7 @@ x86ModelParse(xmlXPathContextPtr ctxt, goto cleanup; } - model->signature = x86MakeSignature(sigFamily, sigModel); + model->signature = x86MakeSignature(sigFamily, sigModel, 0); } if (virXPathBoolean("boolean(./vendor)", ctxt)) { @@ -2971,9 +2972,10 @@ virCPUx86DataAddCPUID(virCPUDataPtr cpuData, int virCPUx86DataSetSignature(virCPUDataPtr cpuData, unsigned int family, - unsigned int model) + unsigned int model, + unsigned int stepping) { - uint32_t signature = x86MakeSignature(family, model); + uint32_t signature = x86MakeSignature(family, model, stepping); return x86DataAddSignature(&cpuData->data.x86, signature); } diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h index 91ec43fea9..5d14d83e1b 100644 --- a/src/cpu/cpu_x86.h +++ b/src/cpu/cpu_x86.h @@ -34,7 +34,8 @@ int virCPUx86DataAddCPUID(virCPUDataPtr cpuData, int virCPUx86DataSetSignature(virCPUDataPtr cpuData, unsigned int family, - unsigned int model); + unsigned int model, + unsigned int stepping); int virCPUx86DataSetVendor(virCPUDataPtr cpuData, const char *vendor); diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4de411e397..6cea1ccfa5 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3353,6 +3353,7 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, virCPUDataPtr data = NULL; unsigned long long sigFamily = 0; unsigned long long sigModel = 0; + unsigned long long sigStepping = 0; int ret = -1; size_t i; @@ -3387,6 +3388,8 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, sigFamily = prop->value.number; else if (STREQ(prop->name, "model")) sigModel = prop->value.number; + else if (STREQ(prop->name, "stepping")) + sigStepping = prop->value.number; break; case QEMU_MONITOR_CPU_PROPERTY_LAST: @@ -3394,7 +3397,7 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, } } - if (virCPUx86DataSetSignature(data, sigFamily, sigModel) < 0) + if (virCPUx86DataSetSignature(data, sigFamily, sigModel, sigStepping) < 0) goto cleanup; if (cpuDecode(cpu, data, virQEMUCapsGetCPUDefinitions(qemuCaps, type)) < 0)