virCPUDefPtr cpuBaseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, unsigned int nmodels) { struct cpuArchDriver *driver; unsigned int i; VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels); if (cpus) { for (i = 0; i < ncpus; i++) VIR_DEBUG("cpus[%u]=%p", i, cpus[i]); } if (models) { for (i = 0; i < nmodels; i++) VIR_DEBUG("models[%u]=%s", i, NULLSTR(models[i])); } if (cpus == NULL && ncpus != 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nonzero ncpus doesn't match with NULL cpus")); return NULL; } if (ncpus < 1) { virCPUReportError(VIR_ERR_INVALID_ARG, "%s", _("No CPUs given")); return NULL; } if (models == NULL && nmodels != 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nonzero nmodels doesn't match with NULL models")); return NULL; } if ((driver = cpuGetSubDriver(cpus[0]->arch)) == NULL) return NULL; if (driver->baseline == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot compute baseline CPU of %s architecture"), cpus[0]->arch); return NULL; } return driver->baseline(cpus, ncpus, models, nmodels); }
int virCPUDefAddFeature(virCPUDefPtr def, const char *name, int policy) { int i; for (i = 0 ; i < def->nfeatures ; i++) { if (STREQ(name, def->features[i].name)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU feature `%s' specified more than once"), name); return -1; } } if (VIR_RESIZE_N(def->features, def->nfeatures_max, def->nfeatures, 1) < 0) goto no_memory; if (def->type == VIR_CPU_TYPE_HOST) policy = -1; if (!(def->features[def->nfeatures].name = strdup(name))) goto no_memory; def->features[def->nfeatures].policy = policy; def->nfeatures++; return 0; no_memory: virReportOOMError(); return -1; }
int cpuEncode(const char *arch, const virCPUDefPtr cpu, union cpuData **forced, union cpuData **required, union cpuData **optional, union cpuData **disabled, union cpuData **forbidden, union cpuData **vendor) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s, cpu=%p, forced=%p, required=%p, " "optional=%p, disabled=%p, forbidden=%p, vendor=%p", NULLSTR(arch), cpu, forced, required, optional, disabled, forbidden, vendor); if ((driver = cpuGetSubDriver(arch)) == NULL) return -1; if (driver->encode == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot encode CPU data for %s architecture"), arch); return -1; } return driver->encode(cpu, forced, required, optional, disabled, forbidden, vendor); }
virCPUCompareResult cpuCompareXML(virCPUDefPtr host, const char *xml) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; VIR_DEBUG("host=%p, xml=%s", host, NULLSTR(xml)); if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt))) goto cleanup; cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO); if (cpu == NULL) goto cleanup; if (!cpu->model) { virCPUReportError(VIR_ERR_OPERATION_INVALID, "%s", _("no CPU model specified")); goto cleanup; } ret = cpuCompare(host, cpu); cleanup: virCPUDefFree(cpu); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); return ret; }
int virCPUDefFormatBufFull(virBufferPtr buf, virCPUDefPtr def, unsigned int flags) { if (!def) return 0; virBufferAddLit(buf, "<cpu"); if (def->type == VIR_CPU_TYPE_GUEST) { const char *tmp; if (def->mode != VIR_CPU_MODE_CUSTOM || def->model) { if (!(tmp = virCPUModeTypeToString(def->mode))) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU mode %d"), def->mode); return -1; } virBufferAsprintf(buf, " mode='%s'", tmp); } if (def->model && (def->mode == VIR_CPU_MODE_CUSTOM || (flags & VIR_DOMAIN_XML_UPDATE_CPU))) { if (!(tmp = virCPUMatchTypeToString(def->match))) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU match policy %d"), def->match); return -1; } virBufferAsprintf(buf, " match='%s'", tmp); } } virBufferAddLit(buf, ">\n"); if (def->arch) virBufferAsprintf(buf, " <arch>%s</arch>\n", def->arch); virBufferAdjustIndent(buf, 2); if (virCPUDefFormatBuf(buf, def, flags) < 0) return -1; virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</cpu>\n"); return 0; }
int cpuDecode(virCPUDefPtr cpu, const union cpuData *data, const char **models, unsigned int nmodels, const char *preferred) { struct cpuArchDriver *driver; 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++) VIR_DEBUG("models[%u]=%s", i, NULLSTR(models[i])); } if (models == NULL && nmodels != 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nonzero nmodels doesn't match with NULL models")); return -1; } if (cpu == NULL) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("invalid CPU definition")); return -1; } if ((driver = cpuGetSubDriver(cpu->arch)) == NULL) return -1; if (driver->decode == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot decode CPU data for %s architecture"), cpu->arch); return -1; } return driver->decode(cpu, data, models, nmodels, preferred); }
union cpuData * cpuNodeData(const char *arch) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s", NULLSTR(arch)); if ((driver = cpuGetSubDriver(arch)) == NULL) return NULL; if (driver->nodeData == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot get node CPU data for %s architecture"), arch); return NULL; } return driver->nodeData(); }
int cpuUpdate(virCPUDefPtr guest, const virCPUDefPtr host) { struct cpuArchDriver *driver; VIR_DEBUG("guest=%p, host=%p", guest, host); if ((driver = cpuGetSubDriver(host->arch)) == NULL) return -1; if (driver->update == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot update guest CPU data for %s architecture"), host->arch); return -1; } return driver->update(guest, host); }
virCPUCompareResult cpuCompare(virCPUDefPtr host, virCPUDefPtr cpu) { struct cpuArchDriver *driver; VIR_DEBUG("host=%p, cpu=%p", host, cpu); if ((driver = cpuGetSubDriver(host->arch)) == NULL) return VIR_CPU_COMPARE_ERROR; if (driver->compare == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot compare CPUs of %s architecture"), host->arch); return VIR_CPU_COMPARE_ERROR; } return driver->compare(host, cpu); }
virCPUCompareResult cpuGuestData(virCPUDefPtr host, virCPUDefPtr guest, union cpuData **data) { struct cpuArchDriver *driver; VIR_DEBUG("host=%p, guest=%p, data=%p", host, guest, data); if ((driver = cpuGetSubDriver(host->arch)) == NULL) return VIR_CPU_COMPARE_ERROR; if (driver->guestData == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot compute guest CPU data for %s architecture"), host->arch); return VIR_CPU_COMPARE_ERROR; } return driver->guestData(host, guest, data); }
static struct cpuArchDriver * cpuGetSubDriver(const char *arch) { unsigned int i; unsigned int j; if (arch == NULL) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("undefined hardware architecture")); return NULL; } for (i = 0; i < NR_DRIVERS - 1; i++) { for (j = 0; j < drivers[i]->narch; j++) { if (STREQ(arch, drivers[i]->arch[j])) return drivers[i]; } } /* use generic driver by default */ return drivers[NR_DRIVERS - 1]; }
int cpuHasFeature(const char *arch, const union cpuData *data, const char *feature) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s, data=%p, feature=%s", arch, data, feature); if ((driver = cpuGetSubDriver(arch)) == NULL) return -1; if (driver->hasFeature == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot check guest CPU data for %s architecture"), arch); return -1; } return driver->hasFeature(data, feature); }
void cpuDataFree(const char *arch, union cpuData *data) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s, data=%p", NULLSTR(arch), data); if (data == NULL) return; if ((driver = cpuGetSubDriver(arch)) == NULL) return; if (driver->free == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot free CPU data for %s architecture"), arch); return; } (driver->free)(data); }
static virCPUDefPtr genericBaseline(virCPUDefPtr *cpus, unsigned int ncpus, const char **models, unsigned int nmodels) { virCPUDefPtr cpu = NULL; virCPUFeatureDefPtr features = NULL; unsigned int nfeatures; unsigned int count; unsigned int i, j; if (models) { bool found = false; for (i = 0; i < nmodels; i++) { if (STREQ(cpus[0]->model, models[i])) { found = true; break; } } if (!found) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU model '%s' is not support by hypervisor"), cpus[0]->model); goto error; } } if (VIR_ALLOC(cpu) < 0 || !(cpu->arch = strdup(cpus[0]->arch)) || !(cpu->model = strdup(cpus[0]->model)) || VIR_ALLOC_N(features, cpus[0]->nfeatures) < 0) goto no_memory; cpu->type = VIR_CPU_TYPE_HOST; count = nfeatures = cpus[0]->nfeatures; for (i = 0; i < nfeatures; i++) features[i].name = cpus[0]->features[i].name; for (i = 1; i < ncpus; i++) { virHashTablePtr hash; if (STRNEQ(cpu->arch, cpus[i]->arch)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPUs have incompatible architectures: '%s' != '%s'"), cpu->arch, cpus[i]->arch); goto error; } if (STRNEQ(cpu->model, cpus[i]->model)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU models don't match: '%s' != '%s'"), cpu->model, cpus[i]->model); goto error; } if (!(hash = genericHashFeatures(cpus[i]))) goto no_memory; for (j = 0; j < nfeatures; j++) { if (features[j].name && !virHashLookup(hash, features[j].name)) { features[j].name = NULL; count--; } } virHashFree(hash); } if (VIR_ALLOC_N(cpu->features, count) < 0) goto no_memory; cpu->nfeatures = count; j = 0; for (i = 0; i < nfeatures; i++) { if (!features[i].name) continue; if (!(cpu->features[j++].name = strdup(features[i].name))) goto no_memory; } cleanup: VIR_FREE(features); return cpu; no_memory: virReportOOMError(); error: virCPUDefFree(cpu); cpu = NULL; goto cleanup; }
virCPUDefPtr virCPUDefParseXML(const xmlNodePtr node, xmlXPathContextPtr ctxt, enum virCPUType mode) { virCPUDefPtr def; xmlNodePtr *nodes = NULL; int n; unsigned int i; if (!xmlStrEqual(node->name, BAD_CAST "cpu")) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("XML does not contain expected 'cpu' element")); return NULL; } if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } if (mode == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { virCPUReportError(VIR_ERR_XML_ERROR, "%s", _("'arch' element element cannot be used inside 'cpu'" " element with 'match' attribute'")); goto error; } def->type = VIR_CPU_TYPE_HOST; } else def->type = VIR_CPU_TYPE_GUEST; } else def->type = mode; if (def->type == VIR_CPU_TYPE_GUEST) { char *match = virXMLPropString(node, "match"); if (!match) { if (virXPathBoolean("boolean(./model)", ctxt)) def->match = VIR_CPU_MATCH_EXACT; else def->match = -1; } else { def->match = virCPUMatchTypeFromString(match); VIR_FREE(match); if (def->match < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid match attribute for CPU specification")); goto error; } } } if (def->type == VIR_CPU_TYPE_HOST) { def->arch = virXPathString("string(./arch[1])", ctxt); if (!def->arch) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU architecture")); goto error; } } if (!(def->model = virXPathString("string(./model[1])", ctxt)) && def->type == VIR_CPU_TYPE_HOST) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU model name")); goto error; } def->vendor = virXPathString("string(./vendor[1])", ctxt); if (def->vendor && !def->model) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("CPU vendor specified without CPU model")); goto error; } if (virXPathNode("./topology[1]", ctxt)) { int ret; unsigned long ul; ret = virXPathULong("string(./topology[1]/@sockets)", ctxt, &ul); if (ret < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'sockets' attribute in CPU topology")); goto error; } def->sockets = (unsigned int) ul; ret = virXPathULong("string(./topology[1]/@cores)", ctxt, &ul); if (ret < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'cores' attribute in CPU topology")); goto error; } def->cores = (unsigned int) ul; ret = virXPathULong("string(./topology[1]/@threads)", ctxt, &ul); if (ret < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'threads' attribute in CPU topology")); goto error; } def->threads = (unsigned int) ul; if (!def->sockets || !def->cores || !def->threads) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU topology")); goto error; } } n = virXPathNodeSet("./feature", ctxt, &nodes); if (n < 0) goto error; if (n > 0) { if (!def->model) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Non-empty feature list specified without CPU model")); goto error; } if (VIR_RESIZE_N(def->features, def->nfeatures_max, def->nfeatures, n) < 0) goto no_memory; def->nfeatures = n; } for (i = 0 ; i < n ; i++) { char *name; int policy; /* enum virDomainCPUFeaturePolicy */ unsigned int j; if (def->type == VIR_CPU_TYPE_GUEST) { char *strpolicy; strpolicy = virXMLPropString(nodes[i], "policy"); if (strpolicy == NULL) policy = VIR_CPU_FEATURE_REQUIRE; else policy = virCPUFeaturePolicyTypeFromString(strpolicy); VIR_FREE(strpolicy); if (policy < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature policy")); goto error; } } else policy = -1; if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) { VIR_FREE(name); virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature name")); goto error; } for (j = 0 ; j < i ; j++) { if (STREQ(name, def->features[j].name)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU feature `%s' specified more than once"), name); VIR_FREE(name); goto error; } } def->features[i].name = name; def->features[i].policy = policy; } cleanup: VIR_FREE(nodes); return def; no_memory: virReportOOMError(); error: virCPUDefFree(def); def = NULL; goto cleanup; }
char * cpuBaselineXML(const char **xmlCPUs, unsigned int ncpus, const char **models, unsigned int nmodels) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr *cpus = NULL; virCPUDefPtr cpu = NULL; char *cpustr; unsigned int i; VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels); if (xmlCPUs) { for (i = 0; i < ncpus; i++) VIR_DEBUG("xmlCPUs[%u]=%s", i, NULLSTR(xmlCPUs[i])); } if (models) { for (i = 0; i < nmodels; i++) VIR_DEBUG("models[%u]=%s", i, NULLSTR(models[i])); } if (xmlCPUs == NULL && ncpus != 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nonzero ncpus doesn't match with NULL xmlCPUs")); return NULL; } if (ncpus < 1) { virCPUReportError(VIR_ERR_INVALID_ARG, "%s", _("No CPUs given")); return NULL; } if (VIR_ALLOC_N(cpus, ncpus)) goto no_memory; for (i = 0; i < ncpus; i++) { if (!(doc = virXMLParseStringCtxt(xmlCPUs[i], _("(CPU_definition)"), &ctxt))) goto error; cpus[i] = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_HOST); if (cpus[i] == NULL) goto error; xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); ctxt = NULL; doc = NULL; } if (!(cpu = cpuBaseline(cpus, ncpus, models, nmodels))) goto error; cpustr = virCPUDefFormat(cpu, 0); cleanup: if (cpus) { for (i = 0; i < ncpus; i++) virCPUDefFree(cpus[i]); VIR_FREE(cpus); } virCPUDefFree(cpu); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); return cpustr; no_memory: virReportOOMError(); error: cpustr = NULL; goto cleanup; }
int virCPUDefFormatBuf(virBufferPtr buf, virCPUDefPtr def, const char *indent, int flags) { unsigned int i; if (!def) return 0; if (indent == NULL) indent = ""; if (!def->model && def->nfeatures) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Non-empty feature list specified without CPU model")); return -1; } if (!(flags & VIR_CPU_FORMAT_EMBEDED)) { if (def->type == VIR_CPU_TYPE_GUEST && def->model) { const char *match; if (!(match = virCPUMatchTypeToString(def->match))) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU match policy %d"), def->match); return -1; } virBufferAsprintf(buf, "%s<cpu match='%s'>\n", indent, match); } else virBufferAsprintf(buf, "%s<cpu>\n", indent); if (def->arch) virBufferAsprintf(buf, "%s <arch>%s</arch>\n", indent, def->arch); } if (def->model) virBufferAsprintf(buf, "%s <model>%s</model>\n", indent, def->model); if (def->vendor) { virBufferAsprintf(buf, "%s <vendor>%s</vendor>\n", indent, def->vendor); } if (def->sockets && def->cores && def->threads) { virBufferAsprintf(buf, "%s <topology", indent); virBufferAsprintf(buf, " sockets='%u'", def->sockets); virBufferAsprintf(buf, " cores='%u'", def->cores); virBufferAsprintf(buf, " threads='%u'", def->threads); virBufferAddLit(buf, "/>\n"); } for (i = 0 ; i < def->nfeatures ; i++) { virCPUFeatureDefPtr feature = def->features + i; if (!feature->name) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU feature name")); return -1; } if (def->type == VIR_CPU_TYPE_GUEST) { const char *policy; policy = virCPUFeaturePolicyTypeToString(feature->policy); if (!policy) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU feature policy %d"), feature->policy); return -1; } virBufferAsprintf(buf, "%s <feature policy='%s' name='%s'/>\n", indent, policy, feature->name); } else { virBufferAsprintf(buf, "%s <feature name='%s'/>\n", indent, feature->name); } } if (!(flags & VIR_CPU_FORMAT_EMBEDED)) virBufferAsprintf(buf, "%s</cpu>\n", indent); return 0; }
bool virCPUDefIsEqual(virCPUDefPtr src, virCPUDefPtr dst) { bool identical = false; int i; if (!src && !dst) return true; if ((src && !dst) || (!src && dst)) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Target CPU does not match source")); goto cleanup; } if (src->type != dst->type) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU type %s does not match source %s"), virCPUTypeToString(dst->type), virCPUTypeToString(src->type)); goto cleanup; } if (src->mode != dst->mode) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU mode %s does not match source %s"), virCPUModeTypeToString(dst->mode), virCPUModeTypeToString(src->mode)); goto cleanup; } if (STRNEQ_NULLABLE(src->arch, dst->arch)) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU arch %s does not match source %s"), NULLSTR(dst->arch), NULLSTR(src->arch)); goto cleanup; } if (STRNEQ_NULLABLE(src->model, dst->model)) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU model %s does not match source %s"), NULLSTR(dst->model), NULLSTR(src->model)); goto cleanup; } if (STRNEQ_NULLABLE(src->vendor, dst->vendor)) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU vendor %s does not match source %s"), NULLSTR(dst->vendor), NULLSTR(src->vendor)); goto cleanup; } if (src->sockets != dst->sockets) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU sockets %d does not match source %d"), dst->sockets, src->sockets); goto cleanup; } if (src->cores != dst->cores) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU cores %d does not match source %d"), dst->cores, src->cores); goto cleanup; } if (src->threads != dst->threads) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU threads %d does not match source %d"), dst->threads, src->threads); goto cleanup; } if (src->nfeatures != dst->nfeatures) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU feature count %zu does not match source %zu"), dst->nfeatures, src->nfeatures); goto cleanup; } for (i = 0 ; i < src->nfeatures ; i++) { if (STRNEQ(src->features[i].name, dst->features[i].name)) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU feature %s does not match source %s"), dst->features[i].name, src->features[i].name); goto cleanup; } if (src->features[i].policy != dst->features[i].policy) { virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target CPU feature policy %s does not match source %s"), virCPUFeaturePolicyTypeToString(dst->features[i].policy), virCPUFeaturePolicyTypeToString(src->features[i].policy)); goto cleanup; } } identical = true; cleanup: return identical; }
virCPUDefPtr virCPUDefParseXML(const xmlNodePtr node, xmlXPathContextPtr ctxt, enum virCPUType mode) { virCPUDefPtr def; xmlNodePtr *nodes = NULL; int n; unsigned int i; char *cpuMode; if (!xmlStrEqual(node->name, BAD_CAST "cpu")) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("XML does not contain expected 'cpu' element")); return NULL; } if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; } if (mode == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { virCPUReportError(VIR_ERR_XML_ERROR, "%s", _("'arch' element element cannot be used inside 'cpu'" " element with 'match' attribute'")); goto error; } def->type = VIR_CPU_TYPE_HOST; } else { def->type = VIR_CPU_TYPE_GUEST; } } else { def->type = mode; } if ((cpuMode = virXMLPropString(node, "mode"))) { if (def->type == VIR_CPU_TYPE_HOST) { VIR_FREE(cpuMode); virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Attribute mode is only allowed for guest CPU")); goto error; } else { def->mode = virCPUModeTypeFromString(cpuMode); if (def->mode < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid mode attribute '%s'"), cpuMode); VIR_FREE(cpuMode); goto error; } VIR_FREE(cpuMode); } } else { if (def->type == VIR_CPU_TYPE_HOST) def->mode = -1; else def->mode = VIR_CPU_MODE_CUSTOM; } if (def->type == VIR_CPU_TYPE_GUEST) { char *match = virXMLPropString(node, "match"); if (!match) { if (virXPathBoolean("boolean(./model)", ctxt)) def->match = VIR_CPU_MATCH_EXACT; else def->match = -1; } else { def->match = virCPUMatchTypeFromString(match); VIR_FREE(match); if (def->match < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid match attribute for CPU specification")); goto error; } } } if (def->type == VIR_CPU_TYPE_HOST) { def->arch = virXPathString("string(./arch[1])", ctxt); if (!def->arch) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU architecture")); goto error; } } if (!(def->model = virXPathString("string(./model[1])", ctxt)) && def->type == VIR_CPU_TYPE_HOST) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU model name")); goto error; } if (def->type == VIR_CPU_TYPE_GUEST && def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH && virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) { const char *fallback; fallback = virXPathString("string(./model[1]/@fallback)", ctxt); if (fallback) { def->fallback = virCPUFallbackTypeFromString(fallback); VIR_FREE(fallback); if (def->fallback < 0) { virCPUReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid fallback attribute")); goto error; } } } def->vendor = virXPathString("string(./vendor[1])", ctxt); if (def->vendor && !def->model) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("CPU vendor specified without CPU model")); goto error; } if (virXPathNode("./topology[1]", ctxt)) { int ret; unsigned long ul; ret = virXPathULong("string(./topology[1]/@sockets)", ctxt, &ul); if (ret < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'sockets' attribute in CPU topology")); goto error; } def->sockets = (unsigned int) ul; ret = virXPathULong("string(./topology[1]/@cores)", ctxt, &ul); if (ret < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'cores' attribute in CPU topology")); goto error; } def->cores = (unsigned int) ul; ret = virXPathULong("string(./topology[1]/@threads)", ctxt, &ul); if (ret < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'threads' attribute in CPU topology")); goto error; } def->threads = (unsigned int) ul; if (!def->sockets || !def->cores || !def->threads) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU topology")); goto error; } } n = virXPathNodeSet("./feature", ctxt, &nodes); if (n < 0) goto error; if (n > 0) { if (!def->model) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Non-empty feature list specified without CPU model")); goto error; } if (VIR_RESIZE_N(def->features, def->nfeatures_max, def->nfeatures, n) < 0) goto no_memory; def->nfeatures = n; } for (i = 0 ; i < n ; i++) { char *name; int policy; /* enum virDomainCPUFeaturePolicy */ unsigned int j; if (def->type == VIR_CPU_TYPE_GUEST) { char *strpolicy; strpolicy = virXMLPropString(nodes[i], "policy"); if (strpolicy == NULL) policy = VIR_CPU_FEATURE_REQUIRE; else policy = virCPUFeaturePolicyTypeFromString(strpolicy); VIR_FREE(strpolicy); if (policy < 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature policy")); goto error; } } else { policy = -1; } if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) { VIR_FREE(name); virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid CPU feature name")); goto error; } for (j = 0 ; j < i ; j++) { if (STREQ(name, def->features[j].name)) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("CPU feature `%s' specified more than once"), name); VIR_FREE(name); goto error; } } def->features[i].name = name; def->features[i].policy = policy; } if (virXPathNode("./numa[1]", ctxt)) { VIR_FREE(nodes); n = virXPathNodeSet("./numa[1]/cell", ctxt, &nodes); if (n <= 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("NUMA topology defined without NUMA cells")); goto error; } if (VIR_RESIZE_N(def->cells, def->ncells_max, def->ncells, n) < 0) goto no_memory; def->ncells = n; for (i = 0 ; i < n ; i++) { char *cpus, *memory; int cpumasklen = VIR_DOMAIN_CPUMASK_LEN; int ret, ncpus = 0; def->cells[i].cellid = i; cpus = virXMLPropString(nodes[i], "cpus"); if (!cpus) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'cpus' attribute in NUMA cell")); goto error; } def->cells[i].cpustr = cpus; if (VIR_ALLOC_N(def->cells[i].cpumask, cpumasklen) < 0) goto no_memory; ncpus = virDomainCpuSetParse(cpus, 0, def->cells[i].cpumask, cpumasklen); if (ncpus <= 0) goto error; def->cells_cpus += ncpus; memory = virXMLPropString(nodes[i], "memory"); if (!memory) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing 'memory' attribute in NUMA cell")); goto error; } ret = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem); if (ret == -1) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid 'memory' attribute in NUMA cell")); VIR_FREE(memory); goto error; } VIR_FREE(memory); } } cleanup: VIR_FREE(nodes); return def; no_memory: virReportOOMError(); error: virCPUDefFree(def); def = NULL; goto cleanup; }
int virCPUDefFormatBuf(virBufferPtr buf, virCPUDefPtr def, unsigned int flags) { unsigned int i; bool formatModel; bool formatFallback; if (!def) return 0; formatModel = (def->mode == VIR_CPU_MODE_CUSTOM || (flags & VIR_DOMAIN_XML_UPDATE_CPU)); formatFallback = (def->type == VIR_CPU_TYPE_GUEST && (def->mode == VIR_CPU_MODE_HOST_MODEL || (def->mode == VIR_CPU_MODE_CUSTOM && def->model))); if (!def->model && def->nfeatures) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Non-empty feature list specified without CPU model")); return -1; } if ((formatModel && def->model) || formatFallback) { virBufferAddLit(buf, "<model"); if (formatFallback) { const char *fallback; fallback = virCPUFallbackTypeToString(def->fallback); if (!fallback) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU fallback value: %d"), def->fallback); return -1; } virBufferAsprintf(buf, " fallback='%s'", fallback); } if (formatModel && def->model) { virBufferAsprintf(buf, ">%s</model>\n", def->model); } else { virBufferAddLit(buf, "/>\n"); } } if (formatModel && def->vendor) virBufferAsprintf(buf, "<vendor>%s</vendor>\n", def->vendor); if (def->sockets && def->cores && def->threads) { virBufferAddLit(buf, "<topology"); virBufferAsprintf(buf, " sockets='%u'", def->sockets); virBufferAsprintf(buf, " cores='%u'", def->cores); virBufferAsprintf(buf, " threads='%u'", def->threads); virBufferAddLit(buf, "/>\n"); } if (formatModel) { for (i = 0 ; i < def->nfeatures ; i++) { virCPUFeatureDefPtr feature = def->features + i; if (!feature->name) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing CPU feature name")); return -1; } if (def->type == VIR_CPU_TYPE_GUEST) { const char *policy; policy = virCPUFeaturePolicyTypeToString(feature->policy); if (!policy) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU feature policy %d"), feature->policy); return -1; } virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n", policy, feature->name); } else { virBufferAsprintf(buf, "<feature name='%s'/>\n", feature->name); } } } if (def->ncells) { virBufferAddLit(buf, "<numa>\n"); for (i = 0; i < def->ncells; i++) { virBufferAddLit(buf, " <cell"); virBufferAsprintf(buf, " cpus='%s'", def->cells[i].cpustr); virBufferAsprintf(buf, " memory='%d'", def->cells[i].mem); virBufferAddLit(buf, "/>\n"); } virBufferAddLit(buf, "</numa>\n"); } return 0; }