From: Nicolin Chen <nicol...@nvidia.com> If a vSMMU is configured as a accelerated one, HW IOTLB will be used and all cache invalidation should be done to the HW IOTLB too, v.s. the emulated iotlb. In this case, an iommu notifier isn't registered, as the devices behind a SMMUv3-accel would stay in the system address space for stage-2 mappings.
However, the KVM code still requests an iommu address space to translate an MSI doorbell gIOVA via get_msi_address_space() and translate(). Since a SMMUv3-accel doesn't register an iommu notifier to flush emulated iotlb, bypass the emulated IOTLB and always walk through the guest-level IO page table. Signed-off-by: Nicolin Chen <nicol...@nvidia.com> Signed-off-by: Shameer Kolothum <shameerali.kolothum.th...@huawei.com> --- hw/arm/smmu-common.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 9fd455baa0..fd10df8866 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -77,6 +77,17 @@ static SMMUTLBEntry *smmu_iotlb_lookup_all_levels(SMMUState *bs, uint8_t level = 4 - (inputsize - 4) / stride; SMMUTLBEntry *entry = NULL; + /* + * Stage-1 translation with a accel SMMU in general uses HW IOTLB. However, + * KVM still requests for an iommu address space for an MSI fixup by looking + * up stage-1 page table. Make sure we don't go through the emulated pathway + * so that the emulated iotlb will not need any invalidation. + */ + + if (bs->accel) { + return NULL; + } + while (level <= 3) { uint64_t subpage_size = 1ULL << level_shift(level, tt->granule_sz); uint64_t mask = subpage_size - 1; @@ -142,6 +153,16 @@ void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *new) SMMUIOTLBKey *key = g_new0(SMMUIOTLBKey, 1); uint8_t tg = (new->granule - 10) / 2; + /* + * Stage-1 translation with a accel SMMU in general uses HW IOTLB. However, + * KVM still requests for an iommu address space for an MSI fixup by looking + * up stage-1 page table. Make sure we don't go through the emulated pathway + * so that the emulated iotlb will not need any invalidation. + */ + if (bs->accel) { + return; + } + if (g_hash_table_size(bs->iotlb) >= SMMU_IOTLB_MAX_SIZE) { smmu_iotlb_inv_all(bs); } -- 2.34.1