Skip to content

Commit 85ce8e1

Browse files
yiliu1765joergroedel
authored andcommitted
iommu/vt-d: Track nested domains in parent
Today the parent domain (s2_domain) is unaware of which DID's are used by and which devices are attached to nested domains (s1_domain) nested on it. This leads to a problem that some operations (flush iotlb/devtlb and enable dirty tracking) on parent domain only apply to DID's and devices directly tracked in the parent domain hence are incomplete. This tracks the nested domains in list in parent domain. With this, operations on parent domain can loop the nested domains and refer to the devices and iommu_array to ensure the operations on parent domain take effect on all the affected devices and iommus. 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 b401b62 commit 85ce8e1

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3883,6 +3883,7 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
38833883
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
38843884
bool nested_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT;
38853885
struct intel_iommu *iommu = info->iommu;
3886+
struct dmar_domain *dmar_domain;
38863887
struct iommu_domain *domain;
38873888

38883889
/* Must be NESTING domain */
@@ -3908,11 +3909,16 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
39083909
if (!domain)
39093910
return ERR_PTR(-ENOMEM);
39103911

3911-
if (nested_parent)
3912-
to_dmar_domain(domain)->nested_parent = true;
3912+
dmar_domain = to_dmar_domain(domain);
3913+
3914+
if (nested_parent) {
3915+
dmar_domain->nested_parent = true;
3916+
INIT_LIST_HEAD(&dmar_domain->s1_domains);
3917+
spin_lock_init(&dmar_domain->s1_lock);
3918+
}
39133919

39143920
if (dirty_tracking) {
3915-
if (to_dmar_domain(domain)->use_first_level) {
3921+
if (dmar_domain->use_first_level) {
39163922
iommu_domain_free(domain);
39173923
return ERR_PTR(-EOPNOTSUPP);
39183924
}
@@ -3924,8 +3930,12 @@ intel_iommu_domain_alloc_user(struct device *dev, u32 flags,
39243930

39253931
static void intel_iommu_domain_free(struct iommu_domain *domain)
39263932
{
3933+
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
3934+
3935+
WARN_ON(dmar_domain->nested_parent &&
3936+
!list_empty(&dmar_domain->s1_domains));
39273937
if (domain != &si_domain->domain)
3928-
domain_exit(to_dmar_domain(domain));
3938+
domain_exit(dmar_domain);
39293939
}
39303940

39313941
int prepare_domain_attach_device(struct iommu_domain *domain,

drivers/iommu/intel/iommu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,10 @@ struct dmar_domain {
627627
int agaw;
628628
/* maximum mapped address */
629629
u64 max_addr;
630+
/* Protect the s1_domains list */
631+
spinlock_t s1_lock;
632+
/* Track s1_domains nested on this domain */
633+
struct list_head s1_domains;
630634
};
631635

632636
/* Nested user domain */
@@ -637,6 +641,8 @@ struct dmar_domain {
637641
unsigned long s1_pgtbl;
638642
/* page table attributes */
639643
struct iommu_hwpt_vtd_s1 s1_cfg;
644+
/* link to parent domain siblings */
645+
struct list_head s2_link;
640646
};
641647
};
642648

drivers/iommu/intel/nested.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,13 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
7070

7171
static void intel_nested_domain_free(struct iommu_domain *domain)
7272
{
73-
kfree(to_dmar_domain(domain));
73+
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
74+
struct dmar_domain *s2_domain = dmar_domain->s2_domain;
75+
76+
spin_lock(&s2_domain->s1_lock);
77+
list_del(&dmar_domain->s2_link);
78+
spin_unlock(&s2_domain->s1_lock);
79+
kfree(dmar_domain);
7480
}
7581

7682
static void nested_flush_dev_iotlb(struct dmar_domain *domain, u64 addr,
@@ -201,5 +207,9 @@ struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
201207
spin_lock_init(&domain->lock);
202208
xa_init(&domain->iommu_array);
203209

210+
spin_lock(&s2_domain->s1_lock);
211+
list_add(&domain->s2_link, &s2_domain->s1_domains);
212+
spin_unlock(&s2_domain->s1_lock);
213+
204214
return &domain->domain;
205215
}

0 commit comments

Comments
 (0)