Skip to content

Commit 7af6c72

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Fix incorrect domain ID in context flush helper
The helper intel_context_flush_present() is designed to flush all related caches when a context entry with the present bit set is modified. It currently retrieves the domain ID from the context entry and uses it to flush the IOTLB and context caches. This is incorrect when the context entry transitions from present to non-present, as the domain ID field is cleared before calling the helper. Fix it by passing the domain ID programmed in the context entry before the change to intel_context_flush_present(). This ensures that the correct domain ID is used for cache invalidation. Fixes: f90584f ("iommu/vt-d: Add helper to flush caches for context change") Reported-by: Alex Williamson <[email protected]> Closes: https://lore.kernel.org/linux-iommu/[email protected]/ Signed-off-by: Lu Baolu <[email protected]> Tested-by: Alex Williamson <[email protected]> Reviewed-by: Alex Williamson <[email protected]> Reviewed-by: Jerry Snitselaar <[email protected]> Reviewed-by: Jacob Pan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent b58b133 commit 7af6c72

File tree

3 files changed

+11
-6
lines changed

3 files changed

+11
-6
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,7 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
19441944
{
19451945
struct intel_iommu *iommu = info->iommu;
19461946
struct context_entry *context;
1947+
u16 did;
19471948

19481949
spin_lock(&iommu->lock);
19491950
context = iommu_context_addr(iommu, bus, devfn, 0);
@@ -1952,10 +1953,11 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
19521953
return;
19531954
}
19541955

1956+
did = context_domain_id(context);
19551957
context_clear_entry(context);
19561958
__iommu_flush_cache(iommu, context, sizeof(*context));
19571959
spin_unlock(&iommu->lock);
1958-
intel_context_flush_present(info, context, true);
1960+
intel_context_flush_present(info, context, did, true);
19591961
}
19601962

19611963
static int domain_setup_first_level(struct intel_iommu *iommu,
@@ -4249,6 +4251,7 @@ static int context_flip_pri(struct device_domain_info *info, bool enable)
42494251
struct intel_iommu *iommu = info->iommu;
42504252
u8 bus = info->bus, devfn = info->devfn;
42514253
struct context_entry *context;
4254+
u16 did;
42524255

42534256
spin_lock(&iommu->lock);
42544257
if (context_copied(iommu, bus, devfn)) {
@@ -4261,6 +4264,7 @@ static int context_flip_pri(struct device_domain_info *info, bool enable)
42614264
spin_unlock(&iommu->lock);
42624265
return -ENODEV;
42634266
}
4267+
did = context_domain_id(context);
42644268

42654269
if (enable)
42664270
context_set_sm_pre(context);
@@ -4269,7 +4273,7 @@ static int context_flip_pri(struct device_domain_info *info, bool enable)
42694273

42704274
if (!ecap_coherent(iommu->ecap))
42714275
clflush_cache_range(context, sizeof(*context));
4272-
intel_context_flush_present(info, context, true);
4276+
intel_context_flush_present(info, context, did, true);
42734277
spin_unlock(&iommu->lock);
42744278

42754279
return 0;

drivers/iommu/intel/iommu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ void cache_tag_flush_range_np(struct dmar_domain *domain, unsigned long start,
11541154

11551155
void intel_context_flush_present(struct device_domain_info *info,
11561156
struct context_entry *context,
1157-
bool affect_domains);
1157+
u16 did, bool affect_domains);
11581158

11591159
#ifdef CONFIG_INTEL_IOMMU_SVM
11601160
void intel_svm_check(struct intel_iommu *iommu);

drivers/iommu/intel/pasid.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
683683
struct device_domain_info *info = dev_iommu_priv_get(dev);
684684
struct intel_iommu *iommu = info->iommu;
685685
struct context_entry *context;
686+
u16 did;
686687

687688
spin_lock(&iommu->lock);
688689
context = iommu_context_addr(iommu, bus, devfn, false);
@@ -691,10 +692,11 @@ static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
691692
return;
692693
}
693694

695+
did = context_domain_id(context);
694696
context_clear_entry(context);
695697
__iommu_flush_cache(iommu, context, sizeof(*context));
696698
spin_unlock(&iommu->lock);
697-
intel_context_flush_present(info, context, false);
699+
intel_context_flush_present(info, context, did, false);
698700
}
699701

700702
static int pci_pasid_table_teardown(struct pci_dev *pdev, u16 alias, void *data)
@@ -885,10 +887,9 @@ static void __context_flush_dev_iotlb(struct device_domain_info *info)
885887
*/
886888
void intel_context_flush_present(struct device_domain_info *info,
887889
struct context_entry *context,
888-
bool flush_domains)
890+
u16 did, bool flush_domains)
889891
{
890892
struct intel_iommu *iommu = info->iommu;
891-
u16 did = context_domain_id(context);
892893
struct pasid_entry *pte;
893894
int i;
894895

0 commit comments

Comments
 (0)