[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1fe65cf21f9eb6c82fde80a6591c644d7224146b.1766088962.git.nicolinc@nvidia.com>
Date: Thu, 18 Dec 2025 12:26:51 -0800
From: Nicolin Chen <nicolinc@...dia.com>
To: <will@...nel.org>, <robin.murphy@....com>, <jgg@...dia.com>
CC: <joro@...tes.org>, <jpb@...nel.org>, <praan@...gle.com>,
<miko.lenczewski@....com>, <linux-arm-kernel@...ts.infradead.org>,
<iommu@...ts.linux.dev>, <linux-kernel@...r.kernel.org>,
<patches@...ts.linux.dev>
Subject: [PATCH v1 5/9] iommu/arm-smmu-v3: Install to CD/STE the ASID/VMID stored in the master
Now the iotlb tag (ASID/VMID) allocated in arm_smmu_invs_merge() is stored
in the master, with a proper release and revert pathways. Replace the old
smmu_domain->cd.asid and smmu_domain->s2_cfg.vmid with the master ones.
The old asid/vmid will be depracated.
Note that the nested pathway needs vsmmu->vmid to be updated to align with
the VMID programmed in the STE as its invalidation code will overwrite the
VMID field using vsmmu->vmid.
Signed-off-by: Nicolin Chen <nicolinc@...dia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 +
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 15 +++++++++++++--
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 4 ++--
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 10 ++++------
4 files changed, 20 insertions(+), 10 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 230ab902a9b6..dac412ff0d71 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1186,6 +1186,7 @@ struct arm_vsmmu {
struct iommufd_viommu core;
struct arm_smmu_device *smmu;
struct arm_smmu_domain *s2_parent;
+ int nr_vmasters;
u16 vmid;
};
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 93fdadd07431..1c877d30f86e 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
@@ -136,6 +136,19 @@ void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state)
struct arm_smmu_master *master = state->master;
mutex_lock(&master->smmu->streams_mutex);
+
+ /* Clear the old vsmmu's VMID and set the new vsmmu's VMID */
+ if (master->vmaster && master->vmaster->vsmmu) {
+ if (--master->vmaster->vsmmu->nr_vmasters == 0)
+ master->vmaster->vsmmu->vmid = 0;
+ WARN_ON(master->vmaster->vsmmu->nr_vmasters < 0);
+ }
+ if (state->vmaster && state->vmaster->vsmmu) {
+ cmpxchg(&state->vmaster->vsmmu->vmid, 0, master->vmid);
+ WARN_ON(state->vmaster->vsmmu->vmid != master->vmid);
+ state->vmaster->vsmmu->nr_vmasters++;
+ }
+
kfree(master->vmaster);
master->vmaster = state->vmaster;
mutex_unlock(&master->smmu->streams_mutex);
@@ -454,8 +467,6 @@ int arm_vsmmu_init(struct iommufd_viommu *viommu,
vsmmu->smmu = smmu;
vsmmu->s2_parent = s2_parent;
- /* FIXME Move VMID allocation from the S2 domain allocation to here */
- vsmmu->vmid = s2_parent->s2_cfg.vmid;
if (viommu->type == IOMMU_VIOMMU_TYPE_ARM_SMMUV3) {
viommu->ops = &arm_vsmmu_ops;
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 adf802f165d1..0e534f2b72e0 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
@@ -164,7 +164,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
if (WARN_ON(!cdptr))
continue;
arm_smmu_make_sva_cd(&target, master, NULL,
- smmu_domain->cd.asid);
+ master->asid[master_domain->ssid]);
arm_smmu_write_cd_entry(master, master_domain->ssid, cdptr,
&target);
}
@@ -266,7 +266,7 @@ static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
* This does not need the arm_smmu_asid_lock because SVA domains never
* get reassigned
*/
- arm_smmu_make_sva_cd(&target, master, domain->mm, smmu_domain->cd.asid);
+ arm_smmu_make_sva_cd(&target, master, domain->mm, master->asid[id]);
ret = arm_smmu_set_pasid(master, smmu_domain, id, &target, old);
mmput(domain->mm);
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 ec370e54b1bc..d6ae630d0de3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1661,7 +1661,6 @@ void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
struct arm_smmu_master *master,
struct arm_smmu_domain *smmu_domain, ioasid_t ssid)
{
- struct arm_smmu_ctx_desc *cd = &smmu_domain->cd;
const struct io_pgtable_cfg *pgtbl_cfg =
&io_pgtable_ops_to_pgtable(smmu_domain->pgtbl_ops)->cfg;
typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr =
@@ -1686,7 +1685,7 @@ void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
CTXDESC_CD_0_R |
CTXDESC_CD_0_A |
CTXDESC_CD_0_ASET |
- FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid)
+ FIELD_PREP(CTXDESC_CD_0_ASID, master->asid[ssid])
);
/* To enable dirty flag update, set both Access flag and dirty state update */
@@ -1945,7 +1944,6 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
struct arm_smmu_domain *smmu_domain,
bool ats_enabled)
{
- struct arm_smmu_s2_cfg *s2_cfg = &smmu_domain->s2_cfg;
const struct io_pgtable_cfg *pgtbl_cfg =
&io_pgtable_ops_to_pgtable(smmu_domain->pgtbl_ops)->cfg;
typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr =
@@ -1976,7 +1974,7 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
FIELD_PREP(STRTAB_STE_2_VTCR_S2TG, vtcr->tg) |
FIELD_PREP(STRTAB_STE_2_VTCR_S2PS, vtcr->ps);
target->data[2] = cpu_to_le64(
- FIELD_PREP(STRTAB_STE_2_S2VMID, s2_cfg->vmid) |
+ FIELD_PREP(STRTAB_STE_2_S2VMID, master->vmid) |
FIELD_PREP(STRTAB_STE_2_VTCR, vtcr_val) |
STRTAB_STE_2_S2AA64 |
#ifdef __BIG_ENDIAN
@@ -3850,7 +3848,7 @@ static int arm_smmu_s1_set_dev_pasid(struct iommu_domain *domain,
return -EINVAL;
/*
- * We can read cd.asid outside the lock because arm_smmu_set_pasid()
+ * We can read master.asid outside the lock because arm_smmu_set_pasid()
* will fix it
*/
arm_smmu_make_s1_cd(&target_cd, master, smmu_domain, id);
@@ -3921,7 +3919,7 @@ int arm_smmu_set_pasid(struct arm_smmu_master *master,
*/
cd->data[0] &= ~cpu_to_le64(CTXDESC_CD_0_ASID);
cd->data[0] |= cpu_to_le64(
- FIELD_PREP(CTXDESC_CD_0_ASID, smmu_domain->cd.asid));
+ FIELD_PREP(CTXDESC_CD_0_ASID, master->asid[pasid]));
arm_smmu_write_cd_entry(master, pasid, cdptr, cd);
arm_smmu_update_ste(master, sid_domain, state.ats_enabled);
--
2.43.0
Powered by blists - more mailing lists