Adds ability to provide a preferred CPU model for CPUID data decoding.
Such model would be considered as the best possible model (if it's
supported by hypervisor) regardless on number of features which have to
be added or removed for describing required CPU.
---
src/cpu/cpu.c | 8 +++++---
src/cpu/cpu.h | 6 ++++--
src/cpu/cpu_x86.c | 11 +++++++++--
src/qemu/qemu_conf.c | 10 ++++++++--
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 4a1588d..580b767 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -127,11 +127,13 @@ int
cpuDecode(virCPUDefPtr cpu,
const union cpuData *data,
const char **models,
- unsigned int nmodels)
+ unsigned int nmodels,
+ const char *preferred)
{
struct cpuArchDriver *driver;
- VIR_DEBUG("cpu=%p, data=%p, nmodels=%u", cpu, data, nmodels);
+ VIR_DEBUG("cpu=%p, data=%p, nmodels=%u, preferred=%s",
+ cpu, data, nmodels, NULLSTR(preferred));
if (models) {
unsigned int i;
for (i = 0; i < nmodels; i++)
@@ -160,7 +162,7 @@ cpuDecode(virCPUDefPtr cpu,
return -1;
}
- return driver->decode(cpu, data, models, nmodels);
+ return driver->decode(cpu, data, models, nmodels, preferred);
}
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 1494a7f..40f2a7d 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -49,7 +49,8 @@ typedef int
(*cpuArchDecode) (virCPUDefPtr cpu,
const union cpuData *data,
const char **models,
- unsigned int nmodels);
+ unsigned int nmodels,
+ const char *preferred);
typedef int
(*cpuArchEncode) (const virCPUDefPtr cpu,
@@ -108,7 +109,8 @@ extern int
cpuDecode (virCPUDefPtr cpu,
const union cpuData *data,
const char **models,
- unsigned int nmodels);
+ unsigned int nmodels,
+ const char *preferred);
extern int
cpuEncode (const char *arch,
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index b2ca8c8..633eb69 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -1064,7 +1064,8 @@ static int
x86Decode(virCPUDefPtr cpu,
const union cpuData *data,
const char **models,
- unsigned int nmodels)
+ unsigned int nmodels,
+ const char *preferred)
{
int ret = -1;
struct x86_map *map;
@@ -1109,6 +1110,12 @@ x86Decode(virCPUDefPtr cpu,
}
}
+ if (preferred && STREQ(cpuCandidate->model, preferred)) {
+ virCPUDefFree(cpuModel);
+ cpuModel = cpuCandidate;
+ break;
+ }
+
if (cpuModel == NULL
|| cpuModel->nfeatures > cpuCandidate->nfeatures) {
virCPUDefFree(cpuModel);
@@ -1356,7 +1363,7 @@ x86Baseline(virCPUDefPtr *cpus,
if (!(data = x86DataFromModel(base_model)))
goto no_memory;
- if (x86Decode(cpu, data, models, nmodels) < 0)
+ if (x86Decode(cpu, data, models, nmodels, NULL) < 0)
goto error;
cleanup:
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 669d10d..afb63f3 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1029,7 +1029,7 @@ qemudCapsInitCPU(virCapsPtr caps,
cpu->threads = nodeinfo.threads;
if (!(data = cpuNodeData(arch))
- || cpuDecode(cpu, data, NULL, 0) < 0)
+ || cpuDecode(cpu, data, NULL, 0, NULL) < 0)
goto error;
caps->host.cpu = cpu;
@@ -3292,6 +3292,7 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
if (ncpus > 0 && host) {
virCPUCompareResult cmp;
+ const char *preferred;
cmp = cpuGuestData(host, def->cpu, &data);
switch (cmp) {
@@ -3309,8 +3310,13 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(ut->machine)))
goto no_memory;
+ if (def->cpu->match == VIR_CPU_MATCH_MINIMUM)
+ preferred = host->model;
+ else
+ preferred = def->cpu->model;
+
guest->type = VIR_CPU_TYPE_GUEST;
- if (cpuDecode(guest, data, cpus, ncpus) < 0)
+ if (cpuDecode(guest, data, cpus, ncpus, preferred) < 0)
goto cleanup;
virBufferVSprintf(&buf, "%s", guest->model);
--
1.7.0.4