mirror of https://github.com/torvalds/linux.git
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: 6cbc09b771 ("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>
This commit is contained in:
parent
d856f9d278
commit
1eb0ae6fbd
|
|
@ -2708,10 +2708,13 @@ static struct iommu_domain *amd_iommu_domain_alloc_paging_v2(struct device *dev,
|
|||
* in both modes the top bit is removed and PT_FEAT_SIGN_EXTEND is not
|
||||
* set which creates a table that is compatible in both modes.
|
||||
*/
|
||||
if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL)
|
||||
if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL) {
|
||||
cfg.common.hw_max_vasz_lg2 = 56;
|
||||
else
|
||||
cfg.top_level = 4;
|
||||
} else {
|
||||
cfg.common.hw_max_vasz_lg2 = 47;
|
||||
cfg.top_level = 3;
|
||||
}
|
||||
cfg.common.hw_max_oasz_lg2 = 52;
|
||||
domain->domain.ops = &amdv2_ops;
|
||||
|
||||
|
|
|
|||
|
|
@ -241,13 +241,10 @@ x86_64_pt_iommu_fmt_init(struct pt_iommu_x86_64 *iommu_table,
|
|||
{
|
||||
struct pt_x86_64 *table = &iommu_table->x86_64_pt;
|
||||
|
||||
if (cfg->common.hw_max_vasz_lg2 < 31 ||
|
||||
cfg->common.hw_max_vasz_lg2 > 57)
|
||||
return -EINVAL;
|
||||
if (cfg->top_level < 3 || cfg->top_level > 4)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Top of 2, 3, 4 */
|
||||
pt_top_set_level(&table->common,
|
||||
(cfg->common.hw_max_vasz_lg2 - 31) / 9 + 2);
|
||||
pt_top_set_level(&table->common, cfg->top_level);
|
||||
|
||||
table->common.max_oasz_lg2 =
|
||||
min(PT_MAX_OUTPUT_ADDRESS_LG2, cfg->common.hw_max_oasz_lg2);
|
||||
|
|
@ -269,12 +266,12 @@ x86_64_pt_iommu_fmt_hw_info(struct pt_iommu_x86_64 *table,
|
|||
#if defined(GENERIC_PT_KUNIT)
|
||||
static const struct pt_iommu_x86_64_cfg x86_64_kunit_fmt_cfgs[] = {
|
||||
[0] = { .common.features = BIT(PT_FEAT_SIGN_EXTEND),
|
||||
.common.hw_max_vasz_lg2 = 48 },
|
||||
.common.hw_max_vasz_lg2 = 48, .top_level = 3 },
|
||||
[1] = { .common.features = BIT(PT_FEAT_SIGN_EXTEND),
|
||||
.common.hw_max_vasz_lg2 = 57 },
|
||||
.common.hw_max_vasz_lg2 = 57, .top_level = 4 },
|
||||
/* AMD IOMMU PASID 0 formats with no SIGN_EXTEND */
|
||||
[2] = { .common.hw_max_vasz_lg2 = 47 },
|
||||
[3] = { .common.hw_max_vasz_lg2 = 56 },
|
||||
[2] = { .common.hw_max_vasz_lg2 = 47, .top_level = 3 },
|
||||
[3] = { .common.hw_max_vasz_lg2 = 56, .top_level = 4},
|
||||
};
|
||||
#define kunit_fmt_cfgs x86_64_kunit_fmt_cfgs
|
||||
enum { KUNIT_FMT_FEATURES = BIT(PT_FEAT_SIGN_EXTEND)};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -277,6 +277,8 @@ IOMMU_FORMAT(vtdss, vtdss_pt);
|
|||
|
||||
struct pt_iommu_x86_64_cfg {
|
||||
struct pt_iommu_cfg common;
|
||||
/* 4 is a 57 bit 5 level table */
|
||||
unsigned int top_level;
|
||||
};
|
||||
|
||||
struct pt_iommu_x86_64_hw_info {
|
||||
|
|
|
|||
Loading…
Reference in New Issue