Check if the domain definition is valid for PCI passthrough and update it if necessary. Signed-off-by: Praveen K Paladugu <prapal@xxxxxxxxxxxxxxxxxxx> --- po/POTFILES | 1 + src/ch/ch_hostdev.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ src/ch/ch_hostdev.h | 3 ++ src/ch/ch_process.c | 39 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) diff --git a/po/POTFILES b/po/POTFILES index 1ed4086d2c..66465b798f 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -21,6 +21,7 @@ src/bhyve/bhyve_process.c src/ch/ch_conf.c src/ch/ch_domain.c src/ch/ch_driver.c +src/ch/ch_hostdev.c src/ch/ch_interface.c src/ch/ch_monitor.c src/ch/ch_process.c diff --git a/src/ch/ch_hostdev.c b/src/ch/ch_hostdev.c index 20ce6efa10..1e6210e162 100644 --- a/src/ch/ch_hostdev.c +++ b/src/ch/ch_hostdev.c @@ -26,3 +26,70 @@ #define VIR_FROM_THIS VIR_FROM_CH VIR_LOG_INIT("ch.ch_hostdev"); + +static int +virCHDomainPrepareHostdevPCI(virDomainHostdevDef *hostdev) +{ + bool supportsPassthroughVFIO = virHostdevHostSupportsPassthroughVFIO(); + virDeviceHostdevPCIDriverName *driverName = + &hostdev->source.subsys.u.pci.driver.name; + + /* assign defaults for hostdev passthrough */ + switch (*driverName) { + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_DEFAULT: + if (supportsPassthroughVFIO) { + *driverName = VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("host doesn't support passthrough of host PCI devices")); + return -1; + } + break; + + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_VFIO: + if (!supportsPassthroughVFIO) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("host doesn't support VFIO PCI passthrough")); + return false; + } + break; + + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_KVM: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("host doesn't support legacy PCI passthrough")); + return false; + + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_XEN: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("CH does not support device assignment mode '%1$s'"), + virDeviceHostdevPCIDriverNameTypeToString(*driverName)); + return false; + + default: + case VIR_DEVICE_HOSTDEV_PCI_DRIVER_NAME_LAST: + virReportEnumRangeError(virDeviceHostdevPCIDriverName, *driverName); + break; + } + + return true; +} + +int +virCHDomainPrepareHostdev(virDomainHostdevDef *hostdev) +{ + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + return 0; + + switch (hostdev->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: + return virCHDomainPrepareHostdevPCI(hostdev); + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + 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: + break; + } + + return 0; +} diff --git a/src/ch/ch_hostdev.h b/src/ch/ch_hostdev.h index 02b7f9c2d8..f9ba40ab71 100644 --- a/src/ch/ch_hostdev.h +++ b/src/ch/ch_hostdev.h @@ -22,3 +22,6 @@ #include "ch_conf.h" #include "domain_conf.h" + +int +virCHDomainPrepareHostdev(virDomainHostdevDef *hostdev); diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c index 9816509e49..c5b5b6ebb2 100644 --- a/src/ch/ch_process.c +++ b/src/ch/ch_process.c @@ -37,6 +37,7 @@ #include "virnuma.h" #include "virstring.h" #include "ch_interface.h" +#include "ch_hostdev.h" #define VIR_FROM_THIS VIR_FROM_CH @@ -808,6 +809,40 @@ virCHProcessStartValidate(virCHDriver *driver, return 0; } +static int +virCHProcessPrepareDomainHostdevs(virDomainObj *vm) +{ + size_t i; + + for (i = 0; i < vm->def->nhostdevs; i++) { + virDomainHostdevDef *hostdev = vm->def->hostdevs[i]; + + if (virCHDomainPrepareHostdev(hostdev) < 0) + return -1; + } + + return 0; +} + +/** + * virCHProcessPrepareDomain: + * @vm: domain object + * + * This function groups all code that modifies only live XML of a domain which + * is about to start and it's the only place to do those modifications. + * + * This function MUST be called before virCHProcessPrepareHost(). + * + */ +static int +virCHProcessPrepareDomain(virDomainObj *vm) +{ + if (virCHProcessPrepareDomainHostdevs(vm) < 0) + return -1; + + return 0; +} + /** * virCHProcessStart: * @driver: pointer to driver structure @@ -839,6 +874,10 @@ virCHProcessStart(virCHDriver *driver, return -1; } + if (virCHProcessPrepareDomain(vm) < 0) { + return -1; + } + if (!priv->monitor) { /* And we can get the first monitor connection now too */ if (!(priv->monitor = virCHProcessConnectMonitor(driver, vm))) { -- 2.44.0