Skip to content

Commit 0fa1a15

Browse files
yiliu1765joergroedel
authored andcommitted
iommu/vt-d: Fix devTLB flush for vSVA
For guest SVA usage, in order to optimize for less VMEXIT, guest request of IOTLB flush also includes device TLB. On the host side, IOMMU driver performs IOTLB and implicit devTLB invalidation. When PASID-selective granularity is requested by the guest we need to derive the equivalent address range for devTLB instead of using the address information in the UAPI data. The reason for that is, unlike IOTLB flush, devTLB flush does not support PASID-selective granularity. This is to say, we need to set the following in the PASID based devTLB invalidation descriptor: - entire 64 bit range in address ~(0x1 << 63) - S bit = 1 (VT-d CH 6.5.2.6). Without this fix, device TLB flush range is not set properly for PASID selective granularity. This patch also merged devTLB flush code for both implicit and explicit cases. Fixes: 6ee1b77 ("iommu/vt-d: Add svm/sva invalidate function") Signed-off-by: Liu Yi L <[email protected]> Signed-off-by: Jacob Pan <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Eric Auger <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 288d08e commit 0fa1a15

File tree

1 file changed

+21
-10
lines changed

1 file changed

+21
-10
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5416,7 +5416,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
54165416
sid = PCI_DEVID(bus, devfn);
54175417

54185418
/* Size is only valid in address selective invalidation */
5419-
if (inv_info->granularity != IOMMU_INV_GRANU_PASID)
5419+
if (inv_info->granularity == IOMMU_INV_GRANU_ADDR)
54205420
size = to_vtd_size(inv_info->addr_info.granule_size,
54215421
inv_info->addr_info.nb_granules);
54225422

@@ -5425,6 +5425,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
54255425
IOMMU_CACHE_INV_TYPE_NR) {
54265426
int granu = 0;
54275427
u64 pasid = 0;
5428+
u64 addr = 0;
54285429

54295430
granu = to_vtd_granularity(cache_type, inv_info->granularity);
54305431
if (granu == -EINVAL) {
@@ -5464,24 +5465,34 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
54645465
(granu == QI_GRAN_NONG_PASID) ? -1 : 1 << size,
54655466
inv_info->addr_info.flags & IOMMU_INV_ADDR_FLAGS_LEAF);
54665467

5468+
if (!info->ats_enabled)
5469+
break;
54675470
/*
54685471
* Always flush device IOTLB if ATS is enabled. vIOMMU
54695472
* in the guest may assume IOTLB flush is inclusive,
54705473
* which is more efficient.
54715474
*/
5472-
if (info->ats_enabled)
5473-
qi_flush_dev_iotlb_pasid(iommu, sid,
5474-
info->pfsid, pasid,
5475-
info->ats_qdep,
5476-
inv_info->addr_info.addr,
5477-
size);
5478-
break;
5475+
fallthrough;
54795476
case IOMMU_CACHE_INV_TYPE_DEV_IOTLB:
5477+
/*
5478+
* PASID based device TLB invalidation does not support
5479+
* IOMMU_INV_GRANU_PASID granularity but only supports
5480+
* IOMMU_INV_GRANU_ADDR.
5481+
* The equivalent of that is we set the size to be the
5482+
* entire range of 64 bit. User only provides PASID info
5483+
* without address info. So we set addr to 0.
5484+
*/
5485+
if (inv_info->granularity == IOMMU_INV_GRANU_PASID) {
5486+
size = 64 - VTD_PAGE_SHIFT;
5487+
addr = 0;
5488+
} else if (inv_info->granularity == IOMMU_INV_GRANU_ADDR) {
5489+
addr = inv_info->addr_info.addr;
5490+
}
5491+
54805492
if (info->ats_enabled)
54815493
qi_flush_dev_iotlb_pasid(iommu, sid,
54825494
info->pfsid, pasid,
5483-
info->ats_qdep,
5484-
inv_info->addr_info.addr,
5495+
info->ats_qdep, addr,
54855496
size);
54865497
else
54875498
pr_warn_ratelimited("Passdown device IOTLB flush w/o ATS!\n");

0 commit comments

Comments
 (0)