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

Ankit Soni posted 2 patches 1 month ago
There is a newer version of this series
[PATCH v3 2/2] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
Posted by Ankit Soni 1 month ago
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.

Signed-off-by: Ankit Soni <Ankit.Soni@amd.com>
---
 drivers/iommu/amd/amd_iommu.h       |  2 +-
 drivers/iommu/amd/amd_iommu_types.h |  1 +
 drivers/iommu/amd/init.c            | 13 +++++++++----
 drivers/iommu/amd/iommu.c           |  3 +--
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 1342e764a548..f915938a3a08 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -41,7 +41,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 c685d3771436..6a85a38d34bd 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -395,6 +395,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 f3fd7f39efb4..e874a4135d5c 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -152,8 +152,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;
 
@@ -3188,7 +3188,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;
@@ -3218,6 +3218,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);
 
@@ -3240,7 +3244,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 81c4d7733872..e8d15ac9b2bd 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2712,8 +2712,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;
-- 
2.43.0

Re: [PATCH v3 2/2] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
Posted by Jason Gunthorpe 3 weeks, 6 days ago
On Mon, Mar 09, 2026 at 02:05:28PM +0000, Ankit Soni wrote:
> 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.
> 
> Signed-off-by: Ankit Soni <Ankit.Soni@amd.com>
> ---
>  drivers/iommu/amd/amd_iommu.h       |  2 +-
>  drivers/iommu/amd/amd_iommu_types.h |  1 +
>  drivers/iommu/amd/init.c            | 13 +++++++++----
>  drivers/iommu/amd/iommu.c           |  3 +--
>  4 files changed, 12 insertions(+), 7 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>

Jason
Re: [PATCH v3 2/2] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
Posted by Vasant Hegde 4 weeks ago

On 3/9/2026 7:35 PM, Ankit Soni wrote:
> 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.


> 
> Signed-off-by: Ankit Soni <Ankit.Soni@amd.com>

Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>

-Vasant

> ---
>  drivers/iommu/amd/amd_iommu.h       |  2 +-
>  drivers/iommu/amd/amd_iommu_types.h |  1 +
>  drivers/iommu/amd/init.c            | 13 +++++++++----
>  drivers/iommu/amd/iommu.c           |  3 +--
>  4 files changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
> index 1342e764a548..f915938a3a08 100644
> --- a/drivers/iommu/amd/amd_iommu.h
> +++ b/drivers/iommu/amd/amd_iommu.h
> @@ -41,7 +41,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 c685d3771436..6a85a38d34bd 100644
> --- a/drivers/iommu/amd/amd_iommu_types.h
> +++ b/drivers/iommu/amd/amd_iommu_types.h
> @@ -395,6 +395,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 f3fd7f39efb4..e874a4135d5c 100644
> --- a/drivers/iommu/amd/init.c
> +++ b/drivers/iommu/amd/init.c
> @@ -152,8 +152,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;
>  
> @@ -3188,7 +3188,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;
> @@ -3218,6 +3218,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);
>  
> @@ -3240,7 +3244,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 81c4d7733872..e8d15ac9b2bd 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -2712,8 +2712,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;