From: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
On Power platform, Power7+ can support Power7 guest.
It needs to define XML configuration to specify guest's CPU model.
For exmaple:
<cpu match='exact'>
<model>POWER7_v2.1</model>
<vendor>IBM</vendor>
</cpu>
Signed-off-by: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
---
src/cpu/cpu_powerpc.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 174 insertions(+), 4 deletions(-)
diff --git a/src/cpu/cpu_powerpc.c b/src/cpu/cpu_powerpc.c
index 647a8a1..62a789e 100644
--- a/src/cpu/cpu_powerpc.c
+++ b/src/cpu/cpu_powerpc.c
@@ -99,6 +99,23 @@ ppcModelFindPVR(const struct ppc_map *map,
return NULL;
}
+static struct ppc_model *
+ppcModelCopy(const struct ppc_model *model)
+{
+ struct ppc_model *copy;
+
+ if (VIR_ALLOC(copy) < 0 ||
+ VIR_STRDUP(copy->name, model->name) < 0) {
+ ppcModelFree(copy);
+ return NULL;
+ }
+
+ copy->data.pvr = model->data.pvr;
+ copy->vendor = model->vendor;
+
+ return copy;
+}
+
static struct ppc_vendor *
ppcVendorFind(const struct ppc_map *map,
const char *name)
@@ -126,6 +143,29 @@ ppcVendorFree(struct ppc_vendor *vendor)
VIR_FREE(vendor);
}
+static struct ppc_model *
+ppcModelFromCPU(const virCPUDefPtr cpu,
+ const struct ppc_map *map)
+{
+ struct ppc_model *model = NULL;
+
+ if ((model = ppcModelFind(map, cpu->model)) == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown CPU model %s"), cpu->model);
+ goto error;
+ }
+
+ if ((model = ppcModelCopy(model)) == NULL)
+ goto error;
+
+ return model;
+
+error:
+ ppcModelFree(model);
+ return NULL;
+}
+
+
static int
ppcVendorLoad(xmlXPathContextPtr ctxt,
struct ppc_map *map)
@@ -288,6 +328,111 @@ error:
return NULL;
}
+static virCPUDataPtr
+ppcMakeCPUData(virArch arch, struct cpuPPCData *data)
+{
+ virCPUDataPtr cpuData;
+
+ if (VIR_ALLOC(cpuData) < 0)
+ return NULL;
+
+ cpuData->arch = arch;
+ cpuData->data.ppc = *data;
+ data = NULL;
+
+ return cpuData;
+}
+
+static virCPUCompareResult
+ppcCompute(virCPUDefPtr host,
+ const virCPUDefPtr cpu,
+ virCPUDataPtr *guestData,
+ char **message)
+
+{
+ struct ppc_map *map = NULL;
+ struct ppc_model *host_model = NULL;
+ struct ppc_model *guest_model = NULL;
+
+ int ret = 0;
+ virArch arch;
+ size_t i;
+
+ if (cpu->arch != VIR_ARCH_NONE) {
+ bool found = false;
+
+ for (i = 0; i < ARRAY_CARDINALITY(archs); i++) {
+ if (archs[i] == cpu->arch) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ VIR_DEBUG("CPU arch %s does not match host arch",
+ virArchToString(cpu->arch));
+ if (message &&
+ virAsprintf(message,
+ _("CPU arch %s does not match host arch"),
+ virArchToString(cpu->arch)) < 0)
+ goto error;
+ return VIR_CPU_COMPARE_INCOMPATIBLE;
+ }
+ arch = cpu->arch;
+ } else {
+ arch = host->arch;
+ }
+
+ if (cpu->vendor &&
+ (!host->vendor || STRNEQ(cpu->vendor, host->vendor))) {
+ VIR_DEBUG("host CPU vendor does not match required CPU vendor %s",
+ cpu->vendor);
+ if (message &&
+ virAsprintf(message,
+ _("host CPU vendor does not match required "
+ "CPU vendor %s"),
+ cpu->vendor) < 0)
+ goto error;
+ return VIR_CPU_COMPARE_INCOMPATIBLE;
+ }
+
+ if (!(map = ppcLoadMap()) ||
+ !(host_model = ppcModelFromCPU(host, map)) ||
+ !(guest_model = ppcModelFromCPU(cpu, map)))
+ goto error;
+
+ if (guestData != NULL) {
+ if (cpu->type == VIR_CPU_TYPE_GUEST &&
+ cpu->match == VIR_CPU_MATCH_STRICT &&
+ STRNEQ(guest_model->name, host_model->name)) {
+ VIR_DEBUG("host CPU model does not match required CPU model %s",
+ guest_model->name);
+ if (message &&
+ virAsprintf(message,
+ _("host CPU model does not match required "
+ "CPU model %s"),
+ guest_model->name) < 0)
+ goto error;
+ return VIR_CPU_COMPARE_INCOMPATIBLE;
+ }
+
+ if (!(*guestData = ppcMakeCPUData(arch, &guest_model->data)))
+ goto error;
+ }
+
+ ret = VIR_CPU_COMPARE_IDENTICAL;
+
+out:
+ ppcMapFree(map);
+ ppcModelFree(host_model);
+ ppcModelFree(guest_model);
+ return ret;
+
+error:
+ ret = VIR_CPU_COMPARE_ERROR;
+ goto out;
+}
+
static virCPUCompareResult
ppcCompare(virCPUDefPtr host,
virCPUDefPtr cpu)
@@ -369,11 +514,36 @@ ppcNodeData(void)
}
#endif
+static virCPUCompareResult
+ppcGuestData(virCPUDefPtr host,
+ virCPUDefPtr guest,
+ virCPUDataPtr *data,
+ char **message)
+{
+ return ppcCompute(host, guest, data, message);
+}
+
static int
-ppcUpdate(virCPUDefPtr guest ATTRIBUTE_UNUSED,
- const virCPUDefPtr host ATTRIBUTE_UNUSED)
+ppcUpdate(virCPUDefPtr guest,
+ const virCPUDefPtr host)
{
- return 0;
+ switch ((enum virCPUMode) guest->mode) {
+ case VIR_CPU_MODE_HOST_MODEL:
+ case VIR_CPU_MODE_HOST_PASSTHROUGH:
+ guest->match = VIR_CPU_MATCH_EXACT;
+ virCPUDefFreeModel(guest);
+ return virCPUDefCopyModel(guest, host, true);
+
+ case VIR_CPU_MODE_CUSTOM:
+ return 0;
+
+ case VIR_CPU_MODE_LAST:
+ break;
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected CPU mode: %d"), guest->mode);
+ return -1;
}
static virCPUDefPtr
@@ -479,7 +649,7 @@ struct cpuArchDriver cpuDriverPowerPC = {
#else
.nodeData = NULL,
#endif
- .guestData = NULL,
+ .guestData = ppcGuestData,
.baseline = ppcBaseline,
.update = ppcUpdate,
.hasFeature = NULL,
--
1.8.1.4