Skip to content

Commit f1e1610

Browse files
yiliu1765joergroedel
authored andcommitted
iommu/vt-d: Add missing dirty tracking set for parent domain
Setting dirty tracking for a s2 domain requires to loop all the related devices and set the dirty tracking enable bit in the PASID table entry. This includes the devices that are attached to the nested domains of a s2 domain if this s2 domain is used as parent. However, the existing dirty tracking set only loops s2 domain's own devices. It will miss dirty page logs in the parent domain. Now, the parent domain tracks the nested domains, so it can loop the nested domains and the devices attached to the nested domains to ensure dirty tracking on the parent is set completely. Fixes: b41e38e ("iommu/vt-d: Add nested domain allocation") Signed-off-by: Yi Sun <[email protected]> Signed-off-by: Yi Liu <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lu Baolu <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent 0c7f249 commit f1e1610

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4748,6 +4748,35 @@ static int device_set_dirty_tracking(struct list_head *devices, bool enable)
47484748
return ret;
47494749
}
47504750

4751+
static int parent_domain_set_dirty_tracking(struct dmar_domain *domain,
4752+
bool enable)
4753+
{
4754+
struct dmar_domain *s1_domain;
4755+
unsigned long flags;
4756+
int ret;
4757+
4758+
spin_lock(&domain->s1_lock);
4759+
list_for_each_entry(s1_domain, &domain->s1_domains, s2_link) {
4760+
spin_lock_irqsave(&s1_domain->lock, flags);
4761+
ret = device_set_dirty_tracking(&s1_domain->devices, enable);
4762+
spin_unlock_irqrestore(&s1_domain->lock, flags);
4763+
if (ret)
4764+
goto err_unwind;
4765+
}
4766+
spin_unlock(&domain->s1_lock);
4767+
return 0;
4768+
4769+
err_unwind:
4770+
list_for_each_entry(s1_domain, &domain->s1_domains, s2_link) {
4771+
spin_lock_irqsave(&s1_domain->lock, flags);
4772+
device_set_dirty_tracking(&s1_domain->devices,
4773+
domain->dirty_tracking);
4774+
spin_unlock_irqrestore(&s1_domain->lock, flags);
4775+
}
4776+
spin_unlock(&domain->s1_lock);
4777+
return ret;
4778+
}
4779+
47514780
static int intel_iommu_set_dirty_tracking(struct iommu_domain *domain,
47524781
bool enable)
47534782
{
@@ -4762,6 +4791,12 @@ static int intel_iommu_set_dirty_tracking(struct iommu_domain *domain,
47624791
if (ret)
47634792
goto err_unwind;
47644793

4794+
if (dmar_domain->nested_parent) {
4795+
ret = parent_domain_set_dirty_tracking(dmar_domain, enable);
4796+
if (ret)
4797+
goto err_unwind;
4798+
}
4799+
47654800
dmar_domain->dirty_tracking = enable;
47664801
out_unlock:
47674802
spin_unlock(&dmar_domain->lock);

0 commit comments

Comments
 (0)