From: Samiullah Khawaja <skhawaja@google.com>
To: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
Jason Gunthorpe <jgg@ziepe.ca>
Cc: Samiullah Khawaja <skhawaja@google.com>,
Robin Murphy <robin.murphy@arm.com>,
Kevin Tian <kevin.tian@intel.com>,
Alex Williamson <alex@shazbot.org>,
iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org,
Pasha Tatashin <pasha.tatashin@soleen.com>,
David Matlack <dmatlack@google.com>,
Lu Baolu <baolu.lu@linux.intel.com>,
Pranjal Shrivastava <praan@google.com>
Subject: [RFC PATCH 3/3] iommu/arm-smmu-v3: Add support for hitless replace of S1 domains
Date: Fri, 25 Sep 2026 01:13:07 +0000 [thread overview]
Message-ID: <20260925011308.3381953-4-skhawaja@google.com> (raw)
In-Reply-To: <20260925011308.3381953-1-skhawaja@google.com>
S1 domains are programmed by CD entries in the CD table. During a new
domain attach these are updated using write_cd_entry. Since ASID and
TTB0 are in different 64-bit words, the write_cd_entry considers it a
non-hitless update and sets V=0. This means such an update is disruptive
and would generate translation faults if there are ongoing DMAs.
Replace the CD entries by using an unused temporary ASID in following
sequence to allow hitless replacement of CD entry,
- Update the CD entry with temporary ASID.
- Update the CD entry with the target TTB0.
- Update the CD entry with the target ASID.
Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 66 ++++++++++++++++++++-
1 file changed, 64 insertions(+), 2 deletions(-)
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 5732f3ba0122..59f4b8cf89f6 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1641,6 +1641,68 @@ void arm_smmu_write_cd_entry(struct arm_smmu_master *master, int ssid,
arm_smmu_write_entry(&cd_writer.writer, cdptr->data, target->data);
}
+/* Invalidate every stage-1 TLB entry tagged with @asid. */
+static void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
+{
+ enum arm_smmu_cmdq_opcode op = (smmu->features & ARM_SMMU_FEAT_E2H) ?
+ CMDQ_OP_TLBI_EL2_ASID :
+ CMDQ_OP_TLBI_NH_ASID;
+
+ arm_smmu_cmdq_issue_cmd_with_sync(smmu,
+ arm_smmu_make_cmd_tlbi(op, asid, 0));
+}
+
+static void arm_smmu_cd_set_asid(struct arm_smmu_cd *cd, u16 asid)
+{
+ cd->data[0] &= ~cpu_to_le64(CTXDESC_CD_0_ASID);
+ cd->data[0] |= cpu_to_le64(FIELD_PREP(CTXDESC_CD_0_ASID, asid));
+}
+
+static void arm_smmu_replace_cd_entry(struct arm_smmu_master *master, int ssid,
+ struct arm_smmu_cd *cdptr,
+ const struct arm_smmu_cd *target)
+{
+ struct arm_smmu_device *smmu = master->smmu;
+ struct arm_smmu_cd stage;
+ u32 tmp_asid;
+
+ lockdep_assert_held(&arm_smmu_asid_lock);
+
+ /*
+ * Nothing is translating through an invalid CD, and an update that
+ * invalidates one cannot be made hitless anyway.
+ */
+ if (!(cdptr->data[0] & cpu_to_le64(CTXDESC_CD_0_V)) ||
+ !(target->data[0] & cpu_to_le64(CTXDESC_CD_0_V)))
+ goto write_directly;
+
+ if (xa_alloc(&arm_smmu_asid_xa, &tmp_asid, XA_ZERO_ENTRY,
+ XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL))
+ goto write_directly;
+
+ /* Copy the existing cd entry and update only the ASID. */
+ stage = *cdptr;
+ arm_smmu_cd_set_asid(&stage, tmp_asid);
+ arm_smmu_write_cd_entry(master, ssid, cdptr, &stage);
+
+ /* Copy the target cd entry and update ASID to the temporary ASID. */
+ stage = *target;
+ arm_smmu_cd_set_asid(&stage, tmp_asid);
+ arm_smmu_write_cd_entry(master, ssid, cdptr, &stage);
+
+ arm_smmu_tlb_inv_asid(smmu, tmp_asid);
+
+ /* Update to the target cd entry as it should be hitless now. */
+ arm_smmu_write_cd_entry(master, ssid, cdptr, target);
+
+ arm_smmu_tlb_inv_asid(smmu, tmp_asid);
+ xa_erase(&arm_smmu_asid_xa, tmp_asid);
+ return;
+
+write_directly:
+ arm_smmu_write_cd_entry(master, ssid, cdptr, target);
+}
+
void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
struct arm_smmu_master *master,
struct arm_smmu_domain *smmu_domain)
@@ -3664,8 +3726,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev,
struct arm_smmu_cd target_cd;
arm_smmu_make_s1_cd(&target_cd, master, smmu_domain);
- arm_smmu_write_cd_entry(master, IOMMU_NO_PASID, cdptr,
- &target_cd);
+ arm_smmu_replace_cd_entry(master, IOMMU_NO_PASID, cdptr,
+ &target_cd);
arm_smmu_make_cdtable_ste(&target, master, state.ats_enabled,
STRTAB_STE_1_S1DSS_SSID0);
arm_smmu_install_ste_for_dev(master, &target);
--
2.56.0.rc1.315.gc6ed9934b7-goog
next prev parent reply other threads:[~2026-09-25 1:13 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 1:13 [RFC PATCH 0/3] iommu/arm-smmu-v3: Add support for hitless replace of CD entries Samiullah Khawaja
2026-09-25 1:13 ` [RFC PATCH 1/3] vfio: selftests: Add support of creating iommus from iommufd Samiullah Khawaja
2026-09-25 1:13 ` [RFC PATCH 2/3] vfio: selftests: Add iommufd hwpt replace test Samiullah Khawaja
2026-09-25 1:13 ` Samiullah Khawaja [this message]
2026-09-25 21:44 ` [RFC PATCH 0/3] iommu/arm-smmu-v3: Add support for hitless replace of CD entries David Matlack
2026-09-25 22:27 ` Samiullah Khawaja
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=20260925011308.3381953-4-skhawaja@google.com \
--to=skhawaja@google.com \
--cc=alex@shazbot.org \
--cc=baolu.lu@linux.intel.com \
--cc=dmatlack@google.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pasha.tatashin@soleen.com \
--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
all inboxes | Powered by JetHome®