For VTD_INV_DESC_PASIDC_G_PASID_SI typed pc_inv_dsc invalidation, if an
pasid entry is just removed, it can never be a new entry to add. So
calling vtd_replay_pasid_bind_for_dev() is unnecessary.
Introduce a new field accel_pce_deleted in VTDPASIDCacheInfo to mark
this case and to do the bypassing.
Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
---
hw/i386/intel_iommu_internal.h | 1 +
hw/i386/intel_iommu_accel.c | 16 +++++++++++++---
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 623dc24760..2c716c5297 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -630,6 +630,7 @@ typedef struct VTDPASIDCacheInfo {
uint8_t type;
uint16_t did;
uint32_t pasid;
+ bool accel_pce_deleted;
} VTDPASIDCacheInfo;
typedef struct VTDPIOTLBInvInfo {
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index b951d90135..457fdcba62 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -302,10 +302,15 @@ static void vtd_accel_fill_pc(VTDHostIOMMUDevice *vtd_hiod, uint32_t pasid,
QLIST_INSERT_HEAD(&vtd_hiod->pasid_cache_list, vtd_pce, next);
}
-static void vtd_accel_delete_pc(VTDAccelPASIDCacheEntry *vtd_pce)
+static void vtd_accel_delete_pc(VTDAccelPASIDCacheEntry *vtd_pce,
+ VTDPASIDCacheInfo *pc_info)
{
QLIST_REMOVE(vtd_pce, next);
g_free(vtd_pce);
+
+ if (pc_info->type == VTD_INV_DESC_PASIDC_G_PASID_SI) {
+ pc_info->accel_pce_deleted = true;
+ }
}
static void
@@ -339,7 +344,7 @@ vtd_accel_pasid_cache_invalidate_one(VTDAccelPASIDCacheEntry *vtd_pce,
* to be either all-zero or non-present. Either case means existing
* pasid cache should be invalidated.
*/
- vtd_accel_delete_pc(vtd_pce);
+ vtd_accel_delete_pc(vtd_pce, pc_info);
}
}
@@ -502,7 +507,12 @@ void vtd_accel_pasid_cache_sync(IntelIOMMUState *s, VTDPASIDCacheInfo *pc_info)
* removed.
*/
vtd_accel_pasid_cache_invalidate(vtd_hiod, pc_info);
- vtd_accel_replay_pasid_bind_for_dev(vtd_hiod, start, end, pc_info);
+
+ if (pc_info->accel_pce_deleted) {
+ pc_info->accel_pce_deleted = false;
+ } else {
+ vtd_accel_replay_pasid_bind_for_dev(vtd_hiod, start, end, pc_info);
+ }
}
}
--
2.47.3