It is invalid to have secondary functions without the primary functions part of the domain. Prevents new domain define, but existing ones would not vanish. Signed-off-by: Shivaprasad G Bhat <sbhat@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_domain.c | 3 + src/qemu/qemu_domain_address.c | 57 ++++++++++++++++++++ src/qemu/qemu_domain_address.h | 2 + .../hostdev-pci-no-primary-function.xml | 23 ++++++++ tests/qemuxml2argvdata/hostdev-pci-validate.args | 25 +++++++++ tests/qemuxml2argvdata/hostdev-pci-validate.xml | 29 ++++++++++ tests/qemuxml2argvtest.c | 9 +++ 7 files changed, 148 insertions(+) create mode 100644 tests/qemuxml2argvdata/hostdev-pci-no-primary-function.xml create mode 100644 tests/qemuxml2argvdata/hostdev-pci-validate.args create mode 100644 tests/qemuxml2argvdata/hostdev-pci-validate.xml diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 2d108bec1b..12ed68a89b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3565,6 +3565,9 @@ qemuDomainDefValidate(const virDomainDef *def, if (qemuDomainDefValidateFeatures(def) < 0) goto cleanup; + if (qemuDomainDefValidatePCIHostdevs(def) < 0) + goto cleanup; + ret = 0; cleanup: diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index bc72b6e94c..7bee4fb937 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -1996,6 +1996,63 @@ qemuDomainValidateDevicePCISlotsChipsets(virDomainDefPtr def, } +static int +qemuDomainDefPCIHostdevIsPrimaryFunction(qemuDomainPCIHostdevDataPtr data, + virDomainHostdevDefPtr hostdev) +{ + if (!data->device || !hostdev) + return 0; + + if ((hostdev->source.subsys.u.pci.addr.function == 0) && + (virHostdevPCIDevicesBelongToSameSlot(data->device, hostdev))) + return 1; + + return 0; +} + + +static int qemuDomainDefValidatePCIMultifunctionHostdev(qemuDomainPCIHostdevDataPtr data, + virDomainHostdevDefPtr hostdev) +{ + int ret = 0; + qemuDomainPCIHostdevdata hostdevIterData = {data->def, NULL, hostdev}; + + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI || + hostdev->source.subsys.u.pci.addr.function == 0) + goto skip; + + if (virHostdevIsVirtualFunction(hostdev)) + goto skip; + + /* If the device is non-zero function but its Primary function is not + * part of the domain, then error out. + */ + if (!qemuDomainPCIHostDevicesIter(&hostdevIterData, + qemuDomainDefPCIHostdevIsPrimaryFunction)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Secondary functions of a PCI multifunction card " + "cannot be assigned to a domain without the " + "Primary function.")); + ret = -1; + } + + skip: + return ret; +} + +int qemuDomainDefValidatePCIHostdevs(const virDomainDef *def) +{ + qemuDomainPCIHostdevdata hostdevdata = {def, NULL, NULL}; + + if (qemuDomainPCIHostDevicesIter(&hostdevdata, + qemuDomainDefValidatePCIMultifunctionHostdev)) { + return -1; + } + + return 0; +} + + /* * This assigns static PCI slots to all configured devices. * The ordering here is chosen to match the ordering used diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h index 650f977cf7..e1cc467714 100644 --- a/src/qemu/qemu_domain_address.h +++ b/src/qemu/qemu_domain_address.h @@ -62,6 +62,8 @@ int qemuDomainDefDeviceFindSlotAggregateIdx(virDomainDefPtr def, virDomainDeviceDefPtr dev); +int qemuDomainDefValidatePCIHostdevs(const virDomainDef *def); + void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, virDomainDeviceInfoPtr info, diff --git a/tests/qemuxml2argvdata/hostdev-pci-no-primary-function.xml b/tests/qemuxml2argvdata/hostdev-pci-no-primary-function.xml new file mode 100644 index 0000000000..7106ab73b1 --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-pci-no-primary-function.xml @@ -0,0 +1,23 @@ +<domain type='kvm'> + <name>delete</name> + <uuid>583a8e8e-f0ce-4f53-89ab-092862148b25</uuid> + <memory unit='KiB'>262144</memory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0005' bus='0x09' slot='0x00' function='0x1'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/hostdev-pci-validate.args b/tests/qemuxml2argvdata/hostdev-pci-validate.args new file mode 100644 index 0000000000..bda8cab6c9 --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-pci-validate.args @@ -0,0 +1,25 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name delete \ +-S \ +-M pc \ +-m 256 \ +-smp 4,sockets=4,cores=1,threads=1 \ +-uuid 583a8e8e-f0ce-4f53-89ab-092862148b25 \ +-nographic \ +-nodefconfig \ +-nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-delete/monitor.sock,\ +server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi \ +-boot c \ +-usb \ +-device vfio-pci,host=06:12.1,id=hostdev0,bus=pci.0,addr=0x3 \ +-device vfio-pci,host=06:12.2,id=hostdev1,bus=pci.0,addr=0x4 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 diff --git a/tests/qemuxml2argvdata/hostdev-pci-validate.xml b/tests/qemuxml2argvdata/hostdev-pci-validate.xml new file mode 100644 index 0000000000..54797c2dda --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-pci-validate.xml @@ -0,0 +1,29 @@ +<domain type='kvm'> + <name>delete</name> + <uuid>583a8e8e-f0ce-4f53-89ab-092862148b25</uuid> + <memory unit='KiB'>262144</memory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + </os> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x1'/> + </source> + </hostdev> + <hostdev mode='subsystem' type='pci' managed='yes'> + <driver name='vfio'/> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x2'/> + </source> + </hostdev> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 583598dfec..659f20cb28 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1610,6 +1610,15 @@ mymain(void) QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, QEMU_CAPS_PCI_MULTIFUNCTION); + DO_TEST("hostdev-pci-validate", + QEMU_CAPS_KVM, + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST_PARSE_ERROR("hostdev-pci-no-primary-function", + QEMU_CAPS_KVM, + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_HOST_PCI_MULTIDOMAIN, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST("hostdev-mdev-precreated", QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VFIO_PCI); -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list