[libvirt] [PATCH v2] util: disallow assigning or resetting a pci-bridge device

Laine Stump laine at laine.org
Fri Jan 20 20:20:48 UTC 2017


On 01/18/2017 11:10 AM, Martin Kletzander wrote:
> On Wed, Jan 18, 2017 at 07:29:29PM +0530, Shivaprasad G Bhat wrote:
>> It is destructive to attempt reset on a pci-bridge, the host can crash.
>> The bridges won't contain any guest data and neither they can be
>> passed through using vfio/stub. So, no point in allowing a reset on 
>> them.
>>
>
> Wasn't resetting non-endpoint the only way in some cases when you needed
> to passthrough 2 endpoint devices when none of them could be reset?  I
> might be very easily wrong, though.

What you're thinking of is the code in virPCIDeviceReset() that attempts 
to do a "secondary bus reset" on the parent of an endpoint device if the 
reset of the endpoint device itself fails. This is never initiated 
directly by the user (or the top level of the libvirt API) though, but 
only done internally when attempts to reset an endpoint device fail 
(libvirt then tries doing a secondary bus reset of the endpoint's parent 
device).

Of course *all* of the PCI reset stuff in libvirt is a moot point if 
you're using vfio anyway - vfio itself will handle any device resets 
that need to be done at the appropriate time. That's why 
virPCIDeviceReset() returns success almost immediately if the device is 
bound to vfio-pci. Since the only time the device would *not* be bound 
to vfio-pci would be 1) if a domain was using legacy KVM device 
assignment (which is deprecated, and I think may even be completely 
removed from new kernels) or 2) if a user manually requested a device 
reset with libvirt's virNodeDeviceReset() API (which realistically 
speaking nobody should ever need to do), there's really not much chance 
of this making an actual difference. (This makes me wonder where 
Shivaprasad encountered this in the real world...)

>
>> Signed-off-by: Shivaprasad G Bhat <sbhat at linux.vnet.ibm.com>
>> ---
>> src/util/virhostdev.c |   10 ++++++++++
>> src/util/virpci.c     |   11 +++++++++++
>> 2 files changed, 21 insertions(+)
>>
>> diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
>> index 0673afb..16b96f3 100644
>> --- a/src/util/virhostdev.c
>> +++ b/src/util/virhostdev.c
>> @@ -532,6 +532,16 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr 
>> mgr,
>>         bool strict_acs_check = !!(flags & 
>> VIR_HOSTDEV_STRICT_ACS_CHECK);
>>         bool usesVFIO = (virPCIDeviceGetStubDriver(pci) == 
>> VIR_PCI_STUB_DRIVER_VFIO);
>>         struct virHostdevIsPCINodeDeviceUsedData data = { mgr, 
>> dom_name, usesVFIO };
>> +        int hdrType = -1;
>> +
>> +        if (virPCIGetHeaderType(pci, &hdrType) < 0)
>> +            goto cleanup;
>> +
>> +        if (hdrType == VIR_PCI_HEADER_PCI_BRIDGE) {

I verified with the VFIO author/maintainer (Alex Williamson) that vfio 
will assign only endpoint devices - cardbus bridge devices and PCI 
bridge devices are both not allowed. So I think that this check should 
also be for "hdrType != VIR_PCI_HEADER_ENDPOINT".

Also, it's kind of nit-picking, but I think this chunk should be in a 
separate patch from the other. One is preventing attempts to assign a 
device that isn't an endpoint, and the otehr is preventing attemps to 
reset a device that isn't an endpoint.


>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("PCI bridge devices"
>> +                           " cannot be assigned to guests"));

When a string is split into multiple lines, the final character of each 
line's substring must be a space (this is in the contribution guidelines 
and is enforced by make syntax-check)


>> +            goto cleanup;
>> +        }
>>
>>         if (!usesVFIO && !virPCIDeviceIsAssignable(pci, 
>> strict_acs_check)) {
>>             virReportError(VIR_ERR_OPERATION_INVALID,
>> diff --git a/src/util/virpci.c b/src/util/virpci.c
>> index 0601f49..f205abf 100644
>> --- a/src/util/virpci.c
>> +++ b/src/util/virpci.c
>> @@ -933,6 +933,17 @@ virPCIDeviceReset(virPCIDevicePtr dev,
>>     char *drvName = NULL;
>>     int ret = -1;
>>     int fd = -1;
>> +    int hdrType = -1;
>> +
>> +    if (virPCIGetHeaderType(dev, &hdrType) < 0)
>> +        return -1;
>> +
>> +    if (hdrType != VIR_PCI_HEADER_ENDPOINT) {
>> +        virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                       _("Invalid attempt to reset non-endpoint PCI 
>> device %s."
>> +                         " Only PCI endpoint devices can be reset"), 
>> dev->name);

Same problem. make syntax-check will catch it.


If you split this in two, change the first check to be for != endpoint 
rather than == bridge, and fix the strings, then these can be pushed.




More information about the libvir-list mailing list