提交 d4952d36 编写于 作者: D Don Dugger 提交者: Eric Blake

Add flag to BaselineCPU API to return detailed CPU features

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_CPU_EXPAND_FEATURES, that causes the API to explicitly
list all features that are part of that model.
Signed-off-by: NDon Dugger <donald.d.dugger@intel.com>
Signed-off-by: NEric Blake <eblake@redhat.com>
上级 10ec6410
......@@ -4007,6 +4007,15 @@ int virConnectCompareCPU(virConnectPtr conn,
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:
*
......
......@@ -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);
}
......@@ -276,7 +276,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;
......@@ -323,7 +324,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);
......@@ -350,7 +351,8 @@ virCPUDefPtr
cpuBaseline(virCPUDefPtr *cpus,
unsigned int ncpus,
const char **models,
unsigned int nmodels)
unsigned int nmodels,
unsigned int flags)
{
struct cpuArchDriver *driver;
size_t i;
......@@ -392,7 +394,7 @@ cpuBaseline(virCPUDefPtr *cpus,
return NULL;
}
return driver->baseline(cpus, ncpus, models, nmodels);
return driver->baseline(cpus, ncpus, models, nmodels, flags);
}
......
......@@ -53,7 +53,8 @@ typedef int
const virCPUDataPtr data,
const char **models,
unsigned int nmodels,
const char *preferred);
const char *preferred,
unsigned int flags);
typedef int
(*cpuArchEncode) (virArch arch,
......@@ -81,7 +82,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,
......@@ -149,13 +151,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,
......
......@@ -44,8 +44,12 @@ ArmDecode(virCPUDefPtr cpu ATTRIBUTE_UNUSED,
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;
}
......
......@@ -113,7 +113,8 @@ static virCPUDefPtr
genericBaseline(virCPUDefPtr *cpus,
unsigned int ncpus,
const char **models,
unsigned int nmodels)
unsigned int nmodels,
unsigned int flags)
{
virCPUDefPtr cpu = NULL;
virCPUFeatureDefPtr features = NULL;
......@@ -121,6 +122,8 @@ genericBaseline(virCPUDefPtr *cpus,
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"),
......
......@@ -304,12 +304,15 @@ ppcDecode(virCPUDefPtr cpu,
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;
......@@ -377,7 +380,8 @@ static virCPUDefPtr
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;
......@@ -385,6 +389,8 @@ ppcBaseline(virCPUDefPtr *cpus,
virCPUDefPtr cpu = NULL;
size_t i;
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);
if (!(map = ppcLoadMap()))
goto error;
......
......@@ -48,8 +48,12 @@ s390Decode(virCPUDefPtr cpu ATTRIBUTE_UNUSED,
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;
}
......
......@@ -1319,13 +1319,42 @@ x86GuestData(virCPUDefPtr host,
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;
......@@ -1334,6 +1363,8 @@ x86Decode(virCPUDefPtr cpu,
virCPUDefPtr cpuModel = NULL;
size_t i;
virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, -1);
if (data == NULL || (map = x86LoadMap()) == NULL)
return -1;
......@@ -1406,6 +1437,9 @@ x86Decode(virCPUDefPtr cpu,
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;
......@@ -1426,9 +1460,10 @@ x86DecodeCPUData(virCPUDefPtr cpu,
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);
}
......@@ -1674,7 +1709,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;
......@@ -1755,7 +1791,7 @@ x86Baseline(virCPUDefPtr *cpus,
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)
......
......@@ -18524,11 +18524,16 @@ error:
* @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 *
......
......@@ -11056,12 +11056,12 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
{
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;
......
......@@ -75,6 +75,7 @@ struct data {
const char *modelsName;
unsigned int nmodels;
const char *preferred;
unsigned int flags;
int result;
};
......@@ -330,7 +331,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)
......@@ -510,12 +511,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; \
......@@ -524,31 +525,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);
......@@ -593,11 +594,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_CPU_EXPAND_FEATURES, 0);
/* CPU features */
DO_TEST_HASFEATURE("x86", "host", "vmx", YES);
......
<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>
<cpuTest>
<cpu>
<arch>x86_64</arch>
<model>Westmere</model>
<topology sockets='1' cores='2' threads='1'/>
</cpu>
</cpuTest>
......@@ -6157,6 +6157,10 @@ static const vshCmdOptDef opts_cpu_baseline[] = {
.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}
};
......@@ -6168,6 +6172,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;
......@@ -6177,6 +6182,9 @@ cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd)
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;
......@@ -6220,7 +6228,7 @@ 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);
if (result) {
vshPrint(ctl, "%s", result);
......
......@@ -485,13 +485,16 @@ cell and the total free memory on the machine. Finally, with a
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>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册