[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v6 3/5] IOMMU: Make the pcidevs_lock a recursive one



>>> On 04.03.16 at 03:45, <quan.xu@xxxxxxxxx> wrote:
> On March 04, 2016 7:59am, <dario.faggioli@xxxxxxxxxx> wrote:
>> On Wed, 2016-03-02 at 22:31 +0800, Quan Xu wrote:
>> > @@ -788,10 +787,10 @@ static bool_t __init
>> > set_iommu_interrupt_handler(struct amd_iommu *iommu)
>> >          return 0;
>> >      }
>> >
>> > -    spin_lock_irqsave(&pcidevs_lock, flags);
>> > +    pcidevs_lock();
>> >
>> So, spin_lock_irqsave() does:
>>   local_irq_save()
>>     local_save_flags()
>>     local_irq_disable()
>>   _spin_lock()
>> 
>> i.e., it saves the flags and disable interrupts.
>> 
>> pcidevs_lock() does:
>>   spin_lock_recursive()
>>     ... //handle recursion
>>     _spin_lock()
>> 
>> i.e., it does not disable interrupts.
>> 
>> And therefore it is possible that we are actually skipping disabling 
> interrupts (if
>> they're not disabled already), isn't it?
>> 
>> And, of course, the same reasoning --mutatis mutandis-- applies to the unlock
>> side of things.
>> 
>> >      iommu->msi.dev = pci_get_pdev(iommu->seg, PCI_BUS(iommu->bdf),
>> >                                    PCI_DEVFN2(iommu->bdf));
>> > -    spin_unlock_irqrestore(&pcidevs_lock, flags);
>> > +    pcidevs_unlock();
>> >
>> i.e., spin_unlock_irqrestore() restore the flags, including the interrupt
>> enabled/disabled status, which means it can re-enable the interrupts or not,
>> depending on whether they were enabled at the time of the previous
>> spin_lock_irqsave(); pcidevs_unlock() just don't affect interrupt
>> enabling/disabling at all.
>> 
>> So, if the original code is correct in using
>> spin_lock_irqsave()/spin_unlock_irqrestore(), I think that we need
>> _irqsave() and _irqrestore() variants of recursive spinlocks, in order to 
>> deal with
>> this case.
>> 
>> However, from a quick inspection, it looks to me that:
>>  - this can only be called (during initialization), with interrupt
>>    enabled, so least saving & restoring flags shouldn't be necessary
>>    (unless I missed where they can be disabled in the call chain
>>    from iommu_setup() toward set_iommu_interrupt_handler()).
>>  - This protects pci_get_dev(); looking at other places where
>>    pci_get_dev() is called, I don't think it is really necessary to
>>    disable interrupts.
>> 
>> If I'm right, it means that the original code could well have been using 
> just plain
>> spin_lock() and spin_unlock(), and it would then be fine to turn them into
>> pcidevs_lock() and pcidevs_unlock(), and so no need to add more
>> spin_[un]lock_recursive() variants.
>> 
>> That would also mean that the patch is indeed ok, 
> 
> Yes, I fully agree your analysis and conclusion.
> I tried to implement _irqsave() and _irqrestore() variants of recursive 
> spinlocks, but I found that it is no need to add them.
> 
> Also I'd highlight the below modification:
> -    if ( !spin_trylock(&pcidevs_lock) )
> -        return -ERESTART;
> -
> +    pcidevs_lock();
> 
> IMO, it is right too.

Well, I'll have to see where exactly this is (pulling such out of
context is pretty unhelpful), but I suspect it can't be replaced
like this.

>> but I'd add a mention of this in the changelog.
> 
> In git log?

To be honest, changes like this would better not be buried in a
big rework like the one here. Make it a prereq patch, where you
then will kind of automatically describe why it's correct. (I agree
current code is bogus, and we're not hitting the respective
BUG_ON() in check_lock() only because spin_debug gets set to
true only after most __init code has run.)

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

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