From b2a68c99c4c7f4d202dbb413209a94c6f3231e80 Mon Sep 17 00:00:00 2001 From: Li Zhang Date: Tue, 3 Sep 2013 14:28:24 +0800 Subject: [PATCH] cpu: Implement guestData and update for PPC On Power platform, Power7+ can support Power7 guest. It needs to define XML configuration to specify guest's CPU model. For exmaple: POWER7_v2.1 IBM Signed-off-by: Li Zhang --- 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 35cb9490cb..a47ee38ea8 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) @@ -371,11 +516,36 @@ ppcNodeData(virArch arch) return cpuData; } +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 @@ -477,7 +647,7 @@ struct cpuArchDriver cpuDriverPowerPC = { .encode = NULL, .free = ppcDataFree, .nodeData = ppcNodeData, - .guestData = NULL, + .guestData = ppcGuestData, .baseline = ppcBaseline, .update = ppcUpdate, .hasFeature = NULL, -- GitLab