diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 3aa348cf6f..8fabe8deb5 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -385,6 +385,12 @@ struct _virQEMUCaps { size_t ngicCapabilities; virGICCapability *gicCapabilities; + + /* Anything below is not stored in the cache since the values are + * re-computed from the other fields or external data sources every + * time we probe QEMU or load the results from the cache. + */ + virCPUDefPtr hostCPUModel; }; struct virQEMUCapsSearchData { @@ -2113,6 +2119,10 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) goto error; } + if (qemuCaps->hostCPUModel && + !(ret->hostCPUModel = virCPUDefCopy(qemuCaps->hostCPUModel))) + goto error; + if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0) goto error; ret->nmachineTypes = qemuCaps->nmachineTypes; @@ -2157,6 +2167,8 @@ void virQEMUCapsDispose(void *obj) VIR_FREE(qemuCaps->binary); VIR_FREE(qemuCaps->gicCapabilities); + + virCPUDefFree(qemuCaps->hostCPUModel); } void @@ -2902,6 +2914,38 @@ int virQEMUCapsProbeQMP(virQEMUCapsPtr qemuCaps, } +void +virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + virCapsHostPtr host) +{ + virCPUDefPtr cpu = NULL; + + if (!virQEMUCapsGuestIsNative(host->arch, qemuCaps->arch)) + goto error; + + if (host->cpu && host->cpu->model) { + if (VIR_ALLOC(cpu) < 0) + goto error; + + cpu->sockets = cpu->cores = cpu->threads = 0; + cpu->type = VIR_CPU_TYPE_GUEST; + cpu->mode = VIR_CPU_MODE_CUSTOM; + cpu->match = VIR_CPU_MATCH_EXACT; + + if (virCPUDefCopyModel(cpu, host->cpu, true) < 0) + goto error; + } + + qemuCaps->hostCPUModel = cpu; + return; + + error: + virCPUDefFree(cpu); + qemuCaps->hostCPUModel = NULL; + virResetLastError(); +} + + /* * Parsing a doc that looks like * @@ -2920,8 +2964,11 @@ int virQEMUCapsProbeQMP(virQEMUCapsPtr qemuCaps, * */ int -virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, const char *filename, - time_t *qemuctime, time_t *selfctime, +virQEMUCapsLoadCache(virCapsPtr caps, + virQEMUCapsPtr qemuCaps, + const char *filename, + time_t *qemuctime, + time_t *selfctime, unsigned long *selfvers) { xmlDocPtr doc = NULL; @@ -3154,6 +3201,8 @@ virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, const char *filename, } VIR_FREE(nodes); + virQEMUCapsInitHostCPUModel(qemuCaps, &caps->host); + ret = 0; cleanup: VIR_FREE(str); @@ -3344,7 +3393,9 @@ virQEMUCapsReset(virQEMUCapsPtr qemuCaps) static int -virQEMUCapsInitCached(virQEMUCapsPtr qemuCaps, const char *cacheDir) +virQEMUCapsInitCached(virCapsPtr caps, + virQEMUCapsPtr qemuCaps, + const char *cacheDir) { char *capsdir = NULL; char *capsfile = NULL; @@ -3386,8 +3437,8 @@ virQEMUCapsInitCached(virQEMUCapsPtr qemuCaps, const char *cacheDir) goto cleanup; } - if (virQEMUCapsLoadCache(qemuCaps, capsfile, &qemuctime, &selfctime, - &selfvers) < 0) { + if (virQEMUCapsLoadCache(caps, qemuCaps, capsfile, + &qemuctime, &selfctime, &selfvers) < 0) { VIR_WARN("Failed to load cached caps from '%s' for '%s': %s", capsfile, qemuCaps->binary, virGetLastErrorMessage()); virResetLastError(); @@ -3871,7 +3922,7 @@ virQEMUCapsLogProbeFailure(const char *binary) virQEMUCapsPtr -virQEMUCapsNewForBinaryInternal(virCapsPtr caps ATTRIBUTE_UNUSED, +virQEMUCapsNewForBinaryInternal(virCapsPtr caps, const char *binary, const char *libDir, const char *cacheDir, @@ -3911,7 +3962,7 @@ virQEMUCapsNewForBinaryInternal(virCapsPtr caps ATTRIBUTE_UNUSED, if (!cacheDir) rv = 0; - else if ((rv = virQEMUCapsInitCached(qemuCaps, cacheDir)) < 0) + else if ((rv = virQEMUCapsInitCached(caps, qemuCaps, cacheDir)) < 0) goto error; if (rv == 0) { @@ -3937,16 +3988,18 @@ virQEMUCapsNewForBinaryInternal(virCapsPtr caps ATTRIBUTE_UNUSED, if (cacheDir && virQEMUCapsRememberCached(qemuCaps, cacheDir) < 0) goto error; + + virQEMUCapsInitHostCPUModel(qemuCaps, &caps->host); } + cleanup: VIR_FREE(qmperr); return qemuCaps; error: - VIR_FREE(qmperr); virObjectUnref(qemuCaps); qemuCaps = NULL; - return NULL; + goto cleanup; } static virQEMUCapsPtr diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h index ac3693b5ca..22c5a8ae5b 100644 --- a/src/qemu/qemu_capspriv.h +++ b/src/qemu/qemu_capspriv.h @@ -48,7 +48,8 @@ virQEMUCapsNewForBinaryInternal(virCapsPtr caps, gid_t runGid, bool qmpOnly); -int virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, +int virQEMUCapsLoadCache(virCapsPtr caps, + virQEMUCapsPtr qemuCaps, const char *filename, time_t *qemuctime, time_t *selfctime, @@ -60,4 +61,8 @@ char *virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps, void virQEMUCapsSetArch(virQEMUCapsPtr qemuCaps, virArch arch); + +void +virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + virCapsHostPtr host); #endif diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 511066d9ab..99971c27d1 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -173,9 +173,13 @@ fillQemuCaps(virDomainCapsPtr domCaps, virQEMUCapsPtr qemuCaps = NULL; virDomainCapsLoaderPtr loader = &domCaps->os.loader; + if (!(caps = virCapabilitiesNew(domCaps->arch, false, false)) || + fakeHostCPU(caps, domCaps->arch) < 0) + goto cleanup; + if (virAsprintf(&path, "%s/qemucapabilitiesdata/%s.%s.xml", abs_srcdir, name, arch) < 0 || - !(qemuCaps = qemuTestParseCapabilities(path))) + !(qemuCaps = qemuTestParseCapabilities(caps, path))) goto cleanup; if (machine && @@ -188,10 +192,6 @@ fillQemuCaps(virDomainCapsPtr domCaps, virQEMUCapsGetDefaultMachine(qemuCaps)) < 0) goto cleanup; - if (!(caps = virCapabilitiesNew(domCaps->arch, false, false)) || - fakeHostCPU(caps, domCaps->arch) < 0) - goto cleanup; - if (virQEMUCapsFillDomainCaps(caps, domCaps, qemuCaps, cfg->firmwares, cfg->nfirmwares) < 0) diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c index 3924bce811..10cfa43768 100644 --- a/tests/qemucapabilitiestest.c +++ b/tests/qemucapabilitiestest.c @@ -97,7 +97,7 @@ testQemuCapsCopy(const void *opaque) false, false))) goto cleanup; - if (!(orig = qemuTestParseCapabilities(capsFile))) + if (!(orig = qemuTestParseCapabilities(caps, capsFile))) goto cleanup; if (!(copy = virQEMUCapsNewCopy(orig))) diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 156a45a9d5..7080484a6e 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -347,7 +347,8 @@ testInitQEMUCaps(struct testInfo *info, static int testUpdateQEMUCaps(const struct testInfo *info, - virDomainObjPtr vm) + virDomainObjPtr vm, + virCapsPtr caps) { int ret = -1; @@ -356,6 +357,8 @@ testUpdateQEMUCaps(const struct testInfo *info, if (testAddCPUModels(info->qemuCaps, info->skipLegacyCPUs) < 0) goto cleanup; + virQEMUCapsInitHostCPUModel(info->qemuCaps, &caps->host); + virQEMUCapsFilterByMachineType(info->qemuCaps, vm->def->os.machine); if (ARCH_IS_X86(vm->def->os.arch)) @@ -448,7 +451,7 @@ testCompareXMLToArgv(const void *data) goto cleanup; } - if (testUpdateQEMUCaps(info, vm) < 0) + if (testUpdateQEMUCaps(info, vm, driver.caps) < 0) goto cleanup; log = virTestLogContentAndReset(); diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index 8c2c8b4624..e66903a3b0 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -491,7 +491,8 @@ qemuTestSetHostCPU(virCapsPtr caps, virQEMUCapsPtr -qemuTestParseCapabilities(const char *capsFile) +qemuTestParseCapabilities(virCapsPtr caps, + const char *capsFile) { virQEMUCapsPtr qemuCaps = NULL; time_t qemuctime; @@ -499,7 +500,7 @@ qemuTestParseCapabilities(const char *capsFile) unsigned long version; if (!(qemuCaps = virQEMUCapsNew()) || - virQEMUCapsLoadCache(qemuCaps, capsFile, + virQEMUCapsLoadCache(caps, qemuCaps, capsFile, &qemuctime, &selfctime, &version) < 0) goto error; diff --git a/tests/testutilsqemu.h b/tests/testutilsqemu.h index 6d35116f36..047a64d1ac 100644 --- a/tests/testutilsqemu.h +++ b/tests/testutilsqemu.h @@ -15,7 +15,8 @@ enum { virCapsPtr testQemuCapsInit(void); virDomainXMLOptionPtr testQemuXMLConfInit(void); -virQEMUCapsPtr qemuTestParseCapabilities(const char *capsFile); +virQEMUCapsPtr qemuTestParseCapabilities(virCapsPtr caps, + const char *capsFile); extern virCPUDefPtr cpuDefault; extern virCPUDefPtr cpuHaswell;