diff options
| author | Nicolin Chen <nicolinc@nvidia.com> | 2026-07-28 10:33:33 -0700 |
|---|---|---|
| committer | Will Deacon <will@kernel.org> | 2026-08-02 10:18:15 +0000 |
| commit | 773f2b9e367019c03ed18f2736c8f67307305088 (patch) | |
| tree | e103e9994e24edafc69ef98845e136bd5f39a0ff | |
| parent | eced8058c82a3a81ae480a6546e2da32100dddfa (diff) | |
| download | linux-next-773f2b9e367019c03ed18f2736c8f67307305088.tar.gz linux-next-773f2b9e367019c03ed18f2736c8f67307305088.zip | |
iommu/arm-smmu-v3: Support IDR5.DS and widen the TLBI SCALE field
An SMMU implementing SMMU_IDR5.DS extends the range invalidation commands:
the SCALE field grows a 6th bit, raising its maximum value from 31 to 39,
and TTL == 0b01 becomes a valid level hint for a 16KB translation granule.
Add a new ARM_SMMU_FEAT_DS feature detecting the DS bit, and widen the
CMDQ_TLBI_0_SCALE field to its architectural 6 bits. Mask the scale value
explicitly in arm_smmu_cmdq_batch_add_range(), so the range invalidation
path emits the same commands as before, keeping the pre-existing 5-bit
truncation of a scale above 31.
Also list DS as a valid IDR5 field in the iommu_hw_info_arm_smmuv3 kdoc:
iommufd has always reported the raw IDR5 register, so a VMM may conclude
from that bit alone that it can expose DS to its guest.
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Assisted-by: Claude:claude-fable-5
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Will Deacon <will@kernel.org>
| -rw-r--r-- | drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 6 | ||||
| -rw-r--r-- | drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 4 | ||||
| -rw-r--r-- | include/uapi/linux/iommufd.h | 4 |
3 files changed, 10 insertions, 4 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 de5fba0b6d09..2587c33c778f 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2511,9 +2511,10 @@ static void arm_smmu_cmdq_batch_add_range(struct arm_smmu_device *smmu, /* Determine how many chunks of 2^scale size we have */ num = (num_pages >> scale) & CMDQ_TLBI_RANGE_NUM_MAX; + /* Keep the pre-DS 5-bit truncation when scale > 31 */ cmd->data[0] = orig_data0 | FIELD_PREP(CMDQ_TLBI_0_NUM, num - 1) | - FIELD_PREP(CMDQ_TLBI_0_SCALE, scale); + FIELD_PREP(CMDQ_TLBI_0_SCALE, scale & 0x1f); /* range is num * 2^scale * pgsize */ inv_range = num << (scale + tg); @@ -5197,6 +5198,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) /* Maximum number of outstanding stalls */ smmu->evtq.max_stalls = FIELD_GET(IDR5_STALL_MAX, reg); + if (reg & IDR5_DS) + smmu->features |= ARM_SMMU_FEAT_DS; + /* Page sizes */ if (reg & IDR5_GRAN64K) smmu->pgsize_bitmap |= SZ_64K | SZ_512M; 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 98191075242a..50f8321e979c 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -65,6 +65,7 @@ struct arm_vsmmu; #define ARM_SMMU_IDR5 0x14 #define IDR5_STALL_MAX GENMASK(31, 16) +#define IDR5_DS (1 << 7) #define IDR5_GRAN64K (1 << 6) #define IDR5_GRAN16K (1 << 5) #define IDR5_GRAN4K (1 << 4) @@ -417,7 +418,7 @@ struct arm_smmu_cmd { #define CMDQ_TLBI_0_NUM GENMASK_ULL(16, 12) #define CMDQ_TLBI_RANGE_NUM_MAX 31 -#define CMDQ_TLBI_0_SCALE GENMASK_ULL(24, 20) +#define CMDQ_TLBI_0_SCALE GENMASK_ULL(25, 20) #define CMDQ_TLBI_0_VMID GENMASK_ULL(47, 32) #define CMDQ_TLBI_0_ASID GENMASK_ULL(63, 48) #define CMDQ_TLBI_1_LEAF (1UL << 0) @@ -925,6 +926,7 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_S2FWB (1 << 23) #define ARM_SMMU_FEAT_BBML2 (1 << 24) #define ARM_SMMU_FEAT_HAFT (1 << 25) +#define ARM_SMMU_FEAT_DS (1 << 26) u32 features; #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h index f73a392b3d3f..c6851c7655c6 100644 --- a/include/uapi/linux/iommufd.h +++ b/include/uapi/linux/iommufd.h @@ -605,7 +605,7 @@ enum iommu_hw_info_arm_smmuv3_flags { * idr[0]: ST_LEVEL, TERM_MODEL, STALL_MODEL, TTENDIAN , CD2L, ASID16, TTF * idr[1]: SIDSIZE, SSIDSIZE * idr[3]: BBML, RIL - * idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K + * idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K, DS * * - S1P should be assumed to be true if a NESTED HWPT can be created * - VFIO/iommufd only support platforms with COHACC, it should be assumed to be @@ -613,7 +613,7 @@ enum iommu_hw_info_arm_smmuv3_flags { * - ATS is a per-device property. If the VMM describes any devices as ATS * capable in ACPI/DT it should set the corresponding idr. * - * This list may expand in future (eg E0PD, AIE, PBHA, D128, DS etc). It is + * This list may expand in future (eg E0PD, AIE, PBHA, D128 etc). It is * important that VMMs do not read bits outside the list to allow for * compatibility with future kernels. Several features in the SMMUv3 * architecture are not currently supported by the kernel for nesting: HTTU, |
