[libvirt] [PATCH v6 17/17] qemu: assign vfio devices to PCIe addresses when appropriate

Laine Stump laine at laine.org
Wed Nov 9 18:33:04 UTC 2016


On 11/07/2016 03:26 PM, Alex Williamson wrote:
> On Mon,  7 Nov 2016 14:50:25 -0500
> Laine Stump <laine at laine.org> wrote:
>
>> Although nearly all host devices that are assigned to guests using
>> vfio ("<hostdev>" devices in libvirt) are physically PCI Express
>> devices, until now libvirt's PCI address assignment has always
>> assigned them addresses on legacy PCI controllers.
>>
>> This patch tries to assign them to an address on a PCIe controller
>> instead. First we do some preliminary checks that might allow setting
>> the flags without doing any extra work, and if those conditions aren't
>> met (and if libvirt is running privileged so that it has proper
>> permissions), we perform the (relatively) time consuming task of
>> reading the device's PCI config to see if it is an Express device. If
>> this is successful, the connect flags are set based on the result, but
>> if we aren't able to read the PCI config (most likely due to the
>> device not being present on the system at the time of the check) we
>> assume it is (or will be) and Express device, since that is almost
>> always the case anyway.
>> ---
>>   src/qemu/qemu_domain_address.c | 66 ++++++++++++++++++++++++++++++++++++++++--
>>   1 file changed, 63 insertions(+), 3 deletions(-)
>>
>> diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
>> index 65753c5..86984fb 100644
>> --- a/src/qemu/qemu_domain_address.c
>> +++ b/src/qemu/qemu_domain_address.c
>> @@ -428,7 +428,7 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
>>    */
>>   static virDomainPCIConnectFlags
>>   qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
>> -                                         virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
>> +                                         virQEMUDriverPtr driver,
>>                                            virDomainPCIConnectFlags pcieFlags,
>>                                            virDomainPCIConnectFlags virtioFlags)
>>   {
>> @@ -558,8 +558,68 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev,
>>               return 0;
>>           }
>>   
>> -    case VIR_DOMAIN_DEVICE_HOSTDEV:
>> -        return pciFlags;
>> +    case VIR_DOMAIN_DEVICE_HOSTDEV: {
>> +        virDomainHostdevDefPtr hostdev = dev->data.hostdev;
>> +
>> +        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
>> +            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
>> +            bool isExpress = false;
>> +            virPCIDevicePtr pciDev;
>> +            virPCIDeviceAddressPtr hostAddr = &hostdev->source.subsys.u.pci.addr;
>> +
>> +            if (pciFlags == pcieFlags) {
>> +                /* This arch/qemu only supports legacy PCI, so there
>> +                 * is no point in checking if the device is an Express
>> +                 * device.
>> +                 */
>> +                return pciFlags;
>> +            }
>> +
>> +            if (virDeviceInfoPCIAddressPresent(hostdev->info)) {
>> +                /* A guest-side address has already been assigned, so
>> +                 * we can avoid reading the PCI config, and just use
>> +                 * pcieFlags, since the pciConnectFlags checking is
>> +                 * more relaxed when an address is already assigned
>> +                 * than it is when we're looking for a new address (so
>> +                 * validation will pass regardless of whether we set
>> +                 * the flags to PCI or PCIE).
>> +                 */
>> +                return pcieFlags;
>> +            }
>> +
>> +            if (!driver->privileged) {
>> +                /* unprivileged libvirtd is unable to read a device's
>> +                 * PCI config, so instead of trying and failing, we
>> +                 * will just assume what is by far the most likely
>> +                 * version of reality: this is a PCIE device.
>> +                 */
>> +                return pcieFlags;
>
> Don't you still have permission to stat the config file?  You can tell
> pretty well by whether the config file is 4096 bytes that the device is
> either PCIe or PCIx (and given the rarity of PCIx in most systems
> assume that it's PCIe).  Conventional PCI will be 256 bytes.  Thanks,

Interesting idea. Although still not 100%, it would reduce the 
possibility of false positives to "nearly 0".




More information about the libvir-list mailing list