diff options
| author | Jason Gunthorpe <jgg@nvidia.com> | 2025-11-27 19:54:08 -0400 |
|---|---|---|
| committer | Joerg Roedel <joerg.roedel@amd.com> | 2025-11-28 08:43:55 +0100 |
| commit | 1eb0ae6fbd544619c50b4a4d96ccb4676cac03cb (patch) | |
| tree | 43bae54d7fee3fa9d047271cec63a9ce14f1c5ca /drivers/iommu/intel | |
| parent | d856f9d27885c499d96ab7fe506083346ccf145d (diff) | |
iommupt/vtd: Support mgaw's less than a 4 level walk for first stage
If the IOVA is limited to less than 48 the page table will be constructed
with a 3 level configuration which is unsupported by hardware.
Like the second stage the caller needs to pass in both the top_level an
the vasz to specify a table that has more levels than required to hold the
IOVA range.
Fixes: 6cbc09b7719e ("iommu/vt-d: Restore previous domain::aperture_end calculation")
Reported-by: Calvin Owens <calvin@wbinvd.org>
Closes: https://lore.kernel.org/r/8f257d2651eb8a4358fcbd47b0145002e5f1d638.1764237717.git.calvin@wbinvd.org
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Tested-by: Calvin Owens <calvin@wbinvd.org>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu/intel')
| -rw-r--r-- | drivers/iommu/intel/iommu.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index f117349d67db..4e888867e85c 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -2794,6 +2794,28 @@ static struct dmar_domain *paging_domain_alloc(void) return domain; } +static unsigned int compute_vasz_lg2_fs(struct intel_iommu *iommu, + unsigned int *top_level) +{ + unsigned int mgaw = cap_mgaw(iommu->cap); + + /* + * Spec 3.6 First-Stage Translation: + * + * Software must limit addresses to less than the minimum of MGAW + * and the lower canonical address width implied by FSPM (i.e., + * 47-bit when FSPM is 4-level and 56-bit when FSPM is 5-level). + */ + if (mgaw > 48 && cap_fl5lp_support(iommu->cap)) { + *top_level = 4; + return min(57, mgaw); + } + + /* Four level is always supported */ + *top_level = 3; + return min(48, mgaw); +} + static struct iommu_domain * intel_iommu_domain_alloc_first_stage(struct device *dev, struct intel_iommu *iommu, u32 flags) @@ -2813,20 +2835,8 @@ intel_iommu_domain_alloc_first_stage(struct device *dev, if (IS_ERR(dmar_domain)) return ERR_CAST(dmar_domain); - if (cap_fl5lp_support(iommu->cap)) - cfg.common.hw_max_vasz_lg2 = 57; - else - cfg.common.hw_max_vasz_lg2 = 48; - - /* - * Spec 3.6 First-Stage Translation: - * - * Software must limit addresses to less than the minimum of MGAW - * and the lower canonical address width implied by FSPM (i.e., - * 47-bit when FSPM is 4-level and 56-bit when FSPM is 5-level). - */ - cfg.common.hw_max_vasz_lg2 = min(cap_mgaw(iommu->cap), - cfg.common.hw_max_vasz_lg2); + cfg.common.hw_max_vasz_lg2 = + compute_vasz_lg2_fs(iommu, &cfg.top_level); cfg.common.hw_max_oasz_lg2 = 52; cfg.common.features = BIT(PT_FEAT_SIGN_EXTEND) | BIT(PT_FEAT_FLUSH_RANGE); |