unsigned int flags);
+/**
+ * virConnectBaselineCPUFlags
+ *
+ * Flags when getting XML description of a computed CPU
+ */
+typedef enum {
+ VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES = (1 << 0), /* show all features */
+} virConnectBaselineCPUFlags;
+
/**
* virConnectBaselineCPU:
*
return -1;
}
- return driver->decode(cpu, data, models, nmodels, preferred);
+ return driver->decode(cpu, data, models, nmodels, preferred, 0);
}
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;
doc = NULL;
}
- if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels)))
+ if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels, flags)))
goto error;
cpustr = virCPUDefFormat(cpu, 0);
cpuBaseline(virCPUDefPtr *cpus,
unsigned int ncpus,
const char **models,
- unsigned int nmodels)
+ unsigned int nmodels,
+ unsigned int flags)
{
struct cpuArchDriver *driver;
size_t i;
return NULL;
}
- return driver->baseline(cpus, ncpus, models, nmodels);
+ return driver->baseline(cpus, ncpus, models, nmodels, flags);
}
const virCPUDataPtr data,
const char **models,
unsigned int nmodels,
- const char *preferred);
+ const char *preferred,
+ unsigned int flags);
typedef int
(*cpuArchEncode) (virArch arch,
(*cpuArchBaseline) (virCPUDefPtr *cpus,
unsigned int ncpus,
const char **models,
- unsigned int nmodels);
+ unsigned int nmodels,
+ unsigned int flags);
typedef int
(*cpuArchUpdate) (virCPUDefPtr guest,
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,
const virCPUDataPtr 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)
{
+
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
+
return 0;
}
genericBaseline(virCPUDefPtr *cpus,
unsigned int ncpus,
const char **models,
- unsigned int nmodels)
+ unsigned int nmodels,
+ unsigned int flags)
{
virCPUDefPtr cpu = NULL;
virCPUFeatureDefPtr features = NULL;
unsigned int count;
size_t i, j;
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
+
if (!cpuModelIsAllowed(cpus[0]->model, models, nmodels)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("CPU model %s is not supported by hypervisor"),
const virCPUDataPtr data,
const char **models,
unsigned int nmodels,
- const char *preferred ATTRIBUTE_UNUSED)
+ const char *preferred ATTRIBUTE_UNUSED,
+ unsigned int flags)
{
int ret = -1;
struct ppc_map *map;
const struct ppc_model *model;
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
+
if (data == NULL || (map = ppcLoadMap()) == NULL)
return -1;
ppcBaseline(virCPUDefPtr *cpus,
unsigned int ncpus,
const char **models,
- unsigned int nmodels)
+ unsigned int nmodels,
+ unsigned int flags)
{
struct ppc_map *map = NULL;
const struct ppc_model *model;
virCPUDefPtr cpu = NULL;
size_t i;
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
+
if (!(map = ppcLoadMap()))
goto error;
const virCPUDataPtr 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)
{
+
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
+
return 0;
}
return x86Compute(host, guest, data, message);
}
+static int
+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) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%s not a known CPU model"), cpu->model);
+ return -1;
+ }
+ while (feature != NULL) {
+ if (x86DataIsSubset(candidate->data, feature->data) &&
+ virCPUDefAddFeature(cpu, feature->name,
+ VIR_CPU_FEATURE_REQUIRE) < 0)
+ return -1;
+ feature = feature->next;
+ }
+ return 0;
+}
+
static int
x86Decode(virCPUDefPtr cpu,
const struct cpuX86Data *data,
const char **models,
unsigned int nmodels,
- const char *preferred)
+ const char *preferred,
+ unsigned int flags)
{
int ret = -1;
struct x86_map *map;
virCPUDefPtr cpuModel = NULL;
size_t i;
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
+
if (data == NULL || (map = x86LoadMap()) == NULL)
return -1;
goto out;
}
+ if (flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES &&
+ x86AddFeatures(cpuModel, map) < 0)
+ goto out;
cpu->model = cpuModel->model;
cpu->vendor = cpuModel->vendor;
cpu->nfeatures = cpuModel->nfeatures;
const virCPUDataPtr data,
const char **models,
unsigned int nmodels,
- const char *preferred)
+ const char *preferred,
+ unsigned int flags)
{
- return x86Decode(cpu, data->data.x86, models, nmodels, preferred);
+ return x86Decode(cpu, data->data.x86, models, nmodels, preferred, flags);
}
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;
if (vendor && x86DataAddCpuid(base_model->data, &vendor->cpuid) < 0)
goto error;
- 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)
* @conn: virConnect connection
* @xmlCPUs: array of XML descriptions of host CPUs
* @ncpus: number of CPUs in xmlCPUs
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virConnectBaselineCPUFlags
*
* Computes the most feature-rich CPU which is compatible with all given
* host CPUs.
*
+ * If @flags includes VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES then libvirt
+ * will explicitly list all CPU features that are part of the host CPU,
+ * without this flag features that are part of the CPU model will not be
+ * listed.
+ *
* Returns XML description of the computed CPU or NULL on error.
*/
char *
{
char *cpu = NULL;
- virCheckFlags(0, NULL);
+ virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
if (virConnectBaselineCPUEnsureACL(conn) < 0)
goto cleanup;
- cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0);
+ cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);
cleanup:
return cpu;
const char *modelsName;
unsigned int nmodels;
const char *preferred;
+ unsigned int flags;
int result;
};
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)
}
#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; \
#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);
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_CPU_EXPAND_FEATURES, 0);
/* CPU features */
DO_TEST_HASFEATURE("x86", "host", "vmx", YES);
--- /dev/null
+<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>
--- /dev/null
+<cpuTest>
+<cpu>
+ <arch>x86_64</arch>
+ <model>Westmere</model>
+ <topology sockets='1' cores='2' threads='1'/>
+</cpu>
+</cpuTest>
.flags = VSH_OFLAG_REQ,
.help = N_("file containing XML CPU descriptions")
},
+ {.name = "features",
+ .type = VSH_OT_BOOL,
+ .help = N_("Show features that are part of the CPU model type")
+ },
{.name = NULL}
};
char *buffer;
char *result = NULL;
const char **list = NULL;
+ unsigned int flags = 0;
int count = 0;
xmlDocPtr xml = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
size_t i;
+ if (vshCommandOptBool(cmd, "features"))
+ flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES;
+
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
list[i] = vshStrdup(ctl, (const char *)xmlBufferContent(xml_buf));
}
- result = virConnectBaselineCPU(ctl->conn, list, count, 0);
+ result = virConnectBaselineCPU(ctl->conn, list, count, flags);
if (result) {
vshPrint(ctl, "%s", result);
numeric argument or with --cellno plus a cell number it will display
the free memory for the specified cell only.
-=item B<cpu-baseline> I<FILE>
+=item B<cpu-baseline> I<FILE> [I<--features>]
Compute baseline CPU which will be supported by all host CPUs given in <file>.
The list of host CPUs is built by extracting all <cpu> elements from the
<file>. Thus, the <file> can contain either a set of <cpu> elements separated
by new lines or even a set of complete <capabilities> elements printed by
-B<capabilities> command.
+B<capabilities> command. If I<--features> is specified then the
+resulting XML description will explicitly include all features that make
+up the CPU, without this option features that are part of the CPU model
+will not be listed in the XML description.
=item B<cpu-compare> I<FILE>