|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v12.2 01/15] vpci: use per-domain PCI lock to protect vpci structure
On Tue, Jan 23, 2024 at 03:26:26PM +0100, Jan Beulich wrote:
> On 15.01.2024 20:43, Stewart Hildebrand wrote:
> > --- a/xen/arch/x86/hvm/vmsi.c
> > +++ b/xen/arch/x86/hvm/vmsi.c
> > @@ -468,7 +468,7 @@ int msixtbl_pt_register(struct domain *d, struct pirq
> > *pirq, uint64_t gtable)
> > struct msixtbl_entry *entry, *new_entry;
> > int r = -EINVAL;
> >
> > - ASSERT(pcidevs_locked());
> > + ASSERT(pcidevs_locked() || rw_is_locked(&d->pci_lock));
> > ASSERT(rw_is_write_locked(&d->event_lock));
> >
> > if ( !msixtbl_initialised(d) )
> > @@ -538,7 +538,7 @@ void msixtbl_pt_unregister(struct domain *d, struct
> > pirq *pirq)
> > struct pci_dev *pdev;
> > struct msixtbl_entry *entry;
> >
> > - ASSERT(pcidevs_locked());
> > + ASSERT(pcidevs_locked() || rw_is_locked(&d->pci_lock));
> > ASSERT(rw_is_write_locked(&d->event_lock));
>
> I was hoping to just ack this patch, but the two changes above look
> questionable to me: How can it be that holding _either_ lock is okay?
> It's not obvious in this context that consumers have to hold both
> locks now. In fact consumers looks to be the callers of
> msixtbl_find_entry(), yet the list is RCU-protected. Whereas races
> against themselves or against one another are avoided by holding
> d->event_lock.
The reason for the change here is that msixtbl_pt_{un,}register() gets
called by pt_irq_{create,destroy}_bind(), which is in turn called by
vPCI code (pcidevs_locked()) that has been switched to not take the
pcidevs lock anymore, and hence the ASSERT would trigger.
> My only guess then for the original need of holding pcidevs_lock is
> the use of msi_desc->dev, with the desire for the device to not go
> away. Yet the description doesn't talk about interactions of the per-
> domain PCI lock with that one at all; it all circles around the
> domain'd vPCI lock.
I do agree that it looks like the original intention of holding
pcidevs_lock is to prevent msi_desc->dev from being removed - yet I'm
not sure it's possible for the device to go away while the domain
event_lock is hold, as device removal would need to take that same
lock in order to destroy the irq_desc.
> Feels like I'm missing something that's obvious to everyone else.
> Or maybe this part of the patch is actually unrelated, and should be
> split off (with its own [proper] justification)? Or wouldn't it then
> be better to also change the other paths leading here to acquire the
> per-domain PCI lock?
Other paths in vPCI vpci_msi_update(), vpci_msi_arch_update(),
vpci_msi_arch_enable()... are switched in this patch to use the
per-domain pci_lock instead of pcidevs lock.
> > --- a/xen/arch/x86/hvm/vmx/vmx.c
> > +++ b/xen/arch/x86/hvm/vmx/vmx.c
> > @@ -413,7 +413,7 @@ static int cf_check vmx_pi_update_irte(const struct
> > vcpu *v,
> >
> > spin_unlock_irq(&desc->lock);
> >
> > - ASSERT(pcidevs_locked());
> > + ASSERT(pcidevs_locked() ||
> > rw_is_locked(&msi_desc->dev->domain->pci_lock));
> >
> > return iommu_update_ire_from_msi(msi_desc, &msi_desc->msg);
>
> This then falls in the same category. And apparently there are more.
This one is again a result of such function being called from
pt_irq_create_bind() from vPCI code that has been switched to use the
per-domain pci_lock.
IOMMU state is already protected by it's own internal locks, and
doesn't rely on pcidevs lock. Hence I can also only guess that the
usage here is to prevent the device from being removed.
Regards, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |