Skip to content

Commit 37764b9

Browse files
skuma24joergroedel
authored andcommitted
iommu/vt-d: Global devTLB flush when present context entry changed
This fixes a bug in context cache clear operation. The code was not following the correct invalidation flow. A global device TLB invalidation should be added after the IOTLB invalidation. At the same time, it uses the domain ID from the context entry. But in scalable mode, the domain ID is in PASID table entry, not context entry. Fixes: 7373a8c ("iommu/vt-d: Setup context and enable RID2PASID support") Cc: stable@vger.kernel.org # v5.0+ Signed-off-by: Sanjay Kumar <sanjay.k.kumar@intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Link: https://lore.kernel.org/r/20210712071315.3416543-1-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent ce36c94 commit 37764b9

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,10 +2429,11 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
24292429
return 0;
24302430
}
24312431

2432-
static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
2432+
static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8 devfn)
24332433
{
2434-
unsigned long flags;
2434+
struct intel_iommu *iommu = info->iommu;
24352435
struct context_entry *context;
2436+
unsigned long flags;
24362437
u16 did_old;
24372438

24382439
if (!iommu)
@@ -2444,7 +2445,16 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn
24442445
spin_unlock_irqrestore(&iommu->lock, flags);
24452446
return;
24462447
}
2447-
did_old = context_domain_id(context);
2448+
2449+
if (sm_supported(iommu)) {
2450+
if (hw_pass_through && domain_type_is_si(info->domain))
2451+
did_old = FLPT_DEFAULT_DID;
2452+
else
2453+
did_old = info->domain->iommu_did[iommu->seq_id];
2454+
} else {
2455+
did_old = context_domain_id(context);
2456+
}
2457+
24482458
context_clear_entry(context);
24492459
__iommu_flush_cache(iommu, context, sizeof(*context));
24502460
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -2462,6 +2472,8 @@ static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn
24622472
0,
24632473
0,
24642474
DMA_TLB_DSI_FLUSH);
2475+
2476+
__iommu_flush_dev_iotlb(info, 0, MAX_AGAW_PFN_WIDTH);
24652477
}
24662478

24672479
static inline void unlink_domain_info(struct device_domain_info *info)
@@ -4425,9 +4437,9 @@ int __init intel_iommu_init(void)
44254437

44264438
static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
44274439
{
4428-
struct intel_iommu *iommu = opaque;
4440+
struct device_domain_info *info = opaque;
44294441

4430-
domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
4442+
domain_context_clear_one(info, PCI_BUS_NUM(alias), alias & 0xff);
44314443
return 0;
44324444
}
44334445

@@ -4437,12 +4449,13 @@ static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *op
44374449
* devices, unbinding the driver from any one of them will possibly leave
44384450
* the others unable to operate.
44394451
*/
4440-
static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
4452+
static void domain_context_clear(struct device_domain_info *info)
44414453
{
4442-
if (!iommu || !dev || !dev_is_pci(dev))
4454+
if (!info->iommu || !info->dev || !dev_is_pci(info->dev))
44434455
return;
44444456

4445-
pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
4457+
pci_for_each_dma_alias(to_pci_dev(info->dev),
4458+
&domain_context_clear_one_cb, info);
44464459
}
44474460

44484461
static void __dmar_remove_one_dev_info(struct device_domain_info *info)
@@ -4466,7 +4479,7 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
44664479

44674480
iommu_disable_dev_iotlb(info);
44684481
if (!dev_is_real_dma_subdevice(info->dev))
4469-
domain_context_clear(iommu, info->dev);
4482+
domain_context_clear(info);
44704483
intel_pasid_free_table(info->dev);
44714484
}
44724485

0 commit comments

Comments
 (0)