iommu/amd: Adhere to IVINFO[VASIZE] for address limits

ACPI IVRS IVHD’s IVINFO field reports the maximum virtual address
size (VASIZE) supported by the IOMMU. The AMD IOMMU driver currently
caps this with pagetable level reported by EFR[HATS] when configuring
paging domains (hw_max_vasz_lg2). On systems where firmware or VM
advertises smaller or different limits, the driver may over-advertise
capabilities and create domains outside the hardware’s actual bounds.

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Signed-off-by: Ankit Soni <Ankit.Soni@amd.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
Ankit Soni 2026-04-13 14:45:21 +00:00 committed by Joerg Roedel
parent d9f759704b
commit 33730f0688
4 changed files with 12 additions and 7 deletions

View File

@ -44,7 +44,7 @@ int amd_iommu_enable_faulting(unsigned int cpu);
extern int amd_iommu_guest_ir;
extern enum protection_domain_mode amd_iommu_pgtable;
extern int amd_iommu_gpt_level;
extern u8 amd_iommu_hpt_level;
extern u8 amd_iommu_hpt_vasize;
extern unsigned long amd_iommu_pgsize_bitmap;
extern bool amd_iommu_hatdis;

View File

@ -400,6 +400,7 @@
#define IOMMU_IVINFO_OFFSET 36
#define IOMMU_IVINFO_EFRSUP BIT(0)
#define IOMMU_IVINFO_DMA_REMAP BIT(1)
#define IOMMU_IVINFO_VASIZE GENMASK_ULL(21, 15)
/* IOMMU Feature Reporting Field (for IVHD type 10h */
#define IOMMU_FEAT_GASUP_SHIFT 6

View File

@ -155,8 +155,8 @@ bool amd_iommu_dump;
bool amd_iommu_irq_remap __read_mostly;
enum protection_domain_mode amd_iommu_pgtable = PD_MODE_V1;
/* Host page table level */
u8 amd_iommu_hpt_level;
/* Virtual address size */
u8 amd_iommu_hpt_vasize;
/* Guest page table level */
int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;
@ -3202,7 +3202,7 @@ static int __init early_amd_iommu_init(void)
struct acpi_table_header *ivrs_base;
int ret;
acpi_status status;
u8 efr_hats;
u8 efr_hats, max_vasize;
if (!amd_iommu_detected)
return -ENODEV;
@ -3232,6 +3232,10 @@ static int __init early_amd_iommu_init(void)
ivinfo_init(ivrs_base);
max_vasize = FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo);
if (!max_vasize)
max_vasize = 64;
amd_iommu_target_ivhd_type = get_highest_supported_ivhd_type(ivrs_base);
DUMP_printk("Using IVHD type %#x\n", amd_iommu_target_ivhd_type);
@ -3254,7 +3258,8 @@ static int __init early_amd_iommu_init(void)
* efr[HATS] bits specify the maximum host translation level
* supported, with LEVEL 4 being initial max level.
*/
amd_iommu_hpt_level = efr_hats + PAGE_MODE_4_LEVEL;
amd_iommu_hpt_vasize = min_t(unsigned int, max_vasize,
(efr_hats + PAGE_MODE_4_LEVEL - 1) * 9 + 21);
} else {
pr_warn_once(FW_BUG "Disable host address translation due to invalid translation level (%#x).\n",
efr_hats);

View File

@ -2714,8 +2714,7 @@ static struct iommu_domain *amd_iommu_domain_alloc_paging_v1(struct device *dev,
else
cfg.common.features |= BIT(PT_FEAT_FLUSH_RANGE);
cfg.common.hw_max_vasz_lg2 =
min(64, (amd_iommu_hpt_level - 1) * 9 + 21);
cfg.common.hw_max_vasz_lg2 = amd_iommu_hpt_vasize;
cfg.common.hw_max_oasz_lg2 = 52;
cfg.starting_level = 2;
domain->domain.ops = &amdv1_ops;