From: Nicolin Chen <nicolinc@nvidia.com>
To: Jason Gunthorpe <jgg@nvidia.com>
Cc: Will Deacon <will@kernel.org>, <jean-philippe@linaro.org>,
<robin.murphy@arm.com>, <joro@8bytes.org>, <balbirs@nvidia.com>,
<miko.lenczewski@arm.com>, <peterz@infradead.org>,
<kevin.tian@intel.com>, <praan@google.com>,
<linux-arm-kernel@lists.infradead.org>, <iommu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v5 5/7] iommu/arm-smmu-v3: Populate smmu_domain->invs when attaching masters
Date: Tue, 25 Nov 2025 16:56:42 -0800 [thread overview]
Message-ID: <aSZQSsP9t0nyfNkx@Asurada-Nvidia> (raw)
In-Reply-To: <20251124231341.GO153257@nvidia.com>
On Mon, Nov 24, 2025 at 07:13:41PM -0400, Jason Gunthorpe wrote:
> On Mon, Nov 24, 2025 at 09:43:18PM +0000, Will Deacon wrote:
> > > + switch (smmu_domain->stage) {
> > > + case ARM_SMMU_DOMAIN_SVA:
> > > + case ARM_SMMU_DOMAIN_S1:
> > > + *cur = (struct arm_smmu_inv){
> > > + .smmu = master->smmu,
> > > + .type = INV_TYPE_S1_ASID,
> > > + .id = smmu_domain->cd.asid,
> > > + .size_opcode = e2h ? CMDQ_OP_TLBI_EL2_VA :
> > > + CMDQ_OP_TLBI_NH_VA,
> > > + .nsize_opcode = e2h ? CMDQ_OP_TLBI_EL2_ASID :
> > > + CMDQ_OP_TLBI_NH_ASID
> > > + };
> > > + break;
> > > + case ARM_SMMU_DOMAIN_S2:
> > > + *cur = (struct arm_smmu_inv){
> > > + .smmu = master->smmu,
> > > + .type = INV_TYPE_S2_VMID,
> > > + .id = smmu_domain->s2_cfg.vmid,
> > > + .size_opcode = CMDQ_OP_TLBI_S2_IPA,
> > > + .nsize_opcode = CMDQ_OP_TLBI_S12_VMALL,
> > > + };
> > > + break;
> >
> > Having a helper to add an invalidation command would make this a little
> > more compact and you could also check against the size of the array.
>
> Yeah but it makes all the parameters positional instead of nicely
> named..
Will's remarks did raise an issue that __counted_by() requires a
max_invs v.s. num_invs that can be smaller due to the removal of
tailing trash entries.
Then, it's probably nicer to add a check against the max_invs.
I did the following, which doesn't look too bad to me:
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 b04936e76cfd..28765febf99f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3066,6 +3066,51 @@ static void arm_smmu_disable_iopf(struct arm_smmu_master *master,
iopf_queue_remove_device(master->smmu->evtq.iopf, master->dev);
}
+static struct arm_smmu_inv *
+arm_smmu_master_build_inv(struct arm_smmu_master *master,
+ enum arm_smmu_inv_type type, u32 id, ioasid_t ssid,
+ size_t pgsize)
+{
+ struct arm_smmu_invs *build_invs = master->build_invs;
+ struct arm_smmu_inv *cur, inv = {
+ .smmu = master->smmu,
+ .type = type,
+ .id = id,
+ .pgsize = pgsize,
+ };
+
+ if (WARN_ON(build_invs->num_invs >= build_invs->max_invs))
+ return NULL;
+ cur = &build_invs->inv[build_invs->num_invs];
+ build_invs->num_invs++;
+
+ *cur = inv;
+ switch (type) {
+ case INV_TYPE_S1_ASID:
+ if (master->smmu->features & ARM_SMMU_FEAT_E2H) {
+ cur->size_opcode = CMDQ_OP_TLBI_EL2_VA;
+ cur->nsize_opcode = CMDQ_OP_TLBI_EL2_ASID;
+ } else {
+ cur->size_opcode = CMDQ_OP_TLBI_NH_VA;
+ cur->nsize_opcode = CMDQ_OP_TLBI_NH_ASID;
+ }
+ break;
+ case INV_TYPE_S2_VMID:
+ cur->size_opcode = CMDQ_OP_TLBI_S2_IPA;
+ cur->nsize_opcode = CMDQ_OP_TLBI_S12_VMALL;
+ break;
+ case INV_TYPE_S2_VMID_S1_CLEAR:
+ cur->size_opcode = cur->nsize_opcode = CMDQ_OP_TLBI_NH_ALL;
+ break;
+ case INV_TYPE_ATS:
+ case INV_TYPE_ATS_FULL:
+ cur->size_opcode = cur->nsize_opcode = CMDQ_OP_ATC_INV;
+ break;
+ }
+
+ return cur;
+}
+
/*
* Use the preallocated scratch array at master->build_invs, to build a to_merge
* or to_unref array, to pass into a following arm_smmu_invs_merge/unref() call.
@@ -3077,84 +3122,58 @@ static struct arm_smmu_invs *
arm_smmu_master_build_invs(struct arm_smmu_master *master, bool ats_enabled,
ioasid_t ssid, struct arm_smmu_domain *smmu_domain)
{
- const bool e2h = master->smmu->features & ARM_SMMU_FEAT_E2H;
- struct arm_smmu_invs *build_invs = master->build_invs;
const bool nesting = smmu_domain->nest_parent;
- struct arm_smmu_inv *cur;
+ size_t pgsize = 0, i;
iommu_group_mutex_assert(master->dev);
- cur = build_invs->inv;
+ master->build_invs->num_invs = 0;
+
+ /* Range-based invalidation requires the leaf pgsize for calculation */
+ if (master->smmu->features & ARM_SMMU_FEAT_RANGE_INV)
+ pgsize = __ffs(smmu_domain->domain.pgsize_bitmap);
switch (smmu_domain->stage) {
case ARM_SMMU_DOMAIN_SVA:
case ARM_SMMU_DOMAIN_S1:
- *cur = (struct arm_smmu_inv){
- .smmu = master->smmu,
- .type = INV_TYPE_S1_ASID,
- .id = smmu_domain->cd.asid,
- .size_opcode = e2h ? CMDQ_OP_TLBI_EL2_VA :
- CMDQ_OP_TLBI_NH_VA,
- .nsize_opcode = e2h ? CMDQ_OP_TLBI_EL2_ASID :
- CMDQ_OP_TLBI_NH_ASID
- };
+ if (!arm_smmu_master_build_inv(master, INV_TYPE_S1_ASID,
+ smmu_domain->cd.asid,
+ IOMMU_NO_PASID, pgsize))
+ return NULL;
break;
case ARM_SMMU_DOMAIN_S2:
- *cur = (struct arm_smmu_inv){
- .smmu = master->smmu,
- .type = INV_TYPE_S2_VMID,
- .id = smmu_domain->s2_cfg.vmid,
- .size_opcode = CMDQ_OP_TLBI_S2_IPA,
- .nsize_opcode = CMDQ_OP_TLBI_S12_VMALL,
- };
+ if (!arm_smmu_master_build_inv(master, INV_TYPE_S2_VMID,
+ smmu_domain->s2_cfg.vmid,
+ IOMMU_NO_PASID, pgsize))
+ return NULL;
break;
default:
WARN_ON(true);
return NULL;
}
- /* Range-based invalidation requires the leaf pgsize for calculation */
- if (master->smmu->features & ARM_SMMU_FEAT_RANGE_INV)
- cur->pgsize = __ffs(smmu_domain->domain.pgsize_bitmap);
- cur++;
-
/* All the nested S1 ASIDs have to be flushed when S2 parent changes */
if (nesting) {
- *cur = (struct arm_smmu_inv){
- .smmu = master->smmu,
- .type = INV_TYPE_S2_VMID_S1_CLEAR,
- .id = smmu_domain->s2_cfg.vmid,
- .size_opcode = CMDQ_OP_TLBI_NH_ALL,
- .nsize_opcode = CMDQ_OP_TLBI_NH_ALL,
- };
- cur++;
+ if (!arm_smmu_master_build_inv(
+ master, INV_TYPE_S2_VMID_S1_CLEAR,
+ smmu_domain->s2_cfg.vmid, IOMMU_NO_PASID, 0))
+ return NULL;
}
- if (ats_enabled) {
- size_t i;
-
- for (i = 0; i < master->num_streams; i++) {
- /*
- * If an S2 used as a nesting parent is changed we have
- * no option but to completely flush the ATC.
- */
- *cur = (struct arm_smmu_inv){
- .smmu = master->smmu,
- .type = nesting ? INV_TYPE_ATS_FULL :
- INV_TYPE_ATS,
- .id = master->streams[i].id,
- .ssid = ssid,
- .size_opcode = CMDQ_OP_ATC_INV,
- .nsize_opcode = CMDQ_OP_ATC_INV,
- };
- cur++;
- }
+ for (i = 0; ats_enabled && i < master->num_streams; i++) {
+ /*
+ * If an S2 used as a nesting parent is changed we have no
+ * option but to completely flush the ATC.
+ */
+ if (!arm_smmu_master_build_inv(
+ master, nesting ? INV_TYPE_ATS_FULL : INV_TYPE_ATS,
+ master->streams[i].id, ssid, 0))
+ return NULL;
}
/* Note this build_invs must have been sorted */
- build_invs->num_invs = cur - build_invs->inv;
- return build_invs;
+ return master->build_invs;
}
static void arm_smmu_remove_master_domain(struct arm_smmu_master *master,
Thanks
Nicolin
next prev parent reply other threads:[~2025-11-26 0:57 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-08 8:08 [PATCH v5 0/7] iommu/arm-smmu-v3: Introduce an RCU-protected invalidation array Nicolin Chen
2025-11-08 8:08 ` [PATCH v5 1/7] iommu/arm-smmu-v3: Explicitly set smmu_domain->stage for SVA Nicolin Chen
2025-11-08 8:08 ` [PATCH v5 2/7] iommu/arm-smmu-v3: Add an inline arm_smmu_domain_free() Nicolin Chen
2025-11-08 8:08 ` [PATCH v5 3/7] iommu/arm-smmu-v3: Introduce a per-domain arm_smmu_invs array Nicolin Chen
2025-11-24 21:42 ` Will Deacon
2025-11-24 22:41 ` Nicolin Chen
2025-11-24 23:03 ` Jason Gunthorpe
2025-11-26 1:07 ` Nicolin Chen
2025-11-25 4:14 ` Nicolin Chen
2025-11-25 13:43 ` Jason Gunthorpe
2025-11-25 16:20 ` Nicolin Chen
2025-11-08 8:08 ` [PATCH v5 4/7] iommu/arm-smmu-v3: Pre-allocate a per-master invalidation array Nicolin Chen
2025-11-24 21:42 ` Will Deacon
2025-11-24 22:43 ` Nicolin Chen
2025-11-24 23:08 ` Jason Gunthorpe
2025-11-24 23:31 ` Nicolin Chen
2025-11-25 7:43 ` Nicolin Chen
2025-11-25 13:07 ` Jason Gunthorpe
2025-11-08 8:08 ` [PATCH v5 5/7] iommu/arm-smmu-v3: Populate smmu_domain->invs when attaching masters Nicolin Chen
2025-11-24 21:43 ` Will Deacon
2025-11-24 23:13 ` Jason Gunthorpe
2025-11-24 23:19 ` Nicolin Chen
2025-11-26 0:56 ` Nicolin Chen [this message]
2025-11-08 8:08 ` [PATCH v5 6/7] iommu/arm-smmu-v3: Add arm_smmu_invs based arm_smmu_domain_inv_range() Nicolin Chen
2025-11-08 8:08 ` [PATCH v5 7/7] iommu/arm-smmu-v3: Perform per-domain invalidations using arm_smmu_invs Nicolin Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aSZQSsP9t0nyfNkx@Asurada-Nvidia \
--to=nicolinc@nvidia.com \
--cc=balbirs@nvidia.com \
--cc=iommu@lists.linux.dev \
--cc=jean-philippe@linaro.org \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=miko.lenczewski@arm.com \
--cc=peterz@infradead.org \
--cc=praan@google.com \
--cc=robin.murphy@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).