[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.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.