On 29/04/2025 8:01 am, Duan, Zhenzhong wrote:
> Caution: External email. Do not open attachments or click links, unless this 
> email comes from a known sender and you know the content is safe.
>
>
>> -----Original Message-----
>> From: CLEMENT MATHIEU--DRIF <clement.mathieu--d...@eviden.com>
>> Subject: Re: [PATCH v4 3/3] intel_iommu: Take the VTD lock when looking for 
>> and
>> creating address spaces
>>
>> Hi Zhenzhong,
>>
>> On 28/04/2025 10:55 am, Duan, Zhenzhong wrote:
>>> Caution: External email. Do not open attachments or click links, unless this
>> email comes from a known sender and you know the content is safe.
>>>
>>> Hi Clement,
>>>
>>>> -----Original Message-----
>>>> From: CLEMENT MATHIEU--DRIF <clement.mathieu--d...@eviden.com>
>>>> Subject: [PATCH v4 3/3] intel_iommu: Take the VTD lock when looking for and
>>>> creating address spaces
>>>>
>>>> vtd_find_add_as can be called by multiple threads which leads to a race
>>>> condition on address space creation. The IOMMU lock must be taken to
>>>> avoid such a race.
>>>>
>>>> Signed-off-by: Clement Mathieu--Drif <clement.mathieu--d...@eviden.com>
>>>> ---
>>>> hw/i386/intel_iommu.c | 28 ++++++++++++++++++++++++++--
>>>> 1 file changed, 26 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
>>>> index b7855f4b87..931ac01ef0 100644
>>>> --- a/hw/i386/intel_iommu.c
>>>> +++ b/hw/i386/intel_iommu.c
>>>> @@ -4203,11 +4203,15 @@ VTDAddressSpace
>>>> *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus,
>>>>           .pasid = pasid,
>>>>       };
>>>>       VTDAddressSpace *vtd_dev_as;
>>>> +    struct vtd_as_key *new_key = NULL;
>>>>       char name[128];
>>>>
>>>> +    vtd_iommu_lock(s);
>>>>       vtd_dev_as = g_hash_table_lookup(s->vtd_address_spaces, &key);
>>>> +    vtd_iommu_unlock(s);
>>>> +
>>>>       if (!vtd_dev_as) {
>>>> -        struct vtd_as_key *new_key = g_malloc(sizeof(*new_key));
>>>> +        new_key = g_malloc(sizeof(*new_key));
>>>>
>>>>           new_key->bus = bus;
>>>>           new_key->devfn = devfn;
>>>> @@ -4302,9 +4306,29 @@ VTDAddressSpace
>>>> *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus,
>>>>                                               &vtd_dev_as->nodmar, 0);
>>>>
>>>>           vtd_switch_address_space(vtd_dev_as);
>>>> +    }
>>>>
>>>> -        g_hash_table_insert(s->vtd_address_spaces, new_key, vtd_dev_as);
>>>> +    if (new_key != NULL) {
>>>> +        VTDAddressSpace *second_vtd_dev_as;
>>>> +
>>>> +        /*
>>>> +         * Take the lock again and recheck as the AS might have
>>>> +         * been created in the meantime.
>>>> +         */
>>>> +        vtd_iommu_lock(s);
>>>> +
>>>> +        second_vtd_dev_as = g_hash_table_lookup(s->vtd_address_spaces,
>> &key);
>>>> +        if (!second_vtd_dev_as) {
>>>> +            g_hash_table_insert(s->vtd_address_spaces, new_key, 
>>>> vtd_dev_as);
>>>> +        } else {
>>>> +            vtd_dev_as = second_vtd_dev_as;
>>>> +            g_free(vtd_dev_as);
>>>> +            g_free(new_key);
>>> We need to release memory regions under this vtd_dev_as to avoid leak.
>>
>> Indeed, I'll have to take the BQL again.
>>
>> Is it ok for you if it look like this:
>>
>> vtd_iommu_lock(s);
>>
>> second_vtd_dev_as = g_hash_table_lookup(s->vtd_address_spaces, &key);
>> if (!second_vtd_dev_as) {
>>      g_hash_table_insert(s->vtd_address_spaces, new_key, vtd_dev_as);
>>      vtd_iommu_unlock(s);
>> } else {
>>      vtd_iommu_unlock(s);
>>      BQL_LOCK_GUARD();
>>
>>      memory_region_del_subregion(&vtd_dev_as->root, &vtd_dev_as->nodmar);
>>      memory_region_del_subregion(&vtd_dev_as->root,
>>                                  MEMORY_REGION(&vtd_dev_as->iommu));
>>      memory_region_del_subregion(&vtd_dev_as->root,
>>                                  &vtd_dev_as->iommu_ir_fault);
>>      memory_region_del_subregion(&vtd_dev_as->root,
>>                                  &vtd_dev_as->iommu_ir);
>>
>>      memory_region_unref(MEMORY_REGION(&vtd_dev_as->iommu));
>>      memory_region_unref(&vtd_dev_as->iommu_ir_fault);
>>      memory_region_unref(&vtd_dev_as->iommu_ir);
>>      memory_region_unref(&vtd_dev_as->nodmar);
> s/memory_region_unref/object_unparent?
>
>>      address_space_destroy(&vtd_dev_as->as);
> object_unparent(vtd_dev_as->root);

Hi Zhenzhong,

I think the issue can be fixed differently in a cleaner way.
I sent a v5 for that.

Thanks

>
> Thanks
> Zhenzhong

Reply via email to