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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.