Currently the virConnectBaselineCPU API does not expose the CPU features that are part of the CPU's model. This patch adds a new flag, VIR_CONNECT_BASELINE_SHOW_MODEL, that causes the API to explictly list all features that are part of that model. Signed-off-by: Don Dugger <donald.d.dugger@xxxxxxxxx> --- include/libvirt/libvirt.h.in | 9 +++++++ src/cpu/cpu.c | 12 +++++---- src/cpu/cpu.h | 12 ++++++--- src/cpu/cpu_arm.c | 3 ++- src/cpu/cpu_generic.c | 3 ++- src/cpu/cpu_powerpc.c | 6 +++-- src/cpu/cpu_s390.c | 3 ++- src/cpu/cpu_x86.c | 39 ++++++++++++++++++++++++--- src/qemu/qemu_driver.c | 4 +-- tests/cputest.c | 30 +++++++++++---------- tests/cputestdata/x86-baseline-3-result.xml | 35 ++++++++++++++++++++++++ tests/cputestdata/x86-baseline-3.xml | 7 +++++ tools/virsh-domain.c | 11 +++++++- 13 files changed, 140 insertions(+), 34 deletions(-) create mode 100644 tests/cputestdata/x86-baseline-3-result.xml create mode 100644 tests/cputestdata/x86-baseline-3.xml diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 1804c93..d0afc65 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -3890,6 +3890,15 @@ int virConnectCompareCPU(virConnectPtr conn, /** + * virConnectBaselineCPUFlags + * + * Flags when getting XML description of a computed CPU + */ +typedef enum { + VIR_CONNECT_BASELINE_SHOW_MODEL = (1 << 0), /* show model features*/ +} virConnectBaselineCPUFlags; + +/** * virConnectBaselineCPU: * * @conn: virConnect connection diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 68125a5..c96f669 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -167,7 +167,7 @@ cpuDecode(virCPUDefPtr cpu, return -1; } - return driver->decode(cpu, data, models, nmodels, preferred); + return driver->decode(cpu, data, models, nmodels, preferred, 0); } @@ -277,7 +277,8 @@ char * cpuBaselineXML(const char **xmlCPUs, unsigned int ncpus, const char **models, - unsigned int nmodels) + unsigned int nmodels, + unsigned int flags) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; @@ -324,7 +325,7 @@ cpuBaselineXML(const char **xmlCPUs, doc = NULL; } - if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels))) + if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels, flags))) goto error; cpustr = virCPUDefFormat(cpu, 0); @@ -353,7 +354,8 @@ virCPUDefPtr cpuBaseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, - unsigned int nmodels) + unsigned int nmodels, + unsigned int flags) { struct cpuArchDriver *driver; unsigned int i; @@ -395,7 +397,7 @@ cpuBaseline(virCPUDefPtr *cpus, return NULL; } - return driver->baseline(cpus, ncpus, models, nmodels); + return driver->baseline(cpus, ncpus, models, nmodels, flags); } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index cba7149..9148871 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -49,7 +49,8 @@ typedef int const union cpuData *data, const char **models, unsigned int nmodels, - const char *preferred); + const char *preferred, + unsigned int flags); typedef int (*cpuArchEncode) (const virCPUDefPtr cpu, @@ -76,7 +77,8 @@ typedef virCPUDefPtr (*cpuArchBaseline) (virCPUDefPtr *cpus, unsigned int ncpus, const char **models, - unsigned int nmodels); + unsigned int nmodels, + unsigned int /* flags */); typedef int (*cpuArchUpdate) (virCPUDefPtr guest, @@ -145,13 +147,15 @@ extern char * cpuBaselineXML(const char **xmlCPUs, unsigned int ncpus, const char **models, - unsigned int nmodels); + unsigned int nmodels, + unsigned int /* flags */); extern virCPUDefPtr cpuBaseline (virCPUDefPtr *cpus, unsigned int ncpus, const char **models, - unsigned int nmodels); + unsigned int nmodels, + unsigned int /* flags */); extern int cpuUpdate (virCPUDefPtr guest, diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index cfe1a23..af1309c 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -48,7 +48,8 @@ ArmDecode(virCPUDefPtr cpu ATTRIBUTE_UNUSED, const union cpuData *data ATTRIBUTE_UNUSED, const char **models ATTRIBUTE_UNUSED, unsigned int nmodels ATTRIBUTE_UNUSED, - const char *preferred ATTRIBUTE_UNUSED) + const char *preferred ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) { return 0; } diff --git a/src/cpu/cpu_generic.c b/src/cpu/cpu_generic.c index 7e3eda2..cad1782 100644 --- a/src/cpu/cpu_generic.c +++ b/src/cpu/cpu_generic.c @@ -115,7 +115,8 @@ static virCPUDefPtr genericBaseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, - unsigned int nmodels) + unsigned int nmodels, + unsigned int flags ATTRIBUTE_UNUSED) { virCPUDefPtr cpu = NULL; virCPUFeatureDefPtr features = NULL; diff --git a/src/cpu/cpu_powerpc.c b/src/cpu/cpu_powerpc.c index d17f9ca..cd468dd 100644 --- a/src/cpu/cpu_powerpc.c +++ b/src/cpu/cpu_powerpc.c @@ -310,7 +310,8 @@ ppcDecode(virCPUDefPtr cpu, const union cpuData *data, const char **models, unsigned int nmodels, - const char *preferred ATTRIBUTE_UNUSED) + const char *preferred ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) { int ret = -1; struct ppc_map *map; @@ -385,7 +386,8 @@ static virCPUDefPtr ppcBaseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, - unsigned int nmodels) + unsigned int nmodels, + unsigned int flags ATTRIBUTE_UNUSED) { struct ppc_map *map = NULL; const struct ppc_model *model; diff --git a/src/cpu/cpu_s390.c b/src/cpu/cpu_s390.c index 998197c..32ab2d9 100644 --- a/src/cpu/cpu_s390.c +++ b/src/cpu/cpu_s390.c @@ -50,7 +50,8 @@ s390Decode(virCPUDefPtr cpu ATTRIBUTE_UNUSED, const union cpuData *data ATTRIBUTE_UNUSED, const char **models ATTRIBUTE_UNUSED, unsigned int nmodels ATTRIBUTE_UNUSED, - const char *preferred ATTRIBUTE_UNUSED) + const char *preferred ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) { return 0; } diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 5d479c2..6cb8263 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1296,13 +1296,43 @@ x86GuestData(virCPUDefPtr host, return x86Compute(host, guest, data, message); } +static void +x86AddFeatures(virCPUDefPtr cpu, + struct x86_map *map) +{ + const struct x86_model *candidate; + const struct x86_feature *feature = map->features; + + candidate = map->models; + while (candidate != NULL) { + if (STREQ(cpu->model, candidate->name)) + break; + candidate = candidate->next; + } + if (!candidate) { + VIR_WARN("Odd, %s not a known CPU model\n", cpu->model); + return; + } + while (feature != NULL) { + if (x86DataIsSubset(candidate->data, feature->data)) { + if (virCPUDefAddFeature(cpu, feature->name, VIR_CPU_FEATURE_REQUIRE) < 0) { + VIR_WARN("CPU model %s, no room for feature %s", cpu->model, feature->name); + return; + } + } + feature = feature->next; + } + return; +} + static int x86Decode(virCPUDefPtr cpu, const union cpuData *data, const char **models, unsigned int nmodels, - const char *preferred) + const char *preferred, + unsigned int flags) { int ret = -1; struct x86_map *map; @@ -1383,6 +1413,8 @@ x86Decode(virCPUDefPtr cpu, goto out; } + if (flags & VIR_CONNECT_BASELINE_SHOW_MODEL) + x86AddFeatures(cpuModel, map); cpu->model = cpuModel->model; cpu->vendor = cpuModel->vendor; cpu->nfeatures = cpuModel->nfeatures; @@ -1610,7 +1642,8 @@ static virCPUDefPtr x86Baseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, - unsigned int nmodels) + unsigned int nmodels, + unsigned int flags) { struct x86_map *map = NULL; struct x86_model *base_model = NULL; @@ -1691,7 +1724,7 @@ x86Baseline(virCPUDefPtr *cpus, if (vendor && x86DataAddCpuid(base_model->data, &vendor->cpuid) < 0) goto no_memory; - if (x86Decode(cpu, base_model->data, models, nmodels, NULL) < 0) + if (x86Decode(cpu, base_model->data, models, nmodels, NULL, flags) < 0) goto error; if (!outputVendor) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4a76f14..b87c73a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10260,9 +10260,9 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED, { char *cpu; - virCheckFlags(0, NULL); + virCheckFlags(VIR_CONNECT_BASELINE_SHOW_MODEL, NULL); - cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0); + cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags); return cpu; } diff --git a/tests/cputest.c b/tests/cputest.c index 0105440..227faa0 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -75,6 +75,7 @@ struct data { const char *modelsName; unsigned int nmodels; const char *preferred; + int flags; int result; }; @@ -331,7 +332,7 @@ cpuTestBaseline(const void *arg) if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus))) goto cleanup; - baseline = cpuBaseline(cpus, ncpus, NULL, 0); + baseline = cpuBaseline(cpus, ncpus, NULL, 0, data->flags); if (data->result < 0) { virResetLastError(); if (!baseline) @@ -512,12 +513,12 @@ mymain(void) } #define DO_TEST(arch, api, name, host, cpu, \ - models, nmodels, preferred, result) \ + models, nmodels, preferred, flags, result) \ do { \ static struct data data = { \ arch, api, host, cpu, models, \ models == NULL ? NULL : #models, \ - nmodels, preferred, result \ + nmodels, preferred, flags, result \ }; \ if (cpuTestRun(name, &data) < 0) \ ret = -1; \ @@ -526,31 +527,31 @@ mymain(void) #define DO_TEST_COMPARE(arch, host, cpu, result) \ DO_TEST(arch, API_COMPARE, \ host "/" cpu " (" #result ")", \ - host, cpu, NULL, 0, NULL, result) + host, cpu, NULL, 0, NULL, 0, result) #define DO_TEST_UPDATE(arch, host, cpu, result) \ do { \ DO_TEST(arch, API_UPDATE, \ cpu " on " host, \ - host, cpu, NULL, 0, NULL, 0); \ + host, cpu, NULL, 0, NULL, 0, 0); \ DO_TEST_COMPARE(arch, host, host "+" cpu, result); \ } while (0) -#define DO_TEST_BASELINE(arch, name, result) \ +#define DO_TEST_BASELINE(arch, name, flags, result) \ DO_TEST(arch, API_BASELINE, name, NULL, "baseline-" name, \ - NULL, 0, NULL, result) + NULL, 0, NULL, flags, result) #define DO_TEST_HASFEATURE(arch, host, feature, result) \ DO_TEST(arch, API_HAS_FEATURE, \ host "/" feature " (" #result ")", \ - host, feature, NULL, 0, NULL, result) + host, feature, NULL, 0, NULL, 0, result) #define DO_TEST_GUESTDATA(arch, host, cpu, models, preferred, result) \ DO_TEST(arch, API_GUEST_DATA, \ host "/" cpu " (" #models ", pref=" #preferred ")", \ host, cpu, models, \ models == NULL ? 0 : sizeof(models) / sizeof(char *), \ - preferred, result) + preferred, 0, result) /* host to host comparison */ DO_TEST_COMPARE("x86", "host", "host", VIR_CPU_COMPARE_IDENTICAL); @@ -594,11 +595,12 @@ mymain(void) DO_TEST_UPDATE("x86", "host", "host-passthrough", VIR_CPU_COMPARE_IDENTICAL); /* computing baseline CPUs */ - DO_TEST_BASELINE("x86", "incompatible-vendors", -1); - DO_TEST_BASELINE("x86", "no-vendor", 0); - DO_TEST_BASELINE("x86", "some-vendors", 0); - DO_TEST_BASELINE("x86", "1", 0); - DO_TEST_BASELINE("x86", "2", 0); + DO_TEST_BASELINE("x86", "incompatible-vendors", 0, -1); + DO_TEST_BASELINE("x86", "no-vendor", 0, 0); + DO_TEST_BASELINE("x86", "some-vendors", 0, 0); + DO_TEST_BASELINE("x86", "1", 0, 0); + DO_TEST_BASELINE("x86", "2", 0, 0); + DO_TEST_BASELINE("x86", "3", VIR_CONNECT_BASELINE_SHOW_MODEL, 0); /* CPU features */ DO_TEST_HASFEATURE("x86", "host", "vmx", YES); diff --git a/tests/cputestdata/x86-baseline-3-result.xml b/tests/cputestdata/x86-baseline-3-result.xml new file mode 100644 index 0000000..d196112 --- /dev/null +++ b/tests/cputestdata/x86-baseline-3-result.xml @@ -0,0 +1,35 @@ +<cpu mode='custom' match='exact'> + <model fallback='allow'>Westmere</model> + <feature policy='require' name='lahf_lm'/> + <feature policy='require' name='lm'/> + <feature policy='require' name='nx'/> + <feature policy='require' name='syscall'/> + <feature policy='require' name='aes'/> + <feature policy='require' name='popcnt'/> + <feature policy='require' name='sse4.2'/> + <feature policy='require' name='sse4.1'/> + <feature policy='require' name='cx16'/> + <feature policy='require' name='ssse3'/> + <feature policy='require' name='pni'/> + <feature policy='require' name='sse2'/> + <feature policy='require' name='sse'/> + <feature policy='require' name='fxsr'/> + <feature policy='require' name='mmx'/> + <feature policy='require' name='clflush'/> + <feature policy='require' name='pse36'/> + <feature policy='require' name='pat'/> + <feature policy='require' name='cmov'/> + <feature policy='require' name='mca'/> + <feature policy='require' name='pge'/> + <feature policy='require' name='mtrr'/> + <feature policy='require' name='sep'/> + <feature policy='require' name='apic'/> + <feature policy='require' name='cx8'/> + <feature policy='require' name='mce'/> + <feature policy='require' name='pae'/> + <feature policy='require' name='msr'/> + <feature policy='require' name='tsc'/> + <feature policy='require' name='pse'/> + <feature policy='require' name='de'/> + <feature policy='require' name='fpu'/> +</cpu> diff --git a/tests/cputestdata/x86-baseline-3.xml b/tests/cputestdata/x86-baseline-3.xml new file mode 100644 index 0000000..7654a1d --- /dev/null +++ b/tests/cputestdata/x86-baseline-3.xml @@ -0,0 +1,7 @@ +<cpuTest> +<cpu> + <arch>x86_64</arch> + <model>Westmere</model> + <topology sockets='1' cores='2' threads='1'/> +</cpu> +</cpuTest> diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 0402aef..0aa8b60 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5986,6 +5986,10 @@ static const vshCmdOptDef opts_cpu_baseline[] = { .flags = VSH_OFLAG_REQ, .help = N_("file containing XML CPU descriptions") }, + {.name = "model_features", + .type = VSH_OT_BOOL, + .help = N_("Show features that are part of the CPU model type") + }, {.name = NULL} }; @@ -5997,6 +6001,7 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) char *buffer; char *result = NULL; const char **list = NULL; + unsigned int flags = 0; int count = 0; xmlDocPtr xml = NULL; @@ -6006,6 +6011,9 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) virBuffer buf = VIR_BUFFER_INITIALIZER; int i; + if (vshCommandOptBool(cmd, "model_features")) + flags |= VIR_CONNECT_BASELINE_SHOW_MODEL; + if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0) return false; @@ -6049,7 +6057,8 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd) list[i] = vshStrdup(ctl, (const char *)xmlBufferContent(xml_buf)); } - result = virConnectBaselineCPU(ctl->conn, list, count, 0); + result = virConnectBaselineCPU(ctl->conn, list, count, flags); +vshPrint(ctl, "result - %p\n", result); if (result) { vshPrint(ctl, "%s", result); -- 1.7.10.4 -- Don Dugger "Censeo Toto nos in Kansa esse decisse." - D. Gale n0ano@xxxxxxxxx Ph: 303/443-3786 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list