[PATCH v10 09/13] iommu/arm-smmu-v3-kdump: Reserve crashed kernel's ASIDs and VMIDs
Nicolin Chen
nicolinc at nvidia.com
Sun Aug 30 16:18:10 PDT 2026
The adopted stream table keeps translating in-flight DMA, so the SMMU keeps
caching TLB entries tagged with the crashed kernel's ASIDs and VMIDs. If
this kernel handed one of those IDs to its own domain, the new domain's DMA
could hit the crashed kernel's cached translations, e.g. a stale entry left
behind by an invalidation that the crash cut short.
Scan the adopted stream table at adoption time, reserving every ID in use
via arm_smmu_kexec_scan_and_resv_ids(), and roll all of them back through
arm_smmu_kexec_unresv_ids() should the scan fail.
A nested STE's guest-owned CD table is left alone, since its ASIDs live in
a space of their own under that STE's VMID. Reserving that VMID covers all
of them, so there is no reason for the scan to walk the (VMID, ASID) pairs
behind it. The only ASIDs needing a reservation are those in the space that
this kernel uses for its own domains.
Note that, on an E2H/VHE host, the kernel's stage-1 domains are tagged by
the EL2 ASID, and the TLBI_EL2_* commands take no VMID. So isolating this
kernel by a reserved VMID alone would not work. Reserving the ASIDs covers
both the E2H and the NSEL1 cases.
Reservations are never released: a kdump kernel reboots after it saves the
vmcore, and the full-reset fallback flushes the entire TLB, which turns any
stale reservation into a merely unused ID.
If the scan finds any inconsistent structure, toss the entire adoption and
fall back to the full reset.
Suggested-by: Jason Gunthorpe <jgg at nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg at nvidia.com>
Assisted-by: Claude:claude-fable-5
Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c | 12 +++++++++++-
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 1 +
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c
index a074d59ce3445..6740cc7e671cb 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kdump.c
@@ -205,16 +205,26 @@ int arm_smmu_kdump_adopt_strtab(struct arm_smmu_device *smmu)
goto err;
}
+ ret = arm_smmu_kexec_scan_and_resv_ids(smmu);
+ if (ret) {
+ dev_warn(smmu->dev, "failed to reserve in-use ASIDs/VMIDs\n");
+ arm_smmu_kdump_adopt_cleanup(smmu);
+ goto err_unresv;
+ }
+
ret = devm_add_action_or_reset(smmu->dev, arm_smmu_kdump_adopt_cleanup,
smmu);
/* devm_add_action_or_reset ran the cleanup upon failure */
if (ret) {
dev_warn(smmu->dev, "failed to set up cleanup action\n");
- goto err;
+ goto err_unresv;
}
return 0;
+err_unresv:
+ /* The full reset will flush the entire TLB, so release everything */
+ arm_smmu_kexec_unresv_ids(smmu);
err:
dev_warn(smmu->dev, "falling back to full reset\n");
/*
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 971b12517941f..1d4fb6c4f0a91 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4610,6 +4610,7 @@ static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
{
int ret;
+ /* Init both first, as a kdump adoption reserves in-use ASIDs/VMIDs */
ida_init(&smmu->vmid_map);
ret = devm_add_action_or_reset(smmu->dev, arm_smmu_destroy_vmid_map,
&smmu->vmid_map);
--
2.43.0
More information about the linux-arm-kernel
mailing list