[PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake

Yuan Wang posted 1 patch 1 month ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260825090435.1492485-1-yuan1.wang@intel.com
Maintainers: Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>, Tomita Moeko <tomitamoeko@gmail.com>
hw/vfio/igd.c | 2 ++
1 file changed, 2 insertions(+)
[PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Yuan Wang 1 month ago
Currently, igd_gen() does not include the PCI device IDs for Meteor
Lake and Arrow Lake platforms, causing it to return -1 for these GPUs.

As a result, QEMU calculates the stolen memory size as 0 and exposes a
zero-sized 'etc/igd-bdsm-size' entry via fw_cfg. When OVMF boots,
IgdAssignmentDxe fails validation on the zero BDSM size and aborts
without programming the ASLS register. Consequently, the guest Intel
GOP driver fails to locate and read the OpRegion (ASLS remains 0x0).

Add the device ID prefixes (0x7D00 and 0xB600) to igd_gen() as Gen 12
so that stolen memory is correctly determined, allowing OVMF to properly
initialize the OpRegion and BDSM for the Intel GOP driver.

Signed-off-by: Yuan Wang <yuan1.wang@intel.com>
---
v2:
- Resending because the v1 patch was sent with an incorrect future 
  system timestamp due to an unsynchronized local clock. No code
  changes.
---
 hw/vfio/igd.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
index 413a49aae9..a0b6b34d81 100644
--- a/hw/vfio/igd.c
+++ b/hw/vfio/igd.c
@@ -96,6 +96,8 @@ static int igd_gen(VFIOPCIDevice *vdev)
     case 0x4C00:    /* Rocket Lake */
     case 0x4600:    /* Alder Lake */
     case 0xA700:    /* Raptor Lake */
+    case 0x7D00:    /* Meteor Lake / Arrow Lake */
+    case 0xB600:    /* Arrow Lake */
         return 12;
     }
 
-- 
2.34.1
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Tomita Moeko 2 weeks, 4 days ago
Reviewed-by: Tomita Moeko <tomitamoeko@gmail.com>

Thank you for your contribution!

On 2026-08-25 17:04, Yuan Wang wrote:
> Currently, igd_gen() does not include the PCI device IDs for Meteor
> Lake and Arrow Lake platforms, causing it to return -1 for these GPUs.
> 
> As a result, QEMU calculates the stolen memory size as 0 and exposes a
> zero-sized 'etc/igd-bdsm-size' entry via fw_cfg. When OVMF boots,
> IgdAssignmentDxe fails validation on the zero BDSM size and aborts
> without programming the ASLS register. Consequently, the guest Intel
> GOP driver fails to locate and read the OpRegion (ASLS remains 0x0).
> 
> Add the device ID prefixes (0x7D00 and 0xB600) to igd_gen() as Gen 12
> so that stolen memory is correctly determined, allowing OVMF to properly
> initialize the OpRegion and BDSM for the Intel GOP driver.
> 
> Signed-off-by: Yuan Wang <yuan1.wang@intel.com>
> ---
> v2:
> - Resending because the v1 patch was sent with an incorrect future 
>   system timestamp due to an unsynchronized local clock. No code
>   changes.
> ---
>  hw/vfio/igd.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
> index 413a49aae9..a0b6b34d81 100644
> --- a/hw/vfio/igd.c
> +++ b/hw/vfio/igd.c
> @@ -96,6 +96,8 @@ static int igd_gen(VFIOPCIDevice *vdev)
>      case 0x4C00:    /* Rocket Lake */
>      case 0x4600:    /* Alder Lake */
>      case 0xA700:    /* Raptor Lake */
> +    case 0x7D00:    /* Meteor Lake / Arrow Lake */
> +    case 0xB600:    /* Arrow Lake */
>          return 12;
>      }
>
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Tomita Moeko 2 weeks, 4 days ago
On 2026-09-08 13:09, Tomita Moeko wrote:
> Reviewed-by: Tomita Moeko <tomitamoeko@gmail.com>

Sorry I'd like to withdraw this Reviewed-by... 
> Thank you for your contribution!
> 
> On 2026-08-25 17:04, Yuan Wang wrote:
>> Currently, igd_gen() does not include the PCI device IDs for Meteor
>> Lake and Arrow Lake platforms, causing it to return -1 for these GPUs.
>>
>> As a result, QEMU calculates the stolen memory size as 0 and exposes a
>> zero-sized 'etc/igd-bdsm-size' entry via fw_cfg. When OVMF boots,
>> IgdAssignmentDxe fails validation on the zero BDSM size and aborts
>> without programming the ASLS register. Consequently, the guest Intel
>> GOP driver fails to locate and read the OpRegion (ASLS remains 0x0).
>>
>> Add the device ID prefixes (0x7D00 and 0xB600) to igd_gen() as Gen 12
>> so that stolen memory is correctly determined, allowing OVMF to properly
>> initialize the OpRegion and BDSM for the Intel GOP driver.
>>
>> Signed-off-by: Yuan Wang <yuan1.wang@intel.com>
I took a deeper look about the change, this change actually changes
vfio_probe_igd_bar0_quirk() to go with the 64-bit emulated BDSM register
path, right? But the problem is, does the BDSM register really exists on
Meteor/Arrow Lake and later iGPUs?

In drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c:xe_ttm_stolen_mgr_init()

	if (IS_SRIOV_VF(xe))
		stolen_size = 0;
	else if (IS_DGFX(xe))
		stolen_size = detect_bar2_dgfx(xe, mgr);
	else if (GRAPHICS_VERx100(xe) >= 1270)  // MTL+
		stolen_size = detect_bar2_integrated(xe, mgr);
	else
		stolen_size = detect_stolen(xe, mgr);

For Meteor Lake and later, detect_bar2_integrated() is called. The DSM
region used is at (BAR2 + 8M).

	/*
	 * Graphics >= 1270 uses the offset to the GSMBASE as address in the
	 * PTEs, together with the DM flag being set. Previously there was no
	 * such flag so the address was the io_base.
	 *
	 * DSMBASE = GSMBASE + 8MB
	 */
	mgr->stolen_base = SZ_8M;
	mgr->io_base = pci_resource_start(pdev, 2) + mgr->stolen_base;

drivers/gpu/drm/i915/gem/i915_gem_stolen.c:i915_gem_stolen_lmem_setup()
also suggests it is (BAR2 + 8M) on MTL (i915 only supports up to MTL)

	if (HAS_LMEMBAR_SMEM_STOLEN(i915)) {  // Only True for MTL
		/*
		 * MTL dsm size is in GGC register.
		 * Also MTL uses offset to GSMBASE in ptes, so i915
		 * uses dsm_base = 8MBs to setup stolen region, since
		 * DSMBASE = GSMBASE + 8MB.
		 */
		ret = mtl_get_gms_size(uncore);
		if (ret < 0) {
			drm_err(&i915->drm, "invalid MTL GGC register setting\n");
			return ERR_PTR(ret);
		}

		dsm_base = SZ_8M;
		dsm_size = (resource_size_t)(ret * SZ_1M);

		GEM_BUG_ON(pci_resource_len(pdev, GEN12_LMEM_BAR) != SZ_256M);
		GEM_BUG_ON((dsm_base + dsm_size) > lmem_size);
	} else {
		...
	}

	if (i915_direct_stolen_access(i915)) {
		...
	} else if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) {
		...
	} else {  // MTL
		io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base;
		io_size = dsm_size;
	}

In addition, nothing about the BDSM register can be found in MTL datasheet vol2,
neither 32-bit 0x5C nor 64-bit 0xC0. I believed it is removed since Meteor Lake.
https://edc.intel.com/content/www/us/en/design/publications/14th-generation-core-processors-cfg-and-mem-registers/d2-f0-processor-graphics-registers/

Since you are probably an intel employee (from your mail address), you may check
the GOP driver code to see if the BDSM register (0x5C/0xC0 in config space and
0x1080C0 in BAR0) is really used or not. Please kindly correct me if I am wrong.

For the "IgdAssignmentDxe fails validation on the zero BDSM size and aborts
without programming the ASLS register", having a fix skipping BDSM size check
on Meteor Lake and later ones could make it work? OpRegion is automatically
detected and exposed to guest on IGD as I remember.

Thanks,
Moeko
>> ---
>> v2:
>> - Resending because the v1 patch was sent with an incorrect future 
>>   system timestamp due to an unsynchronized local clock. No code
>>   changes.
>> ---
>>  hw/vfio/igd.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
>> index 413a49aae9..a0b6b34d81 100644
>> --- a/hw/vfio/igd.c
>> +++ b/hw/vfio/igd.c
>> @@ -96,6 +96,8 @@ static int igd_gen(VFIOPCIDevice *vdev)
>>      case 0x4C00:    /* Rocket Lake */
>>      case 0x4600:    /* Alder Lake */
>>      case 0xA700:    /* Raptor Lake */
>> +    case 0x7D00:    /* Meteor Lake / Arrow Lake */
>> +    case 0xB600:    /* Arrow Lake */
>>          return 12;
>>      }
>>  
>
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Wang, Yuan1 2 weeks, 1 day ago
Hi Moeko

Thanks for the kind review.

On 9/8/2026 5:09 PM, Tomita Moeko wrote:
> I took a deeper look about the change, this change actually changes
> vfio_probe_igd_bar0_quirk() to go with the 64-bit emulated BDSM register
> path, right? But the problem is, does the BDSM register really exists on
> Meteor/Arrow Lake and later iGPUs?
>
> In drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c:xe_ttm_stolen_mgr_init()
>
> 	if (IS_SRIOV_VF(xe))
> 		stolen_size = 0;
> 	else if (IS_DGFX(xe))
> 		stolen_size = detect_bar2_dgfx(xe, mgr);
> 	else if (GRAPHICS_VERx100(xe) >= 1270)  // MTL+
> 		stolen_size = detect_bar2_integrated(xe, mgr);
> 	else
> 		stolen_size = detect_stolen(xe, mgr);
>
> For Meteor Lake and later, detect_bar2_integrated() is called. The DSM
> region used is at (BAR2 + 8M).
>
> 	/*
> 	 * Graphics >= 1270 uses the offset to the GSMBASE as address in the
> 	 * PTEs, together with the DM flag being set. Previously there was no
> 	 * such flag so the address was the io_base.
> 	 *
> 	 * DSMBASE = GSMBASE + 8MB
> 	 */
> 	mgr->stolen_base = SZ_8M;
> 	mgr->io_base = pci_resource_start(pdev, 2) + mgr->stolen_base;
>
> drivers/gpu/drm/i915/gem/i915_gem_stolen.c:i915_gem_stolen_lmem_setup()
> also suggests it is (BAR2 + 8M) on MTL (i915 only supports up to MTL)
>
> 	if (HAS_LMEMBAR_SMEM_STOLEN(i915)) {  // Only True for MTL
> 		/*
> 		 * MTL dsm size is in GGC register.
> 		 * Also MTL uses offset to GSMBASE in ptes, so i915
> 		 * uses dsm_base = 8MBs to setup stolen region, since
> 		 * DSMBASE = GSMBASE + 8MB.
> 		 */
> 		ret = mtl_get_gms_size(uncore);
> 		if (ret < 0) {
> 			drm_err(&i915->drm, "invalid MTL GGC register setting\n");
> 			return ERR_PTR(ret);
> 		}
>
> 		dsm_base = SZ_8M;
> 		dsm_size = (resource_size_t)(ret * SZ_1M);
>
> 		GEM_BUG_ON(pci_resource_len(pdev, GEN12_LMEM_BAR) != SZ_256M);
> 		GEM_BUG_ON((dsm_base + dsm_size) > lmem_size);
> 	} else {
> 		...
> 	}
>
> 	if (i915_direct_stolen_access(i915)) {
> 		...
> 	} else if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) {
> 		...
> 	} else {  // MTL
> 		io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base;
> 		io_size = dsm_size;
> 	}
>
> In addition, nothing about the BDSM register can be found in MTL datasheet vol2,
> neither 32-bit 0x5C nor 64-bit 0xC0. I believed it is removed since Meteor Lake.
> https://edc.intel.com/content/www/us/en/design/publications/14th-generation-core-processors-cfg-and-mem-registers/d2-f0-processor-graphics-registers/
Correct. The BDSM register at PCIe config space offsets 0x5C/0xC0 has
been removed on Meteor Lake and Arrow Lake.
> Since you are probably an intel employee (from your mail address), you may check
> the GOP driver code to see if the BDSM register (0x5C/0xC0 in config space and
> 0x1080C0 in BAR0) is really used or not. Please kindly correct me if I am wrong.

For Meteor Lake and Arrow Lake, BDSM is still present and located in the
MMIO space at offset 0x1080C0 of BAR0. 

The GOP driver continues to read this register to obtain the stolen
memory base address.

And for MTL, there is a WA which there in Linux Gfx driver which cause
it to read 0x1080c0.
Please check the following function i915_direct_stolen_access().

drivers/gpu/drm/i915/i915_utils.c: i915_direct_stolen_access()
bool i915_direct_stolen_access(struct drm_i915_private *i915)
{
    /*
     * Wa_22018444074
     *
     * Access via BAR can hang MTL, go directly to GSM/DSM,
     * except for VM guests which won't have access to it.
     *
     * Normally this would not work but on MTL the system firmware
     * should have relaxed the access permissions sufficiently.
     * 0x138914==0x1 indicates that the firmware has done its job.
     */
    return IS_METEORLAKE(i915) && !i915_run_as_guest() &&
!IS_SRIOV_VF(i915) &&
        intel_uncore_read(&i915->uncore, MTL_PCODE_STOLEN_ACCESS) ==
STOLEN_ACCESS_ALLOWED;
}

Consequently, MTL still needs to read BDSM to obtain the DSM base
address in i915_gem_stolen_lmem_setup() function.
As seen in i915_direct_stolen_access(), this bypass logic only applies
to the bare-metal environment (it falls back for VMs).
However, the GOP driver does not differentiate between bare-metal and
virtualized environments, so we still have to provide a valid BDSM value
to it in GOP driver.

> For the "IgdAssignmentDxe fails validation on the zero BDSM size and aborts
> without programming the ASLS register", having a fix skipping BDSM size check
> on Meteor Lake and later ones could make it work? OpRegion is automatically
> detected and exposed to guest on IGD as I remember.
The MTL GOP driver always attempts to read from the BDSM register, so a
valid BDSM base address and size must be provided.

Thanks

Yuan


Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Tomita Moeko 1 week, 5 days ago
On 2026-09-11 16:36, Wang, Yuan1 wrote:
> Hi Moeko
> 
> Thanks for the kind review.
> 
> On 9/8/2026 5:09 PM, Tomita Moeko wrote:
>> I took a deeper look about the change, this change actually changes
>> vfio_probe_igd_bar0_quirk() to go with the 64-bit emulated BDSM register
>> path, right? But the problem is, does the BDSM register really exists on
>> Meteor/Arrow Lake and later iGPUs?
>>
>> In drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c:xe_ttm_stolen_mgr_init()
>>
>> 	if (IS_SRIOV_VF(xe))
>> 		stolen_size = 0;
>> 	else if (IS_DGFX(xe))
>> 		stolen_size = detect_bar2_dgfx(xe, mgr);
>> 	else if (GRAPHICS_VERx100(xe) >= 1270)  // MTL+
>> 		stolen_size = detect_bar2_integrated(xe, mgr);
>> 	else
>> 		stolen_size = detect_stolen(xe, mgr);
>>
>> For Meteor Lake and later, detect_bar2_integrated() is called. The DSM
>> region used is at (BAR2 + 8M).
>>
>> 	/*
>> 	 * Graphics >= 1270 uses the offset to the GSMBASE as address in the
>> 	 * PTEs, together with the DM flag being set. Previously there was no
>> 	 * such flag so the address was the io_base.
>> 	 *
>> 	 * DSMBASE = GSMBASE + 8MB
>> 	 */
>> 	mgr->stolen_base = SZ_8M;
>> 	mgr->io_base = pci_resource_start(pdev, 2) + mgr->stolen_base;
>>
>> drivers/gpu/drm/i915/gem/i915_gem_stolen.c:i915_gem_stolen_lmem_setup()
>> also suggests it is (BAR2 + 8M) on MTL (i915 only supports up to MTL)
>>
>> 	if (HAS_LMEMBAR_SMEM_STOLEN(i915)) {  // Only True for MTL
>> 		/*
>> 		 * MTL dsm size is in GGC register.
>> 		 * Also MTL uses offset to GSMBASE in ptes, so i915
>> 		 * uses dsm_base = 8MBs to setup stolen region, since
>> 		 * DSMBASE = GSMBASE + 8MB.
>> 		 */
>> 		ret = mtl_get_gms_size(uncore);
>> 		if (ret < 0) {
>> 			drm_err(&i915->drm, "invalid MTL GGC register setting\n");
>> 			return ERR_PTR(ret);
>> 		}
>>
>> 		dsm_base = SZ_8M;
>> 		dsm_size = (resource_size_t)(ret * SZ_1M);
>>
>> 		GEM_BUG_ON(pci_resource_len(pdev, GEN12_LMEM_BAR) != SZ_256M);
>> 		GEM_BUG_ON((dsm_base + dsm_size) > lmem_size);
>> 	} else {
>> 		...
>> 	}
>>
>> 	if (i915_direct_stolen_access(i915)) {
>> 		...
>> 	} else if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) {
>> 		...
>> 	} else {  // MTL
>> 		io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base;
>> 		io_size = dsm_size;
>> 	}
>>
>> In addition, nothing about the BDSM register can be found in MTL datasheet vol2,
>> neither 32-bit 0x5C nor 64-bit 0xC0. I believed it is removed since Meteor Lake.
>> https://edc.intel.com/content/www/us/en/design/publications/14th-generation-core-processors-cfg-and-mem-registers/d2-f0-processor-graphics-registers/
> Correct. The BDSM register at PCIe config space offsets 0x5C/0xC0 has
> been removed on Meteor Lake and Arrow Lake.

Got it.

>> Since you are probably an intel employee (from your mail address), you may check
>> the GOP driver code to see if the BDSM register (0x5C/0xC0 in config space and
>> 0x1080C0 in BAR0) is really used or not. Please kindly correct me if I am wrong.
> 
> For Meteor Lake and Arrow Lake, BDSM is still present and located in the
> MMIO space at offset 0x1080C0 of BAR0. 

Just curious, on host side, does the value of 0x1080C0 equals (BAR2 + 8M)
on Meteor and Arrow Lake?

> The GOP driver continues to read this register to obtain the stolen
> memory base address.
> 
> And for MTL, there is a WA which there in Linux Gfx driver which cause
> it to read 0x1080c0.
> Please check the following function i915_direct_stolen_access().
> 
> drivers/gpu/drm/i915/i915_utils.c: i915_direct_stolen_access()
> bool i915_direct_stolen_access(struct drm_i915_private *i915)
> {
>     /*
>      * Wa_22018444074
>      *
>      * Access via BAR can hang MTL, go directly to GSM/DSM,
>      * except for VM guests which won't have access to it.
>      *
>      * Normally this would not work but on MTL the system firmware
>      * should have relaxed the access permissions sufficiently.
>      * 0x138914==0x1 indicates that the firmware has done its job.
>      */
>     return IS_METEORLAKE(i915) && !i915_run_as_guest() &&
> !IS_SRIOV_VF(i915) &&
>         intel_uncore_read(&i915->uncore, MTL_PCODE_STOLEN_ACCESS) ==
> STOLEN_ACCESS_ALLOWED;
> }
> 
> Consequently, MTL still needs to read BDSM to obtain the DSM base
> address in i915_gem_stolen_lmem_setup() function.
> As seen in i915_direct_stolen_access(), this bypass logic only applies
> to the bare-metal environment (it falls back for VMs).
> However, the GOP driver does not differentiate between bare-metal and
> virtualized environments, so we still have to provide a valid BDSM value
> to it in GOP driver.
> 
>> For the "IgdAssignmentDxe fails validation on the zero BDSM size and aborts
>> without programming the ASLS register", having a fix skipping BDSM size check
>> on Meteor Lake and later ones could make it work? OpRegion is automatically
>> detected and exposed to guest on IGD as I remember.
> The MTL GOP driver always attempts to read from the BDSM register, so a
> valid BDSM base address and size must be provided.
> 
> Thanks
> 
> Yuan


My concern is that if guest driver still uses (BAR2 + 8M) as DSM base, while
0x1080C0 pointing to the mocked region, will this bring any inconsistency?
Having the register pointing to guest's (BAR2 + 8M) sounds more reasonable,
but it would require more efforts, monitoring config space writes to BAR2 and
changing the emulated value in QEMU.

Possibly an easier way is emulating MTL_PCODE_STOLEN_ACCESS(0x138914) to
disallowed in QEMU, if the GOP driver code checks it, to enforce the access
via BAR2 in guest. I'm also not sure if the issue in Wa_22018444074 also
applies to virtualized guests and how ofter it reproduces :(

Best Regards,
Moeko
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Junjie Cao 1 week, 4 days ago
On Mon, 14 Sep 2026 16:41:58 +0800, Tomita Moeko wrote:
> Just curious, on host side, does the value of 0x1080C0 equals (BAR2 + 8M)
> on Meteor and Arrow Lake?

No.  Measured on Meteor Lake-P (8086:7d55, host i915):

  BAR2 (LMEMBAR)            0x4000000000, 256MB
  MMIO 0x108100 GSMBASE     0x70000000
  MMIO 0x1080C0 DSMBASE     0x70800000      (GSMBASE + 8MB)
  MMIO 0x108040 GGC         0x4c0           (GGMS=3, GMS=4 -> 128MB)
  config 0x50 GGC           0x4c0
  config 0x5C               0
  config 0xC0-0xC3          MSI Pending Bits (MSI cap at 0xac, 64-bit + PVM)
  config 0xC4-0xC7          0
  MMIO 0x138914             1
  /proc/iomem               64000000-787fffff : Reserved

DSMBASE is a system physical address inside the BIOS reserved range, and
DSMBASE + 128MB is exactly the end of that range.  BAR2 + 8M is the
aperture onto the same memory: i915_gem_stolen.c and xe_ttm_stolen_mgr.c
use either DSMBASE or LMEMBAR + 8M as the io base of the same stolen
region.

So with igd_gen() == -1, where no BAR0 quirk is installed, a guest reads
the host physical DSMBASE from 0x1080C0.  Given Yuan's point that the
GOP reads this register for its stolen base, that is a host address
handed to guest firmware, and something QEMU should fix.

> My concern is that if guest driver still uses (BAR2 + 8M) as DSM base, while
> 0x1080C0 pointing to the mocked region, will this bring any inconsistency?

The drivers map stolen on MTL+ with DM-flagged PTEs as offsets from
GSMBASE (xe_ttm_stolen_mgr.c; i915 sets PTE_LM for stolen-local), which
a region in guest RAM cannot satisfy.  Whether the GOP maps its frame
buffer the same way I cannot check from here.  Yuan, if the display has
come up for you with v2 and the stock GOP, that answers it; the variant
below does not depend on the answer.

> Having the register pointing to guest's (BAR2 + 8M) sounds more reasonable,
> but it would require more efforts, monitoring config space writes to BAR2 and
> changing the emulated value in QEMU.

Agree with the direction, and it is cheaper than that: a read-only BAR0
quirk can take pci_get_bar_addr(pdev, 2) at read time, returning BAR2 at
0x108100 and BAR2 + 8M at 0x1080C0.  Then the CPU-side address resolves
to real stolen memory through the aperture instead of guest RAM,
bdsm-size stays 0 as documented, and nothing in config space is
invented.

> Possibly an easier way is emulating MTL_PCODE_STOLEN_ACCESS(0x138914) to
> disallowed in QEMU, if the GOP driver code checks it, to enforce the access
> via BAR2 in guest.

0x138914 reads 1 on the host and is not quirked, so a guest sees 1 too.
Returning 0 there is a small addition and covers a GOP that checks it;
the DSMBASE quirk covers one that does not.  On the Wa itself: i915
already takes the BAR path in guests (i915_run_as_guest() short-circuits
i915_direct_stolen_access()), so that path has upstream precedent; we
have not measured whether the hang reproduces there.

The firmware still has to program ASLS.  The IgdAssignmentDxe build the
v2 commit message describes aborts on bdsm-size=0 before doing so;
VfioIgdPkg has no such check and programs ASLS for MTL+ as is.

I'll write the quirk.  It can go into Yuan's v3 or on top of it as a
separate patch -- Yuan, your call.  Either way it needs a run with the
stock GOP build on your setup.

Junjie
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Tomita Moeko 1 week, 3 days ago

On 2026-09-15 09:30, Junjie Cao wrote:
> On Mon, 14 Sep 2026 16:41:58 +0800, Tomita Moeko wrote:
>> Just curious, on host side, does the value of 0x1080C0 equals (BAR2 + 8M)
>> on Meteor and Arrow Lake?
> 
> No.  Measured on Meteor Lake-P (8086:7d55, host i915):
> 
>   BAR2 (LMEMBAR)            0x4000000000, 256MB
>   MMIO 0x108100 GSMBASE     0x70000000
>   MMIO 0x1080C0 DSMBASE     0x70800000      (GSMBASE + 8MB)
>   MMIO 0x108040 GGC         0x4c0           (GGMS=3, GMS=4 -> 128MB)
>   config 0x50 GGC           0x4c0
>   config 0x5C               0
>   config 0xC0-0xC3          MSI Pending Bits (MSI cap at 0xac, 64-bit + PVM)
>   config 0xC4-0xC7          0
>   MMIO 0x138914             1
>   /proc/iomem               64000000-787fffff : Reserved
> 
> DSMBASE is a system physical address inside the BIOS reserved range, and
> DSMBASE + 128MB is exactly the end of that range.  BAR2 + 8M is the
> aperture onto the same memory: i915_gem_stolen.c and xe_ttm_stolen_mgr.c
> use either DSMBASE or LMEMBAR + 8M as the io base of the same stolen
> region.
> 
> So with igd_gen() == -1, where no BAR0 quirk is installed, a guest reads
> the host physical DSMBASE from 0x1080C0.  Given Yuan's point that the
> GOP reads this register for its stolen base, that is a host address
> handed to guest firmware, and something QEMU should fix.
> 
>> My concern is that if guest driver still uses (BAR2 + 8M) as DSM base, while
>> 0x1080C0 pointing to the mocked region, will this bring any inconsistency?
> 
> The drivers map stolen on MTL+ with DM-flagged PTEs as offsets from
> GSMBASE (xe_ttm_stolen_mgr.c; i915 sets PTE_LM for stolen-local), which
> a region in guest RAM cannot satisfy.  Whether the GOP maps its frame
> buffer the same way I cannot check from here.  Yuan, if the display has
> come up for you with v2 and the stock GOP, that answers it; the variant
> below does not depend on the answer.
> 
So on MTL+ BAR2 is mapped to the physical memory at GSMBASE, with first 8M
for GTT. PTE addresses are relative addresses so that accessing indirectly
from BAR or directly works. That makes sense. 

Meteor and later IGDs are supposed to access DSM from BAR2 instead of directly
from DSMBASE, but there is some hardware issues in Meteor Lake and Arrow Lake's
BAR2, software workarounds it to by falling back to DSMBASE. i915 won't read
DSMBASE register if the WA is not enabled (and it's always disabled when
virtualization enabled), while it's possible for GOP driver (and maybe windows
driver) to read it. Is my understanding correct?


>> Having the register pointing to guest's (BAR2 + 8M) sounds more reasonable,
>> but it would require more efforts, monitoring config space writes to BAR2 and
>> changing the emulated value in QEMU.
> 
> Agree with the direction, and it is cheaper than that: a read-only BAR0
> quirk can take pci_get_bar_addr(pdev, 2) at read time, returning BAR2 at
> 0x108100 and BAR2 + 8M at 0x1080C0.  Then the CPU-side address resolves
> to real stolen memory through the aperture instead of guest RAM,
> bdsm-size stays 0 as documented, and nothing in config space is
> invented.

Yes hooking on 0x1080C0 register read is easier and more straightforward.

>> Possibly an easier way is emulating MTL_PCODE_STOLEN_ACCESS(0x138914) to
>> disallowed in QEMU, if the GOP driver code checks it, to enforce the access
>> via BAR2 in guest.
> 
> 0x138914 reads 1 on the host and is not quirked, so a guest sees 1 too.
> Returning 0 there is a small addition and covers a GOP that checks it;
> the DSMBASE quirk covers one that does not.  On the Wa itself: i915
> already takes the BAR path in guests (i915_run_as_guest() short-circuits
> i915_direct_stolen_access()), so that path has upstream precedent; we
> have not measured whether the hang reproduces there.
> 

Quirking 0x138914 prevents driver applying that WA, but we are not sure
if driver checks it before WA. While hooking read to 0x1080C0 fakes the
DSMBASE to (BAR2 + 8M) in guest address space. Both tries to enforce
guest accesses to DSM via BAR2. I personally prefers hooking 0x1080C0
as it's driver-independent.

Btw, this quirk seems only necessary for Meteor and Arrow lake. That WA
is not applied in Xe driver. I'm not sure if it still presents in GOP or
windows driver for later generations.

> The firmware still has to program ASLS.  The IgdAssignmentDxe build the
> v2 commit message describes aborts on bdsm-size=0 before doing so;
> VfioIgdPkg has no such check and programs ASLS for MTL+ as is.
> 
> I'll write the quirk.  It can go into Yuan's v3 or on top of it as a
> separate patch -- Yuan, your call.  Either way it needs a run with the
> stock GOP build on your setup.
> 
> Junjie

Yes OpRegion is needed for display to work. In the "hooking 0x1080C0 read"
approach above, allocating DSM in guest is not needed. It sounds better to
make your IgdAssignmentDxe not aborting if bdsm-size=0.

Best Regards,
Moeko
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Wang, Yuan1 1 week, 1 day ago
On 9/16/2026 1:33 PM, Tomita Moeko wrote:
> So on MTL+ BAR2 is mapped to the physical memory at GSMBASE, with first 8M
> for GTT. PTE addresses are relative addresses so that accessing indirectly
> from BAR or directly works. That makes sense. 
>
> Meteor and later IGDs are supposed to access DSM from BAR2 instead of directly
> from DSMBASE, but there is some hardware issues in Meteor Lake and Arrow Lake's
> BAR2, software workarounds it to by falling back to DSMBASE. i915 won't read
> DSMBASE register if the WA is not enabled (and it's always disabled when
> virtualization enabled), while it's possible for GOP driver (and maybe windows
> driver) to read it. Is my understanding correct?
>
Yes, your understanding is correct. In virtualization, we still go to BAR2.

>> Agree with the direction, and it is cheaper than that: a read-only BAR0
>> quirk can take pci_get_bar_addr(pdev, 2) at read time, returning BAR2 at
>> 0x108100 and BAR2 + 8M at 0x1080C0.  Then the CPU-side address resolves
>> to real stolen memory through the aperture instead of guest RAM,
>> bdsm-size stays 0 as documented, and nothing in config space is
>> invented.
> Yes hooking on 0x1080C0 register read is easier and more straightforward.
>
>>> Possibly an easier way is emulating MTL_PCODE_STOLEN_ACCESS(0x138914) to
>>> disallowed in QEMU, if the GOP driver code checks it, to enforce the access
>>> via BAR2 in guest.
>> 0x138914 reads 1 on the host and is not quirked, so a guest sees 1 too.
>> Returning 0 there is a small addition and covers a GOP that checks it;
>> the DSMBASE quirk covers one that does not.  On the Wa itself: i915
>> already takes the BAR path in guests (i915_run_as_guest() short-circuits
>> i915_direct_stolen_access()), so that path has upstream precedent; we
>> have not measured whether the hang reproduces there.
>>
> Quirking 0x138914 prevents driver applying that WA, but we are not sure
> if driver checks it before WA. While hooking read to 0x1080C0 fakes the
> DSMBASE to (BAR2 + 8M) in guest address space. Both tries to enforce
> guest accesses to DSM via BAR2. I personally prefers hooking 0x1080C0
> as it's driver-independent.
By some internal sync with Junjie and Bosheng, we plan to quirk 0x138914 as you point

before. We have checked the GOP code, it always checks the 0x138914 first to determine

the address it used.  If you think it is ok, we will raise a V3 patch based on it.

> Btw, this quirk seems only necessary for Meteor and Arrow lake. That WA
> is not applied in Xe driver. I'm not sure if it still presents in GOP or
> windows driver for later generations.

The WA is only needed for MTL/ARL. The later ones don't need this WA.

>> The firmware still has to program ASLS.  The IgdAssignmentDxe build the
>> v2 commit message describes aborts on bdsm-size=0 before doing so;
>> VfioIgdPkg has no such check and programs ASLS for MTL+ as is.
>>
>> I'll write the quirk.  It can go into Yuan's v3 or on top of it as a
>> separate patch -- Yuan, your call.  Either way it needs a run with the
>> stock GOP build on your setup.
>>
>> Junjie
> Yes OpRegion is needed for display to work. In the "hooking 0x1080C0 read"
> approach above, allocating DSM in guest is not needed. It sounds better to
> make your IgdAssignmentDxe not aborting if bdsm-size=0.
>
> Best Regards,
> Moeko

Yes,  that's a good idea. If we can make IgdAssignmentDxe not aborting, it looks better. 

And this function is in the offline patch of OVMF and is maintained in ECI's website.

We are discussing this with the ECI team to update the offline patch. The gen_id() may not

need to be changed now if they accepted. And the V3 patch should only include the

quirk for 0x138914 for MTL/ARL.


Thanks

Yuan


Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Tomita Moeko 1 week, 1 day ago
On 2026-09-18 16:00, Wang, Yuan1 wrote:
> 
> On 9/16/2026 1:33 PM, Tomita Moeko wrote:
>> So on MTL+ BAR2 is mapped to the physical memory at GSMBASE, with first 8M
>> for GTT. PTE addresses are relative addresses so that accessing indirectly
>> from BAR or directly works. That makes sense. 
>>
>> Meteor and later IGDs are supposed to access DSM from BAR2 instead of directly
>> from DSMBASE, but there is some hardware issues in Meteor Lake and Arrow Lake's
>> BAR2, software workarounds it to by falling back to DSMBASE. i915 won't read
>> DSMBASE register if the WA is not enabled (and it's always disabled when
>> virtualization enabled), while it's possible for GOP driver (and maybe windows
>> driver) to read it. Is my understanding correct?
>>
> Yes, your understanding is correct. In virtualization, we still go to BAR2.
> 
>>> Agree with the direction, and it is cheaper than that: a read-only BAR0
>>> quirk can take pci_get_bar_addr(pdev, 2) at read time, returning BAR2 at
>>> 0x108100 and BAR2 + 8M at 0x1080C0.  Then the CPU-side address resolves
>>> to real stolen memory through the aperture instead of guest RAM,
>>> bdsm-size stays 0 as documented, and nothing in config space is
>>> invented.
>> Yes hooking on 0x1080C0 register read is easier and more straightforward.
>>
>>>> Possibly an easier way is emulating MTL_PCODE_STOLEN_ACCESS(0x138914) to
>>>> disallowed in QEMU, if the GOP driver code checks it, to enforce the access
>>>> via BAR2 in guest.
>>> 0x138914 reads 1 on the host and is not quirked, so a guest sees 1 too.
>>> Returning 0 there is a small addition and covers a GOP that checks it;
>>> the DSMBASE quirk covers one that does not.  On the Wa itself: i915
>>> already takes the BAR path in guests (i915_run_as_guest() short-circuits
>>> i915_direct_stolen_access()), so that path has upstream precedent; we
>>> have not measured whether the hang reproduces there.
>>>
>> Quirking 0x138914 prevents driver applying that WA, but we are not sure
>> if driver checks it before WA. While hooking read to 0x1080C0 fakes the
>> DSMBASE to (BAR2 + 8M) in guest address space. Both tries to enforce
>> guest accesses to DSM via BAR2. I personally prefers hooking 0x1080C0
>> as it's driver-independent.
> By some internal sync with Junjie and Bosheng, we plan to quirk 0x138914 as you point
> 
> before. We have checked the GOP code, it always checks the 0x138914 first to determine
> 
> the address it used.  If you think it is ok, we will raise a V3 patch based on it.

Sure please proceed with that.

>> Btw, this quirk seems only necessary for Meteor and Arrow lake. That WA
>> is not applied in Xe driver. I'm not sure if it still presents in GOP or
>> windows driver for later generations.
> 
> The WA is only needed for MTL/ARL. The later ones don't need this WA.
> 
>>> The firmware still has to program ASLS.  The IgdAssignmentDxe build the
>>> v2 commit message describes aborts on bdsm-size=0 before doing so;
>>> VfioIgdPkg has no such check and programs ASLS for MTL+ as is.
>>>
>>> I'll write the quirk.  It can go into Yuan's v3 or on top of it as a
>>> separate patch -- Yuan, your call.  Either way it needs a run with the
>>> stock GOP build on your setup.
>>>
>>> Junjie
>> Yes OpRegion is needed for display to work. In the "hooking 0x1080C0 read"
>> approach above, allocating DSM in guest is not needed. It sounds better to
>> make your IgdAssignmentDxe not aborting if bdsm-size=0.
>>
>> Best Regards,
>> Moeko
> 
> Yes,  that's a good idea. If we can make IgdAssignmentDxe not aborting, it looks better. 
> 
> And this function is in the offline patch of OVMF and is maintained in ECI's website.
> 
> We are discussing this with the ECI team to update the offline patch. The gen_id() may not
> 
> need to be changed now if they accepted. And the V3 patch should only include the
> 
> quirk for 0x138914 for MTL/ARL.
> 
> 
> Thanks
> 
> Yuan
Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Wang, Yuan1 5 days, 13 hours ago
On 9/18/2026 4:23 PM, Tomita Moeko wrote:
>>>>> Possibly an easier way is emulating MTL_PCODE_STOLEN_ACCESS(0x138914) to
>>>>> disallowed in QEMU, if the GOP driver code checks it, to enforce the access
>>>>> via BAR2 in guest.
>>>> 0x138914 reads 1 on the host and is not quirked, so a guest sees 1 too.
>>>> Returning 0 there is a small addition and covers a GOP that checks it;
>>>> the DSMBASE quirk covers one that does not.  On the Wa itself: i915
>>>> already takes the BAR path in guests (i915_run_as_guest() short-circuits
>>>> i915_direct_stolen_access()), so that path has upstream precedent; we
>>>> have not measured whether the hang reproduces there.
>>>>
>>> Quirking 0x138914 prevents driver applying that WA, but we are not sure
>>> if driver checks it before WA. While hooking read to 0x1080C0 fakes the
>>> DSMBASE to (BAR2 + 8M) in guest address space. Both tries to enforce
>>> guest accesses to DSM via BAR2. I personally prefers hooking 0x1080C0
>>> as it's driver-independent.
>> By some internal sync with Junjie and Bosheng, we plan to quirk 0x138914 as you point
>>
>> before. We have checked the GOP code, it always checks the 0x138914 first to determine
>>
>> the address it used.  If you think it is ok, we will raise a V3 patch based on it.
> Sure please proceed with that.

Thanks everyone for the valuable feedback on v2!

I have addressed the comments and sent out the v3 patch series in a new thread for review.

Looking forward to your feedback there.

Best regards,
Yuan


Re: [PATCH v2] vfio/igd: Add device ID support for Meteor Lake and Arrow Lake
Posted by Cédric Le Goater 3 weeks, 2 days ago
On 8/25/26 11:04, Yuan Wang wrote:
> Currently, igd_gen() does not include the PCI device IDs for Meteor
> Lake and Arrow Lake platforms, causing it to return -1 for these GPUs.
> 
> As a result, QEMU calculates the stolen memory size as 0 and exposes a
> zero-sized 'etc/igd-bdsm-size' entry via fw_cfg. When OVMF boots,
> IgdAssignmentDxe fails validation on the zero BDSM size and aborts
> without programming the ASLS register. Consequently, the guest Intel
> GOP driver fails to locate and read the OpRegion (ASLS remains 0x0).
> 
> Add the device ID prefixes (0x7D00 and 0xB600) to igd_gen() as Gen 12
> so that stolen memory is correctly determined, allowing OVMF to properly
> initialize the OpRegion and BDSM for the Intel GOP driver.
> 
> Signed-off-by: Yuan Wang <yuan1.wang@intel.com>
> ---
> v2:
> - Resending because the v1 patch was sent with an incorrect future
>    system timestamp due to an unsynchronized local clock. No code
>    changes.
> ---
>   hw/vfio/igd.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
> index 413a49aae9..a0b6b34d81 100644
> --- a/hw/vfio/igd.c
> +++ b/hw/vfio/igd.c
> @@ -96,6 +96,8 @@ static int igd_gen(VFIOPCIDevice *vdev)
>       case 0x4C00:    /* Rocket Lake */
>       case 0x4600:    /* Alder Lake */
>       case 0xA700:    /* Raptor Lake */
> +    case 0x7D00:    /* Meteor Lake / Arrow Lake */
> +    case 0xB600:    /* Arrow Lake */
>           return 12;
>       }
>   

Reviewed-by: Cédric Le Goater <clg@redhat.com>

Thanks,

C.