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(a)intel.com>
---
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(a)n0ano.com
Ph: 303/443-3786