[PATCH kernel] powerpc/iommu: Annotate nested lock for lockdep

Alexey Kardashevskiy aik at ozlabs.ru
Mon Feb 22 20:35:58 AEDT 2021



On 20/02/2021 14:49, Alexey Kardashevskiy wrote:
> 
> 
> On 18/02/2021 23:59, Frederic Barrat wrote:
>>
>>
>> On 16/02/2021 04:20, Alexey Kardashevskiy wrote:
>>> The IOMMU table is divided into pools for concurrent mappings and each
>>> pool has a separate spinlock. When taking the ownership of an IOMMU 
>>> group
>>> to pass through a device to a VM, we lock these spinlocks which triggers
>>> a false negative warning in lockdep (below).
>>>
>>> This fixes it by annotating the large pool's spinlock as a nest lock.
>>>
>>> ===
>>> WARNING: possible recursive locking detected
>>> 5.11.0-le_syzkaller_a+fstn1 #100 Not tainted
>>> --------------------------------------------
>>> qemu-system-ppc/4129 is trying to acquire lock:
>>> c0000000119bddb0 (&(p->lock)/1){....}-{2:2}, at: 
>>> iommu_take_ownership+0xac/0x1e0
>>>
>>> but task is already holding lock:
>>> c0000000119bdd30 (&(p->lock)/1){....}-{2:2}, at: 
>>> iommu_take_ownership+0xac/0x1e0
>>>
>>> other info that might help us debug this:
>>>   Possible unsafe locking scenario:
>>>
>>>         CPU0
>>>         ----
>>>    lock(&(p->lock)/1);
>>>    lock(&(p->lock)/1);
>>> ===
>>>
>>> Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
>>> ---
>>>   arch/powerpc/kernel/iommu.c | 2 +-
>>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
>>> index 557a09dd5b2f..2ee642a6731a 100644
>>> --- a/arch/powerpc/kernel/iommu.c
>>> +++ b/arch/powerpc/kernel/iommu.c
>>> @@ -1089,7 +1089,7 @@ int iommu_take_ownership(struct iommu_table *tbl)
>>>       spin_lock_irqsave(&tbl->large_pool.lock, flags);
>>>       for (i = 0; i < tbl->nr_pools; i++)
>>> -        spin_lock(&tbl->pools[i].lock);
>>> +        spin_lock_nest_lock(&tbl->pools[i].lock, 
>>> &tbl->large_pool.lock);
>>
>>
>> We have the same pattern and therefore should have the same problem in 
>> iommu_release_ownership().
>>
>> But as I understand, we're hacking our way around lockdep here, since 
>> conceptually, those locks are independent. I was wondering why it 
>> seems to fix it by worrying only about the large pool lock. That loop 
>> can take many locks (up to 4 with current config). However, if the dma 
>> window is less than 1GB, we would only have one, so it would make 
>> sense for lockdep to stop complaining. Is it what happened? In which 
>> case, this patch doesn't really fix it. Or I'm missing something :-)
> 
> 
> My rough undestanding is that when spin_lock_nest_lock is called first 
> time, it does some magic with lockdep classes somewhere in 
> __lock_acquire()/register_lock_class() and right after that the nested 
> lock is not the same as before and it is annotated so  we cannot lock 
> nested locks without locking the nest lock first and no (re)annotation 
> is needed. I'll try to poke this code once again and see, it is just was 
> easier with p9/nested which is gone for now because of little snow in 
> one of the southern states :)


Turns out I have good imagination and in fact it does print this huge 
warning in the release hook as well so v2 is coming. Thanks,


> 
> 
>>
>>    Fred
>>
>>
>>
>>>       iommu_table_release_pages(tbl);
>>>
> 

-- 
Alexey


More information about the Linuxppc-dev mailing list