qemu: Move <hostdev/> PCI backend setting into qemuDomainPrepareHostdev()

virsh command domxml-to-native failed with below error but start
command succeed for same domain xml.

  "internal error: invalid PCI passthrough type 'default'"

If a <hostdev> PCI backend is not set in the XML, the supported
one is then chosen in qemuHostdevPreparePCIDevicesCheckSupport().
But this function is not called anywhere from
qemuConnectDomainXMLToNative(). But qemuDomainPrepareHostdev()
is. And it is also called from domain startup/hotplug code.
Therefore, move the backend setting to the common path and drop
qemuHostdevPreparePCIDevicesCheckSupport().

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Michal Privoznik 2023-04-21 16:56:10 +02:00
parent 6e60e8cb9f
commit 3b87709c76
3 changed files with 53 additions and 63 deletions

View File

@ -11292,6 +11292,53 @@ qemuDomainPrepareHostdevSCSI(virDomainHostdevDef *hostdev,
}
static int
qemuDomainPrepareHostdevPCI(virDomainHostdevDef *hostdev,
virQEMUCaps *qemuCaps)
{
bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
virDomainHostdevSubsysPCIBackendType *backend = &hostdev->source.subsys.u.pci.backend;
/* assign defaults for hostdev passthrough */
switch (*backend) {
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
if (supportsPassthroughVFIO) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
*backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("VFIO PCI device assignment is not supported by this version of QEMU"));
return -1;
}
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("host doesn't support passthrough of host PCI devices"));
return -1;
}
break;
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
if (!supportsPassthroughVFIO) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("host doesn't support VFIO PCI passthrough"));
return false;
}
break;
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("host doesn't support legacy PCI passthrough"));
return false;
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
break;
}
return true;
}
int
qemuDomainPrepareHostdev(virDomainHostdevDef *hostdev,
qemuDomainObjPrivate *priv)
@ -11302,8 +11349,9 @@ qemuDomainPrepareHostdev(virDomainHostdevDef *hostdev,
switch ((virDomainHostdevSubsysType)hostdev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
return qemuDomainPrepareHostdevSCSI(hostdev, priv);
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
return qemuDomainPrepareHostdevPCI(hostdev, priv->qemuCaps);
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:

View File

@ -153,60 +153,6 @@ qemuHostdevHostSupportsPassthroughVFIO(void)
}
static bool
qemuHostdevPreparePCIDevicesCheckSupport(virDomainHostdevDef **hostdevs,
size_t nhostdevs,
virQEMUCaps *qemuCaps)
{
bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
size_t i;
/* assign defaults for hostdev passthrough */
for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDef *hostdev = hostdevs[i];
virDomainHostdevSubsysPCIBackendType *backend = &hostdev->source.subsys.u.pci.backend;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
continue;
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
switch (*backend) {
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
if (supportsPassthroughVFIO &&
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI)) {
*backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("host doesn't support passthrough of "
"host PCI devices"));
return false;
}
break;
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
if (!supportsPassthroughVFIO) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("host doesn't support VFIO PCI passthrough"));
return false;
}
break;
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("host doesn't support legacy PCI passthrough"));
return false;
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
break;
}
}
return true;
}
int
qemuHostdevPrepareOneNVMeDisk(virQEMUDriver *driver,
const char *name,
@ -235,15 +181,11 @@ qemuHostdevPreparePCIDevices(virQEMUDriver *driver,
const unsigned char *uuid,
virDomainHostdevDef **hostdevs,
int nhostdevs,
virQEMUCaps *qemuCaps,
virQEMUCaps *qemuCaps G_GNUC_UNUSED,
unsigned int flags)
{
virHostdevManager *hostdev_mgr = driver->hostdevMgr;
if (!qemuHostdevPreparePCIDevicesCheckSupport(hostdevs, nhostdevs, qemuCaps))
return -1;
return virHostdevPreparePCIDevices(hostdev_mgr, QEMU_DRIVER_NAME,
return virHostdevPreparePCIDevices(driver->hostdevMgr,
QEMU_DRIVER_NAME,
name, uuid, hostdevs,
nhostdevs, flags);
}

View File

@ -1495,7 +1495,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriver *driver,
&hostdev, 1, priv->qemuCaps, flags) < 0)
return -1;
/* this could have been changed by qemuHostdevPreparePCIDevices */
/* this could have been changed by qemuDomainPrepareHostdevPCI() */
backend = hostdev->source.subsys.u.pci.backend;
switch (backend) {