static struct ppc64_model * ppc64ModelCopy(const struct ppc64_model *model) { struct ppc64_model *copy; if (VIR_ALLOC(copy) < 0 || VIR_STRDUP(copy->name, model->name) < 0) { ppc64ModelFree(copy); return NULL; } copy->data.pvr = model->data.pvr; copy->vendor = model->vendor; return copy; }
static void ppc64MapFree(struct ppc64_map *map) { size_t i; if (!map) return; for (i = 0; i < map->nmodels; i++) ppc64ModelFree(map->models[i]); VIR_FREE(map->models); for (i = 0; i < map->nvendors; i++) ppc64VendorFree(map->vendors[i]); VIR_FREE(map->vendors); VIR_FREE(map); }
static void ppc64MapFree(struct ppc64_map *map) { if (map == NULL) return; while (map->models != NULL) { struct ppc64_model *model = map->models; map->models = model->next; ppc64ModelFree(model); } while (map->vendors != NULL) { struct ppc64_vendor *vendor = map->vendors; map->vendors = vendor->next; ppc64VendorFree(vendor); } VIR_FREE(map); }
static struct ppc64_model * ppc64ModelFromCPU(const virCPUDef *cpu, const struct ppc64_map *map) { struct ppc64_model *model = NULL; if ((model = ppc64ModelFind(map, cpu->model)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown CPU model %s"), cpu->model); goto error; } if ((model = ppc64ModelCopy(model)) == NULL) goto error; return model; error: ppc64ModelFree(model); return NULL; }
static struct ppc64_model * ppc64ModelCopy(const struct ppc64_model *model) { struct ppc64_model *copy; if (VIR_ALLOC(copy) < 0) goto error; if (VIR_STRDUP(copy->name, model->name) < 0) goto error; if (ppc64DataCopy(©->data, &model->data) < 0) goto error; copy->vendor = model->vendor; return copy; error: ppc64ModelFree(copy); return NULL; }
static virCPUCompareResult ppc64Compute(virCPUDefPtr host, const virCPUDef *other, virCPUDataPtr *guestData, char **message) { struct ppc64_map *map = NULL; struct ppc64_model *host_model = NULL; struct ppc64_model *guest_model = NULL; virCPUDefPtr cpu = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; virArch arch; size_t i; /* Ensure existing configurations are handled correctly */ if (!(cpu = virCPUDefCopy(other)) || virCPUppc64ConvertLegacy(cpu) < 0) goto cleanup; 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 cleanup; ret = VIR_CPU_COMPARE_INCOMPATIBLE; goto cleanup; } 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 cleanup; ret = VIR_CPU_COMPARE_INCOMPATIBLE; goto cleanup; } if (!(map = ppc64LoadMap())) goto cleanup; /* Host CPU information */ if (!(host_model = ppc64ModelFromCPU(host, map))) goto cleanup; if (cpu->type == VIR_CPU_TYPE_GUEST) { /* Guest CPU information */ virCPUCompareResult tmp; switch (cpu->mode) { case VIR_CPU_MODE_HOST_MODEL: /* host-model only: * we need to take compatibility modes into account */ tmp = ppc64CheckCompatibilityMode(host->model, cpu->model); if (tmp != VIR_CPU_COMPARE_IDENTICAL) { ret = tmp; goto cleanup; } /* fallthrough */ case VIR_CPU_MODE_HOST_PASSTHROUGH: /* host-model and host-passthrough: * the guest CPU is the same as the host */ guest_model = ppc64ModelCopy(host_model); break; case VIR_CPU_MODE_CUSTOM: /* custom: * look up guest CPU information */ guest_model = ppc64ModelFromCPU(cpu, map); break; } } else { /* Other host CPU information */ guest_model = ppc64ModelFromCPU(cpu, map); } if (!guest_model) goto cleanup; if (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 cleanup; ret = VIR_CPU_COMPARE_INCOMPATIBLE; goto cleanup; } if (guestData) if (!(*guestData = ppc64MakeCPUData(arch, &guest_model->data))) goto cleanup; ret = VIR_CPU_COMPARE_IDENTICAL; cleanup: virCPUDefFree(cpu); ppc64MapFree(map); ppc64ModelFree(host_model); ppc64ModelFree(guest_model); return ret; }
static struct ppc64_model * ppc64ModelParse(xmlXPathContextPtr ctxt, struct ppc64_map *map) { struct ppc64_model *model; xmlNodePtr *nodes = NULL; char *vendor = NULL; unsigned long pvr; size_t i; int n; if (VIR_ALLOC(model) < 0) goto error; model->name = virXPathString("string(@name)", ctxt); if (!model->name) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU model name")); goto error; } if (ppc64ModelFind(map, model->name)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("CPU model %s already defined"), model->name); goto error; } if (virXPathBoolean("boolean(./vendor)", ctxt)) { vendor = virXPathString("string(./vendor/@name)", ctxt); if (!vendor) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid vendor element in CPU model %s"), model->name); goto error; } if (!(model->vendor = ppc64VendorFind(map, vendor))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown vendor %s referenced by CPU model %s"), vendor, model->name); goto error; } } if ((n = virXPathNodeSet("./pvr", ctxt, &nodes)) <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing PVR information for CPU model %s"), model->name); goto error; } if (VIR_ALLOC_N(model->data.pvr, n) < 0) goto error; model->data.len = n; for (i = 0; i < n; i++) { ctxt->node = nodes[i]; if (virXPathULongHex("string(./@value)", ctxt, &pvr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing or invalid PVR value in CPU model %s"), model->name); goto error; } model->data.pvr[i].value = pvr; if (virXPathULongHex("string(./@mask)", ctxt, &pvr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing or invalid PVR mask in CPU model %s"), model->name); goto error; } model->data.pvr[i].mask = pvr; } cleanup: VIR_FREE(vendor); VIR_FREE(nodes); return model; error: ppc64ModelFree(model); model = NULL; goto cleanup; }
static virCPUCompareResult ppc64Compute(virCPUDefPtr host, const virCPUDef *cpu, virCPUDataPtr *guestData, char **message) { struct ppc64_map *map = NULL; struct ppc64_model *host_model = NULL; struct ppc64_model *guest_model = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; 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 cleanup; ret = VIR_CPU_COMPARE_INCOMPATIBLE; goto cleanup; } 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 cleanup; ret = VIR_CPU_COMPARE_INCOMPATIBLE; goto cleanup; } if (!(map = ppc64LoadMap()) || !(host_model = ppc64ModelFromCPU(host, map)) || !(guest_model = ppc64ModelFromCPU(cpu, map))) goto cleanup; 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 cleanup; ret = VIR_CPU_COMPARE_INCOMPATIBLE; goto cleanup; } if (!(*guestData = ppc64MakeCPUData(arch, &guest_model->data))) goto cleanup; } ret = VIR_CPU_COMPARE_IDENTICAL; cleanup: ppc64MapFree(map); ppc64ModelFree(host_model); ppc64ModelFree(guest_model); return ret; }
static int ppc64ModelLoad(xmlXPathContextPtr ctxt, struct ppc64_map *map) { struct ppc64_model *model; char *vendor = NULL; unsigned long pvr; if (VIR_ALLOC(model) < 0) return -1; model->name = virXPathString("string(@name)", ctxt); if (!model->name) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU model name")); goto ignore; } if (ppc64ModelFind(map, model->name)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("CPU model %s already defined"), model->name); goto ignore; } if (virXPathBoolean("boolean(./vendor)", ctxt)) { vendor = virXPathString("string(./vendor/@name)", ctxt); if (!vendor) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid vendor element in CPU model %s"), model->name); goto ignore; } if (!(model->vendor = ppc64VendorFind(map, vendor))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown vendor %s referenced by CPU model %s"), vendor, model->name); goto ignore; } } if (!virXPathBoolean("boolean(./pvr)", ctxt) || virXPathULongHex("string(./pvr/@value)", ctxt, &pvr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Missing or invalid PVR value in CPU model %s"), model->name); goto ignore; } model->data.pvr = pvr; if (map->models == NULL) { map->models = model; } else { model->next = map->models; map->models = model; } cleanup: VIR_FREE(vendor); return 0; ignore: ppc64ModelFree(model); goto cleanup; }