mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 20:15:17 +00:00
qemu-caps: Get host model directly from Qemu when available
When qmp query-cpu-model-expansion is available probe Qemu for its view of the host model. In kvm environments this can provide a more complete view of the host model because features supported by Qemu and Kvm can be considered. Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com> Signed-off-by: Jason J. Herne <jjherne@linux.vnet.ibm.com>
This commit is contained in:
parent
fab9d6e1a9
commit
5d513d4659
@ -399,6 +399,8 @@ struct _virQEMUCaps {
|
||||
size_t ngicCapabilities;
|
||||
virGICCapability *gicCapabilities;
|
||||
|
||||
qemuMonitorCPUModelInfoPtr hostCPUModelInfo;
|
||||
|
||||
/* 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.
|
||||
@ -2163,6 +2165,10 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
|
||||
!(ret->hostCPUModel = virCPUDefCopy(qemuCaps->hostCPUModel)))
|
||||
goto error;
|
||||
|
||||
if (qemuCaps->hostCPUModelInfo &&
|
||||
!(ret->hostCPUModelInfo = qemuMonitorCPUModelInfoCopy(qemuCaps->hostCPUModelInfo)))
|
||||
goto error;
|
||||
|
||||
if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0)
|
||||
goto error;
|
||||
ret->nmachineTypes = qemuCaps->nmachineTypes;
|
||||
@ -2811,6 +2817,18 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
|
||||
qemuMonitorPtr mon)
|
||||
{
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION) ||
|
||||
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
|
||||
return 0;
|
||||
|
||||
return qemuMonitorGetCPUModelExpansion(mon, "static", "host",
|
||||
&qemuCaps->hostCPUModelInfo);
|
||||
}
|
||||
|
||||
struct tpmTypeToCaps {
|
||||
int type;
|
||||
virQEMUCapsFlags caps;
|
||||
@ -3020,17 +3038,61 @@ virQEMUCapsCPUFilterFeatures(const char *name,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
||||
virCapsPtr caps)
|
||||
static void
|
||||
virQEMUCapsCopyCPUModelFromQEMU(virQEMUCapsPtr qemuCaps)
|
||||
{
|
||||
virCPUDefPtr cpu = NULL;
|
||||
qemuMonitorCPUModelInfoPtr modelInfo = NULL;
|
||||
size_t i;
|
||||
|
||||
if (!caps)
|
||||
return;
|
||||
|
||||
if (!virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
|
||||
if (!(modelInfo = qemuCaps->hostCPUModelInfo)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("missing host CPU model info from QEMU capabilities"
|
||||
" for binary %s"), qemuCaps->binary);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC(cpu) < 0)
|
||||
goto error;
|
||||
|
||||
if (VIR_STRDUP(cpu->model, modelInfo->name) < 0 ||
|
||||
VIR_ALLOC_N(cpu->features, modelInfo->nprops) < 0)
|
||||
goto error;
|
||||
|
||||
cpu->nfeatures_max = modelInfo->nprops;
|
||||
cpu->nfeatures = 0;
|
||||
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;
|
||||
|
||||
for (i = 0; i < modelInfo->nprops; i++) {
|
||||
if (VIR_STRDUP(cpu->features[i].name, modelInfo->props[i].name) < 0)
|
||||
goto error;
|
||||
|
||||
if (modelInfo->props[i].supported)
|
||||
cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE;
|
||||
else
|
||||
cpu->features[i].policy = VIR_CPU_FEATURE_DISABLE;
|
||||
|
||||
cpu->nfeatures++;
|
||||
}
|
||||
|
||||
qemuCaps->hostCPUModel = cpu;
|
||||
return;
|
||||
|
||||
error:
|
||||
virCPUDefFree(cpu);
|
||||
qemuCaps->hostCPUModel = NULL;
|
||||
virResetLastError();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virQEMUCapsCopyCPUModelFromHost(virQEMUCapsPtr qemuCaps,
|
||||
virCapsPtr caps)
|
||||
{
|
||||
virCPUDefPtr cpu = NULL;
|
||||
|
||||
if (caps->host.cpu && caps->host.cpu->model) {
|
||||
if (VIR_ALLOC(cpu) < 0)
|
||||
@ -3056,6 +3118,102 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
|
||||
virCapsPtr caps)
|
||||
{
|
||||
if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch))
|
||||
return;
|
||||
|
||||
switch (qemuCaps->arch) {
|
||||
case VIR_ARCH_S390:
|
||||
case VIR_ARCH_S390X:
|
||||
virQEMUCapsCopyCPUModelFromQEMU(qemuCaps);
|
||||
break;
|
||||
|
||||
default:
|
||||
virQEMUCapsCopyCPUModelFromHost(qemuCaps, caps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
|
||||
xmlXPathContextPtr ctxt)
|
||||
{
|
||||
char *str = NULL;
|
||||
xmlNodePtr hostCPUNode;
|
||||
xmlNodePtr *featureNodes = NULL;
|
||||
xmlNodePtr oldnode = ctxt->node;
|
||||
qemuMonitorCPUModelInfoPtr hostCPU = NULL;
|
||||
int ret = -1;
|
||||
size_t i;
|
||||
int n;
|
||||
|
||||
if (!(hostCPUNode = virXPathNode("./hostCPU", ctxt))) {
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC(hostCPU) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!(hostCPU->name = virXMLPropString(hostCPUNode, "model"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("missing host CPU model name in QEMU "
|
||||
"capabilities cache"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ctxt->node = hostCPUNode;
|
||||
|
||||
if ((n = virXPathNodeSet("./feature", ctxt, &featureNodes)) > 0) {
|
||||
if (VIR_ALLOC_N(hostCPU->props, n) < 0)
|
||||
goto cleanup;
|
||||
|
||||
hostCPU->nprops = n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
hostCPU->props[i].name = virXMLPropString(featureNodes[i], "name");
|
||||
if (!hostCPU->props[i].name) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("missing 'name' attribute for a host CPU"
|
||||
" model feature in QEMU capabilities cache"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(str = virXMLPropString(featureNodes[i], "supported"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("missing 'supported' attribute for a host CPU"
|
||||
" model feature in QEMU capabilities cache"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (STREQ(str, "yes")) {
|
||||
hostCPU->props[i].supported = true;
|
||||
} else if (STREQ(str, "no")) {
|
||||
hostCPU->props[i].supported = false;
|
||||
} else {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("invalid supported value: '%s'"), str);
|
||||
goto cleanup;
|
||||
}
|
||||
VIR_FREE(str);
|
||||
}
|
||||
}
|
||||
|
||||
qemuCaps->hostCPUModelInfo = hostCPU;
|
||||
hostCPU = NULL;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
ctxt->node = oldnode;
|
||||
VIR_FREE(str);
|
||||
VIR_FREE(featureNodes);
|
||||
qemuMonitorCPUModelInfoFree(hostCPU);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps,
|
||||
xmlXPathContextPtr ctxt,
|
||||
@ -3250,6 +3408,9 @@ virQEMUCapsLoadCache(virCapsPtr caps,
|
||||
}
|
||||
VIR_FREE(str);
|
||||
|
||||
if (virQEMUCapsLoadHostCPUModelInfo(qemuCaps, ctxt) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (virQEMUCapsLoadCPUModels(qemuCaps, ctxt, VIR_DOMAIN_VIRT_KVM) < 0 ||
|
||||
virQEMUCapsLoadCPUModels(qemuCaps, ctxt, VIR_DOMAIN_VIRT_QEMU) < 0)
|
||||
goto cleanup;
|
||||
@ -3443,6 +3604,20 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps,
|
||||
virBufferAsprintf(&buf, "<arch>%s</arch>\n",
|
||||
virArchToString(qemuCaps->arch));
|
||||
|
||||
if (qemuCaps->hostCPUModelInfo) {
|
||||
virBufferAsprintf(&buf, "<hostCPU model='%s'>\n",
|
||||
qemuCaps->hostCPUModelInfo->name);
|
||||
virBufferAdjustIndent(&buf, 2);
|
||||
for (i = 0; i < qemuCaps->hostCPUModelInfo->nprops; i++) {
|
||||
virBufferAsprintf(&buf, "<feature name='%s' supported='%s'/>\n",
|
||||
qemuCaps->hostCPUModelInfo->props[i].name,
|
||||
qemuCaps->hostCPUModelInfo->props[i].supported ?
|
||||
"yes" : "no");
|
||||
}
|
||||
virBufferAdjustIndent(&buf, -2);
|
||||
virBufferAddLit(&buf, "</hostCPU>\n");
|
||||
}
|
||||
|
||||
virQEMUCapsFormatCPUModels(qemuCaps, &buf, VIR_DOMAIN_VIRT_KVM);
|
||||
virQEMUCapsFormatCPUModels(qemuCaps, &buf, VIR_DOMAIN_VIRT_QEMU);
|
||||
|
||||
@ -4135,6 +4310,8 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_QMP_SCHEMA) &&
|
||||
virQEMUCapsProbeQMPSchemaCapabilities(qemuCaps, mon) < 0)
|
||||
goto cleanup;
|
||||
if (virQEMUCapsProbeQMPHostCPU(qemuCaps, mon) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* 'intel-iommu' shows up as a device since 2.2.0, but can
|
||||
* not be used with -device until 2.7.0. Before that it
|
||||
|
@ -20,7 +20,24 @@
|
||||
</os>
|
||||
<cpu>
|
||||
<mode name='host-passthrough' supported='yes'/>
|
||||
<mode name='host-model' supported='no'/>
|
||||
<mode name='host-model' supported='yes'>
|
||||
<model fallback='allow'>zEC12.2-base</model>
|
||||
<feature policy='require' name='aefsi'/>
|
||||
<feature policy='require' name='msa5'/>
|
||||
<feature policy='require' name='msa4'/>
|
||||
<feature policy='require' name='msa3'/>
|
||||
<feature policy='require' name='msa2'/>
|
||||
<feature policy='require' name='msa1'/>
|
||||
<feature policy='require' name='sthyi'/>
|
||||
<feature policy='require' name='edat'/>
|
||||
<feature policy='require' name='ri'/>
|
||||
<feature policy='require' name='edat2'/>
|
||||
<feature policy='require' name='ipter'/>
|
||||
<feature policy='require' name='esop'/>
|
||||
<feature policy='require' name='cte'/>
|
||||
<feature policy='require' name='te'/>
|
||||
<feature policy='require' name='cmm'/>
|
||||
</mode>
|
||||
<mode name='custom' supported='yes'>
|
||||
<model usable='unknown'>z10EC-base</model>
|
||||
<model usable='unknown'>z9EC-base</model>
|
||||
|
@ -13021,6 +13021,32 @@
|
||||
"id": "libvirt-47"
|
||||
}
|
||||
|
||||
{
|
||||
"return": {
|
||||
"model": {
|
||||
"name": "zEC12.2-base",
|
||||
"props": {
|
||||
"aefsi": true,
|
||||
"msa5": true,
|
||||
"msa4": true,
|
||||
"msa3": true,
|
||||
"msa2": true,
|
||||
"msa1": true,
|
||||
"sthyi": true,
|
||||
"edat": true,
|
||||
"ri": true,
|
||||
"edat2": true,
|
||||
"ipter": true,
|
||||
"esop": true,
|
||||
"cte": true,
|
||||
"te": true,
|
||||
"cmm": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "libvirt-48"
|
||||
}
|
||||
|
||||
{
|
||||
"return": {
|
||||
},
|
||||
|
@ -133,6 +133,23 @@
|
||||
<kvmVersion>0</kvmVersion>
|
||||
<package></package>
|
||||
<arch>s390x</arch>
|
||||
<hostCPU model='zEC12.2-base'>
|
||||
<feature name='aefsi' supported='yes'/>
|
||||
<feature name='msa5' supported='yes'/>
|
||||
<feature name='msa4' supported='yes'/>
|
||||
<feature name='msa3' supported='yes'/>
|
||||
<feature name='msa2' supported='yes'/>
|
||||
<feature name='msa1' supported='yes'/>
|
||||
<feature name='sthyi' supported='yes'/>
|
||||
<feature name='edat' supported='yes'/>
|
||||
<feature name='ri' supported='yes'/>
|
||||
<feature name='edat2' supported='yes'/>
|
||||
<feature name='ipter' supported='yes'/>
|
||||
<feature name='esop' supported='yes'/>
|
||||
<feature name='cte' supported='yes'/>
|
||||
<feature name='te' supported='yes'/>
|
||||
<feature name='cmm' supported='yes'/>
|
||||
</hostCPU>
|
||||
<cpu type='kvm' name='z10EC-base'/>
|
||||
<cpu type='kvm' name='z9EC-base'/>
|
||||
<cpu type='kvm' name='z196.2-base'/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user