[PATCH v9 06/12] iommu/arm-smmu-v3-kexec: Add a CD table parse helper

From: Nicolin Chen

Date: Tue Jul 21 2026 - 16:10:12 EST


An S1 STE points to a CD table that both of the kexec flavors decode: the
kdump adoption scans the CD table to reserve all the in-use ASIDs, and the
live-update restoration claims the CD table via the KHO restore API.

Add another read-only helper to the arm-smmu-v3-kexec.c:
- arm_smmu_kexec_check_ste_cdtab()

It validates the CD table geometry in an S1 STE against this kernel's own
ssid_bits and the 2-level HW capability. And it accepts a linear CD table
on the 2-level capable HW too, since a previous kernel might have used one,
like the linear stream table.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 ++
.../iommu/arm/arm-smmu-v3/arm-smmu-v3-kexec.c | 42 +++++++++++++++++++
2 files changed, 45 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 6ef307335d80c..183c617ecb273 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1249,6 +1249,9 @@ int arm_smmu_kexec_parse_strtab_linear(struct arm_smmu_device *smmu,
int arm_smmu_kexec_check_strtab_l1_desc(struct arm_smmu_device *smmu,
u64 l1_desc, u32 idx,
phys_addr_t *l2_base);
+int arm_smmu_kexec_check_ste_cdtab(struct arm_smmu_device *smmu, u64 ste0,
+ phys_addr_t *cdtab, u32 *s1fmt,
+ u32 *max_contexts);
#endif /* CONFIG_ARM_SMMU_V3_KEXEC */

#ifdef CONFIG_CRASH_DUMP
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kexec.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kexec.c
index 5346132529427..5ad1fe1922eec 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kexec.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-kexec.c
@@ -157,3 +157,45 @@ int arm_smmu_kexec_check_strtab_l1_desc(struct arm_smmu_device *smmu,
*l2_base = base;
return 0;
}
+
+/**
+ * arm_smmu_kexec_check_ste_cdtab() - Decode the CD table geometry of an STE
+ * @smmu: SMMU device of this kernel
+ * @ste0: first 64 bits of the previous kernel's S1 STE
+ * @cdtab: pointer to return the CD table's physical address
+ * @s1fmt: pointer to return the CD table format
+ * @max_contexts: pointer to return the number of CDs
+ *
+ * Note that a linear CD table on the 2-level capable hardware is accepted, as a
+ * previous kernel might have used one, like the linear stream table.
+ *
+ * Also, as the CD tables are supposed to be read-only, @cdtab is not validated
+ * against the table size, but only carries the field's own 64-byte alignment.
+ *
+ * Return: 0 on success with the three outputs set, or -EINVAL on a bad geometry
+ */
+int arm_smmu_kexec_check_ste_cdtab(struct arm_smmu_device *smmu, u64 ste0,
+ phys_addr_t *cdtab, u32 *s1fmt,
+ u32 *max_contexts)
+{
+ phys_addr_t base = ste0 & STRTAB_STE_0_S1CTXPTR_MASK;
+ u32 s1cdmax = FIELD_GET(STRTAB_STE_0_S1CDMAX, ste0);
+ u32 fmt = FIELD_GET(STRTAB_STE_0_S1FMT, ste0);
+
+ if (!base || s1cdmax > smmu->ssid_bits)
+ return -EINVAL;
+
+ if (fmt != STRTAB_STE_0_S1FMT_LINEAR &&
+ fmt != STRTAB_STE_0_S1FMT_64K_L2)
+ return -EINVAL;
+
+ /* Both kernels run on the same HW, so a genuine STE never has this */
+ if (fmt == STRTAB_STE_0_S1FMT_64K_L2 &&
+ !(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB))
+ return -EINVAL;
+
+ *cdtab = base;
+ *s1fmt = fmt;
+ *max_contexts = 1U << s1cdmax;
+ return 0;
+}
--
2.43.0