FAILED: patch "[PATCH] iommu/vt-d: Fix ineffective devTLB invalidation for" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 7c29ada5e70083805bc3a68daa23441df421fbee Mon Sep 17 00:00:00 2001
From: Liu Yi L <[email protected]>
Date: Thu, 7 Jan 2021 00:03:57 +0800
Subject: [PATCH] iommu/vt-d: Fix ineffective devTLB invalidation for
subdevices
iommu_flush_dev_iotlb() is called to invalidate caches on a device but only loops over the devices which are fully-attached to the domain. For sub-devices, this is ineffective and can result in invalid caching entries left on the device.
Fix the missing invalidation by adding a loop over the subdevices and ensuring that 'domain->has_iotlb_device' is updated when attaching to subdevices.
drivers/iommu/intel/iommu.c +37 -16
@@ -719,6 +719,8 @@ static int domain_update_device_node(struct dmar_domain *domain)return nid; } +static void domain_update_iotlb (struct dmar_domain *domain); +/* Some capabilities may be different across iommus */ static void domain_update_iommu_cap (struct dmar_domain *domain) {
@@ -744,6 +746,8 @@ static void domain_update_iommu_cap(struct dmar_domain *domain) domain->domain.geometry.aperture_end =__DOMAIN_MAX_ADDR (domain->gaw -1 ); else domain->domain.geometry.aperture_end = __DOMAIN_MAX_ADDR(domain->gaw); + +domain_update_iotlb (domain); } struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
@@ -1464,17 +1468,22 @@ static void domain_update_iotlb(struct dmar_domain *domain)assert_spin_locked (&device_domain_lock); -list_for_each_entry (info, &domain->devices, link) { -struct pci_dev *pdev; - -if (!info->dev || !dev_is_pci (info->dev)) -continue ; - - pdev =to_pci_dev (info->dev); -if (pdev->ats_enabled) { +list_for_each_entry (info, &domain->devices, link) +if (info->ats_enabled) { has_iotlb_device = true;break ; } + +if (!has_iotlb_device) { +struct subdev_domain_info *sinfo; + +list_for_each_entry (sinfo, &domain->subdevices, link_domain) { + info =get_domain_info (sinfo->pdev); +if (info && info->ats_enabled) { + has_iotlb_device = true; +break ; + } + } } domain->has_iotlb_device = has_iotlb_device;
@@ -1555,25 +1564,37 @@ static void iommu_disable_dev_iotlb(struct device_domain_info *info)#endif } +static void __iommu_flush_dev_iotlb (struct device_domain_info *info, +u64 addr,unsigned int mask) +{ +u16 sid, qdep; + +if (!info || !info->ats_enabled) +return ; + + sid = info->bus <<8 | info->devfn; + qdep = info->ats_qdep; +qi_flush_dev_iotlb (info->iommu, sid, info->pfsid, + qdep, addr, mask); +} +static void iommu_flush_dev_iotlb (struct dmar_domain *domain,u64 addr,unsigned mask) { -u16 sid, qdep;unsigned long flags;struct device_domain_info *info; +struct subdev_domain_info *sinfo;if (!domain->has_iotlb_device)return ;spin_lock_irqsave (&device_domain_lock, flags); -list_for_each_entry (info, &domain->devices, link) { -if (!info->ats_enabled) -continue ; +list_for_each_entry (info, &domain->devices, link) +__iommu_flush_dev_iotlb (info, addr, mask); - sid = info->bus <<8 | info->devfn; - qdep = info->ats_qdep; -qi_flush_dev_iotlb (info->iommu, sid, info->pfsid, - qdep, addr, mask); +list_for_each_entry (sinfo, &domain->subdevices, link_domain) { + info =get_domain_info (sinfo->pdev); +__iommu_flush_dev_iotlb (info, addr, mask); }spin_unlock_irqrestore (&device_domain_lock, flags); }