From: Ankit Soni Date: Mon, 13 Apr 2026 14:45:21 +0000 (+0000) Subject: iommu/amd: Adhere to IVINFO[VASIZE] for address limits X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=33730f06881640894d2b4228b04d4f3c7351f6c0;p=thirdparty%2Fkernel%2Flinux.git 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 Reviewed-by: Vasant Hegde Signed-off-by: Ankit Soni Signed-off-by: Joerg Roedel --- diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h index 834d8fabfba38..af720bf14914d 100644 --- a/drivers/iommu/amd/amd_iommu.h +++ b/drivers/iommu/amd/amd_iommu.h @@ -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; diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index f9f7180878930..315c77e5adb2f 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -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 diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 3bdb380d23e9a..b4d810a1cf33c 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -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); diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index f78e23f03938d..65082b9e4b525 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -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;