[PATCH v2 07/10] iommu/arm-smmu-v3: Pass in vsmmu to arm_smmu_domain_get_iotlb_tag()
From: Nicolin Chen <hidden>
Date: 2026-01-22 01:25:06
Also in:
linux-iommu, linux-patches, lkml
Subsystem:
arm smmu drivers, arm smmu sva support, iommu subsystem, the rest · Maintainers:
Will Deacon, Joerg Roedel, Linus Torvalds
When a device attaches to a nested domain, VMID is held by its associated vSMMU instance. So arm_smmu_domain_get_iotlb_tag() should return the VMID from the vSMMU instance rather than allocating a new one. Pass in a vsmmu pointer to arm_smmu_domain_get_iotlb_tag(), to prepare for this. Signed-off-by: Nicolin Chen <redacted> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 9 +++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 1 + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 4 ++-- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 7 +++++-- 4 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 8aecdbceb974..386ac75879c0 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h@@ -1124,6 +1124,7 @@ struct arm_smmu_attach_state { /* Inputs */ struct iommu_domain *old_domain; struct arm_smmu_master *master; + struct arm_vsmmu *vsmmu; bool cd_needs_ats; bool disable_ats; ioasid_t ssid;
@@ -1136,6 +1137,7 @@ struct arm_smmu_attach_state { int arm_smmu_domain_get_iotlb_tag(struct arm_smmu_domain *smmu_domain, struct arm_smmu_device *smmu, + struct arm_vsmmu *vsmmu, struct arm_smmu_inv *tag, bool alloc); int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
@@ -1182,6 +1184,13 @@ struct arm_vsmmu { u16 vmid; }; +static inline struct arm_vsmmu *to_vsmmu(struct iommu_domain *domain) +{ + if (domain->type == IOMMU_DOMAIN_NESTED) + return to_smmu_nested_domain(domain)->vsmmu; + return NULL; +} + #if IS_ENABLED(CONFIG_ARM_SMMU_V3_IOMMUFD) void *arm_smmu_hw_info(struct device *dev, u32 *length, enum iommu_hw_info_type *type);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 9998871f69a0..33b336d494c3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c@@ -162,6 +162,7 @@ static int arm_smmu_attach_dev_nested(struct iommu_domain *domain, struct arm_smmu_master *master = dev_iommu_priv_get(dev); struct arm_smmu_attach_state state = { .master = master, + .vsmmu = nested_domain->vsmmu, .old_domain = old_domain, .ssid = IOMMU_NO_PASID, };
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 5c8960d31a9b..461ccf4bdb03 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c@@ -31,7 +31,7 @@ arm_smmu_update_s1_domain_cd_entry(struct arm_smmu_domain *smmu_domain) continue; if (WARN_ON(arm_smmu_domain_get_iotlb_tag( - smmu_domain, master->smmu, &tag, false))) + smmu_domain, master->smmu, NULL, &tag, false))) continue; if (WARN_ON(tag.type != INV_TYPE_S1_ASID)) continue;
@@ -171,7 +171,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) continue; if (WARN_ON(arm_smmu_domain_get_iotlb_tag( - smmu_domain, master->smmu, &tag, false))) + smmu_domain, master->smmu, NULL, &tag, false))) continue; if (WARN_ON(tag.type != INV_TYPE_S1_ASID)) continue;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 5a7032081553..8323f74c8923 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c@@ -3137,6 +3137,7 @@ static int __arm_smmu_domain_get_iotlb_tag(struct arm_smmu_domain *smmu_domain, int arm_smmu_domain_get_iotlb_tag(struct arm_smmu_domain *smmu_domain, struct arm_smmu_device *smmu, + struct arm_vsmmu *vsmmu, struct arm_smmu_inv *tag, bool alloc) { int ret;
@@ -3360,6 +3361,7 @@ static int arm_smmu_attach_prepare_invs(struct arm_smmu_attach_state *state, */ if (new_smmu_domain) { struct arm_smmu_inv_state *invst = &state->new_domain_invst; + struct arm_vsmmu *vsmmu = state->vsmmu; struct arm_smmu_invs *build_invs; invst->invs_ptr = &new_smmu_domain->invs;
@@ -3368,7 +3370,7 @@ static int arm_smmu_attach_prepare_invs(struct arm_smmu_attach_state *state, lockdep_is_held(&arm_smmu_asid_lock)); ret = arm_smmu_domain_get_iotlb_tag(new_smmu_domain, smmu, - &invst->tag, true); + vsmmu, &invst->tag, true); if (ret) return ret;
@@ -3387,6 +3389,7 @@ static int arm_smmu_attach_prepare_invs(struct arm_smmu_attach_state *state, if (old_smmu_domain) { struct arm_smmu_inv_state *invst = &state->old_domain_invst; + struct arm_vsmmu *vsmmu = to_vsmmu(state->old_domain); invst->invs_ptr = &old_smmu_domain->invs; /* A re-attach case might have a different ats_enabled state */
@@ -3398,7 +3401,7 @@ static int arm_smmu_attach_prepare_invs(struct arm_smmu_attach_state *state, lockdep_is_held(&arm_smmu_asid_lock)); ret = arm_smmu_domain_get_iotlb_tag(old_smmu_domain, smmu, - &invst->tag, false); + vsmmu, &invst->tag, false); if (WARN_ON(ret)) return ret;
--
2.43.0