From: Samiullah Khawaja <skhawaja@google.com>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
Jason Gunthorpe <jgg@ziepe.ca>,
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: Re: [RFC PATCH 3/3] iommu/arm-smmu-v3: Add support for hitless replace of S1 domains
Date: Fri, 23 Oct 2026 23:31:03 +0000 [thread overview]
Message-ID: <atvppceAqBVx8G9S@google.com> (raw)
In-Reply-To: <3d1eb92f-3447-49f0-a210-fd4fa015304b@arm.com>
On Fri, Oct 23, 2026 at 02:43:28PM +0100, Robin Murphy wrote:
>On 25/09/2026 2:13 am, Samiullah Khawaja wrote:
>>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));
>>+}
>
>Feels like this should probably use the existing invalidation machinery...
I see, I can use the arm_smmu_inv_flush_iotlb_tag() to issue
invalidation for the ASID.
>
>>+
>>+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);
>
>No, we cannot blindly do this for arbitrary ->attach_dev calls - the
>majority of S1->S1 transitions are going to be moving back and forth
>between the default domain and user domains, where there is zero
>expectation, let alone guarantee, that the translations would be
>equivalent and thus not liable to lead to TLB conflict aborts or
>amalgamation hell.
>
>This needs to be in a dedicated "I know what I'm doing and I fully
>accept the consequences if I get it wrong" call path.
Agreed.
I will update this to only be triggered with explicit request from the
Core to satisfy my live update use case where a preserved iommu domain
is being replaced by a new domain setup by the user.
Thanks,
Sami
>
>Thanks,
>Robin.
>
>> arm_smmu_make_cdtable_ste(&target, master, state.ats_enabled,
>> STRTAB_STE_1_S1DSS_SSID0);
>> arm_smmu_install_ste_for_dev(master, &target);
>
next prev parent reply other threads:[~2026-10-23 23:31 UTC|newest]
Thread overview: 19+ 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-10-21 22:19 ` David Matlack
2026-10-23 23:04 ` Samiullah Khawaja
2026-09-25 1:13 ` [RFC PATCH 2/3] vfio: selftests: Add iommufd hwpt replace test Samiullah Khawaja
2026-10-21 22:39 ` David Matlack
2026-10-23 23:10 ` Samiullah Khawaja
2026-09-25 1:13 ` [RFC PATCH 3/3] iommu/arm-smmu-v3: Add support for hitless replace of S1 domains Samiullah Khawaja
2026-10-23 13:43 ` Robin Murphy
2026-10-23 13:49 ` Jason Gunthorpe
2026-10-23 14:04 ` Robin Murphy
2026-10-23 14:29 ` Jason Gunthorpe
2026-10-23 23:31 ` 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
2026-10-23 12:10 ` Robin Murphy
2026-10-23 13:46 ` Jason Gunthorpe
2026-10-23 14:12 ` Robin Murphy
2026-10-23 22:59 ` 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=atvppceAqBVx8G9S@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