[PATCH v2 10/14] intel_iommu_accel: Handle PASID entry removal for system reset

Zhenzhong Duan posted 14 patches 1 week ago
Maintainers: Yi Liu <yi.l.liu@intel.com>, Eric Auger <eric.auger@redhat.com>, Zhenzhong Duan <zhenzhong.duan@intel.com>, Peter Maydell <peter.maydell@linaro.org>, "Michael S. Tsirkin" <mst@redhat.com>, Jason Wang <jasowang@redhat.com>, "Clément Mathieu--Drif" <clement.mathieu--drif@bull.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Paolo Bonzini <pbonzini@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>
[PATCH v2 10/14] intel_iommu_accel: Handle PASID entry removal for system reset
Posted by Zhenzhong Duan 1 week ago
When system level reset, DMA translation is turned off, all PASID
entries become stale and should be deleted.

vtd_hiod list is never accessed without BQL, so no need to guard with
iommu lock.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
---
 hw/i386/intel_iommu_accel.h |  5 +++++
 hw/i386/intel_iommu.c       |  2 ++
 hw/i386/intel_iommu_accel.c | 13 +++++++++++++
 3 files changed, 20 insertions(+)

diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
index c5981a23bf..1fb7ca0af6 100644
--- a/hw/i386/intel_iommu_accel.h
+++ b/hw/i386/intel_iommu_accel.h
@@ -28,6 +28,7 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
                                       uint32_t pasid, hwaddr addr,
                                       uint64_t npages, bool ih);
 void vtd_pasid_cache_sync_accel(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info);
+void vtd_pasid_cache_reset_accel(IntelIOMMUState *s);
 void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops);
 #else
 static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
@@ -62,6 +63,10 @@ static inline void vtd_pasid_cache_sync_accel(IntelIOMMUState *s,
 {
 }
 
+static inline void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
+{
+}
+
 static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops)
 {
 }
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 451ede7530..b022f3cb9e 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -391,6 +391,8 @@ static void vtd_reset_caches(IntelIOMMUState *s)
     vtd_reset_context_cache_locked(s);
     vtd_pasid_cache_reset_locked(s);
     vtd_iommu_unlock(s);
+
+    vtd_pasid_cache_reset_accel(s);
 }
 
 static uint64_t vtd_get_iotlb_gfn(hwaddr addr, uint32_t level)
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 1e27c0feb8..e9e67eb1a0 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -511,6 +511,19 @@ void vtd_pasid_cache_sync_accel(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
     }
 }
 
+/* Fake a gloal pasid cache invalidation to remove all pasid cache entries */
+void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
+{
+    VTDPASIDCacheInfo pc_info = { .type = VTD_INV_DESC_PASIDC_G_GLOBAL };
+    VTDHostIOMMUDevice *vtd_hiod;
+    GHashTableIter as_it;
+
+    g_hash_table_iter_init(&as_it, s->vtd_host_iommu_dev);
+    while (g_hash_table_iter_next(&as_it, NULL, (void **)&vtd_hiod)) {
+        vtd_pasid_cache_invalidate(vtd_hiod, &pc_info);
+    }
+}
+
 static uint64_t vtd_get_host_iommu_quirks(uint32_t type,
                                           void *caps, uint32_t size)
 {
-- 
2.47.3
Re: [PATCH v2 10/14] intel_iommu_accel: Handle PASID entry removal for system reset
Posted by Yi Liu 6 days, 17 hours ago
On 3/26/26 17:11, Zhenzhong Duan wrote:
> When system level reset, DMA translation is turned off, all PASID
> entries become stale and should be deleted.
> 
> vtd_hiod list is never accessed without BQL, so no need to guard with
> iommu lock.
> 
> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
> ---
>   hw/i386/intel_iommu_accel.h |  5 +++++
>   hw/i386/intel_iommu.c       |  2 ++
>   hw/i386/intel_iommu_accel.c | 13 +++++++++++++
>   3 files changed, 20 insertions(+)
> 
> diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
> index c5981a23bf..1fb7ca0af6 100644
> --- a/hw/i386/intel_iommu_accel.h
> +++ b/hw/i386/intel_iommu_accel.h
> @@ -28,6 +28,7 @@ void vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
>                                         uint32_t pasid, hwaddr addr,
>                                         uint64_t npages, bool ih);
>   void vtd_pasid_cache_sync_accel(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info);
> +void vtd_pasid_cache_reset_accel(IntelIOMMUState *s);
>   void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops);
>   #else
>   static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
> @@ -62,6 +63,10 @@ static inline void vtd_pasid_cache_sync_accel(IntelIOMMUState *s,
>   {
>   }
>   
> +static inline void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
> +{
> +}
> +
>   static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops)
>   {
>   }
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index 451ede7530..b022f3cb9e 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -391,6 +391,8 @@ static void vtd_reset_caches(IntelIOMMUState *s)
>       vtd_reset_context_cache_locked(s);
>       vtd_pasid_cache_reset_locked(s);
>       vtd_iommu_unlock(s);
> +
> +    vtd_pasid_cache_reset_accel(s);
>   }
>   
>   static uint64_t vtd_get_iotlb_gfn(hwaddr addr, uint32_t level)
> diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
> index 1e27c0feb8..e9e67eb1a0 100644
> --- a/hw/i386/intel_iommu_accel.c
> +++ b/hw/i386/intel_iommu_accel.c
> @@ -511,6 +511,19 @@ void vtd_pasid_cache_sync_accel(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
>       }
>   }
>   
> +/* Fake a gloal pasid cache invalidation to remove all pasid cache entries */
> +void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
> +{
> +    VTDPASIDCacheInfo pc_info = { .type = VTD_INV_DESC_PASIDC_G_GLOBAL };
> +    VTDHostIOMMUDevice *vtd_hiod;
> +    GHashTableIter as_it;
> +
> +    g_hash_table_iter_init(&as_it, s->vtd_host_iommu_dev);
> +    while (g_hash_table_iter_next(&as_it, NULL, (void **)&vtd_hiod)) {

s/as_it/hiod_it/

other part LGTM.

Reviewed-by: Yi Liu <yi.l.liu@intel.com>


> +        vtd_pasid_cache_invalidate(vtd_hiod, &pc_info);
> +    }
> +}
> +
>   static uint64_t vtd_get_host_iommu_quirks(uint32_t type,
>                                             void *caps, uint32_t size)
>   {
Re: [PATCH v2 10/14] intel_iommu_accel: Handle PASID entry removal for system reset
Posted by Yi Liu 3 days, 15 hours ago
On 3/27/26 12:32, Yi Liu wrote:
> On 3/26/26 17:11, Zhenzhong Duan wrote:
>> When system level reset, DMA translation is turned off, all PASID
>> entries become stale and should be deleted.
>>
>> vtd_hiod list is never accessed without BQL, so no need to guard with
>> iommu lock.
>>
>> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
>> ---
>>   hw/i386/intel_iommu_accel.h |  5 +++++
>>   hw/i386/intel_iommu.c       |  2 ++
>>   hw/i386/intel_iommu_accel.c | 13 +++++++++++++
>>   3 files changed, 20 insertions(+)
>>
>> diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
>> index c5981a23bf..1fb7ca0af6 100644
>> --- a/hw/i386/intel_iommu_accel.h
>> +++ b/hw/i386/intel_iommu_accel.h
>> @@ -28,6 +28,7 @@ void 
>> vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
>>                                         uint32_t pasid, hwaddr addr,
>>                                         uint64_t npages, bool ih);
>>   void vtd_pasid_cache_sync_accel(IntelIOMMUState *s, 
>> VTDPASIDCacheInfo *pc_info);
>> +void vtd_pasid_cache_reset_accel(IntelIOMMUState *s);
>>   void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops);
>>   #else
>>   static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
>> @@ -62,6 +63,10 @@ static inline void 
>> vtd_pasid_cache_sync_accel(IntelIOMMUState *s,
>>   {
>>   }
>> +static inline void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
>> +{
>> +}
>> +
>>   static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops)
>>   {
>>   }
>> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
>> index 451ede7530..b022f3cb9e 100644
>> --- a/hw/i386/intel_iommu.c
>> +++ b/hw/i386/intel_iommu.c
>> @@ -391,6 +391,8 @@ static void vtd_reset_caches(IntelIOMMUState *s)
>>       vtd_reset_context_cache_locked(s);
>>       vtd_pasid_cache_reset_locked(s);
>>       vtd_iommu_unlock(s);
>> +
>> +    vtd_pasid_cache_reset_accel(s);
>>   }
>>   static uint64_t vtd_get_iotlb_gfn(hwaddr addr, uint32_t level)
>> diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
>> index 1e27c0feb8..e9e67eb1a0 100644
>> --- a/hw/i386/intel_iommu_accel.c
>> +++ b/hw/i386/intel_iommu_accel.c
>> @@ -511,6 +511,19 @@ void vtd_pasid_cache_sync_accel(IntelIOMMUState 
>> *s, VTDPASIDCacheInfo *pc_info)
>>       }
>>   }
>> +/* Fake a gloal pasid cache invalidation to remove all pasid cache 
>> entries */

nit : s/gloal/global/

>> +void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
>> +{
>> +    VTDPASIDCacheInfo pc_info = { .type = 
>> VTD_INV_DESC_PASIDC_G_GLOBAL };
>> +    VTDHostIOMMUDevice *vtd_hiod;
>> +    GHashTableIter as_it;
>> +
>> +    g_hash_table_iter_init(&as_it, s->vtd_host_iommu_dev);
>> +    while (g_hash_table_iter_next(&as_it, NULL, (void **)&vtd_hiod)) {
> 
> s/as_it/hiod_it/
> 
> other part LGTM.
> 
> Reviewed-by: Yi Liu <yi.l.liu@intel.com>

this function is better to be vtd_accel_pasid_cache_reset()
>> +        vtd_pasid_cache_invalidate(vtd_hiod, &pc_info);
>> +    }
>> +}
>> +
>>   static uint64_t vtd_get_host_iommu_quirks(uint32_t type,
>>                                             void *caps, uint32_t size)
>>   {
> 


RE: [PATCH v2 10/14] intel_iommu_accel: Handle PASID entry removal for system reset
Posted by Duan, Zhenzhong 3 days, 14 hours ago

>-----Original Message-----
>From: Liu, Yi L <yi.l.liu@intel.com>
>Subject: Re: [PATCH v2 10/14] intel_iommu_accel: Handle PASID entry removal for
>system reset
>
>On 3/27/26 12:32, Yi Liu wrote:
>> On 3/26/26 17:11, Zhenzhong Duan wrote:
>>> When system level reset, DMA translation is turned off, all PASID
>>> entries become stale and should be deleted.
>>>
>>> vtd_hiod list is never accessed without BQL, so no need to guard with
>>> iommu lock.
>>>
>>> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
>>> ---
>>>   hw/i386/intel_iommu_accel.h |  5 +++++
>>>   hw/i386/intel_iommu.c       |  2 ++
>>>   hw/i386/intel_iommu_accel.c | 13 +++++++++++++
>>>   3 files changed, 20 insertions(+)
>>>
>>> diff --git a/hw/i386/intel_iommu_accel.h b/hw/i386/intel_iommu_accel.h
>>> index c5981a23bf..1fb7ca0af6 100644
>>> --- a/hw/i386/intel_iommu_accel.h
>>> +++ b/hw/i386/intel_iommu_accel.h
>>> @@ -28,6 +28,7 @@ void
>>> vtd_flush_host_piotlb_all_locked(IntelIOMMUState *s, uint16_t domain_id,
>>>                                         uint32_t pasid, hwaddr addr,
>>>                                         uint64_t npages, bool ih);
>>>   void vtd_pasid_cache_sync_accel(IntelIOMMUState *s,
>>> VTDPASIDCacheInfo *pc_info);
>>> +void vtd_pasid_cache_reset_accel(IntelIOMMUState *s);
>>>   void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops);
>>>   #else
>>>   static inline bool vtd_check_hiod_accel(IntelIOMMUState *s,
>>> @@ -62,6 +63,10 @@ static inline void
>>> vtd_pasid_cache_sync_accel(IntelIOMMUState *s,
>>>   {
>>>   }
>>> +static inline void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
>>> +{
>>> +}
>>> +
>>>   static inline void vtd_iommu_ops_update_accel(PCIIOMMUOps *ops)
>>>   {
>>>   }
>>> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
>>> index 451ede7530..b022f3cb9e 100644
>>> --- a/hw/i386/intel_iommu.c
>>> +++ b/hw/i386/intel_iommu.c
>>> @@ -391,6 +391,8 @@ static void vtd_reset_caches(IntelIOMMUState *s)
>>>       vtd_reset_context_cache_locked(s);
>>>       vtd_pasid_cache_reset_locked(s);
>>>       vtd_iommu_unlock(s);
>>> +
>>> +    vtd_pasid_cache_reset_accel(s);
>>>   }
>>>   static uint64_t vtd_get_iotlb_gfn(hwaddr addr, uint32_t level)
>>> diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
>>> index 1e27c0feb8..e9e67eb1a0 100644
>>> --- a/hw/i386/intel_iommu_accel.c
>>> +++ b/hw/i386/intel_iommu_accel.c
>>> @@ -511,6 +511,19 @@ void vtd_pasid_cache_sync_accel(IntelIOMMUState
>>> *s, VTDPASIDCacheInfo *pc_info)
>>>       }
>>>   }
>>> +/* Fake a gloal pasid cache invalidation to remove all pasid cache
>>> entries */
>
>nit : s/gloal/global/

Good catch, will fix.

>
>>> +void vtd_pasid_cache_reset_accel(IntelIOMMUState *s)
>>> +{
>>> +    VTDPASIDCacheInfo pc_info = { .type =
>>> VTD_INV_DESC_PASIDC_G_GLOBAL };
>>> +    VTDHostIOMMUDevice *vtd_hiod;
>>> +    GHashTableIter as_it;
>>> +
>>> +    g_hash_table_iter_init(&as_it, s->vtd_host_iommu_dev);
>>> +    while (g_hash_table_iter_next(&as_it, NULL, (void **)&vtd_hiod)) {
>>
>> s/as_it/hiod_it/
>>
>> other part LGTM.
>>
>> Reviewed-by: Yi Liu <yi.l.liu@intel.com>
>
>this function is better to be vtd_accel_pasid_cache_reset()

OK.

Thanks
Zhenzhong