/** * virCPUUpdate: * * @arch: CPU architecture * @guest: guest CPU definition to be updated * @host: host CPU definition * * Updates @guest CPU definition according to @host CPU. This is required to * support guest CPU definitions specified relatively to host CPU, such as * CPUs with VIR_CPU_MODE_CUSTOM and optional features or * VIR_CPU_MATCH_MINIMUM, or CPUs with VIR_CPU_MODE_HOST_MODEL. * When the guest CPU was not specified relatively, the function does nothing * and returns success. * * Returns 0 on success, -1 on error. */ int virCPUUpdate(virArch arch, virCPUDefPtr guest, const virCPUDef *host) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s, guest=%p mode=%s model=%s, host=%p model=%s", virArchToString(arch), guest, virCPUModeTypeToString(guest->mode), NULLSTR(guest->model), host, NULLSTR(host ? host->model : NULL)); if (!(driver = cpuGetSubDriver(arch))) return -1; if (guest->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) return 0; if (guest->mode == VIR_CPU_MODE_CUSTOM && guest->match != VIR_CPU_MATCH_MINIMUM) { size_t i; bool optional = false; for (i = 0; i < guest->nfeatures; i++) { if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) { optional = true; break; } } if (!optional) return 0; } /* We get here if guest CPU is either * - host-model * - custom with minimum match * - custom with optional features */ if (!driver->update) { virReportError(VIR_ERR_NO_SUPPORT, _("cannot update guest CPU for %s architecture"), virArchToString(arch)); return -1; } if (driver->update(guest, host) < 0) return -1; VIR_DEBUG("model=%s", NULLSTR(guest->model)); return 0; }
static void virDomainCapsCPUFormat(virBufferPtr buf, virDomainCapsCPUPtr cpu) { virBufferAddLit(buf, "<cpu>\n"); virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "<mode name='%s' supported='%s'/>\n", virCPUModeTypeToString(VIR_CPU_MODE_HOST_PASSTHROUGH), cpu->hostPassthrough ? "yes" : "no"); virBufferAsprintf(buf, "<mode name='%s' ", virCPUModeTypeToString(VIR_CPU_MODE_HOST_MODEL)); if (cpu->hostModel) { virBufferAddLit(buf, "supported='yes'>\n"); virBufferAdjustIndent(buf, 2); virCPUDefFormatBuf(buf, cpu->hostModel, false); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</mode>\n"); } else { virBufferAddLit(buf, "supported='no'/>\n"); } virBufferAsprintf(buf, "<mode name='%s' ", virCPUModeTypeToString(VIR_CPU_MODE_CUSTOM)); if (cpu->custom && cpu->custom->nmodels) { virBufferAddLit(buf, "supported='yes'>\n"); virDomainCapsCPUCustomFormat(buf, cpu->custom); virBufferAddLit(buf, "</mode>\n"); } else { virBufferAddLit(buf, "supported='no'/>\n"); } virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</cpu>\n"); }
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))) { virReportError(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))) { virReportError(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", virArchToString(def->arch)); virBufferAdjustIndent(buf, 2); if (virCPUDefFormatBuf(buf, def, flags) < 0) return -1; virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</cpu>\n"); 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; }
bool virCPUDefIsEqual(virCPUDefPtr src, virCPUDefPtr dst, bool reportError) { bool identical = false; size_t i; if (!src && !dst) return true; #define MISMATCH(fmt, ...) \ if (reportError) \ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, fmt, __VA_ARGS__) if ((src && !dst) || (!src && dst)) { MISMATCH("%s", _("Target CPU does not match source")); goto cleanup; } if (src->type != dst->type) { MISMATCH(_("Target CPU type %s does not match source %s"), virCPUTypeToString(dst->type), virCPUTypeToString(src->type)); goto cleanup; } if (src->mode != dst->mode) { MISMATCH(_("Target CPU mode %s does not match source %s"), virCPUModeTypeToString(dst->mode), virCPUModeTypeToString(src->mode)); goto cleanup; } if (src->check != dst->check) { MISMATCH(_("Target CPU check %s does not match source %s"), virCPUCheckTypeToString(dst->check), virCPUCheckTypeToString(src->check)); goto cleanup; } if (src->arch != dst->arch) { MISMATCH(_("Target CPU arch %s does not match source %s"), virArchToString(dst->arch), virArchToString(src->arch)); goto cleanup; } if (STRNEQ_NULLABLE(src->model, dst->model)) { MISMATCH(_("Target CPU model %s does not match source %s"), NULLSTR(dst->model), NULLSTR(src->model)); goto cleanup; } if (STRNEQ_NULLABLE(src->vendor, dst->vendor)) { MISMATCH(_("Target CPU vendor %s does not match source %s"), NULLSTR(dst->vendor), NULLSTR(src->vendor)); goto cleanup; } if (STRNEQ_NULLABLE(src->vendor_id, dst->vendor_id)) { MISMATCH(_("Target CPU vendor id %s does not match source %s"), NULLSTR(dst->vendor_id), NULLSTR(src->vendor_id)); goto cleanup; } if (src->sockets != dst->sockets) { MISMATCH(_("Target CPU sockets %d does not match source %d"), dst->sockets, src->sockets); goto cleanup; } if (src->cores != dst->cores) { MISMATCH(_("Target CPU cores %d does not match source %d"), dst->cores, src->cores); goto cleanup; } if (src->threads != dst->threads) { MISMATCH(_("Target CPU threads %d does not match source %d"), dst->threads, src->threads); goto cleanup; } if (src->nfeatures != dst->nfeatures) { MISMATCH(_("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)) { MISMATCH(_("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) { MISMATCH(_("Target CPU feature policy %s does not match source %s"), virCPUFeaturePolicyTypeToString(dst->features[i].policy), virCPUFeaturePolicyTypeToString(src->features[i].policy)); goto cleanup; } } if ((src->cache && !dst->cache) || (!src->cache && dst->cache) || (src->cache && dst->cache && (src->cache->level != dst->cache->level || src->cache->mode != dst->cache->mode))) { MISMATCH("%s", _("Target CPU cache does not match source")); goto cleanup; } #undef MISMATCH identical = true; cleanup: return identical; }
int virCPUDefFormatBufFull(virBufferPtr buf, virCPUDefPtr def, virDomainNumaPtr numa) { int ret = -1; virBuffer attributeBuf = VIR_BUFFER_INITIALIZER; virBuffer childrenBuf = VIR_BUFFER_INITIALIZER; if (!def) return 0; /* Format attributes for guest CPUs unless they only specify * topology or cache. */ if (def->type == VIR_CPU_TYPE_GUEST && (def->mode != VIR_CPU_MODE_CUSTOM || def->model)) { const char *tmp; if (!(tmp = virCPUModeTypeToString(def->mode))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU mode %d"), def->mode); goto cleanup; } virBufferAsprintf(&attributeBuf, " mode='%s'", tmp); if (def->mode == VIR_CPU_MODE_CUSTOM) { if (!(tmp = virCPUMatchTypeToString(def->match))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected CPU match policy %d"), def->match); goto cleanup; } virBufferAsprintf(&attributeBuf, " match='%s'", tmp); } if (def->check) { virBufferAsprintf(&attributeBuf, " check='%s'", virCPUCheckTypeToString(def->check)); } } /* Format children */ virBufferSetChildIndent(&childrenBuf, buf); if (def->type == VIR_CPU_TYPE_HOST && def->arch) virBufferAsprintf(&childrenBuf, "<arch>%s</arch>\n", virArchToString(def->arch)); if (virCPUDefFormatBuf(&childrenBuf, def) < 0) goto cleanup; if (virDomainNumaDefCPUFormatXML(&childrenBuf, numa) < 0) goto cleanup; if (virBufferCheckError(&attributeBuf) < 0 || virBufferCheckError(&childrenBuf) < 0) goto cleanup; /* Put it all together */ if (virBufferUse(&attributeBuf) || virBufferUse(&childrenBuf)) { virBufferAddLit(buf, "<cpu"); if (virBufferUse(&attributeBuf)) virBufferAddBuffer(buf, &attributeBuf); if (virBufferUse(&childrenBuf)) { virBufferAddLit(buf, ">\n"); virBufferAddBuffer(buf, &childrenBuf); virBufferAddLit(buf, "</cpu>\n"); } else { virBufferAddLit(buf, "/>\n"); } } ret = 0; cleanup: virBufferFreeAndReset(&attributeBuf); virBufferFreeAndReset(&childrenBuf); return ret; }