public inbox for iommu@lists.linux-foundation.org
 help / color / mirror / Atom feed
* [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
@ 2026-02-27 16:58 Ankit Soni
  2026-02-28 10:56 ` kernel test robot
  2026-03-02 23:57 ` Jason Gunthorpe
  0 siblings, 2 replies; 8+ messages in thread
From: Ankit Soni @ 2026-02-27 16:58 UTC (permalink / raw)
  To: iommu
  Cc: vasant.hegde, suravee.suthikulpanit, joro, will, robin.murphy,
	linux-kernel

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            | 34 +++++++++++++++++++++++++----
 drivers/iommu/amd/iommu.c           |  3 +--
 4 files changed, 33 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..03013189b983 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;
 
@@ -3156,6 +3156,29 @@ static void __init ivinfo_init(void *ivrs)
 	amd_iommu_ivinfo = *((u32 *)(ivrs + IOMMU_IVINFO_OFFSET));
 }
 
+static u8 ivinfo_vasize_bits(void)
+{
+	u8 vasize;
+
+	vasize = FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo);
+
+	/*
+	 * IVINFO[VASIZE] encodes the log2 of the maximum virtual address
+	 * processed by the IOMMU.
+	 */
+	switch (vasize) {
+	case 32:
+	case 40:
+	case 48:
+	case 64:
+		return vasize;
+	default:
+		pr_warn_once("IVRS: IVINFO[VASIZE]=0x%x is invalid, defaulting to 64‑bit VA\n",
+			     vasize);
+		return 64;
+	}
+}
+
 /*
  * This is the hardware init function for AMD IOMMU in the system.
  * This function is called either from amd_iommu_init or from the interrupt
@@ -3188,7 +3211,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 +3241,8 @@ static int __init early_amd_iommu_init(void)
 
 	ivinfo_init(ivrs_base);
 
+	max_vasize = ivinfo_vasize_bits();
+
 	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 +3265,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(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


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-02-27 16:58 [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits Ankit Soni
@ 2026-02-28 10:56 ` kernel test robot
  2026-03-02 23:57 ` Jason Gunthorpe
  1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2026-02-28 10:56 UTC (permalink / raw)
  To: Ankit Soni, iommu
  Cc: llvm, oe-kbuild-all, vasant.hegde, suravee.suthikulpanit, joro,
	will, robin.murphy, linux-kernel

Hi Ankit,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v7.0-rc1 next-20260227]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ankit-Soni/iommu-amd-Adhere-to-IVINFO-VASIZE-for-address-limits/20260228-010009
base:   linus/master
patch link:    https://lore.kernel.org/r/cf1a1e3d96c3571ac5caa528caa84751d40be1bc.1772208939.git.Ankit.Soni%40amd.com
patch subject: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260228/202602281837.QQl5six6-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260228/202602281837.QQl5six6-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602281837.QQl5six6-lkp@intel.com/

All warnings (new ones prefixed by >>, old ones prefixed by <<):

>> WARNING: modpost: vmlinux: section mismatch in reference: ivinfo_vasize_bits+0x8 (section: .text) -> amd_iommu_disabled (section: .init.data)

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-02-27 16:58 [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits Ankit Soni
  2026-02-28 10:56 ` kernel test robot
@ 2026-03-02 23:57 ` Jason Gunthorpe
  2026-03-03 11:47   ` Ankit Soni
  1 sibling, 1 reply; 8+ messages in thread
From: Jason Gunthorpe @ 2026-03-02 23:57 UTC (permalink / raw)
  To: Ankit Soni
  Cc: iommu, vasant.hegde, suravee.suthikulpanit, joro, will,
	robin.murphy, linux-kernel

On Fri, Feb 27, 2026 at 04:58:04PM +0000, Ankit Soni wrote:
> +static u8 ivinfo_vasize_bits(void)
> +{
> +	u8 vasize;
> +
> +	vasize = FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo);
> +
> +	/*
> +	 * IVINFO[VASIZE] encodes the log2 of the maximum virtual address
> +	 * processed by the IOMMU.
> +	 */
> +	switch (vasize) {
> +	case 32:
> +	case 40:
> +	case 48:
> +	case 64:
> +		return vasize;
> +	default:
> +		pr_warn_once("IVRS: IVINFO[VASIZE]=0x%x is invalid, defaulting to 64‑bit VA\n",
> +			     vasize);
> +		return 64;

Why check and limit it like this? 

> -	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;

This has no restriction, you can send it whatever size you want.

Shouldn't the v2 side respect this too? If there is some reason why
not it would be good to include it in a comment.

Jason

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-03-02 23:57 ` Jason Gunthorpe
@ 2026-03-03 11:47   ` Ankit Soni
  2026-03-03 12:05     ` Jason Gunthorpe
  0 siblings, 1 reply; 8+ messages in thread
From: Ankit Soni @ 2026-03-03 11:47 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: iommu, vasant.hegde, suravee.suthikulpanit, joro, will,
	robin.murphy, linux-kernel

Hi,

On Mon, Mar 02, 2026 at 07:57:15PM -0400, Jason Gunthorpe wrote:
> On Fri, Feb 27, 2026 at 04:58:04PM +0000, Ankit Soni wrote:
> > +static u8 ivinfo_vasize_bits(void)
> > +{
> > +	u8 vasize;
> > +
> > +	vasize = FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo);
> > +
> > +	/*
> > +	 * IVINFO[VASIZE] encodes the log2 of the maximum virtual address
> > +	 * processed by the IOMMU.
> > +	 */
> > +	switch (vasize) {
> > +	case 32:
> > +	case 40:
> > +	case 48:
> > +	case 64:
> > +		return vasize;
> > +	default:
> > +		pr_warn_once("IVRS: IVINFO[VASIZE]=0x%x is invalid, defaulting to 64‑bit VA\n",
> > +			     vasize);
> > +		return 64;
> 
> Why check and limit it like this? 
> 

I’ll replace this with a macro and send that in v3. If you have other suggestions,
I’m happy to incorporate.

> > -	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;
> 
> This has no restriction, you can send it whatever size you want.
> 

The intent is for the kernel to respect what the VM advertises in IVINFO.
If we ignore IVINFO[VASIZE] and use a larger limit (i.e. from EFR only),
driver can exceed vasize what the VM allows and break the guest.

> Shouldn't the v2 side respect this too? If there is some reason why
> not it would be good to include it in a comment.
> 
> Jason

For the v2 page table, GVASize is derived from the page table level already
advertised in EFR, so it matches what is reported and driver don’t need an
extra IVINFO-based check for v2.
For the v1 path, the effective VASize can differ from what EFR implies
(i.e. VM can report a smaller limit), so driver should respect IVINFO[VASIZE].

I’ll add a short comment in the code explaining this so the v2 behaviour is clear.

Thanks,
Ankit


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-03-03 11:47   ` Ankit Soni
@ 2026-03-03 12:05     ` Jason Gunthorpe
  2026-03-03 17:11       ` Ankit Soni
  0 siblings, 1 reply; 8+ messages in thread
From: Jason Gunthorpe @ 2026-03-03 12:05 UTC (permalink / raw)
  To: Ankit Soni
  Cc: iommu, vasant.hegde, suravee.suthikulpanit, joro, will,
	robin.murphy, linux-kernel

On Tue, Mar 03, 2026 at 11:47:21AM +0000, Ankit Soni wrote:

> > > +	/*
> > > +	 * IVINFO[VASIZE] encodes the log2 of the maximum virtual address
> > > +	 * processed by the IOMMU.
> > > +	 */
> > > +	switch (vasize) {
> > > +	case 32:
> > > +	case 40:
> > > +	case 48:
> > > +	case 64:
> > > +		return vasize;
> > > +	default:
> > > +		pr_warn_once("IVRS: IVINFO[VASIZE]=0x%x is invalid, defaulting to 64‑bit VA\n",
> > > +			     vasize);
> > > +		return 64;
> > 
> > Why check and limit it like this? 
> > 
> 
> I’ll replace this with a macro and send that in v3. If you have other suggestions,
> I’m happy to incorporate.
> 
> > > -	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;
> > 
> > This has no restriction, you can send it whatever size you want.
> > 
> 
> The intent is for the kernel to respect what the VM advertises in IVINFO.
> If we ignore IVINFO[VASIZE] and use a larger limit (i.e. from EFR only),
> driver can exceed vasize what the VM allows and break the guest.

I mean if FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo) is 35 why
not just pass it to hw_max_vasz_lg2 and be done with it? What is the
point of limiting to only a few values?

Jason

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-03-03 12:05     ` Jason Gunthorpe
@ 2026-03-03 17:11       ` Ankit Soni
  2026-03-03 18:17         ` Jason Gunthorpe
  0 siblings, 1 reply; 8+ messages in thread
From: Ankit Soni @ 2026-03-03 17:11 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: iommu, vasant.hegde, suravee.suthikulpanit, joro, will,
	robin.murphy, linux-kernel

On Tue, Mar 03, 2026 at 08:05:54AM -0400, Jason Gunthorpe wrote:
> On Tue, Mar 03, 2026 at 11:47:21AM +0000, Ankit Soni wrote:
> 
> > > > +	/*
> > > > +	 * IVINFO[VASIZE] encodes the log2 of the maximum virtual address
> > > > +	 * processed by the IOMMU.
> > > > +	 */
> > > > +	switch (vasize) {
> > > > +	case 32:
> > > > +	case 40:
> > > > +	case 48:
> > > > +	case 64:
> > > > +		return vasize;
> > > > +	default:
> > > > +		pr_warn_once("IVRS: IVINFO[VASIZE]=0x%x is invalid, defaulting to 64‑bit VA\n",
> > > > +			     vasize);
> > > > +		return 64;
> > > 
> > > Why check and limit it like this? 
> > > 
> > 
> > I’ll replace this with a macro and send that in v3. If you have other suggestions,
> > I’m happy to incorporate.
> > 
> > > > -	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;
> > > 
> > > This has no restriction, you can send it whatever size you want.
> > > 
> > 
> > The intent is for the kernel to respect what the VM advertises in IVINFO.
> > If we ignore IVINFO[VASIZE] and use a larger limit (i.e. from EFR only),
> > driver can exceed vasize what the VM allows and break the guest.
> 
> I mean if FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo) is 35 why
> not just pass it to hw_max_vasz_lg2 and be done with it? What is the
> point of limiting to only a few values?
> 
> Jason

I got your point, i added the check to match the spec, which defines valid
values are only 32, 40, 48, and 64.

Ankit

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-03-03 17:11       ` Ankit Soni
@ 2026-03-03 18:17         ` Jason Gunthorpe
  2026-03-05 13:51           ` Ankit Soni
  0 siblings, 1 reply; 8+ messages in thread
From: Jason Gunthorpe @ 2026-03-03 18:17 UTC (permalink / raw)
  To: Ankit Soni
  Cc: iommu, vasant.hegde, suravee.suthikulpanit, joro, will,
	robin.murphy, linux-kernel

On Tue, Mar 03, 2026 at 05:11:07PM +0000, Ankit Soni wrote:
> > I mean if FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo) is 35 why
> > not just pass it to hw_max_vasz_lg2 and be done with it? What is the
> > point of limiting to only a few values?
> > 
> > Jason
> 
> I got your point, i added the check to match the spec, which defines valid
> values are only 32, 40, 48, and 64.

I don't think you should do that.. The valid values are the only ones
a hypervisor should install, but the kernel should be permissive and
accept everything..

Certainly it makes little sense to get something like 35 and expand it
to 64.

Jason

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits
  2026-03-03 18:17         ` Jason Gunthorpe
@ 2026-03-05 13:51           ` Ankit Soni
  0 siblings, 0 replies; 8+ messages in thread
From: Ankit Soni @ 2026-03-05 13:51 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: iommu, vasant.hegde, suravee.suthikulpanit, joro, will,
	robin.murphy, linux-kernel

On Tue, Mar 03, 2026 at 02:17:53PM -0400, Jason Gunthorpe wrote:
> On Tue, Mar 03, 2026 at 05:11:07PM +0000, Ankit Soni wrote:
> > > I mean if FIELD_GET(IOMMU_IVINFO_VASIZE, amd_iommu_ivinfo) is 35 why
> > > not just pass it to hw_max_vasz_lg2 and be done with it? What is the
> > > point of limiting to only a few values?
> > > 
> > > Jason
> > 
> > I got your point, i added the check to match the spec, which defines valid
> > values are only 32, 40, 48, and 64.
> 
> I don't think you should do that.. The valid values are the only ones
> a hypervisor should install, but the kernel should be permissive and
> accept everything..
> 

Agreed, will change in v3 and send.

-Ankit

> Certainly it makes little sense to get something like 35 and expand it
> to 64.
> 
> Jason

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-03-05 13:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-27 16:58 [PATCH] iommu/amd: Adhere to IVINFO[VASIZE] for address limits Ankit Soni
2026-02-28 10:56 ` kernel test robot
2026-03-02 23:57 ` Jason Gunthorpe
2026-03-03 11:47   ` Ankit Soni
2026-03-03 12:05     ` Jason Gunthorpe
2026-03-03 17:11       ` Ankit Soni
2026-03-03 18:17         ` Jason Gunthorpe
2026-03-05 13:51           ` Ankit Soni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox