|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v8 11/13] vpci: add initial support for virtual PCI bus topology
Hi Jan,
Jan Beulich <jbeulich@xxxxxxxx> writes:
> On 20.07.2023 02:32, Volodymyr Babchuk wrote:
>> --- a/xen/drivers/vpci/vpci.c
>> +++ b/xen/drivers/vpci/vpci.c
>> @@ -46,6 +46,16 @@ void vpci_remove_device(struct pci_dev *pdev)
>> return;
>>
>> spin_lock(&pdev->vpci->lock);
>> +
>> +#ifdef CONFIG_HAS_VPCI_GUEST_SUPPORT
>> + if ( pdev->vpci->guest_sbdf.sbdf != ~0 )
>> + {
>> + __clear_bit(pdev->vpci->guest_sbdf.dev,
>> + &pdev->domain->vpci_dev_assigned_map);
>> + pdev->vpci->guest_sbdf.sbdf = ~0;
>> + }
>> +#endif
>
> The lock acquired above is not ...
vpci_remove_device() is called when d->pci_lock is already held.
But, I'll move this hunk before spin_lock(&pdev->vpci->lock); we don't
need to hold it while cleaning vpci_dev_assigned_map
>> @@ -115,6 +129,54 @@ int vpci_add_handlers(struct pci_dev *pdev)
>> }
>>
>> #ifdef CONFIG_HAS_VPCI_GUEST_SUPPORT
>> +static int add_virtual_device(struct pci_dev *pdev)
>> +{
>> + struct domain *d = pdev->domain;
>> + pci_sbdf_t sbdf = { 0 };
>> + unsigned long new_dev_number;
>> +
>> + if ( is_hardware_domain(d) )
>> + return 0;
>> +
>> + ASSERT(pcidevs_locked());
>> +
>> + /*
>> + * Each PCI bus supports 32 devices/slots at max or up to 256 when
>> + * there are multi-function ones which are not yet supported.
>> + */
>> + if ( pdev->info.is_extfn )
>> + {
>> + gdprintk(XENLOG_ERR, "%pp: only function 0 passthrough supported\n",
>> + &pdev->sbdf);
>> + return -EOPNOTSUPP;
>> + }
>> +
>> + write_lock(&pdev->domain->pci_lock);
>> + new_dev_number = find_first_zero_bit(d->vpci_dev_assigned_map,
>> + VPCI_MAX_VIRT_DEV);
>> + if ( new_dev_number >= VPCI_MAX_VIRT_DEV )
>> + {
>> + write_unlock(&pdev->domain->pci_lock);
>> + return -ENOSPC;
>> + }
>> +
>> + __set_bit(new_dev_number, &d->vpci_dev_assigned_map);
>
> ... the same as the one held here, so the bitmap still isn't properly
> protected afaics, unless the intention is to continue to rely on
> the global PCI lock (assuming that one's held in both cases, which I
> didn't check it is). Conversely it looks like the vPCI lock isn't
> held here. Both aspects may be intentional, but the locks being
> acquired differing requires suitable code comments imo.
As I stated above, vpci_remove_device() is called when d->pci_lock is
already held.
> I've also briefly looked at patch 1, and I'm afraid that still lacks
> commentary about intended lock nesting. That might be relevant here
> in case locking visible from patch / patch context isn't providing
> the full picture.
>
There is
ASSERT(rw_is_write_locked(&pdev->domain->pci_lock));
at the beginning of vpci_remove_device(), which is added by
"vpci: use per-domain PCI lock to protect vpci structure".
I believe, it will be more beneficial to review series from the
beginning.
>> + /*
>> + * Both segment and bus number are 0:
>> + * - we emulate a single host bridge for the guest, e.g. segment 0
>> + * - with bus 0 the virtual devices are seen as embedded
>> + * endpoints behind the root complex
>> + *
>> + * TODO: add support for multi-function devices.
>> + */
>> + sbdf.devfn = PCI_DEVFN(new_dev_number, 0);
>> + pdev->vpci->guest_sbdf = sbdf;
>> + write_unlock(&pdev->domain->pci_lock);
>
> With the above I also wonder whether this lock can't (and hence
> should) be dropped a little earlier (right after fiddling with the
> bitmap).
This is the good observation, thanks.
--
WBR, Volodymyr
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |