[libvirt] [PATCH] Fix the ACS checking in the PCI code.

Don Dutile ddutile at redhat.com
Wed Jul 28 22:16:58 UTC 2010


Chris Lalancette wrote:
> The code in libvirt that does ACS checking has a pretty
> serious bug that was essentially rendering the check useless.
> When trying to assign a device, we have to check that all
> bridges upstream of this device support ACS.  That means
> that we have to find the parent of the current device,
> check for ACS, then find the parent of that device, check
> for ACS, etc.
> 
> However, the code to find the parent of the device had a
> much too relaxed check.  It would iterate through all PCI
> devices on the system, looking for a device that had a range
> of busses that included the current device's bus.
> 
> That's not correct, though.  Depending on how we iterated
> through the list of PCI devices, we could first find the
> *topmost* bridge in the system; since it necessarily had
> a range of busses including the current device's bus, we
> would only ever check the topmost bridge, and not check
> any of the intermediate bridges.
> 
> This patch is simple in that it looks for the PCI device
> whose secondary device *exactly* equals the bus of the
> device we are looking for.  That means that one, and only one
> bridge will be found, and it will be the correct device.
> 
> Note that this also caused a fairly serious bug in the
> secondary bus reset code, where we could erroneously
> reset the topmost bus instead of the inner bus.
> 
> This patch was tested by me on a 4-port NIC with a
> bridge without ACS (where assignment failed), a 4-port
> NIC with a bridge with ACS (where assignment succeeded),
> and a 2-port NIC with no bridges (where assignment
> succeeded).
> 
> Signed-off-by: Chris Lalancette <clalance at redhat.com>
> ---
>  src/util/pci.c |    5 ++---
>  1 files changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/src/util/pci.c b/src/util/pci.c
> index 26d55b8..df30e04 100644
> --- a/src/util/pci.c
> +++ b/src/util/pci.c
> @@ -513,7 +513,7 @@ static int
>  pciIsParent(pciDevice *dev, pciDevice *check, void *data ATTRIBUTE_UNUSED)
>  {
>      uint16_t device_class;
> -    uint8_t header_type, secondary, subordinate;
> +    uint8_t header_type, secondary;
>  
>      if (dev->domain != check->domain)
>          return 0;
> @@ -529,12 +529,11 @@ pciIsParent(pciDevice *dev, pciDevice *check, void *data ATTRIBUTE_UNUSED)
>          return 0;
>  
>      secondary   = pciRead8(check, PCI_SECONDARY_BUS);
> -    subordinate = pciRead8(check, PCI_SUBORDINATE_BUS);
>  
>      VIR_DEBUG("%s %s: found parent device %s", dev->id, dev->name, check->name);
>  
>      /* No, it's superman! */
> -    return (dev->bus >= secondary && dev->bus <= subordinate);
> +    return (dev->bus == secondary);
>  }
>  
>  static pciDevice *

Acked-by: Donald Dutile <ddutile at redhat.com>




More information about the libvir-list mailing list