* [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
[not found] <20260802050824.10554-1-brchuckz.ref@aol.com>
@ 2026-08-02 5:08 ` Chuck Zmudzinski
2026-08-13 10:35 ` Jan Beulich
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-02 5:08 UTC (permalink / raw)
To: xen-devel
Cc: qemu-devel, Jan Beulich, Andrew Cooper, Roger Pau Monné,
Teddy Astie, Tomita Moeko
Modern Intel IGD devices do not work well with the current
implementation of support for the Intel IGD in hvmloader because
it lacks support for an extended video bios table (VBT).
Code 43 errors in Windows guests and failure of the guest screen
to light up are some of the problems that occur with the
current implementation.
To address this problem, this patch implements support for
Intel IGD devices with an extended VBT and OpRegion version 2
and higher which is required for most modern Intel IGD devices.
This patch also depends on compatible support in the device
model. If hvmloader detects the device model lacks such support,
it will fall back to the currently implemented protocol for
configuring the OpRegion to provide backward compatibiltiy for
systems that lack a device model with support for an extended VBT.
Support for an extended VBT is implemented in the newly introduced
function intel_opregion_setup() which is implemented in the new
file intel_opregion.c.
Major differences between this implementation and the current
implemntation that only supports older devices without an
extended VBT:
1. The current implemntation reserves a constant number of
pages (3) in the E820 map for the OpRegion which is set by
the IGD_OPREGION_PAGES macro in the current implementation.
With OpRegion 2 and higher, the OpRegion can have an
extended VBT that must be provided to the guest with the
OpRegion. This means the size of the region is not fixed,
so in this new implementation the IGD_OPREGION_PAGES constant
is changed to a variable in e820.c, igd_opregion_e820_pages,
that is set to its proper value based on the the size of the
VBT. In this new implemntation, the size of the ACPI NVS region
reserved for the OpRegion in the E820 map is equal to the value
of the igd_opregion_e820_pages variable instead of being set
to the constant value determined by IGD_OPREGION_PAGES.
2. The current implemntation provides the guest with access
to the unmodified OpRegion on the host via memory mapping
from the host to the guest. This is insufficient for
OpRegion 2 and higher because some devices will require
modifications to the OpRegion for proper operation in the
guest. So this new implementation provides hvmloader with a
copy of the host's OpRegion that hvmloader can modify as
needed for proper operation. Mapping the OpRegion from the
host to the guest is only used temporarily during setup of
the OpRegion by hvmloader and once hvmloader has a copy of
the OpRegion and the extended VBT, the device model removes
the host mapping and hvmloader configures the guest to use
the guest's possibly modified copy of the OpRegion instead.
3. The current implementation lacks useful debugging information
for the more recent devices. This new implementation provides
useful debugging output from hvmloader, such as the detected
host OpRegion version and address, the values for rvda, rvds,
and the guest OpRegion address when the guest_loglvl is set
to all/all.
Link: https://lore.kernel.org/kvm/20211012124855.52463-1-colin.xu@gmail.com/
Link: https://lore.kernel.org/kvm/20210325170953.24549-1-fred.gao@intel.com/
Signed-off-by: Chuck Zmudzinski <brchuckz@aol.com>
---
The companion patchset for the device model is available here:
https://lore.kernel.org/xen-devel/20260801001737.16509-1-brchuckz@aol.com/
There is an undocumented setting that works in the xl.cfg(5) domain
configuration file, firmware_override, that makes it possible to use
a patched version of hvmloader alongside an installation of unpatched
upstream Xen or a version of Xen packaged by a distro. So one can
download the source for one's installed version of Xen, apply this
patch and build just hvmloader and then install the patched version of
hvmloader with a different filename, such as hvmloader-igd-testing, into
the same directory where hvmloader is installed (usually something like
/usr/libexec/xen/boot) and then one can configure a guest to use the patched
version of hvmloader with one's installed version of Xen by adding a line
like this to the domain xl.cfg file:
firmware_override = 'hvmloader-igd-testing'
The compatible patch for the device model is part of a larger patchset
that fixes many of the problems that currently affect the feature of
Intel IGD passthrough to Xen HVM guests. This patch should be considered
as a companion patch to that patchset for the device model. Do not try
to test this patch with a real Intel IGD device without also applying
the patchset for the device model because without those patches, the
guest will most likely fail to start if an Intel IGD is passed through
to the guest.
There are different requirements to support OpRegion version 2.0
and OpRegion version 2.1+, with support for OpRegion 2 the more
difficult case because it always requires modifications to the OpRegion
for proper operation in the guest. For some details about OpRegion
2 and higher and the extended VBT, see the links in the commit message.
Changes in v2:
- Correct the name of the new function in the commit message
opregion_setup() -> intel_opregion_setup()
- Add a link to the companion patchset for the device model
- Describe how to use the firmware_override setting in xl.cfg(5)
to simplify testing of this patch.
- Correct a logical flaw that in case the size of the extended VBT
is <= 2 pages, an extra, unnecessary page would be allocated in
the memory hole. This correction is in the intel_opregion.c file.
This code:
/* Update the number of pages we need for the E820 map */
igd_opregion_e820_pages = pages_needed;
/*
* So far we have allocated vbt_pages_needed
* and we will likely need to allocate more
* pages to fully contain OpRegion + VBT.
*/
if ( pages_needed > vbt_pages_needed )
igd_opregion_pgbase = mem_hole_alloc
(pages_needed - vbt_pages_needed);
Is replaced with this code:
/*
* So far we have allocated igd_opregion_e820_pages
* and we will likely need to allocate more
* pages to fully contain OpRegion + VBT.
*/
if ( pages_needed > igd_opregion_e820_pages )
igd_opregion_pgbase = mem_hole_alloc
(pages_needed - igd_opregion_e820_pages);
/* Update the number of pages we need for the E820 map */
igd_opregion_e820_pages = pages_needed;
tools/firmware/hvmloader/Makefile | 1 +
tools/firmware/hvmloader/config.h | 15 +-
tools/firmware/hvmloader/e820.c | 4 +-
tools/firmware/hvmloader/intel_opregion.c | 297 ++++++++++++++++++++++
tools/firmware/hvmloader/pci.c | 10 +-
5 files changed, 313 insertions(+), 14 deletions(-)
create mode 100644 tools/firmware/hvmloader/intel_opregion.c
diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile
index 21de721..ed42915 100644
--- a/tools/firmware/hvmloader/Makefile
+++ b/tools/firmware/hvmloader/Makefile
@@ -35,6 +35,7 @@ OBJS += smp.o cacheattr.o xenbus.o vnuma.o
OBJS += e820.o pci.o pir.o ctype.o
OBJS += hvm_param.o
OBJS += ovmf.o seabios.o
+OBJS += intel_opregion.o
ifeq ($(debug),y)
OBJS += tests.o
endif
diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h
index c159db3..bd3c0f9 100644
--- a/tools/firmware/hvmloader/config.h
+++ b/tools/firmware/hvmloader/config.h
@@ -7,9 +7,6 @@
enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt };
extern enum virtual_vga virtual_vga;
-extern unsigned long igd_opregion_pgbase;
-#define IGD_OPREGION_PAGES 3
-
struct bios_config {
const char *name;
@@ -43,6 +40,18 @@ extern struct bios_config ovmf_config;
#define PAGE_SHIFT 12
#define PAGE_SIZE (1ul << PAGE_SHIFT)
+#define IGD_OPREGION_PAGES 3
+#define IGD_OPREGION_SIZE ((IGD_OPREGION_PAGES - 1) << PAGE_SHIFT)
+#define IGD_OPREGION_RVDA 0x3ba
+#define IGD_OPREGION_RVDS 0x3c2
+#define IGD_OPREGION_VERSION 0x16
+#define IGD_OPREGION_MASK 0xfff
+#define IGD_OPREGION2_SUPPORT_MASK 0x1
+#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
+#define IGD_VBT_SIGNATURE "$VBT"
+extern unsigned long igd_opregion_pgbase;
+extern uint32_t igd_opregion_e820_pages;
+void intel_opregion_setup(uint32_t vga_devfn);
extern uint8_t ioapic_version;
diff --git a/tools/firmware/hvmloader/e820.c b/tools/firmware/hvmloader/e820.c
index 86d3954..97a234e 100644
--- a/tools/firmware/hvmloader/e820.c
+++ b/tools/firmware/hvmloader/e820.c
@@ -243,11 +243,11 @@ int build_e820_table(struct e820entry *e820,
nr++;
e820[nr].addr = igd_opregion_base;
- e820[nr].size = IGD_OPREGION_PAGES * PAGE_SIZE;
+ e820[nr].size = igd_opregion_e820_pages * PAGE_SIZE;
e820[nr].type = E820_NVS;
nr++;
- e820[nr].addr = igd_opregion_base + IGD_OPREGION_PAGES * PAGE_SIZE;
+ e820[nr].addr = igd_opregion_base + igd_opregion_e820_pages * PAGE_SIZE;
e820[nr].size = (uint32_t)-e820[nr].addr;
e820[nr].type = E820_RESERVED;
nr++;
diff --git a/tools/firmware/hvmloader/intel_opregion.c b/tools/firmware/hvmloader/intel_opregion.c
new file mode 100644
index 0000000..59cb2c3
--- /dev/null
+++ b/tools/firmware/hvmloader/intel_opregion.c
@@ -0,0 +1,297 @@
+/*
+ * intel_opregion.c: HVM Intel OpRegion setup.
+ *
+ * Leendert van Doorn, leendert@watson.ibm.com
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * Copyright (c) 2006, Keir Fraser, XenSource Inc.
+ *
+ * Copyright (c) 2026, Charles Zmudzinski.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "util.h"
+#include "config.h"
+#include "pci_regs.h"
+
+unsigned long igd_opregion_pgbase = 0;
+uint32_t igd_opregion_e820_pages = IGD_OPREGION_PAGES;
+
+static bool verify_opregion(const uint32_t addr)
+{
+ const char *opregion_signature = IGD_OPREGION_SIGNATURE;
+ if ( memcmp((const void *)addr, (const void *)opregion_signature, 16) )
+ return false;
+ return true;
+}
+
+static bool verify_vbt(const uint32_t addr)
+{
+ const char *vbt_signature = IGD_VBT_SIGNATURE;
+ if ( memcmp((const void *)addr, (const void *)vbt_signature, 4) )
+ return false;
+ return true;
+}
+
+void intel_opregion_setup(uint32_t vga_devfn)
+{
+ uint32_t igd_guest_opregion;
+ uint32_t pages_needed; /* for OpRegion + VBT */
+ void *opregion_scratch;
+ void *vbt_scratch;
+ void *vbt_source;
+ /*
+ * absolute value in the host/guest except
+ * as noted in the comments
+ */
+ static unsigned long rvda_host;
+ static unsigned long rvda_guest;
+
+ igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
+ /*
+ * Tentative value for the number of pages to reserve
+ * in the E820 map for the OpRegion and VBT.
+ *
+ * This will be the final value for the E820 map if
+ * the device model lacks support for OpRegion 2 or
+ * if the host OpRegion version is < 2 or if we never
+ * allocate more pages in the E820 map for the VBT.
+ */
+ igd_opregion_e820_pages = IGD_OPREGION_PAGES;
+
+ /*
+ * Read the value the device model is initialized with.
+ * If the device model supports OpRegion 2, it will
+ * return the host IGD OpRegion address. If not, it
+ * will return 0. If the device model does not support
+ * OpRegion 2, the device model expects us to give it
+ * the address to which it will map the OpRegion in the
+ * guest and then expects us to do nothing more to setup
+ * the OpRegion, so that is all we will do in that case.
+ */
+ const uint32_t igd_host_opregion = pci_readl(vga_devfn,
+ PCI_INTEL_OPREGION);
+ if ( !igd_host_opregion ) {
+ printf("device model lacks extended VBT "
+ "support. Continuing with legacy support only\n");
+ /*
+ * Write the the OpRegion offset to give the OpRegion
+ * address to the device model. The device model will trap
+ * and map the OpRegion at the give address.
+ */
+ pci_writel(vga_devfn, PCI_INTEL_OPREGION,
+ igd_opregion_pgbase << PAGE_SHIFT);
+ return;
+ } else {
+ printf("host OpRegion address: 0x%x\n",
+ igd_host_opregion);
+ }
+
+ const uint32_t igd_host_opregion_page_offset =
+ igd_host_opregion & IGD_OPREGION_MASK;
+ igd_guest_opregion = (igd_opregion_pgbase << PAGE_SHIFT) |
+ igd_host_opregion_page_offset;
+
+ /*
+ * We know at this point the device model supports
+ * OpRegion 2.
+ *
+ * Indicate to the device model that we support
+ * OpRegion 2 by setting the least significant bit
+ * of the address we give to the device model.
+ * The device model will notice this bit set and
+ * respond appropriately to our writes to the
+ * register where the OpRegion address is stored.
+ */
+ pci_writel(vga_devfn, PCI_INTEL_OPREGION,
+ (igd_opregion_pgbase << PAGE_SHIFT) |
+ IGD_OPREGION2_SUPPORT_MASK);
+
+ printf("guest OpRegion tentative "
+ "address: 0x%x\n", igd_guest_opregion);
+
+ if ( !verify_opregion(igd_guest_opregion) ) {
+ printf("error: IGD OpRegion signature "
+ "not found.\n");
+ BUG();
+ }
+
+ opregion_scratch = scratch_alloc(IGD_OPREGION_SIZE, 0);
+ memcpy(opregion_scratch, (const void *)igd_guest_opregion,
+ IGD_OPREGION_SIZE);
+
+ /* Read OpRegion version, rvda_host, and rvds */
+ const uint16_t version = *(uint16_t *)(opregion_scratch +
+ IGD_OPREGION_VERSION);
+ printf("OpRegion version: 0x%x\n", version);
+ if ( version >= 0x0200 ) {
+ rvda_host = *(unsigned long *)(opregion_scratch +
+ IGD_OPREGION_RVDA);
+ /* It is convenient to make rvda_host absolute */
+ if ( version > 0x0200 )
+ rvda_host += igd_host_opregion;
+ printf("host VBT address: 0x%lx\n", rvda_host);
+ } else {
+ printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
+ rvda_host = 0;
+ }
+ const uint32_t rvda_host_page_offset = rvda_host &
+ IGD_OPREGION_MASK;
+ const uint32_t rvds = *(uint32_t *)(opregion_scratch +
+ IGD_OPREGION_RVDS);
+ const uint32_t rvds_page_offset = rvds & IGD_OPREGION_MASK;
+ printf("VBT size: 0x%x\n", rvds);
+
+ if ( !rvds || !rvda_host ) {
+ printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
+ rvda_host = 0;
+ }
+ /*
+ * Write rvda_host as 2 successive 32-bit values
+ * to communicate location of the VBT to the device
+ * model. If rvda_host is not 0, The device model
+ * unmaps the OpRegion and eventually maps the VBT
+ * after we also write the guest address where the
+ * VBT will be mapped.
+ *
+ * If we send rvda_host = 0 to the device model, it
+ * will assume we do not need OpRegion 2 support and
+ * it will not unmap the OpRegion.
+ */
+ pci_writel(vga_devfn, PCI_INTEL_OPREGION,
+ (uint32_t)(rvda_host & 0xfffffffful));
+ unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
+ pci_writel(vga_devfn, PCI_INTEL_OPREGION,
+ (uint32_t)rvda_host_upper_32);
+
+ /* In this case, we use the mapped OpRegion */
+ if ( !rvda_host )
+ return;
+
+ /*
+ * Update the number of pages the device model
+ * needs to map for us to get a copy of the VBT.
+ *
+ * N.B.: Here, igd_opregion_pgbase is really the page
+ * base of the location where the device model will
+ * map the VBT.
+ */
+ uint32_t vbt_pages_needed = rvds >> PAGE_SHIFT;
+ if ( rvds & IGD_OPREGION_MASK )
+ vbt_pages_needed++;
+ if ( vbt_pages_needed > igd_opregion_e820_pages ) {
+ igd_opregion_pgbase = mem_hole_alloc
+ (vbt_pages_needed - igd_opregion_e820_pages);
+ igd_opregion_e820_pages = vbt_pages_needed;
+ }
+
+ /*
+ * Write the location where the device model is to
+ * map the VBT in the guest with the 12 least
+ * significant bits encoded as the number of pages
+ * for the device model to map (vbt_pages_needed).
+ */
+ pci_writel(vga_devfn, PCI_INTEL_OPREGION,
+ ((igd_opregion_pgbase << PAGE_SHIFT) | vbt_pages_needed));
+
+ /*
+ * When the VBT is mapped from the host, the page offset
+ * of the VBT will be the same as on the host
+ */
+ rvda_guest = (igd_opregion_pgbase << PAGE_SHIFT) |
+ rvda_host_page_offset;
+ if ( !verify_vbt(rvda_guest) ) {
+ printf("error: VBT signature not found.\n");
+ BUG();
+ }
+
+ vbt_source = (void *)rvda_guest;
+ vbt_scratch = scratch_alloc(rvds, 0);
+ memcpy(vbt_scratch, vbt_source, rvds);
+
+ /* Compute how many pages we need for OpRegion + VBT */
+ pages_needed = (IGD_OPREGION_SIZE + rvds) >> PAGE_SHIFT;
+ if ( (IGD_OPREGION_SIZE + rvds) & IGD_OPREGION_MASK )
+ pages_needed++;
+
+ /*
+ * So far we have allocated igd_opregion_e820_pages
+ * and we will likely need to allocate more
+ * pages to fully contain OpRegion + VBT.
+ */
+ if ( pages_needed > igd_opregion_e820_pages )
+ igd_opregion_pgbase = mem_hole_alloc
+ (pages_needed - igd_opregion_e820_pages);
+
+ /* Update the number of pages we need for the E820 map */
+ igd_opregion_e820_pages = pages_needed;
+
+ /*
+ * Compute the final igd_guest_opregion value and
+ * keep the same offset as on the host if doing so
+ * will not push us across another page boundary.
+ */
+ igd_guest_opregion = igd_opregion_pgbase << PAGE_SHIFT;
+ if ( (igd_host_opregion_page_offset + rvds_page_offset) <= PAGE_SIZE )
+ igd_guest_opregion |= igd_host_opregion_page_offset;
+ printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
+
+ /* The device model will unmap the VBT */
+ pci_writel(vga_devfn, PCI_INTEL_OPREGION, igd_guest_opregion);
+
+ /*
+ * After unmapping we need to populate the memory hole.
+ * If the unmapping failed this will crash the guest.
+ *
+ * We could try to use the mapped VBT with our copy of the
+ * OpRegion, but it is probably better to BUG() if the
+ * device model failed to unmap the VBT.
+ */
+ if ( verify_vbt(rvda_guest) )
+ BUG();
+ mem_hole_populate_ram(igd_opregion_pgbase,
+ igd_opregion_e820_pages);
+
+ /*
+ * After unmapping we are free to shift the VBT by
+ * an arbitrary number of bytes. For efficient use
+ * of memory and to keep the memory map simple,
+ * place the VBT contiguous after the OpRegion.
+ */
+ rvda_guest = igd_guest_opregion + IGD_OPREGION_SIZE;
+ printf("guest VBT address: 0x%lx\n", rvda_guest);
+
+ /*
+ * Until now, rvda_guest has been an absolute address
+ * in the guest. We need to translate it to a relative
+ * address if OpRegion version > 0x0200 and in that case
+ * we also verify it is contiguous with the OpRegion.
+ */
+ if ( version > 0x0200 ) {
+ rvda_guest -= igd_guest_opregion;
+ printf("guest rvda (relative): 0x%lx\n", rvda_guest);
+ BUG_ON(rvda_guest != IGD_OPREGION_SIZE);
+ }
+
+ /*
+ * Write the correct rvda_guest value to the
+ * guest copy of the OpRegion and copy the scratch
+ * buffers to the correct address in our E820 region.
+ */
+ *(unsigned long *)(opregion_scratch + IGD_OPREGION_RVDA) = rvda_guest;
+ memcpy((void *)(igd_guest_opregion + IGD_OPREGION_SIZE),
+ (const void *)vbt_scratch, rvds);
+ memcpy((void *)igd_guest_opregion,
+ (const void *)opregion_scratch, IGD_OPREGION_SIZE);
+}
diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c
index c41c8d9..07a37e5 100644
--- a/tools/firmware/hvmloader/pci.c
+++ b/tools/firmware/hvmloader/pci.c
@@ -43,7 +43,6 @@ uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
#define BAR_RELOC_THRESH GB(1)
enum virtual_vga virtual_vga = VGA_none;
-unsigned long igd_opregion_pgbase = 0;
/* Check if the specified range conflicts with any reserved device memory. */
static bool check_overlap_all(uint64_t start, uint64_t size)
@@ -190,14 +189,7 @@ void pci_setup(void)
virtual_vga = VGA_pt;
if ( vendor_id == 0x8086 )
{
- igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
- /*
- * Write the the OpRegion offset to give the opregion
- * address to the device model. The device model will trap
- * and map the OpRegion at the give address.
- */
- pci_writel(vga_devfn, PCI_INTEL_OPREGION,
- igd_opregion_pgbase << PAGE_SHIFT);
+ intel_opregion_setup(vga_devfn);
}
}
break;
--
2.52.0
^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-02 5:08 ` [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support Chuck Zmudzinski
@ 2026-08-13 10:35 ` Jan Beulich
2026-08-14 0:45 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-13 10:35 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 02.08.2026 07:08, Chuck Zmudzinski wrote:
> Modern Intel IGD devices do not work well with the current
> implementation of support for the Intel IGD in hvmloader because
> it lacks support for an extended video bios table (VBT).
>
> Code 43 errors in Windows guests and failure of the guest screen
> to light up are some of the problems that occur with the
> current implementation.
>
> To address this problem, this patch implements support for
> Intel IGD devices with an extended VBT and OpRegion version 2
> and higher which is required for most modern Intel IGD devices.
First of all: Where's the spec of all of this?
> ---
>[...]
>
> tools/firmware/hvmloader/Makefile | 1 +
> tools/firmware/hvmloader/config.h | 15 +-
> tools/firmware/hvmloader/e820.c | 4 +-
> tools/firmware/hvmloader/intel_opregion.c | 297 ++++++++++++++++++++++
Nit: Please use dashes in favor of underscores in new files' names.
> --- a/tools/firmware/hvmloader/Makefile
> +++ b/tools/firmware/hvmloader/Makefile
> @@ -35,6 +35,7 @@ OBJS += smp.o cacheattr.o xenbus.o vnuma.o
> OBJS += e820.o pci.o pir.o ctype.o
> OBJS += hvm_param.o
> OBJS += ovmf.o seabios.o
> +OBJS += intel_opregion.o
While this list isn't well sorted, I think your addition still wants to move
up by a line.
> --- a/tools/firmware/hvmloader/config.h
> +++ b/tools/firmware/hvmloader/config.h
> @@ -7,9 +7,6 @@
> enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt };
> extern enum virtual_vga virtual_vga;
>
> -extern unsigned long igd_opregion_pgbase;
> -#define IGD_OPREGION_PAGES 3
> -
> struct bios_config {
> const char *name;
>
> @@ -43,6 +40,18 @@ extern struct bios_config ovmf_config;
>
> #define PAGE_SHIFT 12
> #define PAGE_SIZE (1ul << PAGE_SHIFT)
> +#define IGD_OPREGION_PAGES 3
> +#define IGD_OPREGION_SIZE ((IGD_OPREGION_PAGES - 1) << PAGE_SHIFT)
This is odd, and hence wants a comment.
> +#define IGD_OPREGION_RVDA 0x3ba
> +#define IGD_OPREGION_RVDS 0x3c2
> +#define IGD_OPREGION_VERSION 0x16
> +#define IGD_OPREGION_MASK 0xfff
> +#define IGD_OPREGION2_SUPPORT_MASK 0x1
> +#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
> +#define IGD_VBT_SIGNATURE "$VBT"
> +extern unsigned long igd_opregion_pgbase;
> +extern uint32_t igd_opregion_e820_pages;
> +void intel_opregion_setup(uint32_t vga_devfn);
Blank lines please ahead of the new #define-s you add and between those new
#define-s and the new decls.
For igd_opregion_e820_pages I further cannot spot any use which would justify
the use of a fixed-width type; unsigned int will do, and will then be in line
with ./CODING_STYLE.
> --- a/tools/firmware/hvmloader/e820.c
> +++ b/tools/firmware/hvmloader/e820.c
> @@ -243,11 +243,11 @@ int build_e820_table(struct e820entry *e820,
> nr++;
>
> e820[nr].addr = igd_opregion_base;
> - e820[nr].size = IGD_OPREGION_PAGES * PAGE_SIZE;
> + e820[nr].size = igd_opregion_e820_pages * PAGE_SIZE;
> e820[nr].type = E820_NVS;
> nr++;
>
> - e820[nr].addr = igd_opregion_base + IGD_OPREGION_PAGES * PAGE_SIZE;
> + e820[nr].addr = igd_opregion_base + igd_opregion_e820_pages * PAGE_SIZE;
Are these new multiplications at risk of overflowing? I.e. how many pages can
there be in an extreme case?
> --- /dev/null
> +++ b/tools/firmware/hvmloader/intel_opregion.c
> @@ -0,0 +1,297 @@
> +/*
> + * intel_opregion.c: HVM Intel OpRegion setup.
> + *
> + * Leendert van Doorn, leendert@watson.ibm.com
> + * Copyright (c) 2005, International Business Machines Corporation.
> + *
> + * Copyright (c) 2006, Keir Fraser, XenSource Inc.
What do these cover?
> + * Copyright (c) 2026, Charles Zmudzinski.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
Please use an SPDX line instead in new files.
> +#include "util.h"
> +#include "config.h"
> +#include "pci_regs.h"
> +
> +unsigned long igd_opregion_pgbase = 0;
> +uint32_t igd_opregion_e820_pages = IGD_OPREGION_PAGES;
> +
> +static bool verify_opregion(const uint32_t addr)
> +{
> + const char *opregion_signature = IGD_OPREGION_SIGNATURE;
> + if ( memcmp((const void *)addr, (const void *)opregion_signature, 16) )
> + return false;
> + return true;
> +}
Style: Blank line please between declaration(s) and statement(s) as well as
ahead of the main "return" of a function. There further isn't really a need
for an if() or two return statements here. Also please avoid casts wherever
possible. Finally, the local variable isn't really needed here either - the
string literal can be passed directly to memcmp(). All of this helps
readability as well.
> +static bool verify_vbt(const uint32_t addr)
> +{
> + const char *vbt_signature = IGD_VBT_SIGNATURE;
> + if ( memcmp((const void *)addr, (const void *)vbt_signature, 4) )
> + return false;
> + return true;
> +}
Same comments here, obviously (and potentially elsewhere).
> +void intel_opregion_setup(uint32_t vga_devfn)
> +{
> + uint32_t igd_guest_opregion;
> + uint32_t pages_needed; /* for OpRegion + VBT */
The former probably wants to be fixed-width, but for the latter I see no need.
> + void *opregion_scratch;
> + void *vbt_scratch;
> + void *vbt_source;
> + /*
> + * absolute value in the host/guest except
> + * as noted in the comments
> + */
Nit: Comment style (see ./CODING_STYLE).
> + static unsigned long rvda_host;
> + static unsigned long rvda_guest;
Why static? The function can't be called more than once, if I'm not mistaken.
> + igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
> + /*
> + * Tentative value for the number of pages to reserve
> + * in the E820 map for the OpRegion and VBT.
> + *
> + * This will be the final value for the E820 map if
> + * the device model lacks support for OpRegion 2 or
> + * if the host OpRegion version is < 2 or if we never
> + * allocate more pages in the E820 map for the VBT.
> + */
> + igd_opregion_e820_pages = IGD_OPREGION_PAGES;
> +
> + /*
> + * Read the value the device model is initialized with.
> + * If the device model supports OpRegion 2, it will
> + * return the host IGD OpRegion address. If not, it
> + * will return 0. If the device model does not support
> + * OpRegion 2, the device model expects us to give it
> + * the address to which it will map the OpRegion in the
> + * guest and then expects us to do nothing more to setup
> + * the OpRegion, so that is all we will do in that case.
> + */
Hmm, exposing the host opregion to a guest certainly feels like an issue.
> + const uint32_t igd_host_opregion = pci_readl(vga_devfn,
> + PCI_INTEL_OPREGION);
> + if ( !igd_host_opregion ) {
Nit (style) Brace placement (throughout).
> + printf("device model lacks extended VBT "
> + "support. Continuing with legacy support only\n");
This message can easily confuse / worry people. (If it was to be kept, it
would also need style adjustment.)
> + /*
> + * Write the the OpRegion offset to give the OpRegion
> + * address to the device model. The device model will trap
> + * and map the OpRegion at the give address.
> + */
> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
> + igd_opregion_pgbase << PAGE_SHIFT);
> + return;
> + } else {
No need for "else" after an unconditional "return".
> + printf("host OpRegion address: 0x%x\n",
The shorter %#x please (also elsewhere).
> + igd_host_opregion);
> + }
> +
> + const uint32_t igd_host_opregion_page_offset =
> + igd_host_opregion & IGD_OPREGION_MASK;
I think like in the hypervisor we don't want to mix declarations and
statements just yet.
> + igd_guest_opregion = (igd_opregion_pgbase << PAGE_SHIFT) |
> + igd_host_opregion_page_offset;
> +
> + /*
> + * We know at this point the device model supports
> + * OpRegion 2.
> + *
> + * Indicate to the device model that we support
> + * OpRegion 2 by setting the least significant bit
> + * of the address we give to the device model.
> + * The device model will notice this bit set and
> + * respond appropriately to our writes to the
> + * register where the OpRegion address is stored.
> + */
Specifically noticeable here: Please make better use of line length in
long(ish) comments.
> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
> + (igd_opregion_pgbase << PAGE_SHIFT) |
> + IGD_OPREGION2_SUPPORT_MASK);
This looks to imply qemu is the only possible device model.
> + printf("guest OpRegion tentative "
> + "address: 0x%x\n", igd_guest_opregion);
> +
> + if ( !verify_opregion(igd_guest_opregion) ) {
> + printf("error: IGD OpRegion signature "
> + "not found.\n");
No full stop in messages please.
> + BUG();
> + }
> +
> + opregion_scratch = scratch_alloc(IGD_OPREGION_SIZE, 0);
> + memcpy(opregion_scratch, (const void *)igd_guest_opregion,
> + IGD_OPREGION_SIZE);
> +
> + /* Read OpRegion version, rvda_host, and rvds */
> + const uint16_t version = *(uint16_t *)(opregion_scratch +
> + IGD_OPREGION_VERSION);
> + printf("OpRegion version: 0x%x\n", version);
> + if ( version >= 0x0200 ) {
> + rvda_host = *(unsigned long *)(opregion_scratch +
> + IGD_OPREGION_RVDA);
> + /* It is convenient to make rvda_host absolute */
> + if ( version > 0x0200 )
> + rvda_host += igd_host_opregion;
> + printf("host VBT address: 0x%lx\n", rvda_host);
> + } else {
> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
> + rvda_host = 0;
> + }
> + const uint32_t rvda_host_page_offset = rvda_host &
> + IGD_OPREGION_MASK;
Why host_page_offset here when ...
> + const uint32_t rvds = *(uint32_t *)(opregion_scratch +
> + IGD_OPREGION_RVDS);
> + const uint32_t rvds_page_offset = rvds & IGD_OPREGION_MASK;
... it's just page_offset here, and when further you use it below to set
rvda_guest?
> + printf("VBT size: 0x%x\n", rvds);
> +
> + if ( !rvds || !rvda_host ) {
> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
> + rvda_host = 0;
> + }
> + /*
> + * Write rvda_host as 2 successive 32-bit values
> + * to communicate location of the VBT to the device
> + * model. If rvda_host is not 0, The device model
> + * unmaps the OpRegion and eventually maps the VBT
> + * after we also write the guest address where the
> + * VBT will be mapped.
> + *
> + * If we send rvda_host = 0 to the device model, it
> + * will assume we do not need OpRegion 2 support and
> + * it will not unmap the OpRegion.
> + */
> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
> + (uint32_t)(rvda_host & 0xfffffffful));
> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
> + (uint32_t)rvda_host_upper_32);
Why would you need to communicate a host property to the DM?
> + /* In this case, we use the mapped OpRegion */
> + if ( !rvda_host )
> + return;
> +
> + /*
> + * Update the number of pages the device model
> + * needs to map for us to get a copy of the VBT.
> + *
> + * N.B.: Here, igd_opregion_pgbase is really the page
> + * base of the location where the device model will
> + * map the VBT.
> + */
> + uint32_t vbt_pages_needed = rvds >> PAGE_SHIFT;
> + if ( rvds & IGD_OPREGION_MASK )
> + vbt_pages_needed++;
> + if ( vbt_pages_needed > igd_opregion_e820_pages ) {
> + igd_opregion_pgbase = mem_hole_alloc
> + (vbt_pages_needed - igd_opregion_e820_pages);
Nit: Indentation.
> --- a/tools/firmware/hvmloader/pci.c
> +++ b/tools/firmware/hvmloader/pci.c
> @@ -43,7 +43,6 @@ uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
> #define BAR_RELOC_THRESH GB(1)
>
> enum virtual_vga virtual_vga = VGA_none;
> -unsigned long igd_opregion_pgbase = 0;
>
> /* Check if the specified range conflicts with any reserved device memory. */
> static bool check_overlap_all(uint64_t start, uint64_t size)
> @@ -190,14 +189,7 @@ void pci_setup(void)
> virtual_vga = VGA_pt;
> if ( vendor_id == 0x8086 )
> {
> - igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
> - /*
> - * Write the the OpRegion offset to give the opregion
> - * address to the device model. The device model will trap
> - * and map the OpRegion at the give address.
> - */
> - pci_writel(vga_devfn, PCI_INTEL_OPREGION,
> - igd_opregion_pgbase << PAGE_SHIFT);
> + intel_opregion_setup(vga_devfn);
> }
With this preferably also drop the figure braces.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-13 10:35 ` Jan Beulich
@ 2026-08-14 0:45 ` Chuck Zmudzinski
2026-08-14 7:35 ` Jan Beulich
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-14 0:45 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/13/2026 6:35 AM, Jan Beulich wrote:
> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>> -- snip --
>> To address this problem, this patch implements support for
>> Intel IGD devices with an extended VBT and OpRegion version 2
>> and higher which is required for most modern Intel IGD devices.
>
> First of all: Where's the spec of all of this?
Hi Jan,
Thank you for your review.
Well, your first question is quite provocative. Certainly more
social/legal than technical.
I presume by "all this" you mean code in this patch such as:
#define IGD_OPREGION_RVDA 0x3ba
#define IGD_OPREGION_RVDS 0x3c2
#define IGD_OPREGION_VERSION 0x16
which defines the offsets of the rvda, rvds, and version fields from
the base address of the Intel OpRegion.
Also, I presume that "all this" includes the meaning of the 8-byte
rvda value, the meaning of the 4-byte rvds value, and the meaning of
the 2-byte version value.
So my answer is as follows:
I do not have access to the official spec that defines "all this" but
I do have access, as does the general public, to the Linux kernel's
implementation of support for the Intel IGD from many sources such as
git.kernel.org. The Linux kernel has enough accurate information about
the spec of "all this" to provide very good support for the Intel IGD
on bare metal.
To elaborate a bit more, the spec of "all this" can be derived from the
Linux kernel code that supports the Intel IGD. It would certainly be better
to have the official spec from Intel, but alas, as far as I can tell, it
is a proprietary spec that is most likely only available to Intel's OEM
customers who need the spec to write the firmware for these devices. Of
course we could ask Intel for the spec because we write firmware for these
Intel IGD devices too. How do you think that would go? You, as the maintainer
of Xen firmware that (at least implicitly in xl.cfg man pages, etc.) claims
to support the Intel IGD, certainly have the right to ask them for the spec.
Me, as a lowly customer/user of a handful of their devices at most, probably
has less of a right to ask them for the spec.
The situation here is analogous to Xen support for the Processor Properties
Topology Table referenced in a commit that you Acked [1] just a few weeks
ago. I presume you Acked that commit not because it is based on an official,
open spec of the Processor Properties Topology Table that is available to
the public, but because it is based on Linux kernel code that supports
the Processor Properties Topology Table.
[1] https://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=99794c8a8ff8b1d277c09d4736384fd5bb94f2d6
So it was acceptable to use a spec of the Processor Properties Topology
Table derived from Linux kernel code as the basis for a commit to the Xen
codebase just a few weeks ago. Why would it not also be acceptable to use
an updated spec for the Intel IGD OpRegion and VBT derived from Linux kernel
code in the code for tools/hvmloader in the Xen codebase that already
has code that is based on the spec for older versions of the Intel IGD
OpRegion and VBT?
>
>> ---
>>[...]
>>
>> tools/firmware/hvmloader/Makefile | 1 +
>> tools/firmware/hvmloader/config.h | 15 +-
>> tools/firmware/hvmloader/e820.c | 4 +-
>> tools/firmware/hvmloader/intel_opregion.c | 297 ++++++++++++++++++++++
>
> Nit: Please use dashes in favor of underscores in new files' names.
Ok.
>
>> --- a/tools/firmware/hvmloader/Makefile
>> +++ b/tools/firmware/hvmloader/Makefile
>> @@ -35,6 +35,7 @@ OBJS += smp.o cacheattr.o xenbus.o vnuma.o
>> OBJS += e820.o pci.o pir.o ctype.o
>> OBJS += hvm_param.o
>> OBJS += ovmf.o seabios.o
>> +OBJS += intel_opregion.o
>
> While this list isn't well sorted, I think your addition still wants to move
> up by a line.
Ok.
>
>> --- a/tools/firmware/hvmloader/config.h
>> +++ b/tools/firmware/hvmloader/config.h
>> -- snip --
>> #define PAGE_SHIFT 12
>> #define PAGE_SIZE (1ul << PAGE_SHIFT)
>> +#define tools/hvmloader/pci.c3
>> +#define IGD_OPREGION_SIZE ((IGD_OPREGION_PAGES - 1) << PAGE_SHIFT)
>
> This is odd, and hence wants a comment.
Yes, I could add a comment, probably a long one, to explain this
oddity. It is a problem of backward compatibility where we have a
definition, IGD_OPREGION_PAGES, that is currently set to 3 both here
in hvmloader and in the Qemu DM, but should be 2 because the OpRegion
size is really exactly two pages but the current implementation set it
to 3 because the host OpRegion is not always aligned on a 4k page
boundary so three pages are needed to map the entire host OpRegion to
the guest. I could re-write the patch setting IGD_OPREGION_PAGES to 2
and avoid a comment here, but that would complicate the logic of how
igd_opregion_e820_pages is calculated and probably introduce the need
for comments in other places.
I am open to suggestions about how best to handle the backward compatibility
problem and the problem of ensuring compatibility between hvmloader support
for Intel IGD passthrough and DM support for that same feature. For now,
however, I am trying to keep what is applicable to the current implementation,
and this odd value of 3 for IGD_OPREGION_PAGES is one of those things
I am keeping for backward compatibility.
Perhaps the best solution would be to presume there are so few current
users of this feature that we do not need to worry about backward
compatibility and breaking existing setups. I say this because the code
here in hvmloader and in Qemu upstream to support Intel IGD passthrough
is very badly bit rotten and I doubt there are very many, if any, working
implementations currently in the wild based on unpatched vanilla Xen/Qemu
upstream code, particularly with more modern Intel IGD devices and more
recent versions of Qemu. If you give your blessing, then I can rework the
patch without worrying so much about backward compatibility and about what
happens when a guest is configured with a version of hvmloader that has
this patch and a version of the DM that lacks the compatible patch, and vice
versa, that is, when hvmloader lacks support instead of the DM lacking
support. Then we could completely remove this oddity of setting
IGD_OPREGION_PAGES to 3 in the current implementation in both hvmloader
and the Qemu DM as well as many other oddities that result from the current
implementation.
>
>> +#define IGD_OPREGION_RVDA 0x3ba
>> +#define IGD_OPREGION_RVDS 0x3c2
>> +#define IGD_OPREGION_VERSION 0x16
>> +#define IGD_OPREGION_MASK 0xfff
>> +#define IGD_OPREGION2_SUPPORT_MASK 0x1
>> +#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
>> +#define IGD_VBT_SIGNATURE "$VBT"
>> +extern unsigned long igd_opregion_pgbase;
>> +extern uint32_t igd_opregion_e820_pages;
>> +void intel_opregion_setup(uint32_t vga_devfn);
>
> Blank lines please ahead of the new #define-s you add and between those new
> #define-s and the new decls.
>
> For igd_opregion_e820_pages I further cannot spot any use which would justify
> the use of a fixed-width type; unsigned int will do, and will then be in line
> with ./CODING_STYLE.
Ok I will pay more attention to CODING_STYLE. I know that libxl
has a specific CODING_STYLE document. Is there a specific one
for hvmloader? I do not see one in the tools/firmware/hvmloader
directory. I assume the one that matters for hvmloader is the
one at the top level of the Xen code source tree, not the libxl one.
>
>> --- a/tools/firmware/hvmloader/e820.c
>> +++ b/tools/firmware/hvmloader/e820.c
>> @@ -243,11 +243,11 @@ int build_e820_table(struct e820entry *e820,
>> nr++;
>>
>> e820[nr].addr = igd_opregion_base;
>> - e820[nr].size = IGD_OPREGION_PAGES * PAGE_SIZE;
>> + e820[nr].size = igd_opregion_e820_pages * PAGE_SIZE;
>> e820[nr].type = E820_NVS;
>> nr++;
>>
>> - e820[nr].addr = igd_opregion_base + IGD_OPREGION_PAGES * PAGE_SIZE;
>> + e820[nr].addr = igd_opregion_base + igd_opregion_e820_pages * PAGE_SIZE;
>
> Are these new multiplications at risk of overflowing? I.e. how many pages can
> there be in an extreme case?
We are allocating down, so as igd_opregion_e820_pages grows, igd_opregion_base
will shrink. The danger is that igd_opregion_base will go below the minimum
possible value that is compatible with our memory map. I could add a check for
that. I think our memory map allows for tens if not hundreds of pages in the
region where the OpRegion and VBT are located, and typically the OpRegion + VBT
is only about 4 or 5 pages. It should probably be a BUG() if somehow we detected
a VBT whose size was large enough to cause this problem.
>
>> --- /dev/null
>> +++ b/tools/firmware/hvmloader/intel_opregion.c
>> @@ -0,0 +1,297 @@
>> +/*
>> + * intel_opregion.c: HVM Intel OpRegion setup.
>> + *
>> + * Leendert van Doorn, leendert@watson.ibm.com
>> + * Copyright (c) 2005, International Business Machines Corporation.
>> + *
>> + * Copyright (c) 2006, Keir Fraser, XenSource Inc.
>
> What do these cover?
I am considering this new file to be a modified/derived version of
tools/hvmloader/pci.c, so if I understand correctly this file needs
to retain the copyright information of tools/hvmloader/pci.c. At the
very least, the #include statements at the top of this new file which
are from tools/hvmloader/pci.c are covered by these copyrights. I also
consider the statements that are moved from tools/hvmloader/pci.c to
this new file to be covered by these copyrights. IANAL, so to be safe,
I include these copyrights even though the covered code is relatively
small compared to the rest of the file.
>
>> + * Copyright (c) 2026, Charles Zmudzinski.
>> + * -- snip --
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program; If not, see <http://www.gnu.org/licenses/>.
>> + */
>
> Please use an SPDX line instead in new files.
OK.
>
>> +#include "util.h"
>> +#include "config.h"
>> +#include "pci_regs.h"
>> +
>> +unsigned long igd_opregion_pgbase = 0;
>> +uint32_t igd_opregion_e820_pages = IGD_OPREGION_PAGES;
>> +
>> +static bool verify_opregion(const uint32_t addr)
>> +{
>> + const char *opregion_signature = IGD_OPREGION_SIGNATURE;
>> + if ( memcmp((const void *)addr, (const void *)opregion_signature, 16) )
>> + return false;
>> + return true;
>> +}
>
> Style: Blank line please between declaration(s) and statement(s) as well as
> ahead of the main "return" of a function. There further isn't really a need
> for an if() or two return statements here. Also please avoid casts wherever
> possible. Finally, the local variable isn't really needed here either - the
> string literal can be passed directly to memcmp(). All of this helps
> readability as well.
OK.
>
>> +static bool verify_vbt(const uint32_t addr)
>> +{
>> + const char *vbt_signature = IGD_VBT_SIGNATURE;
>> + if ( memcmp((const void *)addr, (const void *)vbt_signature, 4) )
>> + return false;
>> + return true;
>> +}
>
> Same comments here, obviously (and potentially elsewhere).
OK.
>
>> +void intel_opregion_setup(uint32_t vga_devfn)
>> +{
>> + uint32_t igd_guest_opregion;
>> + uint32_t pages_needed; /* for OpRegion + VBT */
>
> The former probably wants to be fixed-width, but for the latter I see no need.
OK.
>
>> + void *opregion_scratch;
>> + void *vbt_scratch;
>> + void *vbt_source;
>> + /*
>> + * absolute value in the host/guest except
>> + * as noted in the comments
>> + */
>
> Nit: Comment style (see ./CODING_STYLE).
OK.
>
>> + static unsigned long rvda_host;
>> + static unsigned long rvda_guest;
>
> Why static? The function can't be called more than once, if I'm not mistaken.
I think you are right that we only do the setup once so I will
drop static here. I still think if I drop static I will want to
initialize these to zero later, because (correct me if I am wrong)
only static variables are initialized to zero if not explicitly
initialized, and without either static or an initialized value,
these would be initialized to some undetermined random value
until explicitly set to the desired initial value. Of the two,
I think that the more important one to intitialize to zero is
rvda_host, because I use an initial value of zero for that variable
to test for the case when we do not need extended VBT support.
>
>> + igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
>> + /*
>> + * Tentative value for the number of pages to reserve
>> + * in the E820 map for the OpRegion and VBT.
>> + *
>> + * This will be the final value for the E820 map if
>> + * the device model lacks support for OpRegion 2 or
>> + * if the host OpRegion version is < 2 or if we never
>> + * allocate more pages in the E820 map for the VBT.
>> + */
>> + igd_opregion_e820_pages = IGD_OPREGION_PAGES;
>> +
>> + /*
>> + * Read the value the device model is initialized with.
>> + * If the device model supports OpRegion 2, it will
>> + * return the host IGD OpRegion address. If not, it
>> + * will return 0. If the device model does not support
>> + * OpRegion 2, the device model expects us to give it
>> + * the address to which it will map the OpRegion in the
>> + * guest and then expects us to do nothing more to setup
>> + * the OpRegion, so that is all we will do in that case.
>> + */
>
> Hmm, exposing the host opregion to a guest certainly feels like an issue.
Well, that is how it is now. I am only retaining it to maintain backward
compatiblily with DM versions that do not support the extended VBT and
OpRegion 2+. My previous comment about backward compatibilty and DM
compatibility also applies here. If we don't worry about that, we can do
away with any cases where we are permanently mapping the host opregion to
the guest and implement this new approach of always exposing a copy of
the OpRegion and VBT to the guest instead.
>
>> + const uint32_t igd_host_opregion = pci_readl(vga_devfn,
>> + PCI_INTEL_OPREGION);
>> + if ( !igd_host_opregion ) {
>
> Nit (style) Brace placement (throughout).
Ok. I see this is not the proper coding style.
>
>> + printf("device model lacks extended VBT "
>> + "support. Continuing with legacy support only\n");
>
> This message can easily confuse / worry people. (If it was to be kept, it
> would also need style adjustment.)
I think some message is needed here to indicate the incompatibility of
versions of the DM that do not support the extended VBT with versions
of hvmloader that do, especially if we are not going to worry as much
about the backward compatibility / DM compatibility problem I mentioned
multiple times in previous comments above.
This message could encourage upgrading the DM to a version that supports
the extended VBT instead of just giving this scary notification.
Also, I will more carefully read CODING_STYLE and try to fix all those
issues you have pointed out (and any others I might find).
>
>> + /*
>> + * Write the the OpRegion offset to give the OpRegion
>> + * address to the device model. The device model will trap
>> + * and map the OpRegion at the give address.
>> + */
>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>> + igd_opregion_pgbase << PAGE_SHIFT);
>> + return;
>> + } else {
>
> No need for "else" after an unconditional "return".
Ok.
>
>> + printf("host OpRegion address: 0x%x\n",
>
> The shorter %#x please (also elsewhere).
Ok.
>
>> + igd_host_opregion);
>> + }
>> +
>> + const uint32_t igd_host_opregion_page_offset =
>> + igd_host_opregion & IGD_OPREGION_MASK;
>
> I think like in the hypervisor we don't want to mix declarations and
> statements just yet.
The only way I could separate the declaration from the statement would be
to drop the const modifier because if I do:
const uint32_t igd_host_opregion_page_offset;
...
igd_host_opregion_page_offset = igd_host_opregion &
IGD_OPREGION_MASK;
The compiler will report an error. If I drop the const modifier from
the declaration, the compiler will not report an error but I lose the
protection the compiler gives me from making mistakes by modifying a
variable's value that should be constant.
I am not a C guru but some research indicates that while it is legal in
C to declare a variable with the const modifier without also assigning
it a value at the same time with a statement, it is not recommended to
do this because the variable will be initialized with some undefined
random value that cannot be changed because we used the const modifier
in the declaration. This implies strict enforcemnt of the rule "we
don't mix declarations and statements" results also in the corollary
rule "we never use the const modifier for variables in C."
>
>> + igd_guest_opregion = (igd_opregion_pgbase << PAGE_SHIFT) |
>> + igd_host_opregion_page_offset;
>> +
>> + /*
>> + * We know at this point the device model supports
>> + * OpRegion 2.
>> + *
>> + * Indicate to the device model that we support
>> + * OpRegion 2 by setting the least significant bit
>> + * of the address we give to the device model.
>> + * The device model will notice this bit set and
>> + * respond appropriately to our writes to the
>> + * register where the OpRegion address is stored.
>> + */
>
> Specifically noticeable here: Please make better use of line length in
> long(ish) comments.
Ok.
>
>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>> + IGD_OPREGION2_SUPPORT_MASK);
>
> This looks to imply qemu is the only possible device model.
Yeah, this is an issue. Other device models that intend to support
the Intel IGD with hvmloader will also have to be compatible with this.
It would be easier if we did not have to worry about backward
compatibility and supporting what we had in the codebase for many years
in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
in that case. Instead, we would just completely deprecate all previous
implementations of the Intel IGD passthrough feature in both hvmloader and
the Qemu DM as unsupported. So my previous comments about backward
compatibility apply here again.
>
>> + printf("guest OpRegion tentative "
>> + "address: 0x%x\n", igd_guest_opregion);
>> +
>> + if ( !verify_opregion(igd_guest_opregion) ) {
>> + printf("error: IGD OpRegion signature "
>> + "not found.\n");
>
> No full stop in messages please.
Would it be OK to just get rid of the error message here?
>
>> + BUG();
>> + }
>> + --snip --
>> + rvda_host = 0;
>> + }
>> + const uint32_t rvda_host_page_offset = rvda_host &
>> + IGD_OPREGION_MASK;
>
> Why host_page_offset here when ...
>
>> + const uint32_t rvds = *(uint32_t *)(opregion_scratch +
>> + IGD_OPREGION_RVDS);
>> + const uint32_t rvds_page_offset = rvds & IGD_OPREGION_MASK;
>
> ... it's just page_offset here, and when further you use it below to set
> rvda_guest?
The size of the VBT, rvds, is the same on both host and guest, so we do not
need to specify host or guest, but the base address of the VBT, rvda, is
not the same on the guest as it is on the host, so we need to specify which
one for rvda. I can change this to rvds_host_page_offset because it is
not wrong, but it might be confusing because I use that value later on
for computations involving the guest also.
Actually, I only use rvds_page_offset below to help decide whether or not to
retain the host OpRegion page offset in the guest. I don't know if this is
necessary, though, and I could test without retaining the same page offset in
the guest and always place the both the OpRegion and the VBT on a page
boundary in the guest (if I place the OpRegion on a page boundary and
also always place the VBT contiguous after the OpRegion, the VBT will
always be placed exactly two pages after the base of the OpRegion and thus
also on a page boundary). All the devices I test have enough room to retain
the page offset of the host in the guest without requiring allocation of
an extra page, so if there are regressions I will notice them in my testing.
If always placing OpRegion and VBT on a page boundary works with no regressions,
then I could completely remove rvds_page_offset from the code. I will still
need rvda_host_page_offset though, because it is needed to get the exact
location of the VBT in the guest when the DM temporarily maps the host VBT
to the guest.
>
>> + printf("VBT size: 0x%x\n", rvds);
>> +
>> + if ( !rvds || !rvda_host ) {
>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>> + rvda_host = 0;
>> + }
>> + /*
>> + * Write rvda_host as 2 successive 32-bit values
>> + * to communicate location of the VBT to the device
>> + * model. If rvda_host is not 0, The device model
>> + * unmaps the OpRegion and eventually maps the VBT
>> + * after we also write the guest address where the
>> + * VBT will be mapped.
>> + *
>> + * If we send rvda_host = 0 to the device model, it
>> + * will assume we do not need OpRegion 2 support and
>> + * it will not unmap the OpRegion.
>> + */
>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>> + (uint32_t)(rvda_host & 0xfffffffful));
>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>> + (uint32_t)rvda_host_upper_32);
>
> Why would you need to communicate a host property to the DM?
The DM cannot access the host rvda value because it is only accessible
from the host kernel, and the DM is only a user-space process on the host.
The KVM/vfio solution is to have the kernel vfio driver provide rvda to
Qemu, and I think it would be possible for the xen-pciback kernel driver
to also expose rvda to the DM, but that would likely require patches to
the kernel xen-pciback driver and probably also to libxl or other toolstack
which uses QMP to plug the Xen PCI passthrough devices into the PCI bus
provided by the DM. This solution avoids needing to touch libxl and kernel
drivers.
>
>> + /* In this case, we use the mapped OpRegion */
>> + if ( !rvda_host )
>> + return;
>> +
>> + /*
>> + * Update the number of pages the device model
>> + * needs to map for us to get a copy of the VBT.
>> + *
>> + * N.B.: Here, igd_opregion_pgbase is really the page
>> + * base of the location where the device model will
>> + * map the VBT.
>> + */
>> + uint32_t vbt_pages_needed = rvds >> PAGE_SHIFT;
>> + if ( rvds & IGD_OPREGION_MASK )
>> + vbt_pages_needed++;
>> + if ( vbt_pages_needed > igd_opregion_e820_pages ) {
>> + igd_opregion_pgbase = mem_hole_alloc
>> + (vbt_pages_needed - igd_opregion_e820_pages);
>
> Nit: Indentation.
Ok. It should always be a multiple of four spaces, I presume. I admit I did
not check that.
>
>> --- a/tools/firmware/hvmloader/pci.c
>> +++ b/tools/firmware/hvmloader/pci.c
>> @@ -43,7 +43,6 @@ uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0;
>> #define BAR_RELOC_THRESH GB(1)
>>
>> enum virtual_vga virtual_vga = VGA_none;
>> -unsigned long igd_opregion_pgbase = 0;
>>
>> /* Check if the specified range conflicts with any reserved device memory. */
>> static bool check_overlap_all(uint64_t start, uint64_t size)
>> @@ -190,14 +189,7 @@ void pci_setup(void)
>> virtual_vga = VGA_pt;
>> if ( vendor_id == 0x8086 )
>> {
>> - igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
>> - /*
>> - * Write the the OpRegion offset to give the opregion
>> - * address to the device model. The device model will trap
>> - * and map the OpRegion at the give address.
>> - */
>> - pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>> - igd_opregion_pgbase << PAGE_SHIFT);
>> + intel_opregion_setup(vga_devfn);
>> }
>
> With this preferably also drop the figure braces.
Ok.
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 0:45 ` Chuck Zmudzinski
@ 2026-08-14 7:35 ` Jan Beulich
2026-08-14 13:18 ` Chuck Zmudzinski
2026-08-16 16:38 ` Chuck Zmudzinski
0 siblings, 2 replies; 42+ messages in thread
From: Jan Beulich @ 2026-08-14 7:35 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 14.08.2026 02:45, Chuck Zmudzinski wrote:
> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>> -- snip --
>>> To address this problem, this patch implements support for
>>> Intel IGD devices with an extended VBT and OpRegion version 2
>>> and higher which is required for most modern Intel IGD devices.
>>
>> First of all: Where's the spec of all of this?
>
> Well, your first question is quite provocative. Certainly more
> social/legal than technical.
Well, it was very much meant to be technical. I've had a hard time following
what your new code does, and having a spec to hand would likely have helped.
> I presume by "all this" you mean code in this patch such as:
>
> #define IGD_OPREGION_RVDA 0x3ba
> #define IGD_OPREGION_RVDS 0x3c2
> #define IGD_OPREGION_VERSION 0x16
>
> which defines the offsets of the rvda, rvds, and version fields from
> the base address of the Intel OpRegion.
>
> Also, I presume that "all this" includes the meaning of the 8-byte
> rvda value, the meaning of the 4-byte rvds value, and the meaning of
> the 2-byte version value.
"All this" certainly goes beyond this, i.e. also covering the intended
interactions.
> So my answer is as follows:
>
> I do not have access to the official spec that defines "all this" but
> I do have access, as does the general public, to the Linux kernel's
> implementation of support for the Intel IGD from many sources such as
> git.kernel.org. The Linux kernel has enough accurate information about
> the spec of "all this" to provide very good support for the Intel IGD
> on bare metal.
>
> To elaborate a bit more, the spec of "all this" can be derived from the
> Linux kernel code that supports the Intel IGD.
So you expect every reader to locate and decipher the underlying information
from a (afaik) pretty large piece of code in the Linux kernel? If the Linux
kernel sources are the reference, please can you at least provide pointers
into there?
>>> --- a/tools/firmware/hvmloader/config.h
>>> +++ b/tools/firmware/hvmloader/config.h
>>> -- snip --
>>> #define PAGE_SHIFT 12
>>> #define PAGE_SIZE (1ul << PAGE_SHIFT)
>>> +#define tools/hvmloader/pci.c3
>>> +#define IGD_OPREGION_SIZE ((IGD_OPREGION_PAGES - 1) << PAGE_SHIFT)
>>
>> This is odd, and hence wants a comment.
>
> Yes, I could add a comment, probably a long one, to explain this
> oddity. It is a problem of backward compatibility where we have a
> definition, IGD_OPREGION_PAGES, that is currently set to 3 both here
> in hvmloader and in the Qemu DM, but should be 2 because the OpRegion
> size is really exactly two pages but the current implementation set it
> to 3 because the host OpRegion is not always aligned on a 4k page
> boundary so three pages are needed to map the entire host OpRegion to
> the guest. I could re-write the patch setting IGD_OPREGION_PAGES to 2
> and avoid a comment here, but that would complicate the logic of how
> igd_opregion_e820_pages is calculated and probably introduce the need
> for comments in other places.
>
> I am open to suggestions about how best to handle the backward compatibility
> problem and the problem of ensuring compatibility between hvmloader support
> for Intel IGD passthrough and DM support for that same feature. For now,
> however, I am trying to keep what is applicable to the current implementation,
> and this odd value of 3 for IGD_OPREGION_PAGES is one of those things
> I am keeping for backward compatibility.
Personally I don't view breaking backward compatibility as an option. Hence
a comment is going to be needed, and preferably not an overly long one.
>>> +#define IGD_OPREGION_RVDA 0x3ba
>>> +#define IGD_OPREGION_RVDS 0x3c2
>>> +#define IGD_OPREGION_VERSION 0x16
>>> +#define IGD_OPREGION_MASK 0xfff
>>> +#define IGD_OPREGION2_SUPPORT_MASK 0x1
>>> +#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
>>> +#define IGD_VBT_SIGNATURE "$VBT"
>>> +extern unsigned long igd_opregion_pgbase;
>>> +extern uint32_t igd_opregion_e820_pages;
>>> +void intel_opregion_setup(uint32_t vga_devfn);
>>
>> Blank lines please ahead of the new #define-s you add and between those new
>> #define-s and the new decls.
>>
>> For igd_opregion_e820_pages I further cannot spot any use which would justify
>> the use of a fixed-width type; unsigned int will do, and will then be in line
>> with ./CODING_STYLE.
>
> Ok I will pay more attention to CODING_STYLE. I know that libxl
> has a specific CODING_STYLE document. Is there a specific one
> for hvmloader? I do not see one in the tools/firmware/hvmloader
> directory. I assume the one that matters for hvmloader is the
> one at the top level of the Xen code source tree, not the libxl one.
Yes, hvmloader follows (better: ought to follow) hypervisor style.
>>> --- /dev/null
>>> +++ b/tools/firmware/hvmloader/intel_opregion.c
>>> @@ -0,0 +1,297 @@
>>> +/*
>>> + * intel_opregion.c: HVM Intel OpRegion setup.
>>> + *
>>> + * Leendert van Doorn, leendert@watson.ibm.com
>>> + * Copyright (c) 2005, International Business Machines Corporation.
>>> + *
>>> + * Copyright (c) 2006, Keir Fraser, XenSource Inc.
>>
>> What do these cover?
>
> I am considering this new file to be a modified/derived version of
> tools/hvmloader/pci.c, so if I understand correctly this file needs
> to retain the copyright information of tools/hvmloader/pci.c. At the
> very least, the #include statements at the top of this new file which
> are from tools/hvmloader/pci.c are covered by these copyrights. I also
> consider the statements that are moved from tools/hvmloader/pci.c to
> this new file to be covered by these copyrights. IANAL, so to be safe,
> I include these copyrights even though the covered code is relatively
> small compared to the rest of the file.
Nowadays our preferred option is to omit such copyright statements
altogether, but we wouldn't insist on the omission. I further don't think
#include-s are copyrightable.
>>> + static unsigned long rvda_host;
>>> + static unsigned long rvda_guest;
>>
>> Why static? The function can't be called more than once, if I'm not mistaken.
>
> I think you are right that we only do the setup once so I will
> drop static here. I still think if I drop static I will want to
> initialize these to zero later, because (correct me if I am wrong)
> only static variables are initialized to zero if not explicitly
> initialized, and without either static or an initialized value,
> these would be initialized to some undetermined random value
> until explicitly set to the desired initial value. Of the two,
> I think that the more important one to intitialize to zero is
> rvda_host, because I use an initial value of zero for that variable
> to test for the case when we do not need extended VBT support.
Well, like all variables, these ones also will need to be sensibly
initialized. That's entirely unrelated to the use of static; all
static gets you in this regard is that there's implicit default
initialization. Yet that alone is no reason to use static.
>>> + igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
>>> + /*
>>> + * Tentative value for the number of pages to reserve
>>> + * in the E820 map for the OpRegion and VBT.
>>> + *
>>> + * This will be the final value for the E820 map if
>>> + * the device model lacks support for OpRegion 2 or
>>> + * if the host OpRegion version is < 2 or if we never
>>> + * allocate more pages in the E820 map for the VBT.
>>> + */
>>> + igd_opregion_e820_pages = IGD_OPREGION_PAGES;
>>> +
>>> + /*
>>> + * Read the value the device model is initialized with.
>>> + * If the device model supports OpRegion 2, it will
>>> + * return the host IGD OpRegion address. If not, it
>>> + * will return 0. If the device model does not support
>>> + * OpRegion 2, the device model expects us to give it
>>> + * the address to which it will map the OpRegion in the
>>> + * guest and then expects us to do nothing more to setup
>>> + * the OpRegion, so that is all we will do in that case.
>>> + */
>>
>> Hmm, exposing the host opregion to a guest certainly feels like an issue.
>
> Well, that is how it is now. I am only retaining it to maintain backward
> compatiblily with DM versions that do not support the extended VBT and
> OpRegion 2+. My previous comment about backward compatibilty and DM
> compatibility also applies here. If we don't worry about that, we can do
> away with any cases where we are permanently mapping the host opregion to
> the guest and implement this new approach of always exposing a copy of
> the OpRegion and VBT to the guest instead.
How does "permanently mapping" matter? hvmloader runs inside the guest, so
exposure just to copy the data isn't any better in terms of this being a
layering violation. The more correct thing to do might be for the DM to
put in place a copy before the guest (i.e. hvmloader) even gains control.
(How in turn the DM would learn of the contents of the opregion is a
separate question then.)
>>> + const uint32_t igd_host_opregion = pci_readl(vga_devfn,
>>> + PCI_INTEL_OPREGION);
>>> + if ( !igd_host_opregion ) {
>>
>> Nit (style) Brace placement (throughout).
>
> Ok. I see this is not the proper coding style.
>
>>
>>> + printf("device model lacks extended VBT "
>>> + "support. Continuing with legacy support only\n");
>>
>> This message can easily confuse / worry people. (If it was to be kept, it
>> would also need style adjustment.)
>
> I think some message is needed here to indicate the incompatibility of
> versions of the DM that do not support the extended VBT with versions
> of hvmloader that do, especially if we are not going to worry as much
> about the backward compatibility / DM compatibility problem I mentioned
> multiple times in previous comments above.
>
> This message could encourage upgrading the DM to a version that supports
> the extended VBT instead of just giving this scary notification.
But someone expecting legacy behavior could be misguided by the message
(e.g. into wondering whether there's something wrong.)
>>> + const uint32_t igd_host_opregion_page_offset =
>>> + igd_host_opregion & IGD_OPREGION_MASK;
>>
>> I think like in the hypervisor we don't want to mix declarations and
>> statements just yet.
>
> The only way I could separate the declaration from the statement would be
> to drop the const modifier because if I do:
>
> const uint32_t igd_host_opregion_page_offset;
> ...
> igd_host_opregion_page_offset = igd_host_opregion &
> IGD_OPREGION_MASK;
>
> The compiler will report an error. If I drop the const modifier from
> the declaration, the compiler will not report an error but I lose the
> protection the compiler gives me from making mistakes by modifying a
> variable's value that should be constant.
>
> I am not a C guru but some research indicates that while it is legal in
> C to declare a variable with the const modifier without also assigning
> it a value at the same time with a statement, it is not recommended to
> do this because the variable will be initialized with some undefined
> random value that cannot be changed because we used the const modifier
> in the declaration. This implies strict enforcemnt of the rule "we
> don't mix declarations and statements" results also in the corollary
> rule "we never use the const modifier for variables in C."
Indeed we rarely use const on variables (or parameters) themselves. It's
primary use is on pointed-to types.
>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>>> + IGD_OPREGION2_SUPPORT_MASK);
>>
>> This looks to imply qemu is the only possible device model.
>
> Yeah, this is an issue. Other device models that intend to support
> the Intel IGD with hvmloader will also have to be compatible with this.
> It would be easier if we did not have to worry about backward
> compatibility and supporting what we had in the codebase for many years
> in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
> in that case. Instead, we would just completely deprecate all previous
> implementations of the Intel IGD passthrough feature in both hvmloader and
> the Qemu DM as unsupported. So my previous comments about backward
> compatibility apply here again.
As said, I don't think backward compatibility can be dropped. My comment
also didn't really mean to hint in that direction. Instead I was wondering
in how far, even if perhaps by only a few #define-s, the necessary
interfacing couldn't be put down in a public header, for any DM to consume.
>>> + printf("guest OpRegion tentative "
>>> + "address: 0x%x\n", igd_guest_opregion);
>>> +
>>> + if ( !verify_opregion(igd_guest_opregion) ) {
>>> + printf("error: IGD OpRegion signature "
>>> + "not found.\n");
>>
>> No full stop in messages please.
>
> Would it be OK to just get rid of the error message here?
That would then leave ...
>>> + BUG();
... an un-annotated BUG(), which generally isn't very nice.
>>> + }
>>> + --snip --
>>> + rvda_host = 0;
>>> + }
>>> + const uint32_t rvda_host_page_offset = rvda_host &
>>> + IGD_OPREGION_MASK;
>>
>> Why host_page_offset here when ...
>>
>>> + const uint32_t rvds = *(uint32_t *)(opregion_scratch +
>>> + IGD_OPREGION_RVDS);
>>> + const uint32_t rvds_page_offset = rvds & IGD_OPREGION_MASK;
>>
>> ... it's just page_offset here, and when further you use it below to set
>> rvda_guest?
>
> The size of the VBT, rvds, is the same on both host and guest, so we do not
> need to specify host or guest, but the base address of the VBT, rvda, is
> not the same on the guest as it is on the host, so we need to specify which
> one for rvda. I can change this to rvds_host_page_offset because it is
> not wrong, but it might be confusing because I use that value later on
> for computations involving the guest also.
Why not simply drop the "host" infix, when it's not relevant?
>>> + printf("VBT size: 0x%x\n", rvds);
>>> +
>>> + if ( !rvds || !rvda_host ) {
>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>> + rvda_host = 0;
>>> + }
>>> + /*
>>> + * Write rvda_host as 2 successive 32-bit values
>>> + * to communicate location of the VBT to the device
>>> + * model. If rvda_host is not 0, The device model
>>> + * unmaps the OpRegion and eventually maps the VBT
>>> + * after we also write the guest address where the
>>> + * VBT will be mapped.
>>> + *
>>> + * If we send rvda_host = 0 to the device model, it
>>> + * will assume we do not need OpRegion 2 support and
>>> + * it will not unmap the OpRegion.
>>> + */
>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>> + (uint32_t)rvda_host_upper_32);
>>
>> Why would you need to communicate a host property to the DM?
>
> The DM cannot access the host rvda value because it is only accessible
> from the host kernel, and the DM is only a user-space process on the host.
I don't follow this: Anything the guest can access should also be accessible
by its DM.
>>> + /*
>>> + * Update the number of pages the device model
>>> + * needs to map for us to get a copy of the VBT.
>>> + *
>>> + * N.B.: Here, igd_opregion_pgbase is really the page
>>> + * base of the location where the device model will
>>> + * map the VBT.
>>> + */
>>> + uint32_t vbt_pages_needed = rvds >> PAGE_SHIFT;
>>> + if ( rvds & IGD_OPREGION_MASK )
>>> + vbt_pages_needed++;
>>> + if ( vbt_pages_needed > igd_opregion_e820_pages ) {
>>> + igd_opregion_pgbase = mem_hole_alloc
>>> + (vbt_pages_needed - igd_opregion_e820_pages);
>>
>> Nit: Indentation.
>
> Ok. It should always be a multiple of four spaces, I presume. I admit I did
> not check that.
Not quite. Within a wrapped expression, you need to determine what I like
to call the "anchor point". In a function call that's the start of the
function name. The wrapped part of the expression would then start one
extra level (4 spaces) deeper than the anchor point. Things are different
when there are pending open parentheses: There the wrapped part of an
expression starts with as many extra spaces as there are pending open
parentheses, with the outermost pending open parenthesis being the anchor
point. E.g. (taking the example above and adding extra wrapping in the
function argument expression just for demonstration purposes):
igd_opregion_pgbase = mem_hole_alloc
(vbt_pages_needed -
igd_opregion_e820_pages);
Or alternatively
igd_opregion_pgbase =
mem_hole_alloc(vbt_pages_needed - igd_opregion_e820_pages);
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 7:35 ` Jan Beulich
@ 2026-08-14 13:18 ` Chuck Zmudzinski
2026-08-14 13:46 ` Jan Beulich
2026-08-16 16:38 ` Chuck Zmudzinski
1 sibling, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-14 13:18 UTC (permalink / raw)
To: Jan Beulich, Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/14/2026 3:35 AM, Jan Beulich wrote:
> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>> -- snip --
>>>> To address this problem, this patch implements support for
>>>> Intel IGD devices with an extended VBT and OpRegion version 2
>>>> and higher which is required for most modern Intel IGD devices.
>>>
>>> First of all: Where's the spec of all of this?
>>
>> Well, your first question is quite provocative. Certainly more
>> social/legal than technical.
>
> Well, it was very much meant to be technical. I've had a hard time following
> what your new code does, and having a spec to hand would likely have helped.
I agree that having the spec at hand would be better. To be more precise, I
can say that what this patch essentially does is port the support for
the extended VBT with OpRegion 2+ for the Intel IGD passthrough that exists
in KVM/vfio to Xen. Should I explicitly say in the title of the commit
message that this is a port of KVM/vfio support for extended VBT to Xen?
>
>> I presume by "all this" you mean code in this patch such as:
>>
>> #define IGD_OPREGION_RVDA 0x3ba
>> #define IGD_OPREGION_RVDS 0x3c2
>> #define IGD_OPREGION_VERSION 0x16
>>
>> which defines the offsets of the rvda, rvds, and version fields from
>> the base address of the Intel OpRegion.
>>
>> Also, I presume that "all this" includes the meaning of the 8-byte
>> rvda value, the meaning of the 4-byte rvds value, and the meaning of
>> the 2-byte version value.
>
> "All this" certainly goes beyond this, i.e. also covering the intended
> interactions.
>
>> So my answer is as follows:
>>
>> I do not have access to the official spec that defines "all this" but
>> I do have access, as does the general public, to the Linux kernel's
>> implementation of support for the Intel IGD from many sources such as
>> git.kernel.org. The Linux kernel has enough accurate information about
>> the spec of "all this" to provide very good support for the Intel IGD
>> on bare metal.
>>
>> To elaborate a bit more, the spec of "all this" can be derived from the
>> Linux kernel code that supports the Intel IGD.
>
> So you expect every reader to locate and decipher the underlying information
> from a (afaik) pretty large piece of code in the Linux kernel? If the Linux
> kernel sources are the reference, please can you at least provide pointers
> into there?
No, I do not expect every reader to decipher the underlying information...
That is why I provided these two links at the bottom of the commit message.
Perhaps you did not notice them:
Link: https://lore.kernel.org/kvm/20211012124855.52463-1-colin.xu@gmail.com/
Link: https://lore.kernel.org/kvm/20210325170953.24549-1-fred.gao@intel.com/
They are the patches to the vfio kernel driver that added support for the
extended VBT for KVM/vfio guests. I could provide links to more patches, such
as the ones in Qemu, Seabios, and patches provided by Intel to support extended
VBT in builds of OVMF for the Qemu/KVM platform, but I thought the two patches
above are sufficient for the purpose of this patch. For example, in those patches,
the #defines I added to config.h in hvmloader are included in the two links
I added to the bottom of the commit message.
I think adding more patches to the commit message would make it more difficult to
decipher the essential information needed to do this port of support from KVM/vfio
to Xen. Those two patches are not so large and they do provide the information
needed to add support for the extended VBT on a virtualization platform such
as KVM or Xen. How best to implement such support for the current Xen platform
is what we should focus on in these discussion.
>
>>>> --- a/tools/firmware/hvmloader/config.h
>>>> +++ b/tools/firmware/hvmloader/config.h
>>>> -- snip --
>>>> #define PAGE_SHIFT 12
>>>> #define PAGE_SIZE (1ul << PAGE_SHIFT)
>>>> +#define tools/hvmloader/pci.c3
>>>> +#define IGD_OPREGION_SIZE ((IGD_OPREGION_PAGES - 1) << PAGE_SHIFT)
>>>
>>> This is odd, and hence wants a comment.
>>
>> Yes, I could add a comment, probably a long one, to explain this
>> oddity. It is a problem of backward compatibility where we have a
>> definition, IGD_OPREGION_PAGES, that is currently set to 3 both here
>> in hvmloader and in the Qemu DM, but should be 2 because the OpRegion
>> size is really exactly two pages but the current implementation set it
>> to 3 because the host OpRegion is not always aligned on a 4k page
>> boundary so three pages are needed to map the entire host OpRegion to
>> the guest. I could re-write the patch setting IGD_OPREGION_PAGES to 2
>> and avoid a comment here, but that would complicate the logic of how
>> igd_opregion_e820_pages is calculated and probably introduce the need
>> for comments in other places.
>>
>> I am open to suggestions about how best to handle the backward compatibility
>> problem and the problem of ensuring compatibility between hvmloader support
>> for Intel IGD passthrough and DM support for that same feature. For now,
>> however, I am trying to keep what is applicable to the current implementation,
>> and this odd value of 3 for IGD_OPREGION_PAGES is one of those things
>> I am keeping for backward compatibility.
>
> Personally I don't view breaking backward compatibility as an option. Hence
> a comment is going to be needed, and preferably not an overly long one.
OK.
>
>>>> +#define IGD_OPREGION_RVDA 0x3ba
>>>> +#define IGD_OPREGION_RVDS 0x3c2
>>>> +#define IGD_OPREGION_VERSION 0x16
>>>> +#define IGD_OPREGION_MASK 0xfff
>>>> +#define IGD_OPREGION2_SUPPORT_MASK 0x1
>>>> +#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
>>>> +#define IGD_VBT_SIGNATURE "$VBT"
>>>> +extern unsigned long igd_opregion_pgbase;
>>>> +extern uint32_t igd_opregion_e820_pages;
>>>> +void intel_opregion_setup(uint32_t vga_devfn);
>>>
>>> Blank lines please ahead of the new #define-s you add and between those new
>>> #define-s and the new decls.
>>>
>>> For igd_opregion_e820_pages I further cannot spot any use which would justify
>>> the use of a fixed-width type; unsigned int will do, and will then be in line
>>> with ./CODING_STYLE.
>>
>> Ok I will pay more attention to CODING_STYLE. I know that libxl
>> has a specific CODING_STYLE document. Is there a specific one
>> for hvmloader? I do not see one in the tools/firmware/hvmloader
>> directory. I assume the one that matters for hvmloader is the
>> one at the top level of the Xen code source tree, not the libxl one.
>
> Yes, hvmloader follows (better: ought to follow) hypervisor style.
OK.
>
>
>>>> --- /dev/null
>>>> +++ b/tools/firmware/hvmloader/intel_opregion.c
>>>> @@ -0,0 +1,297 @@
>>>> +/*
>>>> + * intel_opregion.c: HVM Intel OpRegion setup.
>>>> + *
>>>> + * Leendert van Doorn, leendert@watson.ibm.com
>>>> + * Copyright (c) 2005, International Business Machines Corporation.
>>>> + *
>>>> + * Copyright (c) 2006, Keir Fraser, XenSource Inc.
>>>
>>> What do these cover?
>>
>> I am considering this new file to be a modified/derived version of
>> tools/hvmloader/pci.c, so if I understand correctly this file needs
>> to retain the copyright information of tools/hvmloader/pci.c. At the
>> very least, the #include statements at the top of this new file which
>> are from tools/hvmloader/pci.c are covered by these copyrights. I also
>> consider the statements that are moved from tools/hvmloader/pci.c to
>> this new file to be covered by these copyrights. IANAL, so to be safe,
>> I include these copyrights even though the covered code is relatively
>> small compared to the rest of the file.
>
> Nowadays our preferred option is to omit such copyright statements
> altogether, but we wouldn't insist on the omission. I further don't think
> #include-s are copyrightable.
Ok.
>
>>>> + static unsigned long rvda_host;
>>>> + static unsigned long rvda_guest;
>>>
>>> Why static? The function can't be called more than once, if I'm not mistaken.
>>
>> I think you are right that we only do the setup once so I will
>> drop static here. I still think if I drop static I will want to
>> initialize these to zero later, because (correct me if I am wrong)
>> only static variables are initialized to zero if not explicitly
>> initialized, and without either static or an initialized value,
>> these would be initialized to some undetermined random value
>> until explicitly set to the desired initial value. Of the two,
>> I think that the more important one to intitialize to zero is
>> rvda_host, because I use an initial value of zero for that variable
>> to test for the case when we do not need extended VBT support.
>
> Well, like all variables, these ones also will need to be sensibly
> initialized. That's entirely unrelated to the use of static; all
> static gets you in this regard is that there's implicit default
> initialization. Yet that alone is no reason to use static.
Ok.
>
>>>> + igd_opregion_pgbase = mem_hole_alloc(IGD_OPREGION_PAGES);
>>>> + /*
>>>> + * Tentative value for the number of pages to reserve
>>>> + * in the E820 map for the OpRegion and VBT.
>>>> + *
>>>> + * This will be the final value for the E820 map if
>>>> + * the device model lacks support for OpRegion 2 or
>>>> + * if the host OpRegion version is < 2 or if we never
>>>> + * allocate more pages in the E820 map for the VBT.
>>>> + */
>>>> + igd_opregion_e820_pages = IGD_OPREGION_PAGES;
>>>> +
>>>> + /*
>>>> + * Read the value the device model is initialized with.
>>>> + * If the device model supports OpRegion 2, it will
>>>> + * return the host IGD OpRegion address. If not, it
>>>> + * will return 0. If the device model does not support
>>>> + * OpRegion 2, the device model expects us to give it
>>>> + * the address to which it will map the OpRegion in the
>>>> + * guest and then expects us to do nothing more to setup
>>>> + * the OpRegion, so that is all we will do in that case.
>>>> + */
>>>
>>> Hmm, exposing the host opregion to a guest certainly feels like an issue.
>>
>> Well, that is how it is now. I am only retaining it to maintain backward
>> compatiblily with DM versions that do not support the extended VBT and
>> OpRegion 2+. My previous comment about backward compatibilty and DM
>> compatibility also applies here. If we don't worry about that, we can do
>> away with any cases where we are permanently mapping the host opregion to
>> the guest and implement this new approach of always exposing a copy of
>> the OpRegion and VBT to the guest instead.
>
> How does "permanently mapping" matter? hvmloader runs inside the guest, so
> exposure just to copy the data isn't any better in terms of this being a
> layering violation. The more correct thing to do might be for the DM to
> put in place a copy before the guest (i.e. hvmloader) even gains control.
> (How in turn the DM would learn of the contents of the opregion is a
> separate question then.)
OK.
>
>>>> + const uint32_t igd_host_opregion = pci_readl(vga_devfn,
>>>> + PCI_INTEL_OPREGION);
>>>> + if ( !igd_host_opregion ) {
>>>
>>> Nit (style) Brace placement (throughout).
>>
>> Ok. I see this is not the proper coding style.
>>
>>>
>>>> + printf("device model lacks extended VBT "
>>>> + "support. Continuing with legacy support only\n");
>>>
>>> This message can easily confuse / worry people. (If it was to be kept, it
>>> would also need style adjustment.)
>>
>> I think some message is needed here to indicate the incompatibility of
>> versions of the DM that do not support the extended VBT with versions
>> of hvmloader that do, especially if we are not going to worry as much
>> about the backward compatibility / DM compatibility problem I mentioned
>> multiple times in previous comments above.
>>
>> This message could encourage upgrading the DM to a version that supports
>> the extended VBT instead of just giving this scary notification.
>
> But someone expecting legacy behavior could be misguided by the message
> (e.g. into wondering whether there's something wrong.)
It may take a while to arrive at what exactly the message should say here.
I will think about it and propose what seems reasonable in the next version.
>
>>>> + const uint32_t igd_host_opregion_page_offset =
>>>> + igd_host_opregion & IGD_OPREGION_MASK;
>>>
>>> I think like in the hypervisor we don't want to mix declarations and
>>> statements just yet.
>>
>> The only way I could separate the declaration from the statement would be
>> to drop the const modifier because if I do:
>>
>> const uint32_t igd_host_opregion_page_offset;
>> ...
>> igd_host_opregion_page_offset = igd_host_opregion &
>> IGD_OPREGION_MASK;
>>
>> The compiler will report an error. If I drop the const modifier from
>> the declaration, the compiler will not report an error but I lose the
>> protection the compiler gives me from making mistakes by modifying a
>> variable's value that should be constant.
>>
>> I am not a C guru but some research indicates that while it is legal in
>> C to declare a variable with the const modifier without also assigning
>> it a value at the same time with a statement, it is not recommended to
>> do this because the variable will be initialized with some undefined
>> random value that cannot be changed because we used the const modifier
>> in the declaration. This implies strict enforcemnt of the rule "we
>> don't mix declarations and statements" results also in the corollary
>> rule "we never use the const modifier for variables in C."
>
> Indeed we rarely use const on variables (or parameters) themselves. It's
> primary use is on pointed-to types.
Ok.
>
>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>>>> + IGD_OPREGION2_SUPPORT_MASK);
>>>
>>> This looks to imply qemu is the only possible device model.
>>
>> Yeah, this is an issue. Other device models that intend to support
>> the Intel IGD with hvmloader will also have to be compatible with this.
>> It would be easier if we did not have to worry about backward
>> compatibility and supporting what we had in the codebase for many years
>> in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
>> in that case. Instead, we would just completely deprecate all previous
>> implementations of the Intel IGD passthrough feature in both hvmloader and
>> the Qemu DM as unsupported. So my previous comments about backward
>> compatibility apply here again.
>
> As said, I don't think backward compatibility can be dropped. My comment
> also didn't really mean to hint in that direction. Instead I was wondering
> in how far, even if perhaps by only a few #define-s, the necessary
> interfacing couldn't be put down in a public header, for any DM to consume.
Ok. Perhaps the IGD_* defines could be moved to a public header to define the
interface to be used to support the Intel IGD. Would it be OK to move those
to a separate igd.h header and include it in hvmloader/config.h?
>
>>>> + printf("guest OpRegion tentative "
>>>> + "address: 0x%x\n", igd_guest_opregion);
>>>> +
>>>> + if ( !verify_opregion(igd_guest_opregion) ) {
>>>> + printf("error: IGD OpRegion signature "
>>>> + "not found.\n");
>>>
>>> No full stop in messages please.
>>
>> Would it be OK to just get rid of the error message here?
>
> That would then leave ...
>
>>>> + BUG();
>
> ... an un-annotated BUG(), which generally isn't very nice.
I don't think I understand what you mean by "No full stop in messages..."
We have code like this in hvmloader/e820.c:
if ( rc || !nr_entries )
{
printf("Get guest memory maps[%d] failed. (%d)\n", nr_entries, rc);
BUG();
}
>
>>>> + }
>>>> + --snip --
>>>> + rvda_host = 0;
>>>> + }
>>>> + const uint32_t rvda_host_page_offset = rvda_host &
>>>> + IGD_OPREGION_MASK;
>>>
>>> Why host_page_offset here when ...
>>>
>>>> + const uint32_t rvds = *(uint32_t *)(opregion_scratch +
>>>> + IGD_OPREGION_RVDS);
>>>> + const uint32_t rvds_page_offset = rvds & IGD_OPREGION_MASK;
>>>
>>> ... it's just page_offset here, and when further you use it below to set
>>> rvda_guest?
>>
>> The size of the VBT, rvds, is the same on both host and guest, so we do not
>> need to specify host or guest, but the base address of the VBT, rvda, is
>> not the same on the guest as it is on the host, so we need to specify which
>> one for rvda. I can change this to rvds_host_page_offset because it is
>> not wrong, but it might be confusing because I use that value later on
>> for computations involving the guest also.
>
> Why not simply drop the "host" infix, when it's not relevant?
Ok.
>
>>>> + printf("VBT size: 0x%x\n", rvds);
>>>> +
>>>> + if ( !rvds || !rvda_host ) {
>>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>>> + rvda_host = 0;
>>>> + }
>>>> + /*
>>>> + * Write rvda_host as 2 successive 32-bit values
>>>> + * to communicate location of the VBT to the device
>>>> + * model. If rvda_host is not 0, The device model
>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>> + * after we also write the guest address where the
>>>> + * VBT will be mapped.
>>>> + *
>>>> + * If we send rvda_host = 0 to the device model, it
>>>> + * will assume we do not need OpRegion 2 support and
>>>> + * it will not unmap the OpRegion.
>>>> + */
>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>> + (uint32_t)rvda_host_upper_32);
>>>
>>> Why would you need to communicate a host property to the DM?
>>
>> The DM cannot access the host rvda value because it is only accessible
>> from the host kernel, and the DM is only a user-space process on the host.
>
> I don't follow this: Anything the guest can access should also be accessible
> by its DM.
I think the host OpRegion is not currently accessible by the DM. On the KVM
platform, this is made possible via the kernel vfio driver and then Qemu exposes
the OpRegion to the guest using the Qemu FwCfg device interface. How should we make
the OpRegion and VBT accessible to the device model and then, to the guest, on Xen?
I think it could be done via the xen-pciback kernel driver. Should we do that
instead? I think to do that we would have to convince the kernel developers that
the Intel OpRegion, as you say, "should" be accessible by the Xen device model.
I can imagine them saying, why not use the vfio driver?
Teddy Astie, on the Cc: list for this patch, is actually working on this:
https://xcp-ng.org/blog/2024/04/18/iommu-paravirtualization-for-xen/
These decisions about the best approach to support the Intel IDG on Xen are
above my pay grade, obviously. I need some guidance here, please.
>
>>>> + /*
>>>> + * Update the number of pages the device model
>>>> + * needs to map for us to get a copy of the VBT.
>>>> + *
>>>> + * N.B.: Here, igd_opregion_pgbase is really the page
>>>> + * base of the location where the device model will
>>>> + * map the VBT.
>>>> + */
>>>> + uint32_t vbt_pages_needed = rvds >> PAGE_SHIFT;
>>>> + if ( rvds & IGD_OPREGION_MASK )
>>>> + vbt_pages_needed++;
>>>> + if ( vbt_pages_needed > igd_opregion_e820_pages ) {
>>>> + igd_opregion_pgbase = mem_hole_alloc
>>>> + (vbt_pages_needed - igd_opregion_e820_pages);
>>>
>>> Nit: Indentation.
>>
>> Ok. It should always be a multiple of four spaces, I presume. I admit I did
>> not check that.
>
> Not quite. Within a wrapped expression, you need to determine what I like
> to call the "anchor point". In a function call that's the start of the
> function name. The wrapped part of the expression would then start one
> extra level (4 spaces) deeper than the anchor point. Things are different
> when there are pending open parentheses: There the wrapped part of an
> expression starts with as many extra spaces as there are pending open
> parentheses, with the outermost pending open parenthesis being the anchor
> point. E.g. (taking the example above and adding extra wrapping in the
> function argument expression just for demonstration purposes):
>
> igd_opregion_pgbase = mem_hole_alloc
> (vbt_pages_needed -
> igd_opregion_e820_pages);
>
> Or alternatively
>
> igd_opregion_pgbase =
> mem_hole_alloc(vbt_pages_needed - igd_opregion_e820_pages);
Ok.
Thanks,
Chuck
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 13:18 ` Chuck Zmudzinski
@ 2026-08-14 13:46 ` Jan Beulich
2026-08-14 15:23 ` Chuck Zmudzinski
2026-08-15 2:22 ` Chuck Zmudzinski
0 siblings, 2 replies; 42+ messages in thread
From: Jan Beulich @ 2026-08-14 13:46 UTC (permalink / raw)
To: Chuck Zmudzinski, Anthony PERARD
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Chuck Zmudzinski
On 14.08.2026 15:18, Chuck Zmudzinski wrote:
> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>> -- snip --
>>>>> To address this problem, this patch implements support for
>>>>> Intel IGD devices with an extended VBT and OpRegion version 2
>>>>> and higher which is required for most modern Intel IGD devices.
>>>>
>>>> First of all: Where's the spec of all of this?
>>>
>>> Well, your first question is quite provocative. Certainly more
>>> social/legal than technical.
>>
>> Well, it was very much meant to be technical. I've had a hard time following
>> what your new code does, and having a spec to hand would likely have helped.
>
> I agree that having the spec at hand would be better. To be more precise, I
> can say that what this patch essentially does is port the support for
> the extended VBT with OpRegion 2+ for the Intel IGD passthrough that exists
> in KVM/vfio to Xen. Should I explicitly say in the title of the commit
> message that this is a port of KVM/vfio support for extended VBT to Xen?
Not in the title, as that would likely make it too long, but perhaps in the
description.
>>> So my answer is as follows:
>>>
>>> I do not have access to the official spec that defines "all this" but
>>> I do have access, as does the general public, to the Linux kernel's
>>> implementation of support for the Intel IGD from many sources such as
>>> git.kernel.org. The Linux kernel has enough accurate information about
>>> the spec of "all this" to provide very good support for the Intel IGD
>>> on bare metal.
>>>
>>> To elaborate a bit more, the spec of "all this" can be derived from the
>>> Linux kernel code that supports the Intel IGD.
>>
>> So you expect every reader to locate and decipher the underlying information
>> from a (afaik) pretty large piece of code in the Linux kernel? If the Linux
>> kernel sources are the reference, please can you at least provide pointers
>> into there?
>
> No, I do not expect every reader to decipher the underlying information...
>
> That is why I provided these two links at the bottom of the commit message.
> Perhaps you did not notice them:
>
> Link: https://lore.kernel.org/kvm/20211012124855.52463-1-colin.xu@gmail.com/
> Link: https://lore.kernel.org/kvm/20210325170953.24549-1-fred.gao@intel.com/
>
> They are the patches to the vfio kernel driver that added support for the
> extended VBT for KVM/vfio guests.
Patches can still be in flight, so provide only limited help. Would it be a
problem to instead reference commits, or the actual localtion in Linux
sources?
>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>>>>> + IGD_OPREGION2_SUPPORT_MASK);
>>>>
>>>> This looks to imply qemu is the only possible device model.
>>>
>>> Yeah, this is an issue. Other device models that intend to support
>>> the Intel IGD with hvmloader will also have to be compatible with this.
>>> It would be easier if we did not have to worry about backward
>>> compatibility and supporting what we had in the codebase for many years
>>> in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
>>> in that case. Instead, we would just completely deprecate all previous
>>> implementations of the Intel IGD passthrough feature in both hvmloader and
>>> the Qemu DM as unsupported. So my previous comments about backward
>>> compatibility apply here again.
>>
>> As said, I don't think backward compatibility can be dropped. My comment
>> also didn't really mean to hint in that direction. Instead I was wondering
>> in how far, even if perhaps by only a few #define-s, the necessary
>> interfacing couldn't be put down in a public header, for any DM to consume.
>
> Ok. Perhaps the IGD_* defines could be moved to a public header to define the
> interface to be used to support the Intel IGD. Would it be OK to move those
> to a separate igd.h header
This may require input by others, as in the given situation I'm not quite
sure what is best. Anthony - do you possibly have any suggestion here?
> and include it in hvmloader/config.h?
I don't see why that would be needed. The few files which need the #define-s
can include that new public header, without impacting anything else.
>>>>> + printf("guest OpRegion tentative "
>>>>> + "address: 0x%x\n", igd_guest_opregion);
>>>>> +
>>>>> + if ( !verify_opregion(igd_guest_opregion) ) {
>>>>> + printf("error: IGD OpRegion signature "
>>>>> + "not found.\n");
>>>>
>>>> No full stop in messages please.
>>>
>>> Would it be OK to just get rid of the error message here?
>>
>> That would then leave ...
>>
>>>>> + BUG();
>>
>> ... an un-annotated BUG(), which generally isn't very nice.
>
> I don't think I understand what you mean by "No full stop in messages..."
That's the period at the end of a sentence (when in log messages the term
"sentence" is of questionable nature).
> We have code like this in hvmloader/e820.c:
>
> if ( rc || !nr_entries )
> {
> printf("Get guest memory maps[%d] failed. (%d)\n", nr_entries, rc);
> BUG();
> }
Well, you'll almost always be able to find bad pre-existing examples.
>>>>> + printf("VBT size: 0x%x\n", rvds);
>>>>> +
>>>>> + if ( !rvds || !rvda_host ) {
>>>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>>>> + rvda_host = 0;
>>>>> + }
>>>>> + /*
>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>> + * to communicate location of the VBT to the device
>>>>> + * model. If rvda_host is not 0, The device model
>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>> + * after we also write the guest address where the
>>>>> + * VBT will be mapped.
>>>>> + *
>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>> + * will assume we do not need OpRegion 2 support and
>>>>> + * it will not unmap the OpRegion.
>>>>> + */
>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>> + (uint32_t)rvda_host_upper_32);
>>>>
>>>> Why would you need to communicate a host property to the DM?
>>>
>>> The DM cannot access the host rvda value because it is only accessible
>>> from the host kernel, and the DM is only a user-space process on the host.
>>
>> I don't follow this: Anything the guest can access should also be accessible
>> by its DM.
>
> I think the host OpRegion is not currently accessible by the DM.
Can you explain to me how the region becomes accessible to the guest?
That would then (hopefully) help me understand why the DM would not have
access. Fundamentally any MMIO and any I/O ports that are assigned to a
guest are also assigned to its DM.
> On the KVM
> platform, this is made possible via the kernel vfio driver and then Qemu exposes
> the OpRegion to the guest using the Qemu FwCfg device interface. How should we make
> the OpRegion and VBT accessible to the device model and then, to the guest, on Xen?
> I think it could be done via the xen-pciback kernel driver. Should we do that
> instead? I think to do that we would have to convince the kernel developers that
> the Intel OpRegion, as you say, "should" be accessible by the Xen device model.
> I can imagine them saying, why not use the vfio driver?
I can't answer this; all I can say is that it feels wrong to involve e.g.
xen-pciback here.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 13:46 ` Jan Beulich
@ 2026-08-14 15:23 ` Chuck Zmudzinski
2026-08-14 16:18 ` Chuck Zmudzinski
` (2 more replies)
2026-08-15 2:22 ` Chuck Zmudzinski
1 sibling, 3 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-14 15:23 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/14/2026 9:46 AM, Jan Beulich wrote:
> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>> -- snip --
>>>>>> To address this problem, this patch implements support for
>>>>>> Intel IGD devices with an extended VBT and OpRegion version 2
>>>>>> and higher which is required for most modern Intel IGD devices.
>>>>>
>>>>> First of all: Where's the spec of all of this?
>>>>
>>>> Well, your first question is quite provocative. Certainly more
>>>> social/legal than technical.
>>>
>>> Well, it was very much meant to be technical. I've had a hard time following
>>> what your new code does, and having a spec to hand would likely have helped.
>>
>> I agree that having the spec at hand would be better. To be more precise, I
>> can say that what this patch essentially does is port the support for
>> the extended VBT with OpRegion 2+ for the Intel IGD passthrough that exists
>> in KVM/vfio to Xen. Should I explicitly say in the title of the commit
>> message that this is a port of KVM/vfio support for extended VBT to Xen?
>
> Not in the title, as that would likely make it too long, but perhaps in the
> description.
Ok.
>
>>>> So my answer is as follows:
>>>>
>>>> I do not have access to the official spec that defines "all this" but
>>>> I do have access, as does the general public, to the Linux kernel's
>>>> implementation of support for the Intel IGD from many sources such as
>>>> git.kernel.org. The Linux kernel has enough accurate information about
>>>> the spec of "all this" to provide very good support for the Intel IGD
>>>> on bare metal.
>>>>
>>>> To elaborate a bit more, the spec of "all this" can be derived from the
>>>> Linux kernel code that supports the Intel IGD.
>>>
>>> So you expect every reader to locate and decipher the underlying information
>>> from a (afaik) pretty large piece of code in the Linux kernel? If the Linux
>>> kernel sources are the reference, please can you at least provide pointers
>>> into there?
>>
>> No, I do not expect every reader to decipher the underlying information...
>>
>> That is why I provided these two links at the bottom of the commit message.
>> Perhaps you did not notice them:
>>
>> Link: https://lore.kernel.org/kvm/20211012124855.52463-1-colin.xu@gmail.com/
>> Link: https://lore.kernel.org/kvm/20210325170953.24549-1-fred.gao@intel.com/
>>
>> They are the patches to the vfio kernel driver that added support for the
>> extended VBT for KVM/vfio guests.
>
> Patches can still be in flight, so provide only limited help. Would it be a
> problem to instead reference commits, or the actual localtion in Linux
> sources?
No problem. I will format references to kernel commits the way it was done in
this commit message of commit 99794c8a8ff8 in the Xen tree that references
some Linux kernel commits unless you suggest a better way to reference Linux
kernel commits:
xen/acpi: Import PPTT definitions from Linux
Import the Processor Properties Topology Table (PPTT) definitions
from the Linux kernel header (include/acpi/actbl2.h) into Xen.
Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp>
Origin: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git b8355bcac253
Origin: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git e62f8227851d
Origin: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 091c4af3562d
>
>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>>>>>> + IGD_OPREGION2_SUPPORT_MASK);
>>>>>
>>>>> This looks to imply qemu is the only possible device model.
>>>>
>>>> Yeah, this is an issue. Other device models that intend to support
>>>> the Intel IGD with hvmloader will also have to be compatible with this.
>>>> It would be easier if we did not have to worry about backward
>>>> compatibility and supporting what we had in the codebase for many years
>>>> in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
>>>> in that case. Instead, we would just completely deprecate all previous
>>>> implementations of the Intel IGD passthrough feature in both hvmloader and
>>>> the Qemu DM as unsupported. So my previous comments about backward
>>>> compatibility apply here again.
>>>
>>> As said, I don't think backward compatibility can be dropped. My comment
>>> also didn't really mean to hint in that direction. Instead I was wondering
>>> in how far, even if perhaps by only a few #define-s, the necessary
>>> interfacing couldn't be put down in a public header, for any DM to consume.
>>
>> Ok. Perhaps the IGD_* defines could be moved to a public header to define the
>> interface to be used to support the Intel IGD. Would it be OK to move those
>> to a separate igd.h header
>
> This may require input by others, as in the given situation I'm not quite
> sure what is best. Anthony - do you possibly have any suggestion here?
>
>> and include it in hvmloader/config.h?
>
> I don't see why that would be needed. The few files which need the #define-s
> can include that new public header, without impacting anything else.
So I would just include it in the new intel-opregion.c file. Also, maybe igd-related
declarations should be moved there too, such as the currently existing extern variable
igd_opregion_pgbase and my newly proposed extern variable igd_opregion_e820_pages,
which would mean the new header would also need to be included in hvmloader/e820.c.
>
>>>>>> + printf("guest OpRegion tentative "
>>>>>> + "address: 0x%x\n", igd_guest_opregion);
>>>>>> +
>>>>>> + if ( !verify_opregion(igd_guest_opregion) ) {
>>>>>> + printf("error: IGD OpRegion signature "
>>>>>> + "not found.\n");
>>>>>
>>>>> No full stop in messages please.
>>>>
>>>> Would it be OK to just get rid of the error message here?
>>>
>>> That would then leave ...
>>>
>>>>>> + BUG();
>>>
>>> ... an un-annotated BUG(), which generally isn't very nice.
>>
>> I don't think I understand what you mean by "No full stop in messages..."
>
> That's the period at the end of a sentence (when in log messages the term
> "sentence" is of questionable nature).
Ok. I thought you were referring to the BUG() statement which fully stops
the guest.
>
>> We have code like this in hvmloader/e820.c:
>>
>> if ( rc || !nr_entries )
>> {
>> printf("Get guest memory maps[%d] failed. (%d)\n", nr_entries, rc);
>> BUG();
>> }
>
> Well, you'll almost always be able to find bad pre-existing examples.
>
>>>>>> + printf("VBT size: 0x%x\n", rvds);
>>>>>> +
>>>>>> + if ( !rvds || !rvda_host ) {
>>>>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>>>>> + rvda_host = 0;
>>>>>> + }
>>>>>> + /*
>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>> + * to communicate location of the VBT to the device
>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>> + * after we also write the guest address where the
>>>>>> + * VBT will be mapped.
>>>>>> + *
>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>> + * it will not unmap the OpRegion.
>>>>>> + */
>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>
>>>>> Why would you need to communicate a host property to the DM?
>>>>
>>>> The DM cannot access the host rvda value because it is only accessible
>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>
>>> I don't follow this: Anything the guest can access should also be accessible
>>> by its DM.
>>
>> I think the host OpRegion is not currently accessible by the DM.
>
> Can you explain to me how the region becomes accessible to the guest?
> That would then (hopefully) help me understand why the DM would not have
> access. Fundamentally any MMIO and any I/O ports that are assigned to a
> guest are also assigned to its DM.
Currently, in the device model (Qemu) we have:
ret = xc_domain_memory_mapping(xen_xc, xen_domid,
(unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
(unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
XEN_PCI_INTEL_OPREGION_PAGES,
DPCI_ADD_MAPPING);
That statement is in the igd_write_opregion(...) function in the
hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
If I understand our current implementation correctly, this statement
is what gives the guest access to the host OpRegion (3 pages as defined
by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
in hvmloader code). I don't think this statement makes the host OpRegion
accessible to the device model, though, so I think, if I understand your
comment in an earlier about my patch resulting in what you called a "layering
violation" correctly, that our current implementation is also guilty of this
same kind of "layering violation."
So, how do you suggest we fix that?
>
>> On the KVM
>> platform, this is made possible via the kernel vfio driver and then Qemu exposes
>> the OpRegion to the guest using the Qemu FwCfg device interface. How should we make
>> the OpRegion and VBT accessible to the device model and then, to the guest, on Xen?
>> I think it could be done via the xen-pciback kernel driver. Should we do that
>> instead? I think to do that we would have to convince the kernel developers that
>> the Intel OpRegion, as you say, "should" be accessible by the Xen device model.
>> I can imagine them saying, why not use the vfio driver?
>
> I can't answer this; all I can say is that it feels wrong to involve e.g.
> xen-pciback here.
Ok. I guess we need to wait for other experts to weigh in here. I have never looked
carefully at what xen-pciback does. I suppose one of it's jobs is to hide access to
the resources of the passed through device from the dom0 kernel but I am just
guessing about that.
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 15:23 ` Chuck Zmudzinski
@ 2026-08-14 16:18 ` Chuck Zmudzinski
2026-08-14 19:13 ` Chuck Zmudzinski
2026-08-14 17:07 ` Chuck Zmudzinski
2026-08-17 8:42 ` Jan Beulich
2 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-14 16:18 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 8/14/2026 11:23 AM, Chuck Zmudzinski wrote:
> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>> -- snip --
>>>>
>>>> I don't follow this: Anything the guest can access should also be accessible
>>>> by its DM.
>>>
>>> I think the host OpRegion is not currently accessible by the DM.
>>
>> Can you explain to me how the region becomes accessible to the guest?
>> That would then (hopefully) help me understand why the DM would not have
>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>> guest are also assigned to its DM.
>
> Currently, in the device model (Qemu) we have:
>
> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> XEN_PCI_INTEL_OPREGION_PAGES,
> DPCI_ADD_MAPPING);
>
> That statement is in the igd_write_opregion(...) function in the
> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
I forgot to mention: In our current implementation, this statement is
executed in the DM when hvmloader executes this statement, currently in
hvmloader/pci:
pci_writel(vga_devfn, PCI_INTEL_OPREGION,
igd_opregion_pgbase << PAGE_SHIFT);
>
> If I understand our current implementation correctly, this statement
> is what gives the guest access to the host OpRegion (3 pages as defined
> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
> in hvmloader code). I don't think this statement makes the host OpRegion
> accessible to the device model, though, so I think, if I understand your
> comment in an earlier about my patch resulting in what you called a "layering
> violation" correctly, that our current implementation is also guilty of this
> same kind of "layering violation."
>
> So, how do you suggest we fix that?
>
...
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 15:23 ` Chuck Zmudzinski
2026-08-14 16:18 ` Chuck Zmudzinski
@ 2026-08-14 17:07 ` Chuck Zmudzinski
2026-08-17 8:42 ` Jan Beulich
2 siblings, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-14 17:07 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 8/14/2026 11:23 AM, Chuck Zmudzinski wrote:
> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>> -- snip --
>>
>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>>>>>>> + IGD_OPREGION2_SUPPORT_MASK);
>>>>>>
>>>>>> This looks to imply qemu is the only possible device model.
>>>>>
>>>>> Yeah, this is an issue. Other device models that intend to support
>>>>> the Intel IGD with hvmloader will also have to be compatible with this.
>>>>> It would be easier if we did not have to worry about backward
>>>>> compatibility and supporting what we had in the codebase for many years
>>>>> in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
>>>>> in that case. Instead, we would just completely deprecate all previous
>>>>> implementations of the Intel IGD passthrough feature in both hvmloader and
>>>>> the Qemu DM as unsupported. So my previous comments about backward
>>>>> compatibility apply here again.
>>>>
>>>> As said, I don't think backward compatibility can be dropped. My comment
>>>> also didn't really mean to hint in that direction. Instead I was wondering
>>>> in how far, even if perhaps by only a few #define-s, the necessary
>>>> interfacing couldn't be put down in a public header, for any DM to consume.
>>>
>>> Ok. Perhaps the IGD_* defines could be moved to a public header to define the
>>> interface to be used to support the Intel IGD. Would it be OK to move those
>>> to a separate igd.h header
>>
>> This may require input by others, as in the given situation I'm not quite
>> sure what is best. Anthony - do you possibly have any suggestion here?
>>
>>> and include it in hvmloader/config.h?
>>
>> I don't see why that would be needed. The few files which need the #define-s
>> can include that new public header, without impacting anything else.
>
> So I would just include it in the new intel-opregion.c file. Also, maybe igd-related
> declarations should be moved there too, such as the currently existing extern variable
> igd_opregion_pgbase and my newly proposed extern variable igd_opregion_e820_pages,
> which would mean the new header would also need to be included in hvmloader/e820.c.
Actually, those igd-related declarations do not need to be in a public header. But I
think if we go to a public header for any DM to consume, we need to fixup oddities
like the current definition of IGD_OPREGION_PAGES of 3 when the actual number of pages
in the OpRegion is exactly 2. So I propose the next version of this patch should
add a preliminary patch to cleanup the oddities in the current implementation such as
having IGD_OPREGION_PAGES set to 3 without introducing any functional change by
redefining IGD_OPREGION_PAGES to the value it should be, which is 2. Then we can
include IGD_OPREGION2_SUPPORT_MASK, IGD_OPREGION_PAGES, etc. as defines in a public
header for any DM to consume. I can probably build such a public header directly from
IGD-related header files in use in the Linux kernel or in the Qemu/vfio IGD-related
headers files.
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 16:18 ` Chuck Zmudzinski
@ 2026-08-14 19:13 ` Chuck Zmudzinski
0 siblings, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-14 19:13 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 8/14/2026 12:18 PM, Chuck Zmudzinski wrote:
> On 8/14/2026 11:23 AM, Chuck Zmudzinski wrote:
>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>> -- snip --
>>>>>
>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>> by its DM.
>>>>
>>>> I think the host OpRegion is not currently accessible by the DM.
>>>
>>> Can you explain to me how the region becomes accessible to the guest?
>>> That would then (hopefully) help me understand why the DM would not have
>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>> guest are also assigned to its DM.
>>
>> Currently, in the device model (Qemu) we have:
>>
>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>> XEN_PCI_INTEL_OPREGION_PAGES,
>> DPCI_ADD_MAPPING);
>>
>> That statement is in the igd_write_opregion(...) function in the
>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>
> I forgot to mention: In our current implementation, this statement is
> executed in the DM when hvmloader executes this statement, currently in
> hvmloader/pci:
>
> pci_writel(vga_devfn, PCI_INTEL_OPREGION,
> igd_opregion_pgbase << PAGE_SHIFT);
>
>
>
>>
>> If I understand our current implementation correctly, this statement
>> is what gives the guest access to the host OpRegion (3 pages as defined
>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>> in hvmloader code). I don't think this statement makes the host OpRegion
>> accessible to the device model, though, so I think, if I understand your
>> comment in an earlier about my patch resulting in what you called a "layering
>> violation" correctly, that our current implementation is also guilty of this
>> same kind of "layering violation."
>>
>> So, how do you suggest we fix that?
Well, that is a difficult question to answer, and if no one gives an answer
then I ask, what is the harm in making the unorthodox mapping of the OpRegion
from the host to the guest temporary for the purpose of allowing hvmloader
to setup the OpRegion properly for newer devices with new and updated specs
for the OpRegion and VBT when our current implementation permanently maps
the host OpRegion into the guest in the same unorthodox way also, that is,
without following the normal PCI MMIO interfaces?
I think the fundamental problem is the fact that the Intel IGD is an
unorthodox PCI device that does not follow the normal PCI specs and
requires adherence to Intel's proprietary specs instead.
Would that be a fair description of your problem with this patch? Are
the unorthodox requirements of the Intel IGD at the root of your issue
with this patch?
I think the reason this was allowed in the Xen codebase many years ago, I think
over 10 years ago now, is simply because the Intel IGD is such an ubiquitous
device that an exception for it was allowed.
So, to summarize what I am being asked to do in this thread, I propose the
next version of this patch should:
1. Fix style problems in this version.
2. provide a public header to define two protocols for providing
Intel IGD support via interaction between the DM and hvmloader.
The first protocol is the legacy protocol version, and it
is the version that our current implementation follows. The second
version is the new proposed protocol that is able to allow
support for an extended VBT, which is required for newer Intel
IGD devices.
3. For now, since only hvmloader currently has access to the host
OpRegion in both our current implementation and the proposed new
protocol, hvmloader will drive the decision about which protocol
version to use for setting up the guest OpRegion. First, if the
device model lacks support for the new protocol proposed here that
supports the extended VBT, then hvmloader has no choice but to
implement the current legacy protocol. Even in that case, instead
of just printing a scary or confusing message about lack of support
for extended VBT and continuing, which is what this version of this
patch does, we can read the OpRegion and then print an error message
and BUG() (or just a WARN?) only in the case when extended VBT
support is needed for this hardware but such support is not available
in the device model. The message could say something like:
IGD: error: This device requires extended VBT support in the device model.
Please upgrade the device model to a version with extended VBT support
and try again.
If the device does not require extended VBT support, we silently continue
and can expect the guest will operate correctly if all else is also good.
Now for the case when the device model does support extended VBT but the
device is a legacy device that does not need an extended VBT. In that
case, I think it is better to, instead of implementing the current
legacy protocol which unconditionally maps 3 host pages into the guest
when only 2 pages are actually needed, so an extra page from the host
of unknown content is being exposed to the guest, we implement the new
protocol proposed here that will reserve only two pages for the OpRegion
in the E820 map and use a copy of the two-page OpRegion in the guest instead.
This will be a change from this v2 of this patch which just uses the three-page
mapped region in this case.
Then there is the fourth case when the device model supports extended VBT
and the device needs such support.
To understand the approach to this problem that I have implemented in this
patch and plan to implement in future versions until a better alternative
is proposed, please refer to these Linux kernel commits which added support
for extended VBT for KVM/vfio guests and which explain why this patch is
needed for the newer Intel IGD devices that need an extended VBT:
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git bab2c1990b78 ("vfio/pci: Add support for opregion v2.1+")
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 49ba1a2976c8 ("vfio/pci: Add OpRegion 2.0+ Extended VBT support.")
So, in this case, we have to implement some means for exposing both the
OpRegion and the VBT to the guest, and we may need to also modify the
OpRegion in some cases. Specifically, the value of the rvda field in the
OpRegion needs to be modified in at least two cases:
A) Host OpRegion version is 2.0. In this case, rvda is the absolute address
of the VBT and will need to have a different value in the guest than its
value in the host.
B) OpRegion version is 2.1 or higher. In this case, rvda is the VBT address
relative to the OpRegion base but if our memory map does not allow us to
maintain the same relative offset of the VBT from the OpRegion base on the
host, rvda will need to have a different value in the guest than its value
in the host.
For now, until a better way is proposed to expose the OpRegion and VBT to the
guest in a way that allows the guest OpRegion to be modified as described above,
I plan to propose the same approach of temporarily mapping the host IGD OpRegion
and VBT so that hvmloader can obtain a copy of each region and configure the
OpRegion and VBT appropriately for the guest that I have use in this patch,
despite Jan's objections which, as far as I can tell, also apply to our current
implementation.
Thanks,
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 13:46 ` Jan Beulich
2026-08-14 15:23 ` Chuck Zmudzinski
@ 2026-08-15 2:22 ` Chuck Zmudzinski
2026-08-17 9:11 ` Jan Beulich
1 sibling, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-15 2:22 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 8/14/2026 9:46 AM, Jan Beulich wrote:
> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>> -- snip --
>>>>>> To address this problem, this patch implements support for
>>>>>> Intel IGD devices with an extended VBT and OpRegion version 2
>>>>>> and higher which is required for most modern Intel IGD devices.
>>>>>
>>>>> First of all: Where's the spec of all of this?
>>>>
>>>> Well, your first question is quite provocative. Certainly more
>>>> social/legal than technical.
>>>
>>> Well, it was very much meant to be technical. I've had a hard time following
>>> what your new code does, and having a spec to hand would likely have helped.
>>
>> I agree that having the spec at hand would be better. To be more precise, I
>> can say that what this patch essentially does is port the support for
>> the extended VBT with OpRegion 2+ for the Intel IGD passthrough that exists
>> in KVM/vfio to Xen. Should I explicitly say in the title of the commit
>> message that this is a port of KVM/vfio support for extended VBT to Xen?
>
> Not in the title, as that would likely make it too long, but perhaps in the
> description.
>
>>>> So my answer is as follows:
>>>>
>>>> I do not have access to the official spec that defines "all this" but
>>>> I do have access, as does the general public, to the Linux kernel's
>>>> implementation of support for the Intel IGD from many sources such as
>>>> git.kernel.org. The Linux kernel has enough accurate information about
>>>> the spec of "all this" to provide very good support for the Intel IGD
>>>> on bare metal.
>>>>
>>>> To elaborate a bit more, the spec of "all this" can be derived from the
>>>> Linux kernel code that supports the Intel IGD.
>>>
>>> So you expect every reader to locate and decipher the underlying information
>>> from a (afaik) pretty large piece of code in the Linux kernel? If the Linux
>>> kernel sources are the reference, please can you at least provide pointers
>>> into there?
>>
>> No, I do not expect every reader to decipher the underlying information...
>>
>> That is why I provided these two links at the bottom of the commit message.
>> Perhaps you did not notice them:
>>
>> Link: https://lore.kernel.org/kvm/20211012124855.52463-1-colin.xu@gmail.com/
>> Link: https://lore.kernel.org/kvm/20210325170953.24549-1-fred.gao@intel.com/
>>
>> They are the patches to the vfio kernel driver that added support for the
>> extended VBT for KVM/vfio guests.
>
> Patches can still be in flight, so provide only limited help. Would it be a
> problem to instead reference commits, or the actual localtion in Linux
> sources?
>
>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>> + (igd_opregion_pgbase << PAGE_SHIFT) |
>>>>>> + IGD_OPREGION2_SUPPORT_MASK);
>>>>>
>>>>> This looks to imply qemu is the only possible device model.
>>>>
>>>> Yeah, this is an issue. Other device models that intend to support
>>>> the Intel IGD with hvmloader will also have to be compatible with this.
>>>> It would be easier if we did not have to worry about backward
>>>> compatibility and supporting what we had in the codebase for many years
>>>> in both hvmloader and Qemu and we would not need IGD_OPREGION2_SUPPORT_MASK
>>>> in that case. Instead, we would just completely deprecate all previous
>>>> implementations of the Intel IGD passthrough feature in both hvmloader and
>>>> the Qemu DM as unsupported. So my previous comments about backward
>>>> compatibility apply here again.
>>>
>>> As said, I don't think backward compatibility can be dropped. My comment
>>> also didn't really mean to hint in that direction. Instead I was wondering
>>> in how far, even if perhaps by only a few #define-s, the necessary
>>> interfacing couldn't be put down in a public header, for any DM to consume.
>>
>> Ok. Perhaps the IGD_* defines could be moved to a public header to define the
>> interface to be used to support the Intel IGD. Would it be OK to move those
>> to a separate igd.h header
>
> This may require input by others, as in the given situation I'm not quite
> sure what is best. Anthony - do you possibly have any suggestion here?
>
>> and include it in hvmloader/config.h?
>
> I don't see why that would be needed. The few files which need the #define-s
> can include that new public header, without impacting anything else.
>
>>>>>> + printf("guest OpRegion tentative "
>>>>>> + "address: 0x%x\n", igd_guest_opregion);
>>>>>> +
>>>>>> + if ( !verify_opregion(igd_guest_opregion) ) {
>>>>>> + printf("error: IGD OpRegion signature "
>>>>>> + "not found.\n");
>>>>>
>>>>> No full stop in messages please.
>>>>
>>>> Would it be OK to just get rid of the error message here?
>>>
>>> That would then leave ...
>>>
>>>>>> + BUG();
>>>
>>> ... an un-annotated BUG(), which generally isn't very nice.
>>
>> I don't think I understand what you mean by "No full stop in messages..."
>
> That's the period at the end of a sentence (when in log messages the term
> "sentence" is of questionable nature).
>
>> We have code like this in hvmloader/e820.c:
>>
>> if ( rc || !nr_entries )
>> {
>> printf("Get guest memory maps[%d] failed. (%d)\n", nr_entries, rc);
>> BUG();
>> }
>
> Well, you'll almost always be able to find bad pre-existing examples.
>
>>>>>> + printf("VBT size: 0x%x\n", rvds);
>>>>>> +
>>>>>> + if ( !rvds || !rvda_host ) {
>>>>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>>>>> + rvda_host = 0;
>>>>>> + }
>>>>>> + /*
>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>> + * to communicate location of the VBT to the device
>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>> + * after we also write the guest address where the
>>>>>> + * VBT will be mapped.
>>>>>> + *
>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>> + * it will not unmap the OpRegion.
>>>>>> + */
>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>
>>>>> Why would you need to communicate a host property to the DM?
>>>>
>>>> The DM cannot access the host rvda value because it is only accessible
>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>
>>> I don't follow this: Anything the guest can access should also be accessible
>>> by its DM.
>>
>> I think the host OpRegion is not currently accessible by the DM.
>
> Can you explain to me how the region becomes accessible to the guest?
> That would then (hopefully) help me understand why the DM would not have
> access. Fundamentally any MMIO and any I/O ports that are assigned to a
> guest are also assigned to its DM.
This is what I don't understand about your objection to how both the current
implementation and my proposed changes makes the host OpRegion accessible to
the guest. What do you mean when you say any MMIO and I/O ports assigned to
a guest are also assigned to its DM? What does it mean to assign an MMIO
region to a DM? Is it the DM you mean or the DM domain, which need not be
dom0 if we are running the device model in an unprivileged domain. I also
am presuming you know that dom0 for Intel IGD passthrough is a PV dom0,
not a PVH dom0. I have never tried Intel IGD passthrough with a PVH dom0,
because as far as I can tell vt-d is not supported with PVH dom0.
Take a look at this code from our current implementation in qemu-xen. This
is from the current master branch of qemu-xen on xenbits.xen.org, the
hw/xen/xen_pt_graphics.c file, the igd_write_opregion function:
--- snip ---
#define XEN_PCI_INTEL_OPREGION_PAGES 0x3
#define XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED 0x1
void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val)
{
int ret;
if (igd_guest_opregion) {
XEN_PT_LOG(&s->dev, "opregion register already been set, ignoring %x\n",
val);
return;
}
/* We just work with LE. */
xen_host_pci_get_block(&s->real_device, XEN_PCI_INTEL_OPREGION,
(uint8_t *)&igd_host_opregion, 4);
igd_guest_opregion = (unsigned long)(val & ~XEN_PCI_INTEL_OPREGION_MASK)
| (igd_host_opregion & XEN_PCI_INTEL_OPREGION_MASK);
ret = xc_domain_iomem_permission(xen_xc, xen_domid,
(unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
XEN_PCI_INTEL_OPREGION_PAGES,
XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED);
if (ret) {
XEN_PT_ERR(&s->dev, "[%d]:Can't enable to access IGD host opregion:"
" 0x%lx.\n", ret,
(unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT)),
igd_guest_opregion = 0;
return;
}
ret = xc_domain_memory_mapping(xen_xc, xen_domid,
(unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
(unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
XEN_PCI_INTEL_OPREGION_PAGES,
DPCI_ADD_MAPPING);
if (ret) {
XEN_PT_ERR(&s->dev, "[%d]:Can't map IGD host opregion:0x%lx to"
" guest opregion:0x%lx.\n", ret,
(unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
(unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
igd_guest_opregion = 0;
return;
}
XEN_PT_LOG(&s->dev, "Map OpRegion: 0x%lx -> 0x%lx\n",
(unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
(unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
}
--- snip ---
This function is called when the guest (i.e. hvmloader, seabios/ovmf, or
guest kernel code) tries to access (write to) what is known as the ASLS
register in the PCI config space of the Intel IGD. The config space is
256 bytes long, and the ASLS register is the last four bytes of that space
according to the proprietary spec from Intel for the OpRegion. So the address
for the ASLS register in the config space is 0xfc, and the four bytes stored
there is supposed to be the address of the OpRegion according to Intel's spec.
That is fundamentally what we are trying to do here - program that ASLS register
so it points to the location, in the guest, of the OpRegion. If you examine
the code above, you will notice the call to xen_host_pci_get_block(), with
XEN_PCI_INTEL_OPREGION as one of the parameters. Did you look up its value?
It is 0xfc, the value for the ASLS register in the Intel spec. How does the
DM, qemu-xen, get the value stored there? Well, the xen_host_pci_get_block()
function accesses the PCI config space from the device model not directly as
kernel code or platform firmware code such as hvmloader or OVMF/Seabios could,
but only indirectly, through the 256-byte config file that is exposed by the
Linux kernel sysfs interface at /sys/bus/pci/devices/0000:00:02.0/config in
the Linux host filesystem. If you don't believe me, take a look at the code
in hw/xen/xen-host-pci-device.c where the xen_host_pci_get_block() function is
implemented in qemu-xen.
So the device model can, indirectly, access the PCI device's config space
because the Linux kernel exposes it via the sysfs interface. The point is,
the DM's access to these resources of the passed through PCI device has
nothing to do with MMIO or I/O port mappings, but is entirely dependent on
the host dom0 kernel for access. But sysfs does not provide access to the
OpRegion, that is, the actual two pages that comprise the OpRegion whose
base address is the value stored in the ASLS register. That is fundamentally
why the DM does not have access to the OpRegion.
Do you understand now?
Chuck
>
>> On the KVM
>> platform, this is made possible via the kernel vfio driver and then Qemu exposes
>> the OpRegion to the guest using the Qemu FwCfg device interface. How should we make
>> the OpRegion and VBT accessible to the device model and then, to the guest, on Xen?
>> I think it could be done via the xen-pciback kernel driver. Should we do that
>> instead? I think to do that we would have to convince the kernel developers that
>> the Intel OpRegion, as you say, "should" be accessible by the Xen device model.
>> I can imagine them saying, why not use the vfio driver?
>
> I can't answer this; all I can say is that it feels wrong to involve e.g.
> xen-pciback here.
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 7:35 ` Jan Beulich
2026-08-14 13:18 ` Chuck Zmudzinski
@ 2026-08-16 16:38 ` Chuck Zmudzinski
2026-08-17 9:18 ` Jan Beulich
1 sibling, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-16 16:38 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 8/14/2026 3:35 AM, Jan Beulich wrote:
> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>> -- snip --
>>>> + /*
>>>> + * Read the value the device model is initialized with.
>>>> + * If the device model supports OpRegion 2, it will
>>>> + * return the host IGD OpRegion address. If not, it
>>>> + * will return 0. If the device model does not support
>>>> + * OpRegion 2, the device model expects us to give it
>>>> + * the address to which it will map the OpRegion in the
>>>> + * guest and then expects us to do nothing more to setup
>>>> + * the OpRegion, so that is all we will do in that case.
>>>> + */
>>>
>>> Hmm, exposing the host opregion to a guest certainly feels like an issue.
>>
>> Well, that is how it is now. I am only retaining it to maintain backward
>> compatiblily with DM versions that do not support the extended VBT and
>> OpRegion 2+. My previous comment about backward compatibilty and DM
>> compatibility also applies here. If we don't worry about that, we can do
>> away with any cases where we are permanently mapping the host opregion to
>> the guest and implement this new approach of always exposing a copy of
>> the OpRegion and VBT to the guest instead.
>
> How does "permanently mapping" matter? hvmloader runs inside the guest, so
> exposure just to copy the data isn't any better in terms of this being a
> layering violation. The more correct thing to do might be for the DM to
> put in place a copy before the guest (i.e. hvmloader) even gains control.
> (How in turn the DM would learn of the contents of the opregion is a
> separate question then.)
Hi Jan,
I am working on v3 of this patch and I want v3 to address this problem of a
"layering violation" that you mentioned here, but I do not understand exactly
what you mean. Do you mean to say that the current code we have in place and
have had in place for over the past 10 years [1] in the Qemu DM that traps and
maps the OpRegion into the guest is a "layering violation?"
[1] https://xenbits.xen.org/gitweb/?p=qemu-xen.git;a=commitdiff;h=5cec8aa38cc
("xen, gfx passthrough: add opregion mapping")
>>>> + /*
>>>> + * Write rvda_host as 2 successive 32-bit values
>>>> + * to communicate location of the VBT to the device
>>>> + * model. If rvda_host is not 0, The device model
>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>> + * after we also write the guest address where the
>>>> + * VBT will be mapped.
>>>> + *
>>>> + * If we send rvda_host = 0 to the device model, it
>>>> + * will assume we do not need OpRegion 2 support and
>>>> + * it will not unmap the OpRegion.
>>>> + */
>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>> + (uint32_t)rvda_host_upper_32);
>>>
>>> Why would you need to communicate a host property to the DM?
>>
>> The DM cannot access the host rvda value because it is only accessible
>> from the host kernel, and the DM is only a user-space process on the host.
>
> I don't follow this: Anything the guest can access should also be accessible
> by its DM.
I also don't follow your comment here so permit me to comment and ask some
questions for clarification.
I was thinking it is enough for the domain the DM is running in to have
access to the resource for it to be legitimate for the DM to map the resource
into the guest. So I also think that whether or not the DM itself can access
the resource is irrelevant to the question. But you seem to be saying, no,
that is not enough, the DM itself should be able to access the resource
before it can be allowed to map the resource to its guest. Is that what you
are saying?
Perhaps your comment here is related to the concept of a "layering violation"
mentioned above. Are you saying it is a layering violation for the DM to
map an MMIO resource to its guest unless it actually has access to that
resource? If so, what kind of access to those device resources should the
DM have? Read access? Read/Write access?
If the specs only say the DM "should" have access to the resources it maps
into its guest, then I would think it would not be a layering violation.
But if the specs say the DM "must" have access before it asks the hypervisor
to map the resource to the guest, then I would admit that yes, we have a
layering violation because the DM is mapping the OpRegion to the guest
even though it does not have access to the OpRegion.
So, where are the specs for what the DM can and cannot do? Are they publicly
available, or are they proprietary or only available to members of the Linux
Foundation and/or the Xen Project? If the specs are publicly available, then
if possible, please show me the specific place in the specs where the Qemu DM
is violating the specs when it maps the OpRegion to its guest.
Thanks,
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-14 15:23 ` Chuck Zmudzinski
2026-08-14 16:18 ` Chuck Zmudzinski
2026-08-14 17:07 ` Chuck Zmudzinski
@ 2026-08-17 8:42 ` Jan Beulich
2026-08-17 16:04 ` Chuck Zmudzinski
2 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-17 8:42 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 14.08.2026 17:23, Chuck Zmudzinski wrote:
> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>> -- snip --
>>>>>>> To address this problem, this patch implements support for
>>>>>>> Intel IGD devices with an extended VBT and OpRegion version 2
>>>>>>> and higher which is required for most modern Intel IGD devices.
>>>>>>
>>>>>> First of all: Where's the spec of all of this?
>>>>>
>>>>> Well, your first question is quite provocative. Certainly more
>>>>> social/legal than technical.
>>>>
>>>> Well, it was very much meant to be technical. I've had a hard time following
>>>> what your new code does, and having a spec to hand would likely have helped.
>>>
>>> I agree that having the spec at hand would be better. To be more precise, I
>>> can say that what this patch essentially does is port the support for
>>> the extended VBT with OpRegion 2+ for the Intel IGD passthrough that exists
>>> in KVM/vfio to Xen. Should I explicitly say in the title of the commit
>>> message that this is a port of KVM/vfio support for extended VBT to Xen?
>>
>> Not in the title, as that would likely make it too long, but perhaps in the
>> description.
>
> Ok.
>
>>
>>>>> So my answer is as follows:
>>>>>
>>>>> I do not have access to the official spec that defines "all this" but
>>>>> I do have access, as does the general public, to the Linux kernel's
>>>>> implementation of support for the Intel IGD from many sources such as
>>>>> git.kernel.org. The Linux kernel has enough accurate information about
>>>>> the spec of "all this" to provide very good support for the Intel IGD
>>>>> on bare metal.
>>>>>
>>>>> To elaborate a bit more, the spec of "all this" can be derived from the
>>>>> Linux kernel code that supports the Intel IGD.
>>>>
>>>> So you expect every reader to locate and decipher the underlying information
>>>> from a (afaik) pretty large piece of code in the Linux kernel? If the Linux
>>>> kernel sources are the reference, please can you at least provide pointers
>>>> into there?
>>>
>>> No, I do not expect every reader to decipher the underlying information...
>>>
>>> That is why I provided these two links at the bottom of the commit message.
>>> Perhaps you did not notice them:
>>>
>>> Link: https://lore.kernel.org/kvm/20211012124855.52463-1-colin.xu@gmail.com/
>>> Link: https://lore.kernel.org/kvm/20210325170953.24549-1-fred.gao@intel.com/
>>>
>>> They are the patches to the vfio kernel driver that added support for the
>>> extended VBT for KVM/vfio guests.
>>
>> Patches can still be in flight, so provide only limited help. Would it be a
>> problem to instead reference commits, or the actual localtion in Linux
>> sources?
>
> No problem. I will format references to kernel commits the way it was done in
> this commit message of commit 99794c8a8ff8 in the Xen tree that references
> some Linux kernel commits unless you suggest a better way to reference Linux
> kernel commits:
>
> xen/acpi: Import PPTT definitions from Linux
>
> Import the Processor Properties Topology Table (PPTT) definitions
> from the Linux kernel header (include/acpi/actbl2.h) into Xen.
>
> Signed-off-by: Hirokazu Takahashi <taka@valinux.co.jp>
> Origin: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git b8355bcac253
> Origin: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git e62f8227851d
> Origin: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 091c4af3562d
I expect though that Origin: tags would be questionable to use in your case.
Can't you simply use URLs pointing at the commits in Lunus'es tree?
>>>>>>> + printf("VBT size: 0x%x\n", rvds);
>>>>>>> +
>>>>>>> + if ( !rvds || !rvda_host ) {
>>>>>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>>>>>> + rvda_host = 0;
>>>>>>> + }
>>>>>>> + /*
>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>> + * to communicate location of the VBT to the device
>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>> + * after we also write the guest address where the
>>>>>>> + * VBT will be mapped.
>>>>>>> + *
>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>> + * it will not unmap the OpRegion.
>>>>>>> + */
>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>
>>>>>> Why would you need to communicate a host property to the DM?
>>>>>
>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>
>>>> I don't follow this: Anything the guest can access should also be accessible
>>>> by its DM.
>>>
>>> I think the host OpRegion is not currently accessible by the DM.
>>
>> Can you explain to me how the region becomes accessible to the guest?
>> That would then (hopefully) help me understand why the DM would not have
>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>> guest are also assigned to its DM.
>
> Currently, in the device model (Qemu) we have:
>
> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> XEN_PCI_INTEL_OPREGION_PAGES,
> DPCI_ADD_MAPPING);
>
> That statement is in the igd_write_opregion(...) function in the
> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>
> If I understand our current implementation correctly, this statement
> is what gives the guest access to the host OpRegion (3 pages as defined
> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
> in hvmloader code).
No, it introduces mappings of those pages into the guest's P2M.
> I don't think this statement makes the host OpRegion
> accessible to the device model, though, so I think, if I understand your
> comment in an earlier about my patch resulting in what you called a "layering
> violation" correctly, that our current implementation is also guilty of this
> same kind of "layering violation."
That code, if it can be successfully executed, indeed doesn't grant any
permissions (to the DM or the guest). Instead it proves that the DM has the
needed permissions to access the pages itself. This is what the handling of
XEN_DOMCTL_memory_mapping has in this regard:
ret = -EPERM;
if ( !iomem_access_permitted(current->domain, mfn, mfn_end) )
/* Nothing. */;
Subsequently we check that the guest is also permitted access:
else if ( iomem_access_permitted(d, mfn, mfn_end) )
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-15 2:22 ` Chuck Zmudzinski
@ 2026-08-17 9:11 ` Jan Beulich
0 siblings, 0 replies; 42+ messages in thread
From: Jan Beulich @ 2026-08-17 9:11 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 15.08.2026 04:22, Chuck Zmudzinski wrote:
> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>> + printf("VBT size: 0x%x\n", rvds);
>>>>>>> +
>>>>>>> + if ( !rvds || !rvda_host ) {
>>>>>>> + printf("guest OpRegion address: 0x%x\n", igd_guest_opregion);
>>>>>>> + rvda_host = 0;
>>>>>>> + }
>>>>>>> + /*
>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>> + * to communicate location of the VBT to the device
>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>> + * after we also write the guest address where the
>>>>>>> + * VBT will be mapped.
>>>>>>> + *
>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>> + * it will not unmap the OpRegion.
>>>>>>> + */
>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>
>>>>>> Why would you need to communicate a host property to the DM?
>>>>>
>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>
>>>> I don't follow this: Anything the guest can access should also be accessible
>>>> by its DM.
>>>
>>> I think the host OpRegion is not currently accessible by the DM.
>>
>> Can you explain to me how the region becomes accessible to the guest?
>> That would then (hopefully) help me understand why the DM would not have
>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>> guest are also assigned to its DM.
>
> This is what I don't understand about your objection to how both the current
> implementation and my proposed changes makes the host OpRegion accessible to
> the guest. What do you mean when you say any MMIO and I/O ports assigned to
> a guest are also assigned to its DM? What does it mean to assign an MMIO
> region to a DM? Is it the DM you mean or the DM domain, which need not be
> dom0 if we are running the device model in an unprivileged domain.
The DM domain is what I meant. I thought that was clear / unambiguous here,
but apparently it wasn't: Sorry. Beyond that I hope that my reply to your
earlier mail provides sufficient further context.
> I also
> am presuming you know that dom0 for Intel IGD passthrough is a PV dom0,
> not a PVH dom0. I have never tried Intel IGD passthrough with a PVH dom0,
> because as far as I can tell vt-d is not supported with PVH dom0.
I don't see why PVH Dom0 would start to matter here all of the sudden.
> Take a look at this code from our current implementation in qemu-xen. This
> is from the current master branch of qemu-xen on xenbits.xen.org, the
> hw/xen/xen_pt_graphics.c file, the igd_write_opregion function:
>
> --- snip ---
>
> #define XEN_PCI_INTEL_OPREGION_PAGES 0x3
> #define XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED 0x1
> void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val)
> {
> int ret;
>
> if (igd_guest_opregion) {
> XEN_PT_LOG(&s->dev, "opregion register already been set, ignoring %x\n",
> val);
> return;
> }
>
> /* We just work with LE. */
> xen_host_pci_get_block(&s->real_device, XEN_PCI_INTEL_OPREGION,
> (uint8_t *)&igd_host_opregion, 4);
> igd_guest_opregion = (unsigned long)(val & ~XEN_PCI_INTEL_OPREGION_MASK)
> | (igd_host_opregion & XEN_PCI_INTEL_OPREGION_MASK);
>
> ret = xc_domain_iomem_permission(xen_xc, xen_domid,
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> XEN_PCI_INTEL_OPREGION_PAGES,
> XEN_PCI_INTEL_OPREGION_ENABLE_ACCESSED);
So this is where permissions are granted (wrongly imo, as I think permissions
for MMIO or I/O ports should only ever be granted by the control domain).
> if (ret) {
> XEN_PT_ERR(&s->dev, "[%d]:Can't enable to access IGD host opregion:"
> " 0x%lx.\n", ret,
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT)),
> igd_guest_opregion = 0;
> return;
> }
>
> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> XEN_PCI_INTEL_OPREGION_PAGES,
> DPCI_ADD_MAPPING);
This is where, as said in the earlier reply, a mapping is installed in the
guest's P2M.
> if (ret) {
> XEN_PT_ERR(&s->dev, "[%d]:Can't map IGD host opregion:0x%lx to"
> " guest opregion:0x%lx.\n", ret,
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
> igd_guest_opregion = 0;
> return;
> }
>
> XEN_PT_LOG(&s->dev, "Map OpRegion: 0x%lx -> 0x%lx\n",
> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT));
> }
>
> [...]
>
> Do you understand now?
Yes, and as said in the earlier reply: This demonstrates that the DM does
have permission to access the pages in question.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-16 16:38 ` Chuck Zmudzinski
@ 2026-08-17 9:18 ` Jan Beulich
0 siblings, 0 replies; 42+ messages in thread
From: Jan Beulich @ 2026-08-17 9:18 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel, Anthony PERARD
On 16.08.2026 18:38, Chuck Zmudzinski wrote:
> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>> -- snip --
>>>>> + /*
>>>>> + * Read the value the device model is initialized with.
>>>>> + * If the device model supports OpRegion 2, it will
>>>>> + * return the host IGD OpRegion address. If not, it
>>>>> + * will return 0. If the device model does not support
>>>>> + * OpRegion 2, the device model expects us to give it
>>>>> + * the address to which it will map the OpRegion in the
>>>>> + * guest and then expects us to do nothing more to setup
>>>>> + * the OpRegion, so that is all we will do in that case.
>>>>> + */
>>>>
>>>> Hmm, exposing the host opregion to a guest certainly feels like an issue.
>>>
>>> Well, that is how it is now. I am only retaining it to maintain backward
>>> compatiblily with DM versions that do not support the extended VBT and
>>> OpRegion 2+. My previous comment about backward compatibilty and DM
>>> compatibility also applies here. If we don't worry about that, we can do
>>> away with any cases where we are permanently mapping the host opregion to
>>> the guest and implement this new approach of always exposing a copy of
>>> the OpRegion and VBT to the guest instead.
>>
>> How does "permanently mapping" matter? hvmloader runs inside the guest, so
>> exposure just to copy the data isn't any better in terms of this being a
>> layering violation. The more correct thing to do might be for the DM to
>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>> (How in turn the DM would learn of the contents of the opregion is a
>> separate question then.)
>
> I am working on v3 of this patch and I want v3 to address this problem of a
> "layering violation" that you mentioned here, but I do not understand exactly
> what you mean. Do you mean to say that the current code we have in place and
> have had in place for over the past 10 years [1] in the Qemu DM that traps and
> maps the OpRegion into the guest is a "layering violation?"
>
> [1] https://xenbits.xen.org/gitweb/?p=qemu-xen.git;a=commitdiff;h=5cec8aa38cc
> ("xen, gfx passthrough: add opregion mapping")
All I can say is that this at least smells like a layering violation. It maybe
wouldn't have if, in your patch, you didn't demonstrate that the machine page
range doesn't really need mapping, as copying the data and providing that to
the guest is sufficient. In such a case, the machine range should (imo) never
have been exposed. After all the guest then can fiddle with it, potentially
breaking later guests that are to also use the region.
>>>>> + /*
>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>> + * to communicate location of the VBT to the device
>>>>> + * model. If rvda_host is not 0, The device model
>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>> + * after we also write the guest address where the
>>>>> + * VBT will be mapped.
>>>>> + *
>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>> + * will assume we do not need OpRegion 2 support and
>>>>> + * it will not unmap the OpRegion.
>>>>> + */
>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>> + (uint32_t)rvda_host_upper_32);
>>>>
>>>> Why would you need to communicate a host property to the DM?
>>>
>>> The DM cannot access the host rvda value because it is only accessible
>>> from the host kernel, and the DM is only a user-space process on the host.
>>
>> I don't follow this: Anything the guest can access should also be accessible
>> by its DM.
>
> I also don't follow your comment here so permit me to comment and ask some
> questions for clarification.
>
> I was thinking it is enough for the domain the DM is running in to have
> access to the resource for it to be legitimate for the DM to map the resource
> into the guest. So I also think that whether or not the DM itself can access
> the resource is irrelevant to the question. But you seem to be saying, no,
> that is not enough, the DM itself should be able to access the resource
> before it can be allowed to map the resource to its guest. Is that what you
> are saying?
That depends on what you mean by "access": The prereq is that the DM have
permission to access the pages. It may not have an active mapping thereof.
> Perhaps your comment here is related to the concept of a "layering violation"
> mentioned above. Are you saying it is a layering violation for the DM to
> map an MMIO resource to its guest unless it actually has access to that
> resource? If so, what kind of access to those device resources should the
> DM have? Read access? Read/Write access?
No, I'm trying to bring across that (as said above) access to machine pages
should not be granted when that isn't necessary. As in here: A copy of the
pages looks to suffice, so simply give the guest access to a copy.
> If the specs only say the DM "should" have access to the resources it maps
> into its guest, then I would think it would not be a layering violation.
> But if the specs say the DM "must" have access before it asks the hypervisor
> to map the resource to the guest, then I would admit that yes, we have a
> layering violation because the DM is mapping the OpRegion to the guest
> even though it does not have access to the OpRegion.
>
> So, where are the specs for what the DM can and cannot do? Are they publicly
> available, or are they proprietary or only available to members of the Linux
> Foundation and/or the Xen Project?
Sadly the source code (of Xen and/or qemu) is the spec.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-17 8:42 ` Jan Beulich
@ 2026-08-17 16:04 ` Chuck Zmudzinski
2026-08-17 17:04 ` Chuck Zmudzinski
2026-08-18 7:17 ` Jan Beulich
0 siblings, 2 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-17 16:04 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/17/2026 4:42 AM, Jan Beulich wrote:
> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>> -- snip --
>>>>>>>> + /*
>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>> + * after we also write the guest address where the
>>>>>>>> + * VBT will be mapped.
>>>>>>>> + *
>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>> + */
>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>
>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>
>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>
>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>> by its DM.
>>>>
>>>> I think the host OpRegion is not currently accessible by the DM.
>>>
>>> Can you explain to me how the region becomes accessible to the guest?
>>> That would then (hopefully) help me understand why the DM would not have
>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>> guest are also assigned to its DM.
>>
>> Currently, in the device model (Qemu) we have:
>>
>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>> XEN_PCI_INTEL_OPREGION_PAGES,
>> DPCI_ADD_MAPPING);
>>
>> That statement is in the igd_write_opregion(...) function in the
>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>
>> If I understand our current implementation correctly, this statement
>> is what gives the guest access to the host OpRegion (3 pages as defined
>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>> in hvmloader code).
>
> No, it introduces mappings of those pages into the guest's P2M.
>
>> I don't think this statement makes the host OpRegion
>> accessible to the device model, though, so I think, if I understand your
>> comment in an earlier about my patch resulting in what you called a "layering
>> violation" correctly, that our current implementation is also guilty of this
>> same kind of "layering violation."
>
> That code, if it can be successfully executed, indeed doesn't grant any
> permissions (to the DM or the guest). Instead it proves that the DM has the
> needed permissions to access the pages itself.
So, are you saying it should be possible, without any patches to either Xen or
the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
I think I could implement what you proposed in an earlier message and do
all (or most) of this in the DM instead of here in hvmloader:
> The more correct thing to do might be for the DM to
> put in place a copy before the guest (i.e. hvmloader) even gains control.
> (How in turn the DM would learn of the contents of the opregion is a
> separate question then.)
Actually, when I was developing this patch, I tried first to do it that
way, but the problem was, I could not find a way to get a pointer to the
host OpRegion in Qemu.
So, how can I get a pointer to the host OpRegion in Qemu?
This is what the handling of
> XEN_DOMCTL_memory_mapping has in this regard:
>
> ret = -EPERM;
> if ( !iomem_access_permitted(current->domain, mfn, mfn_end) )
> /* Nothing. */;
>
> Subsequently we check that the guest is also permitted access:
>
> else if ( iomem_access_permitted(d, mfn, mfn_end) )
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-17 16:04 ` Chuck Zmudzinski
@ 2026-08-17 17:04 ` Chuck Zmudzinski
2026-08-18 7:17 ` Jan Beulich
1 sibling, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-17 17:04 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/17/2026 12:04 PM, Chuck Zmudzinski wrote:
> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>> -- snip --
>>>>>>>>> + /*
>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>> + * VBT will be mapped.
>>>>>>>>> + *
>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>> + */
>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>
>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>
>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>
>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>> by its DM.
>>>>>
>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>
>>>> Can you explain to me how the region becomes accessible to the guest?
>>>> That would then (hopefully) help me understand why the DM would not have
>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>> guest are also assigned to its DM.
>>>
>>> Currently, in the device model (Qemu) we have:
>>>
>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>> DPCI_ADD_MAPPING);
>>>
>>> That statement is in the igd_write_opregion(...) function in the
>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>
>>> If I understand our current implementation correctly, this statement
>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>> in hvmloader code).
>>
>> No, it introduces mappings of those pages into the guest's P2M.
>>
>>> I don't think this statement makes the host OpRegion
>>> accessible to the device model, though, so I think, if I understand your
>>> comment in an earlier about my patch resulting in what you called a "layering
>>> violation" correctly, that our current implementation is also guilty of this
>>> same kind of "layering violation."
>>
>> That code, if it can be successfully executed, indeed doesn't grant any
>> permissions (to the DM or the guest). Instead it proves that the DM has the
>> needed permissions to access the pages itself.
>
> So, are you saying it should be possible, without any patches to either Xen or
> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>
> I think I could implement what you proposed in an earlier message and do
> all (or most) of this in the DM instead of here in hvmloader:
>
>> The more correct thing to do might be for the DM to
>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>> (How in turn the DM would learn of the contents of the opregion is a
>> separate question then.)
>
> Actually, when I was developing this patch, I tried first to do it that
> way, but the problem was, I could not find a way to get a pointer to the
> host OpRegion in Qemu.
>
> So, how can I get a pointer to the host OpRegion in Qemu?
>
I also think that if we use a fully emulated copy of the OpRegion
instead of passing it through, we might not need to allocate space for
it in the RESERVED region and allocate it instead contiguous with the
rest of the NVS region. This means we might be able to avoid needing
to split the REVERSED region in hvmloader/e820.c which is currently
done like this:
/*
* If igd_opregion_pgbase we need to split the RESERVED region in two.
*/
if ( igd_opregion_pgbase )
{
uint32_t igd_opregion_base = igd_opregion_pgbase << PAGE_SHIFT;
e820[nr].addr = acpi_mem_end;
e820[nr].size = igd_opregion_base - acpi_mem_end;
e820[nr].type = E820_RESERVED;
nr++;
e820[nr].addr = igd_opregion_base;
e820[nr].size = IGD_OPREGION_PAGES * PAGE_SIZE;
e820[nr].type = E820_NVS;
nr++;
e820[nr].addr = igd_opregion_base + IGD_OPREGION_PAGES * PAGE_SIZE;
e820[nr].size = (uint32_t)-e820[nr].addr;
e820[nr].type = E820_RESERVED;
nr++;
}
else
{
e820[nr].addr = acpi_mem_end;
e820[nr].size = (uint32_t)-e820[nr].addr;
e820[nr].type = E820_RESERVED;
nr++;
}
I am not sure this would work but I think the need to map the OpRegion
to the RESERVED region arises from the fact that currently it is passed
directly mapped from the host. I think I will try it out and see if that
would work.
>> This is what the handling of
>> XEN_DOMCTL_memory_mapping has in this regard:
>>
>> ret = -EPERM;
>> if ( !iomem_access_permitted(current->domain, mfn, mfn_end) )
>> /* Nothing. */;
>>
>> Subsequently we check that the guest is also permitted access:
>>
>> else if ( iomem_access_permitted(d, mfn, mfn_end) )
>
>
>
>
>
>>
>> Jan
>
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-17 16:04 ` Chuck Zmudzinski
2026-08-17 17:04 ` Chuck Zmudzinski
@ 2026-08-18 7:17 ` Jan Beulich
2026-08-18 11:52 ` Chuck Zmudzinski
1 sibling, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-18 7:17 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 17.08.2026 18:04, Chuck Zmudzinski wrote:
> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>> -- snip --
>>>>>>>>> + /*
>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>> + * VBT will be mapped.
>>>>>>>>> + *
>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>> + */
>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>
>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>
>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>
>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>> by its DM.
>>>>>
>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>
>>>> Can you explain to me how the region becomes accessible to the guest?
>>>> That would then (hopefully) help me understand why the DM would not have
>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>> guest are also assigned to its DM.
>>>
>>> Currently, in the device model (Qemu) we have:
>>>
>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>> DPCI_ADD_MAPPING);
>>>
>>> That statement is in the igd_write_opregion(...) function in the
>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>
>>> If I understand our current implementation correctly, this statement
>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>> in hvmloader code).
>>
>> No, it introduces mappings of those pages into the guest's P2M.
>>
>>> I don't think this statement makes the host OpRegion
>>> accessible to the device model, though, so I think, if I understand your
>>> comment in an earlier about my patch resulting in what you called a "layering
>>> violation" correctly, that our current implementation is also guilty of this
>>> same kind of "layering violation."
>>
>> That code, if it can be successfully executed, indeed doesn't grant any
>> permissions (to the DM or the guest). Instead it proves that the DM has the
>> needed permissions to access the pages itself.
>
> So, are you saying it should be possible, without any patches to either Xen or
> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>
> I think I could implement what you proposed in an earlier message and do
> all (or most) of this in the DM instead of here in hvmloader:
>
>> The more correct thing to do might be for the DM to
>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>> (How in turn the DM would learn of the contents of the opregion is a
>> separate question then.)
>
> Actually, when I was developing this patch, I tried first to do it that
> way, but the problem was, I could not find a way to get a pointer to the
> host OpRegion in Qemu.
>
> So, how can I get a pointer to the host OpRegion in Qemu?
You don't ask me this question, do you? All I can say is that surely qemu
has an existing way to map (host) physical memory; see e.g. how
xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
device. "Bogusly" there because that's another layering violation. Plus
(independently) there and here there's the issue of how to accomplish
things when not running in Dom0, or when running de-privileged in Dom0.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-18 7:17 ` Jan Beulich
@ 2026-08-18 11:52 ` Chuck Zmudzinski
2026-08-18 12:18 ` Jan Beulich
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-18 11:52 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/18/2026 3:17 AM, Jan Beulich wrote:
> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>> -- snip --
>>>>>>>>>> + /*
>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>> + *
>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>> + */
>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>
>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>
>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>
>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>> by its DM.
>>>>>>
>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>
>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>> guest are also assigned to its DM.
>>>>
>>>> Currently, in the device model (Qemu) we have:
>>>>
>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>> DPCI_ADD_MAPPING);
>>>>
>>>> That statement is in the igd_write_opregion(...) function in the
>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>
>>>> If I understand our current implementation correctly, this statement
>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>> in hvmloader code).
>>>
>>> No, it introduces mappings of those pages into the guest's P2M.
>>>
>>>> I don't think this statement makes the host OpRegion
>>>> accessible to the device model, though, so I think, if I understand your
>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>> violation" correctly, that our current implementation is also guilty of this
>>>> same kind of "layering violation."
>>>
>>> That code, if it can be successfully executed, indeed doesn't grant any
>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>> needed permissions to access the pages itself.
>>
>> So, are you saying it should be possible, without any patches to either Xen or
>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>
>> I think I could implement what you proposed in an earlier message and do
>> all (or most) of this in the DM instead of here in hvmloader:
>>
>>> The more correct thing to do might be for the DM to
>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>> (How in turn the DM would learn of the contents of the opregion is a
>>> separate question then.)
>>
>> Actually, when I was developing this patch, I tried first to do it that
>> way, but the problem was, I could not find a way to get a pointer to the
>> host OpRegion in Qemu.
>>
>> So, how can I get a pointer to the host OpRegion in Qemu?
>
> You don't ask me this question, do you?
Are you offended I asked this question? If so, I am sorry. You make me
afraid to ask it again so I will not do so unless you permit to do so
again.
All I can say is that surely qemu
> has an existing way to map (host) physical memory; see e.g. how
> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
> device. "Bogusly" there because that's another layering violation. Plus
> (independently) there and here there's the issue of how to accomplish
> things when not running in Dom0, or when running de-privileged in Dom0.
Well, that only proves Qemu *might* be able to access the MSI-X table of
a device, that is, if the calls to open /dev/mem and mmap it succeed.
Why is the MSI-X table all of the sudden relevant? Even if Qemu
can access the MSI-X table of some device, that does not prove that
Qemu can access the host OpRegion of an Intel IGD. So I think my point
still stands: I still don't see proof that it is possible for Qemu
to get a pointer to the host OpRegion without any patches to the current
implementations of Xen and the Linux kernel.
Perhaps I should accept your indications that it must be possible to get a
pointer to the host OpRegion. I will admit maybe it is possible and I have
not yet found out how to do it, but I have hardware I can experiment
with, and for me, that is the final authority. Proof for me only comes
from my own tests and experiments that I conduct on my hardware. Until I
see how I can get a pointer to the OpRegion in Qemu on my hardware and
actually realize that goal, I remain skeptical that it is possible to do
so solely by patching Qemu and not patching either Xen or the Linux kernel.
Chuck
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-18 11:52 ` Chuck Zmudzinski
@ 2026-08-18 12:18 ` Jan Beulich
2026-08-18 12:29 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-18 12:18 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 18.08.2026 13:52, Chuck Zmudzinski wrote:
> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>> -- snip --
>>>>>>>>>>> + /*
>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>> + *
>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>> + */
>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>
>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>
>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>
>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>> by its DM.
>>>>>>>
>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>
>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>> guest are also assigned to its DM.
>>>>>
>>>>> Currently, in the device model (Qemu) we have:
>>>>>
>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>> DPCI_ADD_MAPPING);
>>>>>
>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>
>>>>> If I understand our current implementation correctly, this statement
>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>> in hvmloader code).
>>>>
>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>
>>>>> I don't think this statement makes the host OpRegion
>>>>> accessible to the device model, though, so I think, if I understand your
>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>> same kind of "layering violation."
>>>>
>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>> needed permissions to access the pages itself.
>>>
>>> So, are you saying it should be possible, without any patches to either Xen or
>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>
>>> I think I could implement what you proposed in an earlier message and do
>>> all (or most) of this in the DM instead of here in hvmloader:
>>>
>>>> The more correct thing to do might be for the DM to
>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>> separate question then.)
>>>
>>> Actually, when I was developing this patch, I tried first to do it that
>>> way, but the problem was, I could not find a way to get a pointer to the
>>> host OpRegion in Qemu.
>>>
>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>
>> You don't ask me this question, do you?
>
> Are you offended I asked this question? If so, I am sorry. You make me
> afraid to ask it again so I will not do so unless you permit to do so
> again.
"Offended" is the wrong word; "very puzzled" may better get it. I'm not a
qemu person, and I never have been. I can't really help much there.
> All I can say is that surely qemu
>> has an existing way to map (host) physical memory; see e.g. how
>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>> device. "Bogusly" there because that's another layering violation. Plus
>> (independently) there and here there's the issue of how to accomplish
>> things when not running in Dom0, or when running de-privileged in Dom0.
>
> Well, that only proves Qemu *might* be able to access the MSI-X table of
> a device, that is, if the calls to open /dev/mem and mmap it succeed.
> Why is the MSI-X table all of the sudden relevant? Even if Qemu
> can access the MSI-X table of some device, that does not prove that
> Qemu can access the host OpRegion of an Intel IGD. So I think my point
> still stands: I still don't see proof that it is possible for Qemu
> to get a pointer to the host OpRegion without any patches to the current
> implementations of Xen and the Linux kernel.
The MSI-X table (and it being accessible to qemu) is the best analogy I
could come up with, as that's one tiny area of qemu that I know at least
a little.
From a Xen perspective, this analogy should be sufficient: All you need
from Xen is for it to permit to establish mappings of the underlying page.
As I've pointed out when commenting on a code fragment you presented, the
DM (domain) looks to have permission. Everything else is a matter of
establishing such a mapping. There the MSI-X table code may also guide
you. (Sadly it may also misguide you, since (a) I don't know whether it's
appropriate to do things this way in qemu, and since (b) it is, as said,
imo a layering violation.)
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-18 12:18 ` Jan Beulich
@ 2026-08-18 12:29 ` Chuck Zmudzinski
2026-08-18 17:15 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-18 12:29 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/18/2026 8:18 AM, Jan Beulich wrote:
> On 18.08.2026 13:52, Chuck Zmudzinski wrote:
>> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>>> -- snip --
>>>>>>>>>>>> + /*
>>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>>> + *
>>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>>> + */
>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>>
>>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>>
>>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>>
>>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>>> by its DM.
>>>>>>>>
>>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>>
>>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>>> guest are also assigned to its DM.
>>>>>>
>>>>>> Currently, in the device model (Qemu) we have:
>>>>>>
>>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>>> DPCI_ADD_MAPPING);
>>>>>>
>>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>>
>>>>>> If I understand our current implementation correctly, this statement
>>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>>> in hvmloader code).
>>>>>
>>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>>
>>>>>> I don't think this statement makes the host OpRegion
>>>>>> accessible to the device model, though, so I think, if I understand your
>>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>>> same kind of "layering violation."
>>>>>
>>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>>> needed permissions to access the pages itself.
>>>>
>>>> So, are you saying it should be possible, without any patches to either Xen or
>>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>>
>>>> I think I could implement what you proposed in an earlier message and do
>>>> all (or most) of this in the DM instead of here in hvmloader:
>>>>
>>>>> The more correct thing to do might be for the DM to
>>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>>> separate question then.)
>>>>
>>>> Actually, when I was developing this patch, I tried first to do it that
>>>> way, but the problem was, I could not find a way to get a pointer to the
>>>> host OpRegion in Qemu.
>>>>
>>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>>
>>> You don't ask me this question, do you?
>>
>> Are you offended I asked this question? If so, I am sorry. You make me
>> afraid to ask it again so I will not do so unless you permit to do so
>> again.
>
> "Offended" is the wrong word; "very puzzled" may better get it. I'm not a
> qemu person, and I never have been. I can't really help much there.
>
>> All I can say is that surely qemu
>>> has an existing way to map (host) physical memory; see e.g. how
>>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>>> device. "Bogusly" there because that's another layering violation. Plus
>>> (independently) there and here there's the issue of how to accomplish
>>> things when not running in Dom0, or when running de-privileged in Dom0.
>>
>> Well, that only proves Qemu *might* be able to access the MSI-X table of
>> a device, that is, if the calls to open /dev/mem and mmap it succeed.
>> Why is the MSI-X table all of the sudden relevant? Even if Qemu
>> can access the MSI-X table of some device, that does not prove that
>> Qemu can access the host OpRegion of an Intel IGD. So I think my point
>> still stands: I still don't see proof that it is possible for Qemu
>> to get a pointer to the host OpRegion without any patches to the current
>> implementations of Xen and the Linux kernel.
>
> The MSI-X table (and it being accessible to qemu) is the best analogy I
> could come up with, as that's one tiny area of qemu that I know at least
> a little.
>
> From a Xen perspective, this analogy should be sufficient: All you need
> from Xen is for it to permit to establish mappings of the underlying page.
> As I've pointed out when commenting on a code fragment you presented, the
> DM (domain) looks to have permission. Everything else is a matter of
> establishing such a mapping. There the MSI-X table code may also guide
> you. (Sadly it may also misguide you, since (a) I don't know whether it's
> appropriate to do things this way in qemu, and since (b) it is, as said,
> imo a layering violation.)
I agree that accessing the host /dev/mem directly is cringy. I would not
really want to do it that way for the host OpRegion.
Chuck
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-18 12:29 ` Chuck Zmudzinski
@ 2026-08-18 17:15 ` Chuck Zmudzinski
2026-08-19 7:30 ` Jan Beulich
2026-08-19 12:10 ` Chuck Zmudzinski
0 siblings, 2 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-18 17:15 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/18/2026 8:29 AM, Chuck Zmudzinski wrote:
> On 8/18/2026 8:18 AM, Jan Beulich wrote:
>> On 18.08.2026 13:52, Chuck Zmudzinski wrote:
>>> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>>>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>>>> -- snip --
>>>>>>>>>>>>> + /*
>>>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>>>> + *
>>>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>>>> + */
>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>>>
>>>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>>>
>>>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>>>
>>>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>>>> by its DM.
>>>>>>>>>
>>>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>>>
>>>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>>>> guest are also assigned to its DM.
>>>>>>>
>>>>>>> Currently, in the device model (Qemu) we have:
>>>>>>>
>>>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>>>> DPCI_ADD_MAPPING);
>>>>>>>
>>>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>>>
>>>>>>> If I understand our current implementation correctly, this statement
>>>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>>>> in hvmloader code).
>>>>>>
>>>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>>>
>>>>>>> I don't think this statement makes the host OpRegion
>>>>>>> accessible to the device model, though, so I think, if I understand your
>>>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>>>> same kind of "layering violation."
>>>>>>
>>>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>>>> needed permissions to access the pages itself.
>>>>>
>>>>> So, are you saying it should be possible, without any patches to either Xen or
>>>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>>>
>>>>> I think I could implement what you proposed in an earlier message and do
>>>>> all (or most) of this in the DM instead of here in hvmloader:
>>>>>
>>>>>> The more correct thing to do might be for the DM to
>>>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>>>> separate question then.)
>>>>>
>>>>> Actually, when I was developing this patch, I tried first to do it that
>>>>> way, but the problem was, I could not find a way to get a pointer to the
>>>>> host OpRegion in Qemu.
>>>>>
>>>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>>>
>>>> You don't ask me this question, do you?
>>>
>>> Are you offended I asked this question? If so, I am sorry. You make me
>>> afraid to ask it again so I will not do so unless you permit to do so
>>> again.
>>
>> "Offended" is the wrong word; "very puzzled" may better get it. I'm not a
>> qemu person, and I never have been. I can't really help much there.
>>
>>> All I can say is that surely qemu
>>>> has an existing way to map (host) physical memory; see e.g. how
>>>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>>>> device. "Bogusly" there because that's another layering violation. Plus
>>>> (independently) there and here there's the issue of how to accomplish
>>>> things when not running in Dom0, or when running de-privileged in Dom0.
>>>
>>> Well, that only proves Qemu *might* be able to access the MSI-X table of
>>> a device, that is, if the calls to open /dev/mem and mmap it succeed.
>>> Why is the MSI-X table all of the sudden relevant? Even if Qemu
>>> can access the MSI-X table of some device, that does not prove that
>>> Qemu can access the host OpRegion of an Intel IGD. So I think my point
>>> still stands: I still don't see proof that it is possible for Qemu
>>> to get a pointer to the host OpRegion without any patches to the current
>>> implementations of Xen and the Linux kernel.
>>
>> The MSI-X table (and it being accessible to qemu) is the best analogy I
>> could come up with, as that's one tiny area of qemu that I know at least
>> a little.
>>
>> From a Xen perspective, this analogy should be sufficient: All you need
>> from Xen is for it to permit to establish mappings of the underlying page.
>> As I've pointed out when commenting on a code fragment you presented, the
>> DM (domain) looks to have permission. Everything else is a matter of
>> establishing such a mapping. There the MSI-X table code may also guide
>> you. (Sadly it may also misguide you, since (a) I don't know whether it's
>> appropriate to do things this way in qemu, and since (b) it is, as said,
>> imo a layering violation.)
>
> I agree that accessing the host /dev/mem directly is cringy. I would not
> really want to do it that way for the host OpRegion.
I looked at the current mainline Linux kernel code about access to memory using
/dev/mem and modern distros set CONFIG_STRICT_DEVMEM which forbids access to
ordinary system RAM but allows access to what the kernel developers call
non-kernel memory. Here is a quote from a comment in arch/x86/mm/init.c file
in the Linux source code:
> * On x86, access has to be given to the first megabyte of RAM because that
> * area traditionally contains BIOS code and data regions used by X, dosemu,
> * and similar apps. Since they map the entire memory range, the whole range
> * must be allowed (for mapping), but any areas that would otherwise be
> * disallowed are flagged as being "zero filled" instead of rejected.
> * Access has to be given to non-kernel-ram areas as well, these contain the
> * PCI mmio resources as well as potential bios/acpi data regions.
So I think things like the MSI-X table and the OpRegion would qualify for
/dev/men access even with CONFIG_STRICT_DEVMEM set, so after seeing this
I expect I could get a pointer to the OpRegion running in Qemu using
/dev/mem and mmap, as long as it is running in dom0 with root privileges.
But as I said earlier, I agree that /dev/mem and mmap does not feel like
the right way to do it.
So I would like to come back to something else you said in an earlier message:
> (How in turn the DM would learn of the contents of the opregion is a separate
> question then.)
Let me phrase the question like this: How could the DM gain access to the contents
of the OpRegion, and for that matter, also the contents of the MSI-X table, without
also committing a layering violation?
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-18 17:15 ` Chuck Zmudzinski
@ 2026-08-19 7:30 ` Jan Beulich
2026-08-19 12:16 ` Chuck Zmudzinski
2026-08-19 12:10 ` Chuck Zmudzinski
1 sibling, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-19 7:30 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 18.08.2026 19:15, Chuck Zmudzinski wrote:
> On 8/18/2026 8:29 AM, Chuck Zmudzinski wrote:
>> On 8/18/2026 8:18 AM, Jan Beulich wrote:
>>> On 18.08.2026 13:52, Chuck Zmudzinski wrote:
>>>> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>>>>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>>>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>>>>> -- snip --
>>>>>>>>>>>>>> + /*
>>>>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>>>>> + *
>>>>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>>>>> + */
>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>>>>
>>>>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>>>>
>>>>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>>>>
>>>>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>>>>> by its DM.
>>>>>>>>>>
>>>>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>>>>
>>>>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>>>>> guest are also assigned to its DM.
>>>>>>>>
>>>>>>>> Currently, in the device model (Qemu) we have:
>>>>>>>>
>>>>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>>>>> DPCI_ADD_MAPPING);
>>>>>>>>
>>>>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>>>>
>>>>>>>> If I understand our current implementation correctly, this statement
>>>>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>>>>> in hvmloader code).
>>>>>>>
>>>>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>>>>
>>>>>>>> I don't think this statement makes the host OpRegion
>>>>>>>> accessible to the device model, though, so I think, if I understand your
>>>>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>>>>> same kind of "layering violation."
>>>>>>>
>>>>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>>>>> needed permissions to access the pages itself.
>>>>>>
>>>>>> So, are you saying it should be possible, without any patches to either Xen or
>>>>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>>>>
>>>>>> I think I could implement what you proposed in an earlier message and do
>>>>>> all (or most) of this in the DM instead of here in hvmloader:
>>>>>>
>>>>>>> The more correct thing to do might be for the DM to
>>>>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>>>>> separate question then.)
>>>>>>
>>>>>> Actually, when I was developing this patch, I tried first to do it that
>>>>>> way, but the problem was, I could not find a way to get a pointer to the
>>>>>> host OpRegion in Qemu.
>>>>>>
>>>>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>>>>
>>>>> You don't ask me this question, do you?
>>>>
>>>> Are you offended I asked this question? If so, I am sorry. You make me
>>>> afraid to ask it again so I will not do so unless you permit to do so
>>>> again.
>>>
>>> "Offended" is the wrong word; "very puzzled" may better get it. I'm not a
>>> qemu person, and I never have been. I can't really help much there.
>>>
>>>> All I can say is that surely qemu
>>>>> has an existing way to map (host) physical memory; see e.g. how
>>>>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>>>>> device. "Bogusly" there because that's another layering violation. Plus
>>>>> (independently) there and here there's the issue of how to accomplish
>>>>> things when not running in Dom0, or when running de-privileged in Dom0.
>>>>
>>>> Well, that only proves Qemu *might* be able to access the MSI-X table of
>>>> a device, that is, if the calls to open /dev/mem and mmap it succeed.
>>>> Why is the MSI-X table all of the sudden relevant? Even if Qemu
>>>> can access the MSI-X table of some device, that does not prove that
>>>> Qemu can access the host OpRegion of an Intel IGD. So I think my point
>>>> still stands: I still don't see proof that it is possible for Qemu
>>>> to get a pointer to the host OpRegion without any patches to the current
>>>> implementations of Xen and the Linux kernel.
>>>
>>> The MSI-X table (and it being accessible to qemu) is the best analogy I
>>> could come up with, as that's one tiny area of qemu that I know at least
>>> a little.
>>>
>>> From a Xen perspective, this analogy should be sufficient: All you need
>>> from Xen is for it to permit to establish mappings of the underlying page.
>>> As I've pointed out when commenting on a code fragment you presented, the
>>> DM (domain) looks to have permission. Everything else is a matter of
>>> establishing such a mapping. There the MSI-X table code may also guide
>>> you. (Sadly it may also misguide you, since (a) I don't know whether it's
>>> appropriate to do things this way in qemu, and since (b) it is, as said,
>>> imo a layering violation.)
>>
>> I agree that accessing the host /dev/mem directly is cringy. I would not
>> really want to do it that way for the host OpRegion.
>
> I looked at the current mainline Linux kernel code about access to memory using
> /dev/mem and modern distros set CONFIG_STRICT_DEVMEM which forbids access to
> ordinary system RAM but allows access to what the kernel developers call
> non-kernel memory. Here is a quote from a comment in arch/x86/mm/init.c file
> in the Linux source code:
>
>> * On x86, access has to be given to the first megabyte of RAM because that
>> * area traditionally contains BIOS code and data regions used by X, dosemu,
>> * and similar apps. Since they map the entire memory range, the whole range
>> * must be allowed (for mapping), but any areas that would otherwise be
>> * disallowed are flagged as being "zero filled" instead of rejected.
>> * Access has to be given to non-kernel-ram areas as well, these contain the
>> * PCI mmio resources as well as potential bios/acpi data regions.
>
> So I think things like the MSI-X table and the OpRegion would qualify for
> /dev/men access even with CONFIG_STRICT_DEVMEM set, so after seeing this
> I expect I could get a pointer to the OpRegion running in Qemu using
> /dev/mem and mmap, as long as it is running in dom0 with root privileges.
> But as I said earlier, I agree that /dev/mem and mmap does not feel like
> the right way to do it.
>
> So I would like to come back to something else you said in an earlier message:
>
>> (How in turn the DM would learn of the contents of the opregion is a separate
>> question then.)
>
> Let me phrase the question like this: How could the DM gain access to the contents
> of the OpRegion, and for that matter, also the contents of the MSI-X table, without
> also committing a layering violation?
As said previously, I'm not a qemu person at all. Yet it's entirely a qemu
question you raise. From Xen's perspective, as also said previously, the
one prereq is there - the DM domain is permitted to access the page(s) in
question.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-18 17:15 ` Chuck Zmudzinski
2026-08-19 7:30 ` Jan Beulich
@ 2026-08-19 12:10 ` Chuck Zmudzinski
1 sibling, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 12:10 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/18/2026 1:15 PM, Chuck Zmudzinski wrote:
> On 8/18/2026 8:29 AM, Chuck Zmudzinski wrote:
>> On 8/18/2026 8:18 AM, Jan Beulich wrote:
>>> On 18.08.2026 13:52, Chuck Zmudzinski wrote:
>>>> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>>>>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>>>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>>>>> -- snip --
>>>>>>>>>>>>>> + /*
>>>>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>>>>> + *
>>>>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>>>>> + */
>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>>>>
>>>>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>>>>
>>>>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>>>>
>>>>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>>>>> by its DM.
>>>>>>>>>>
>>>>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>>>>
>>>>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>>>>> guest are also assigned to its DM.
>>>>>>>>
>>>>>>>> Currently, in the device model (Qemu) we have:
>>>>>>>>
>>>>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>>>>> DPCI_ADD_MAPPING);
>>>>>>>>
>>>>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>>>>
>>>>>>>> If I understand our current implementation correctly, this statement
>>>>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>>>>> in hvmloader code).
>>>>>>>
>>>>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>>>>
>>>>>>>> I don't think this statement makes the host OpRegion
>>>>>>>> accessible to the device model, though, so I think, if I understand your
>>>>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>>>>> same kind of "layering violation."
>>>>>>>
>>>>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>>>>> needed permissions to access the pages itself.
>>>>>>
>>>>>> So, are you saying it should be possible, without any patches to either Xen or
>>>>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>>>>
>>>>>> I think I could implement what you proposed in an earlier message and do
>>>>>> all (or most) of this in the DM instead of here in hvmloader:
>>>>>>
>>>>>>> The more correct thing to do might be for the DM to
>>>>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>>>>> separate question then.)
>>>>>>
>>>>>> Actually, when I was developing this patch, I tried first to do it that
>>>>>> way, but the problem was, I could not find a way to get a pointer to the
>>>>>> host OpRegion in Qemu.
>>>>>>
>>>>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>>>>
>>>>> You don't ask me this question, do you?
>>>>
>>>> Are you offended I asked this question? If so, I am sorry. You make me
>>>> afraid to ask it again so I will not do so unless you permit to do so
>>>> again.
>>>
>>> "Offended" is the wrong word; "very puzzled" may better get it. I'm not a
>>> qemu person, and I never have been. I can't really help much there.
>>>
>>>> All I can say is that surely qemu
>>>>> has an existing way to map (host) physical memory; see e.g. how
>>>>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>>>>> device. "Bogusly" there because that's another layering violation. Plus
>>>>> (independently) there and here there's the issue of how to accomplish
>>>>> things when not running in Dom0, or when running de-privileged in Dom0.
>>>>
>>>> Well, that only proves Qemu *might* be able to access the MSI-X table of
>>>> a device, that is, if the calls to open /dev/mem and mmap it succeed.
>>>> Why is the MSI-X table all of the sudden relevant? Even if Qemu
>>>> can access the MSI-X table of some device, that does not prove that
>>>> Qemu can access the host OpRegion of an Intel IGD. So I think my point
>>>> still stands: I still don't see proof that it is possible for Qemu
>>>> to get a pointer to the host OpRegion without any patches to the current
>>>> implementations of Xen and the Linux kernel.
>>>
>>> The MSI-X table (and it being accessible to qemu) is the best analogy I
>>> could come up with, as that's one tiny area of qemu that I know at least
>>> a little.
>>>
>>> From a Xen perspective, this analogy should be sufficient: All you need
>>> from Xen is for it to permit to establish mappings of the underlying page.
>>> As I've pointed out when commenting on a code fragment you presented, the
>>> DM (domain) looks to have permission. Everything else is a matter of
>>> establishing such a mapping. There the MSI-X table code may also guide
>>> you. (Sadly it may also misguide you, since (a) I don't know whether it's
>>> appropriate to do things this way in qemu, and since (b) it is, as said,
>>> imo a layering violation.)
>>
>> I agree that accessing the host /dev/mem directly is cringy. I would not
>> really want to do it that way for the host OpRegion.
>
> I looked at the current mainline Linux kernel code about access to memory using
> /dev/mem and modern distros set CONFIG_STRICT_DEVMEM which forbids access to
> ordinary system RAM but allows access to what the kernel developers call
> non-kernel memory. Here is a quote from a comment in arch/x86/mm/init.c file
> in the Linux source code:
>
>> * On x86, access has to be given to the first megabyte of RAM because that
>> * area traditionally contains BIOS code and data regions used by X, dosemu,
>> * and similar apps. Since they map the entire memory range, the whole range
>> * must be allowed (for mapping), but any areas that would otherwise be
>> * disallowed are flagged as being "zero filled" instead of rejected.
>> * Access has to be given to non-kernel-ram areas as well, these contain the
>> * PCI mmio resources as well as potential bios/acpi data regions.
>
> So I think things like the MSI-X table and the OpRegion would qualify for
> /dev/mem access even with CONFIG_STRICT_DEVMEM set, so after seeing this
> I expect I could get a pointer to the OpRegion running in Qemu using
> /dev/mem and mmap, as long as it is running in dom0 with root privileges.
> But as I said earlier, I agree that /dev/mem and mmap does not feel like
> the right way to do it.
Moreover, I tried accessing the OpRegion using /dev/mem and mmap using a
little C program, dumpmem, [1] I found but it does not work in either dom0
or in the guest when IGD is passed through to the guest: mmap returns
MAP_FAILED and reports the EPERM error: Operation not permitted. So it looks
like Qemu cannot access the OpRegion using mmap and /dev/mem with current
Linux kernels. So I am still skeptical that with current Linux kernel
implementation and its hardening mechanisms such as CONFIG_STRICT_DEVMEM, it
is not possible for Qemu to directly access the OpRegion without also adding a
patch to either Linux or Xen to provide access of OpRegion contents to Qemu.
But the good news is I did find a way to dump the OpRegion to a file from
either dom0 or the guest when passed through, but in dom0 it works only before
xl makes the device assignable for passthrough and bound to xen-pciback, so that
is not so helpful since we need Qemu to access it when the IGD is assigned to
its guest and bound to the xen-pciback kernel driver.
Here is how I accessed the OpRegion from dom0 userland before xl assigns it
for Xen PCI passthrough:
Linux debugfs mentioned in the man page for IGT GPU tools [2] exposes the OpRegion:
https://manpages.debian.org/trixie/intel-gpu-tools/intel_vbt_decode.1.en.html
Here is how to dump the OpRegion contents to a file in the home directory:
user@dom0:~$ sudo cat /sys/kernel/debug/dri/0000:00:02.0/i915_opregion > ~/i915_opregion
user@dom0:~$ ls -l ~/i915_opregion
-rw-r--r--. 1 chuckz chuckz 8192 Aug 18 22:41 /home/chuckz/i915_opregion
user@dom0:~$
There it is, the 8k OpRegion dumped to a file.
This also works for the VBT:
user@dom0:~$ sudo cat /sys/kernel/debug/dri/0000:00:02.0/i915_vbt > ~/i915_vbt
user@dom0:~$ ls -l ~/i915_vbt
-rw-r--r--. 1 chuckz chuckz 8704 Aug 18 22:48 /home/chuckz/i915_vbt
user@dom0:~$
So now, with a copy of both the OpRegion and VBT, I can write and test
patches to hvmloader and Qemu using your approach of exposing a copy
and never mapping the host OpRegion to the guest and in that way avoid the
layering violation. The TODO is to find a way for Qemu to get a copy of
the OpRegion on the fly instead of only after the administrator places
a copy of it in the dom0 filesystem where Qemu can access it.
I think one way to make the OpRegion directly accessible to Qemu instead
of being accessible only after dumping it to a file and placing the dumped
file where Qemu can access it would be to provide a xen-intelgpuback kernel
driver whose job would be to make the OpRegion and VBT accessible to Qemu
when the device is assigned to a Xen HVM guest.
Chuck
[1] https://github.com/tchebb/memdump
[2] https://drm.pages.freedesktop.org/igt-gpu-tools/
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 7:30 ` Jan Beulich
@ 2026-08-19 12:16 ` Chuck Zmudzinski
2026-08-19 12:36 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 12:16 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/19/2026 3:30 AM, Jan Beulich wrote:
> On 18.08.2026 19:15, Chuck Zmudzinski wrote:
>> On 8/18/2026 8:29 AM, Chuck Zmudzinski wrote:
>>> On 8/18/2026 8:18 AM, Jan Beulich wrote:
>>>> On 18.08.2026 13:52, Chuck Zmudzinski wrote:
>>>>> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>>>>>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>>>>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>>>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>>>>>> -- snip --
>>>>>>>>>>>>>>> + /*
>>>>>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>>>>>> + *
>>>>>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>>>>>> + */
>>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>>>>>
>>>>>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>>>>>
>>>>>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>>>>>> by its DM.
>>>>>>>>>>>
>>>>>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>>>>>
>>>>>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>>>>>> guest are also assigned to its DM.
>>>>>>>>>
>>>>>>>>> Currently, in the device model (Qemu) we have:
>>>>>>>>>
>>>>>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>>>>>> DPCI_ADD_MAPPING);
>>>>>>>>>
>>>>>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>>>>>
>>>>>>>>> If I understand our current implementation correctly, this statement
>>>>>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>>>>>> in hvmloader code).
>>>>>>>>
>>>>>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>>>>>
>>>>>>>>> I don't think this statement makes the host OpRegion
>>>>>>>>> accessible to the device model, though, so I think, if I understand your
>>>>>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>>>>>> same kind of "layering violation."
>>>>>>>>
>>>>>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>>>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>>>>>> needed permissions to access the pages itself.
>>>>>>>
>>>>>>> So, are you saying it should be possible, without any patches to either Xen or
>>>>>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>>>>>
>>>>>>> I think I could implement what you proposed in an earlier message and do
>>>>>>> all (or most) of this in the DM instead of here in hvmloader:
>>>>>>>
>>>>>>>> The more correct thing to do might be for the DM to
>>>>>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>>>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>>>>>> separate question then.)
>>>>>>>
>>>>>>> Actually, when I was developing this patch, I tried first to do it that
>>>>>>> way, but the problem was, I could not find a way to get a pointer to the
>>>>>>> host OpRegion in Qemu.
>>>>>>>
>>>>>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>>>>>
>>>>>> You don't ask me this question, do you?
>>>>>
>>>>> Are you offended I asked this question? If so, I am sorry. You make me
>>>>> afraid to ask it again so I will not do so unless you permit to do so
>>>>> again.
>>>>
>>>> "Offended" is the wrong word; "very puzzled" may better get it. I'm not a
>>>> qemu person, and I never have been. I can't really help much there.
>>>>
>>>>> All I can say is that surely qemu
>>>>>> has an existing way to map (host) physical memory; see e.g. how
>>>>>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>>>>>> device. "Bogusly" there because that's another layering violation. Plus
>>>>>> (independently) there and here there's the issue of how to accomplish
>>>>>> things when not running in Dom0, or when running de-privileged in Dom0.
>>>>>
>>>>> Well, that only proves Qemu *might* be able to access the MSI-X table of
>>>>> a device, that is, if the calls to open /dev/mem and mmap it succeed.
>>>>> Why is the MSI-X table all of the sudden relevant? Even if Qemu
>>>>> can access the MSI-X table of some device, that does not prove that
>>>>> Qemu can access the host OpRegion of an Intel IGD. So I think my point
>>>>> still stands: I still don't see proof that it is possible for Qemu
>>>>> to get a pointer to the host OpRegion without any patches to the current
>>>>> implementations of Xen and the Linux kernel.
>>>>
>>>> The MSI-X table (and it being accessible to qemu) is the best analogy I
>>>> could come up with, as that's one tiny area of qemu that I know at least
>>>> a little.
>>>>
>>>> From a Xen perspective, this analogy should be sufficient: All you need
>>>> from Xen is for it to permit to establish mappings of the underlying page.
>>>> As I've pointed out when commenting on a code fragment you presented, the
>>>> DM (domain) looks to have permission. Everything else is a matter of
>>>> establishing such a mapping. There the MSI-X table code may also guide
>>>> you. (Sadly it may also misguide you, since (a) I don't know whether it's
>>>> appropriate to do things this way in qemu, and since (b) it is, as said,
>>>> imo a layering violation.)
>>>
>>> I agree that accessing the host /dev/mem directly is cringy. I would not
>>> really want to do it that way for the host OpRegion.
>>
>> I looked at the current mainline Linux kernel code about access to memory using
>> /dev/mem and modern distros set CONFIG_STRICT_DEVMEM which forbids access to
>> ordinary system RAM but allows access to what the kernel developers call
>> non-kernel memory. Here is a quote from a comment in arch/x86/mm/init.c file
>> in the Linux source code:
>>
>>> * On x86, access has to be given to the first megabyte of RAM because that
>>> * area traditionally contains BIOS code and data regions used by X, dosemu,
>>> * and similar apps. Since they map the entire memory range, the whole range
>>> * must be allowed (for mapping), but any areas that would otherwise be
>>> * disallowed are flagged as being "zero filled" instead of rejected.
>>> * Access has to be given to non-kernel-ram areas as well, these contain the
>>> * PCI mmio resources as well as potential bios/acpi data regions.
>>
>> So I think things like the MSI-X table and the OpRegion would qualify for
>> /dev/men access even with CONFIG_STRICT_DEVMEM set, so after seeing this
>> I expect I could get a pointer to the OpRegion running in Qemu using
>> /dev/mem and mmap, as long as it is running in dom0 with root privileges.
>> But as I said earlier, I agree that /dev/mem and mmap does not feel like
>> the right way to do it.
>>
>> So I would like to come back to something else you said in an earlier message:
>>
>>> (How in turn the DM would learn of the contents of the opregion is a separate
>>> question then.)
>>
>> Let me phrase the question like this: How could the DM gain access to the contents
>> of the OpRegion, and for that matter, also the contents of the MSI-X table, without
>> also committing a layering violation?
>
> As said previously, I'm not a qemu person at all. Yet it's entirely a qemu
> question you raise. From Xen's perspective, as also said previously, the
> one prereq is there - the DM domain is permitted to access the page(s) in
> question.
Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
a copy of the OpRegion and read its contents so most of this can be done in the
DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
about avoiding the layering violation than anything else.
Chuck
>
> Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 12:16 ` Chuck Zmudzinski
@ 2026-08-19 12:36 ` Chuck Zmudzinski
2026-08-19 13:51 ` Jan Beulich
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 12:36 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
> On 8/19/2026 3:30 AM, Jan Beulich wrote:
>> On 18.08.2026 19:15, Chuck Zmudzinski wrote:
>>> On 8/18/2026 8:29 AM, Chuck Zmudzinski wrote:
>>>> On 8/18/2026 8:18 AM, Jan Beulich wrote:
>>>>> On 18.08.2026 13:52, Chuck Zmudzinski wrote:
>>>>>> On 8/18/2026 3:17 AM, Jan Beulich wrote:
>>>>>>> On 17.08.2026 18:04, Chuck Zmudzinski wrote:
>>>>>>>> On 8/17/2026 4:42 AM, Jan Beulich wrote:
>>>>>>>>> On 14.08.2026 17:23, Chuck Zmudzinski wrote:
>>>>>>>>>> On 8/14/2026 9:46 AM, Jan Beulich wrote:
>>>>>>>>>>> On 14.08.2026 15:18, Chuck Zmudzinski wrote:
>>>>>>>>>>>> On 8/14/2026 3:35 AM, Jan Beulich wrote:
>>>>>>>>>>>>> On 14.08.2026 02:45, Chuck Zmudzinski wrote:
>>>>>>>>>>>>>> On 8/13/2026 6:35 AM, Jan Beulich wrote:
>>>>>>>>>>>>>>> On 02.08.2026 07:08, Chuck Zmudzinski wrote:
>>>>>>>>>>>>>>>> -- snip --
>>>>>>>>>>>>>>>> + /*
>>>>>>>>>>>>>>>> + * Write rvda_host as 2 successive 32-bit values
>>>>>>>>>>>>>>>> + * to communicate location of the VBT to the device
>>>>>>>>>>>>>>>> + * model. If rvda_host is not 0, The device model
>>>>>>>>>>>>>>>> + * unmaps the OpRegion and eventually maps the VBT
>>>>>>>>>>>>>>>> + * after we also write the guest address where the
>>>>>>>>>>>>>>>> + * VBT will be mapped.
>>>>>>>>>>>>>>>> + *
>>>>>>>>>>>>>>>> + * If we send rvda_host = 0 to the device model, it
>>>>>>>>>>>>>>>> + * will assume we do not need OpRegion 2 support and
>>>>>>>>>>>>>>>> + * it will not unmap the OpRegion.
>>>>>>>>>>>>>>>> + */
>>>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>>>> + (uint32_t)(rvda_host & 0xfffffffful));
>>>>>>>>>>>>>>>> + unsigned long rvda_host_upper_32 = (uint64_t)rvda_host >> 32;
>>>>>>>>>>>>>>>> + pci_writel(vga_devfn, PCI_INTEL_OPREGION,
>>>>>>>>>>>>>>>> + (uint32_t)rvda_host_upper_32);
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Why would you need to communicate a host property to the DM?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The DM cannot access the host rvda value because it is only accessible
>>>>>>>>>>>>>> from the host kernel, and the DM is only a user-space process on the host.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I don't follow this: Anything the guest can access should also be accessible
>>>>>>>>>>>>> by its DM.
>>>>>>>>>>>>
>>>>>>>>>>>> I think the host OpRegion is not currently accessible by the DM.
>>>>>>>>>>>
>>>>>>>>>>> Can you explain to me how the region becomes accessible to the guest?
>>>>>>>>>>> That would then (hopefully) help me understand why the DM would not have
>>>>>>>>>>> access. Fundamentally any MMIO and any I/O ports that are assigned to a
>>>>>>>>>>> guest are also assigned to its DM.
>>>>>>>>>>
>>>>>>>>>> Currently, in the device model (Qemu) we have:
>>>>>>>>>>
>>>>>>>>>> ret = xc_domain_memory_mapping(xen_xc, xen_domid,
>>>>>>>>>> (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT),
>>>>>>>>>> (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT),
>>>>>>>>>> XEN_PCI_INTEL_OPREGION_PAGES,
>>>>>>>>>> DPCI_ADD_MAPPING);
>>>>>>>>>>
>>>>>>>>>> That statement is in the igd_write_opregion(...) function in the
>>>>>>>>>> hw/xen/xen_pt_graphics.c file of the upstream Qemu source.
>>>>>>>>>>
>>>>>>>>>> If I understand our current implementation correctly, this statement
>>>>>>>>>> is what gives the guest access to the host OpRegion (3 pages as defined
>>>>>>>>>> by XEN_PCI_INTEL_OPREGION_PAGES, and in agreement with IGD_OPREGION_PAGES
>>>>>>>>>> in hvmloader code).
>>>>>>>>>
>>>>>>>>> No, it introduces mappings of those pages into the guest's P2M.
>>>>>>>>>
>>>>>>>>>> I don't think this statement makes the host OpRegion
>>>>>>>>>> accessible to the device model, though, so I think, if I understand your
>>>>>>>>>> comment in an earlier about my patch resulting in what you called a "layering
>>>>>>>>>> violation" correctly, that our current implementation is also guilty of this
>>>>>>>>>> same kind of "layering violation."
>>>>>>>>>
>>>>>>>>> That code, if it can be successfully executed, indeed doesn't grant any
>>>>>>>>> permissions (to the DM or the guest). Instead it proves that the DM has the
>>>>>>>>> needed permissions to access the pages itself.
>>>>>>>>
>>>>>>>> So, are you saying it should be possible, without any patches to either Xen or
>>>>>>>> the Linux kernel, for Qemu to get a pointer to the OpRegion? If so, how?
>>>>>>>>
>>>>>>>> I think I could implement what you proposed in an earlier message and do
>>>>>>>> all (or most) of this in the DM instead of here in hvmloader:
>>>>>>>>
>>>>>>>>> The more correct thing to do might be for the DM to
>>>>>>>>> put in place a copy before the guest (i.e. hvmloader) even gains control.
>>>>>>>>> (How in turn the DM would learn of the contents of the opregion is a
>>>>>>>>> separate question then.)
>>>>>>>>
>>>>>>>> Actually, when I was developing this patch, I tried first to do it that
>>>>>>>> way, but the problem was, I could not find a way to get a pointer to the
>>>>>>>> host OpRegion in Qemu.
>>>>>>>>
>>>>>>>> So, how can I get a pointer to the host OpRegion in Qemu?
>>>>>>>
>>>>>>> You don't ask me this question, do you?
>>>>>>
>>>>>> Are you offended I asked this question? If so, I am sorry. You make me
>>>>>> afraid to ask it again so I will not do so unless you permit to do so
>>>>>> again.
>>>>>
>>>>> "Offended" is the wrong word; "very puzzled" may better get it. I'm not a
>>>>> qemu person, and I never have been. I can't really help much there.
>>>>>
>>>>>> All I can say is that surely qemu
>>>>>>> has an existing way to map (host) physical memory; see e.g. how
>>>>>>> xen_pt_msix_init() (imo bogusly) maps the physical MSI-X table of a
>>>>>>> device. "Bogusly" there because that's another layering violation. Plus
>>>>>>> (independently) there and here there's the issue of how to accomplish
>>>>>>> things when not running in Dom0, or when running de-privileged in Dom0.
>>>>>>
>>>>>> Well, that only proves Qemu *might* be able to access the MSI-X table of
>>>>>> a device, that is, if the calls to open /dev/mem and mmap it succeed.
>>>>>> Why is the MSI-X table all of the sudden relevant? Even if Qemu
>>>>>> can access the MSI-X table of some device, that does not prove that
>>>>>> Qemu can access the host OpRegion of an Intel IGD. So I think my point
>>>>>> still stands: I still don't see proof that it is possible for Qemu
>>>>>> to get a pointer to the host OpRegion without any patches to the current
>>>>>> implementations of Xen and the Linux kernel.
>>>>>
>>>>> The MSI-X table (and it being accessible to qemu) is the best analogy I
>>>>> could come up with, as that's one tiny area of qemu that I know at least
>>>>> a little.
>>>>>
>>>>> From a Xen perspective, this analogy should be sufficient: All you need
>>>>> from Xen is for it to permit to establish mappings of the underlying page.
>>>>> As I've pointed out when commenting on a code fragment you presented, the
>>>>> DM (domain) looks to have permission. Everything else is a matter of
>>>>> establishing such a mapping. There the MSI-X table code may also guide
>>>>> you. (Sadly it may also misguide you, since (a) I don't know whether it's
>>>>> appropriate to do things this way in qemu, and since (b) it is, as said,
>>>>> imo a layering violation.)
>>>>
>>>> I agree that accessing the host /dev/mem directly is cringy. I would not
>>>> really want to do it that way for the host OpRegion.
>>>
>>> I looked at the current mainline Linux kernel code about access to memory using
>>> /dev/mem and modern distros set CONFIG_STRICT_DEVMEM which forbids access to
>>> ordinary system RAM but allows access to what the kernel developers call
>>> non-kernel memory. Here is a quote from a comment in arch/x86/mm/init.c file
>>> in the Linux source code:
>>>
>>>> * On x86, access has to be given to the first megabyte of RAM because that
>>>> * area traditionally contains BIOS code and data regions used by X, dosemu,
>>>> * and similar apps. Since they map the entire memory range, the whole range
>>>> * must be allowed (for mapping), but any areas that would otherwise be
>>>> * disallowed are flagged as being "zero filled" instead of rejected.
>>>> * Access has to be given to non-kernel-ram areas as well, these contain the
>>>> * PCI mmio resources as well as potential bios/acpi data regions.
>>>
>>> So I think things like the MSI-X table and the OpRegion would qualify for
>>> /dev/men access even with CONFIG_STRICT_DEVMEM set, so after seeing this
>>> I expect I could get a pointer to the OpRegion running in Qemu using
>>> /dev/mem and mmap, as long as it is running in dom0 with root privileges.
>>> But as I said earlier, I agree that /dev/mem and mmap does not feel like
>>> the right way to do it.
>>>
>>> So I would like to come back to something else you said in an earlier message:
>>>
>>>> (How in turn the DM would learn of the contents of the opregion is a separate
>>>> question then.)
>>>
>>> Let me phrase the question like this: How could the DM gain access to the contents
>>> of the OpRegion, and for that matter, also the contents of the MSI-X table, without
>>> also committing a layering violation?
>>
>> As said previously, I'm not a qemu person at all. Yet it's entirely a qemu
>> question you raise. From Xen's perspective, as also said previously, the
>> one prereq is there - the DM domain is permitted to access the page(s) in
>> question.
>
> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
> a copy of the OpRegion and read its contents so most of this can be done in the
> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
> about avoiding the layering violation than anything else.
However, there is one advantage, from the viewpoint of the Xen virtualization platform
as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
solution for extended VBT support for Intel IGD devices that would be compatible with
all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
in hvmloader?
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 12:36 ` Chuck Zmudzinski
@ 2026-08-19 13:51 ` Jan Beulich
2026-08-19 15:47 ` Chuck Zmudzinski
2026-08-19 17:13 ` Chuck Zmudzinski
0 siblings, 2 replies; 42+ messages in thread
From: Jan Beulich @ 2026-08-19 13:51 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 19.08.2026 14:36, Chuck Zmudzinski wrote:
> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>> a copy of the OpRegion and read its contents so most of this can be done in the
>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>> about avoiding the layering violation than anything else.
>
> However, there is one advantage, from the viewpoint of the Xen virtualization platform
> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>
> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
> solution for extended VBT support for Intel IGD devices that would be compatible with
> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
> in hvmloader?
As indicated before: If the OpRegion holds data that is needed to drive the
device, and if the OpRegion is exposed writable to guests, then guest can
screw up that data such that subsequent guests won't work anymore. Hence
exposing to guests (which includes hvmloader) needs to be stopped, or at
least be limited to r/o. That, in fact, includes exposing to any privilege-
restricted DM as well.
Exposing r/o may be entirely okay (i.e. may not be a layering violation),
depending how exactly an OpRegion surfaces for a device (on the host). Aiui
it's not addressed by any of the BARs, yet it looks like it needs similar
treatment. Earlier on we also talked about the region not necessarily being
page-aligned. That poses, even with r/o exposure, the question of other
data on the same (leading / trailing) pages. This may imply that the
copying needs to be done strictly in Dom0, for both DM and guest to only
ever act on copies (which may then as well be r/w).
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 13:51 ` Jan Beulich
@ 2026-08-19 15:47 ` Chuck Zmudzinski
2026-08-19 17:49 ` Chuck Zmudzinski
2026-08-19 17:13 ` Chuck Zmudzinski
1 sibling, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 15:47 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/19/2026 9:51 AM, Jan Beulich wrote:
> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>> about avoiding the layering violation than anything else.
>>
>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>
>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>> solution for extended VBT support for Intel IGD devices that would be compatible with
>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>> in hvmloader?
>
> As indicated before: If the OpRegion holds data that is needed to drive the
> device, and if the OpRegion is exposed writable to guests, then guest can
> screw up that data such that subsequent guests won't work anymore. Hence
> exposing to guests (which includes hvmloader) needs to be stopped, or at
> least be limited to r/o. That, in fact, includes exposing to any privilege-
> restricted DM as well.
>
> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
> it's not addressed by any of the BARs, yet it looks like it needs similar
> treatment. Earlier on we also talked about the region not necessarily being
> page-aligned. That poses, even with r/o exposure, the question of other
> data on the same (leading / trailing) pages. This may imply that the
> copying needs to be done strictly in Dom0, for both DM and guest to only
> ever act on copies (which may then as well be r/w).
Yes, I am thinking the DM should make a copy host OpRegion and never expose
the host OpRegion to the guest but only a copy of it.
The reason we need a patch like this is that with the introduction of the
rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
so its contents might be unsuitable in the guest address space, so in those cases
we need to patch the copy of the OpRegion that will be exposed to the guest.
If there is an extended VBT the DM will also get a copy of it, make a copy of
it, and expose it to the guest by appending it contiguous with the OpRegion.
Since in this scenario we are assuming the DM knows the contents of the OpRegion,
then it can find the host VBT and make a copy of it without needing hvmloader
to send the rvda and rvds values to it.
Then, the remaining question is which component (DM or hvmloader) will patch it
if it needs to be patched to make the guest's copy of it compatible with the guest
address space. It could be done in the DM only after hvmloader informs the DM
where in the guest it will be in the memory map unless we make the specifications
for how hvmloader determines where it will be in the guest address space public so
the DM can compute where the OpRegion will be in the guest address space. Currently,
the DM learns this from hvmloader when hvmloader writes the guest igd_opregion_phbase
value to the ASLS register of the device (in hmvlmoader code we currently name the
ASLS register for the OpRegion using the PCI_INTEL_OPREGION macro, which is defined to
be 0xfc).
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 13:51 ` Jan Beulich
2026-08-19 15:47 ` Chuck Zmudzinski
@ 2026-08-19 17:13 ` Chuck Zmudzinski
2026-08-20 7:51 ` Jan Beulich
1 sibling, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 17:13 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/19/2026 9:51 AM, Jan Beulich wrote:
> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>> about avoiding the layering violation than anything else.
>>
>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>
>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>> solution for extended VBT support for Intel IGD devices that would be compatible with
>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>> in hvmloader?
>
> As indicated before: If the OpRegion holds data that is needed to drive the
> device, and if the OpRegion is exposed writable to guests, then guest can
> screw up that data such that subsequent guests won't work anymore. Hence
> exposing to guests (which includes hvmloader) needs to be stopped, or at
> least be limited to r/o. That, in fact, includes exposing to any privilege-
> restricted DM as well.
>
> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
> it's not addressed by any of the BARs, yet it looks like it needs similar
> treatment.
Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
it functions more or less like a BAR region with the devices's ASLS register
at offset 0xfc in the PCI device config space of the device acting like the
BAR for that region.
Actually, in hvmloader code, this value of 0xfc for the OpRegion ASLS register
is added to the header file where all the other registers defined by the
PCI spec live: tools/firmware/hvmloader/pci_regs.h, but in that file it is
defined by the PCI_INTEL_OPREGION macro.
So this is another cleanup of this I could do along with this patch: Remove
the define of PCI_INTEL_OPREGION from pci_regs.h (after all, it is not part
of the PCI spec anyways) and pci.c (or the new intel-opregion.c file if some
version of it survives until later versions of this patch) can get the value
for the ASLS register from a header where specs for the IGD OpRegion are
located instead, or it can just be added to config.h where the other IGD related
definitions currently are in hvmloader code.
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 15:47 ` Chuck Zmudzinski
@ 2026-08-19 17:49 ` Chuck Zmudzinski
2026-08-19 19:09 ` Chuck Zmudzinski
2026-08-20 7:53 ` Jan Beulich
0 siblings, 2 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 17:49 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>> about avoiding the layering violation than anything else.
>>>
>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>
>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>> in hvmloader?
>>
>> As indicated before: If the OpRegion holds data that is needed to drive the
>> device, and if the OpRegion is exposed writable to guests, then guest can
>> screw up that data such that subsequent guests won't work anymore. Hence
>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>> restricted DM as well.
>>
>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>> it's not addressed by any of the BARs, yet it looks like it needs similar
>> treatment. Earlier on we also talked about the region not necessarily being
>> page-aligned. That poses, even with r/o exposure, the question of other
>> data on the same (leading / trailing) pages. This may imply that the
>> copying needs to be done strictly in Dom0, for both DM and guest to only
>> ever act on copies (which may then as well be r/w).
>
> Yes, I am thinking the DM should make a copy host OpRegion and never expose
> the host OpRegion to the guest but only a copy of it.
>
> The reason we need a patch like this is that with the introduction of the
> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
> so its contents might be unsuitable in the guest address space, so in those cases
> we need to patch the copy of the OpRegion that will be exposed to the guest.
> If there is an extended VBT the DM will also get a copy of it, make a copy of
> it, and expose it to the guest by appending it contiguous with the OpRegion.
> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
> then it can find the host VBT and make a copy of it without needing hvmloader
> to send the rvda and rvds values to it.
>
> Then, the remaining question is which component (DM or hvmloader) will patch it
> if it needs to be patched to make the guest's copy of it compatible with the guest
> address space.
As I noted earlier, it think it would be advantageous for the Xen platform as whole
for the patching to be done in hvmloader. That way, support for extended VBT is
automatically added for all implementations of the DM, not just for Qemu. But the
downside is that for hvmloader to do the patching, it needs to know the host OpRegion
address, which one could argue it should not need to know. This is the only reason I
can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
avoid disclosing the host OpRegion address to the guest.
But we trust hvmloader, don't we, to not abuse this knowledge of the host's OpRegion
address? The point is, hvmloader will discard the host OpRegion address and not
disclose it to guest firmware (ovmf/seabios) nor to the bootloader or guest OS, so
I think the advantage of adding support for extended VBT to all DMs that rely on
hvmloader outweighs the risk of disclosing the host OpRegion to the guest (hvmloader,
which, for security reasons, should not disclose it to ovmf or seabios).
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 17:49 ` Chuck Zmudzinski
@ 2026-08-19 19:09 ` Chuck Zmudzinski
2026-08-20 7:58 ` Jan Beulich
2026-08-20 7:53 ` Jan Beulich
1 sibling, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-19 19:09 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/19/2026 1:49 PM, Chuck Zmudzinski wrote:
> On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>> about avoiding the layering violation than anything else.
>>>>
>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>
>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>> in hvmloader?
>>>
>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>> screw up that data such that subsequent guests won't work anymore. Hence
>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>> restricted DM as well.
>>>
>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>> treatment. Earlier on we also talked about the region not necessarily being
>>> page-aligned. That poses, even with r/o exposure, the question of other
>>> data on the same (leading / trailing) pages. This may imply that the
>>> copying needs to be done strictly in Dom0, for both DM and guest to only
>>> ever act on copies (which may then as well be r/w).
>>
>> Yes, I am thinking the DM should make a copy host OpRegion and never expose
>> the host OpRegion to the guest but only a copy of it.
>>
>> The reason we need a patch like this is that with the introduction of the
>> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
>> so its contents might be unsuitable in the guest address space, so in those cases
>> we need to patch the copy of the OpRegion that will be exposed to the guest.
>> If there is an extended VBT the DM will also get a copy of it, make a copy of
>> it, and expose it to the guest by appending it contiguous with the OpRegion.
>> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
>> then it can find the host VBT and make a copy of it without needing hvmloader
>> to send the rvda and rvds values to it.
>>
>> Then, the remaining question is which component (DM or hvmloader) will patch it
>> if it needs to be patched to make the guest's copy of it compatible with the guest
>> address space.
>
> As I noted earlier, it think it would be advantageous for the Xen platform as whole
> for the patching to be done in hvmloader. That way, support for extended VBT is
> automatically added for all implementations of the DM, not just for Qemu. But the
> downside is that for hvmloader to do the patching, it needs to know the host OpRegion
> address, which one could argue it should not need to know. This is the only reason I
> can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
> avoid disclosing the host OpRegion address to the guest.
Correction: Actually, with this new scenario, we need not disclose any confidential
host addresses to hvmloader if the DM removes such information from the copy of
the OpRegion that it exposes to hvmloader. Then, all hvmloader needs to know to
ensure the OpRegion is compatible with the guest's address space is the guest
address of the OpRegion. It need not know either the host OpRegion address or the
host VBT address.
So the guidance I need from you to do v3 of the patch is simply to answer these
two questions.
1. Should I write v3 of the patch not only assuming the DM will never expose the
host OpRegion to hvmloader, but also assuming that the DM is responsible for
patching the OpRegion to ensure it is compatible with guest address space?
Or
2. Should I write v3 of the patch assuming that hvmloader is responsible for
patching the OpRegion so it is compatible with the guest address space?
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 17:13 ` Chuck Zmudzinski
@ 2026-08-20 7:51 ` Jan Beulich
2026-08-20 11:47 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-20 7:51 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 19.08.2026 19:13, Chuck Zmudzinski wrote:
> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>> about avoiding the layering violation than anything else.
>>>
>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>
>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>> in hvmloader?
>>
>> As indicated before: If the OpRegion holds data that is needed to drive the
>> device, and if the OpRegion is exposed writable to guests, then guest can
>> screw up that data such that subsequent guests won't work anymore. Hence
>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>> restricted DM as well.
>>
>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>> it's not addressed by any of the BARs, yet it looks like it needs similar
>> treatment.
>
> Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
> it functions more or less like a BAR region with the devices's ASLS register
> at offset 0xfc in the PCI device config space of the device acting like the
> BAR for that region.
That is, on real hardware a write to that register moves the OpRegion? That
would need following by the DM then, i.e. the DM would need to indicate the
original position in the register, and the guest (incl hvmloader) would
then be free to relocate it.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 17:49 ` Chuck Zmudzinski
2026-08-19 19:09 ` Chuck Zmudzinski
@ 2026-08-20 7:53 ` Jan Beulich
2026-08-20 13:03 ` Chuck Zmudzinski
1 sibling, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-20 7:53 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 19.08.2026 19:49, Chuck Zmudzinski wrote:
> On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>> about avoiding the layering violation than anything else.
>>>>
>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>
>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>> in hvmloader?
>>>
>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>> screw up that data such that subsequent guests won't work anymore. Hence
>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>> restricted DM as well.
>>>
>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>> treatment. Earlier on we also talked about the region not necessarily being
>>> page-aligned. That poses, even with r/o exposure, the question of other
>>> data on the same (leading / trailing) pages. This may imply that the
>>> copying needs to be done strictly in Dom0, for both DM and guest to only
>>> ever act on copies (which may then as well be r/w).
>>
>> Yes, I am thinking the DM should make a copy host OpRegion and never expose
>> the host OpRegion to the guest but only a copy of it.
>>
>> The reason we need a patch like this is that with the introduction of the
>> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
>> so its contents might be unsuitable in the guest address space, so in those cases
>> we need to patch the copy of the OpRegion that will be exposed to the guest.
>> If there is an extended VBT the DM will also get a copy of it, make a copy of
>> it, and expose it to the guest by appending it contiguous with the OpRegion.
>> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
>> then it can find the host VBT and make a copy of it without needing hvmloader
>> to send the rvda and rvds values to it.
>>
>> Then, the remaining question is which component (DM or hvmloader) will patch it
>> if it needs to be patched to make the guest's copy of it compatible with the guest
>> address space.
>
> As I noted earlier, it think it would be advantageous for the Xen platform as whole
> for the patching to be done in hvmloader. That way, support for extended VBT is
> automatically added for all implementations of the DM, not just for Qemu. But the
> downside is that for hvmloader to do the patching, it needs to know the host OpRegion
> address, which one could argue it should not need to know. This is the only reason I
> can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
> avoid disclosing the host OpRegion address to the guest.
>
> But we trust hvmloader, don't we, to not abuse this knowledge of the host's OpRegion
> address?
No, we cannot (fully) trust hvmloader.
Jan
> The point is, hvmloader will discard the host OpRegion address and not
> disclose it to guest firmware (ovmf/seabios) nor to the bootloader or guest OS, so
> I think the advantage of adding support for extended VBT to all DMs that rely on
> hvmloader outweighs the risk of disclosing the host OpRegion to the guest (hvmloader,
> which, for security reasons, should not disclose it to ovmf or seabios).
>
> Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-19 19:09 ` Chuck Zmudzinski
@ 2026-08-20 7:58 ` Jan Beulich
2026-08-20 13:03 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-20 7:58 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 19.08.2026 21:09, Chuck Zmudzinski wrote:
> On 8/19/2026 1:49 PM, Chuck Zmudzinski wrote:
>> On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>> about avoiding the layering violation than anything else.
>>>>>
>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>
>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>> in hvmloader?
>>>>
>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>> restricted DM as well.
>>>>
>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>> treatment. Earlier on we also talked about the region not necessarily being
>>>> page-aligned. That poses, even with r/o exposure, the question of other
>>>> data on the same (leading / trailing) pages. This may imply that the
>>>> copying needs to be done strictly in Dom0, for both DM and guest to only
>>>> ever act on copies (which may then as well be r/w).
>>>
>>> Yes, I am thinking the DM should make a copy host OpRegion and never expose
>>> the host OpRegion to the guest but only a copy of it.
>>>
>>> The reason we need a patch like this is that with the introduction of the
>>> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
>>> so its contents might be unsuitable in the guest address space, so in those cases
>>> we need to patch the copy of the OpRegion that will be exposed to the guest.
>>> If there is an extended VBT the DM will also get a copy of it, make a copy of
>>> it, and expose it to the guest by appending it contiguous with the OpRegion.
>>> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
>>> then it can find the host VBT and make a copy of it without needing hvmloader
>>> to send the rvda and rvds values to it.
>>>
>>> Then, the remaining question is which component (DM or hvmloader) will patch it
>>> if it needs to be patched to make the guest's copy of it compatible with the guest
>>> address space.
>>
>> As I noted earlier, it think it would be advantageous for the Xen platform as whole
>> for the patching to be done in hvmloader. That way, support for extended VBT is
>> automatically added for all implementations of the DM, not just for Qemu. But the
>> downside is that for hvmloader to do the patching, it needs to know the host OpRegion
>> address, which one could argue it should not need to know. This is the only reason I
>> can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
>> avoid disclosing the host OpRegion address to the guest.
>
> Correction: Actually, with this new scenario, we need not disclose any confidential
> host addresses to hvmloader if the DM removes such information from the copy of
> the OpRegion that it exposes to hvmloader. Then, all hvmloader needs to know to
> ensure the OpRegion is compatible with the guest's address space is the guest
> address of the OpRegion. It need not know either the host OpRegion address or the
> host VBT address.
>
> So the guidance I need from you to do v3 of the patch is simply to answer these
> two questions.
>
> 1. Should I write v3 of the patch not only assuming the DM will never expose the
> host OpRegion to hvmloader, but also assuming that the DM is responsible for
> patching the OpRegion to ensure it is compatible with guest address space?
>
> Or
>
> 2. Should I write v3 of the patch assuming that hvmloader is responsible for
> patching the OpRegion so it is compatible with the guest address space?
My tentative response is to use option 1, not the least because a mid to long term
plan is to see about removing hvmloader altogether. However, a more firm response
here depends on an answer to the question raised in
<92022f85-9a53-4db8-b489-fc91c86b413c@suse.com> (sorry, the list archive hasn't
caught up yet).
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 7:51 ` Jan Beulich
@ 2026-08-20 11:47 ` Chuck Zmudzinski
2026-08-20 15:17 ` Jan Beulich
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-20 11:47 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/20/2026 3:51 AM, Jan Beulich wrote:
> On 19.08.2026 19:13, Chuck Zmudzinski wrote:
>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>> about avoiding the layering violation than anything else.
>>>>
>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>
>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>> in hvmloader?
>>>
>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>> screw up that data such that subsequent guests won't work anymore. Hence
>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>> restricted DM as well.
>>>
>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>> treatment.
>>
>> Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
>> it functions more or less like a BAR region with the devices's ASLS register
>> at offset 0xfc in the PCI device config space of the device acting like the
>> BAR for that region.
>
> That is, on real hardware a write to that register moves the OpRegion? That
> would need following by the DM then, i.e. the DM would need to indicate the
> original position in the register, and the guest (incl hvmloader) would
> then be free to relocate it.
Why would that "need following by the DM" when the register in the guest is
fully emulated, [1] which means that when the guest (incl hvmloader) writes to the
register, the register on the real hardware is not touched, nor is the OpRegion
in the host address space moved?
Here is how I understand how this works in the current implementation and how
this should be done:
Intel's spec (an old version of it that does not yet define the rvda and rvds
fields) is available online. [2] What that spec says (it is for skylake processors,
released c. 2015 IIRC) is that the ASLS register is a write once register. The
system firmware is to place the OpRegion into memory anywhere below the 4 GiB limit
(because it is a 32-bit register) and mark it as type ACPI NVS memory in the E820 map,
and write once to that register the location of the OpRegion in the address space.
The spec says that from then on it is read-only for the OS graphics driver to consume.
When the IGD is passed through to a Xen HVM guest in the current implementation,
all 32 bits of the ASLS register are emulated from the guest's point of view. That
is, when the guest (hvmloader or seabios/ovmf) writes to it, the register on the
host (i.e. the register on the real, physical hardware) is not touched at all, nor
is the OpRegion moved in the host address space. I am fairly certain this setup of
having the ASLS register emulated is not specific to Qemu but applies to all DMs
that are to interface with the current implementation in hvmloader, because in
hvmloader we have this comment in tools/firmware/hvmloader/pci.c:
/*
* Write the the OpRegion offset to give the opregion
* address to the device model. The device model will trap
* and map the OpRegion at the give address.
*/
What does it mean to say the device model will trap? I think it means the
device model is to emulate all 32 bits of the ASLS register which will leave
the position of the OpRegion in the host address space unchanged and the ASLS
register on the real hardware untouched.
So, hvmloader need not need know the position of the OpRegion in the host address
space since the DM maps the host OpRegion into the guest address space at the
location it is to be accessed at in the guest. That is what the current
implementation in hvmloader presumes the DM will do, as evidenced by the comment
from hvmloader code quoted above, and it is also exactly what Qemu currently does.
Indeed, it is clear that in the current implementation, the host OpRegion address
is not disclosed to the guest (hvmloader) and the guest is able to access the host
OpRegion without knowing the OpRegion address in the host. That is my understanding
of how the current implementation works.
Now, we are proposing that the DM should expose a copy of the OpRegion to the
guest instead of mapping the host OpRegion into the guest address space. Even with
such a change from the way it is done now, hvmloader still need not know where the
OpRegion is on the host as long as the DM remains responsible (as it is in the current
implementation) for making the copy of the OpRegion for the guest accessible to the
OpRegion at (or near, because currently the address hvmloader writes to the register
is just a hint because the DM adds the offset from the page boundary to the address
in the current implementation) the address hvmloader has requested.
I think there are multiple ways for the DM to do this. It could place the copy of the
OpRegion into the guest memory at or near the address hvmloader requested without
disclosing the address of the OpRegion on the host. It could place the copy of the
OpRegion into the DM domain's memory and grant the guest access to it using grant tables.
There are probably also other ways to do it. IIUC, if the DM uses grant tables, it
would not need to disclose the address of the OpRegion in the host address space to
hvmloader.
There are even more options to accomplish this. For example, in a previous comment
you suggested that perhaps the DM should place a copy of the OpRegion *before* the
guest (hvmloader) ever gains control. I noted that would require making the spec
for how hvmloader computes the position the OpRegion will be at in the guest address
space public, and in that case the DM would compute the correct guest address
for the guest and place the suitably patched copy of the OpRegion into guest memory
at the correct address for the guest and program the ASLS register with the correct
guest address.
In this case, the patch to hvmloader would add a read of the ASLS register which
will allow hvmloader to determine, for example, if more space is needed in the E820
map to accommodate an extended VBT and adjust the E820 map appropriately, and also
in that case the device model would ignore any write that hvmloader currently does
to that register because in this case, the DM has already programmed the register
with the correct address.
So with all the different options about how to do this, my head is spinning and
since with your comments you are confusing me about what approach you think is best,
I cannot at the present time write v3 of this patch. What I need is for you or one
of the other maintainers of hvmloader to *make a decision* about how support for
extended VBT is to be added to the Xen platform. I think I have given you and the
other maintainers enough information to make a decision about how best to add support
for the extended VBT to the Xen platform. I understand it may take some time for
you to process all this information and make the decision, but at the present time
we seem to just be going around in circles discussing this, which is not really the
best use of either your time or my time.
Chuck
[1] The specification for how PCI config space registers are programmed for emulation
vs. passthrough, please refer to the official PCI specification.
[2] https://www.intel.com/content/www/us/en/docs/graphics-for-linux/developer-reference/1-0/opregion-specification.html
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 7:58 ` Jan Beulich
@ 2026-08-20 13:03 ` Chuck Zmudzinski
2026-08-20 14:58 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-20 13:03 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/20/2026 3:58 AM, Jan Beulich wrote:
> On 19.08.2026 21:09, Chuck Zmudzinski wrote:
>> On 8/19/2026 1:49 PM, Chuck Zmudzinski wrote:
>>> On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
>>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>>> about avoiding the layering violation than anything else.
>>>>>>
>>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>>
>>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>>> in hvmloader?
>>>>>
>>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>>> restricted DM as well.
>>>>>
>>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>>> treatment. Earlier on we also talked about the region not necessarily being
>>>>> page-aligned. That poses, even with r/o exposure, the question of other
>>>>> data on the same (leading / trailing) pages. This may imply that the
>>>>> copying needs to be done strictly in Dom0, for both DM and guest to only
>>>>> ever act on copies (which may then as well be r/w).
>>>>
>>>> Yes, I am thinking the DM should make a copy host OpRegion and never expose
>>>> the host OpRegion to the guest but only a copy of it.
>>>>
>>>> The reason we need a patch like this is that with the introduction of the
>>>> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
>>>> so its contents might be unsuitable in the guest address space, so in those cases
>>>> we need to patch the copy of the OpRegion that will be exposed to the guest.
>>>> If there is an extended VBT the DM will also get a copy of it, make a copy of
>>>> it, and expose it to the guest by appending it contiguous with the OpRegion.
>>>> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
>>>> then it can find the host VBT and make a copy of it without needing hvmloader
>>>> to send the rvda and rvds values to it.
>>>>
>>>> Then, the remaining question is which component (DM or hvmloader) will patch it
>>>> if it needs to be patched to make the guest's copy of it compatible with the guest
>>>> address space.
>>>
>>> As I noted earlier, it think it would be advantageous for the Xen platform as whole
>>> for the patching to be done in hvmloader. That way, support for extended VBT is
>>> automatically added for all implementations of the DM, not just for Qemu. But the
>>> downside is that for hvmloader to do the patching, it needs to know the host OpRegion
>>> address, which one could argue it should not need to know. This is the only reason I
>>> can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
>>> avoid disclosing the host OpRegion address to the guest.
>>
>> Correction: Actually, with this new scenario, we need not disclose any confidential
>> host addresses to hvmloader if the DM removes such information from the copy of
>> the OpRegion that it exposes to hvmloader. Then, all hvmloader needs to know to
>> ensure the OpRegion is compatible with the guest's address space is the guest
>> address of the OpRegion. It need not know either the host OpRegion address or the
>> host VBT address.
>>
>> So the guidance I need from you to do v3 of the patch is simply to answer these
>> two questions.
>>
>> 1. Should I write v3 of the patch not only assuming the DM will never expose the
>> host OpRegion to hvmloader, but also assuming that the DM is responsible for
>> patching the OpRegion to ensure it is compatible with guest address space?
>>
>> Or
>>
>> 2. Should I write v3 of the patch assuming that hvmloader is responsible for
>> patching the OpRegion so it is compatible with the guest address space?
>
> My tentative response is to use option 1, not the least because a mid to long term
> plan is to see about removing hvmloader altogether. However, a more firm response
> here depends on an answer to the question raised in
> <92022f85-9a53-4db8-b489-fc91c86b413c@suse.com> (sorry, the list archive hasn't
> caught up yet).
I apologize for the tone of my last message which I wrote before I saw this message.
(Unfortunately some of your messages are going to the spam folder, I will try to fix
that, but it seems aol.com's spam filters are not all that smart)
I was really hoping you would answer this question and I appreciate that you are
able to give me a tentative answer favoring option 1.
To follow up on what I did say in the last message, I think we have exhausted what
you and I can agree on and now would be a good time to pause this discussion and
I will write a new version of the Qemu patches and v3 of this patch assuming what
I said in option 1, and hopefully the Qemu maintainers will help us out by replying
to a version of the Qemu patches that does the patching of the OpRegion in Qemu instead
of in hvmloader. So far none of the Qemu maintainers have replied to my Qemu patches,
unfortunately, but ultimately, we at some point will need their input to decide how
best to do this, so until they respond to the Qemu patchsets I posted, I think we
just have to wait now until they weigh in with their thoughts and opinions.
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 7:53 ` Jan Beulich
@ 2026-08-20 13:03 ` Chuck Zmudzinski
0 siblings, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-20 13:03 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/20/2026 3:53 AM, Jan Beulich wrote:
> On 19.08.2026 19:49, Chuck Zmudzinski wrote:
>> On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>> about avoiding the layering violation than anything else.
>>>>>
>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>
>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>> in hvmloader?
>>>>
>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>> restricted DM as well.
>>>>
>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>> treatment. Earlier on we also talked about the region not necessarily being
>>>> page-aligned. That poses, even with r/o exposure, the question of other
>>>> data on the same (leading / trailing) pages. This may imply that the
>>>> copying needs to be done strictly in Dom0, for both DM and guest to only
>>>> ever act on copies (which may then as well be r/w).
>>>
>>> Yes, I am thinking the DM should make a copy host OpRegion and never expose
>>> the host OpRegion to the guest but only a copy of it.
>>>
>>> The reason we need a patch like this is that with the introduction of the
>>> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
>>> so its contents might be unsuitable in the guest address space, so in those cases
>>> we need to patch the copy of the OpRegion that will be exposed to the guest.
>>> If there is an extended VBT the DM will also get a copy of it, make a copy of
>>> it, and expose it to the guest by appending it contiguous with the OpRegion.
>>> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
>>> then it can find the host VBT and make a copy of it without needing hvmloader
>>> to send the rvda and rvds values to it.
>>>
>>> Then, the remaining question is which component (DM or hvmloader) will patch it
>>> if it needs to be patched to make the guest's copy of it compatible with the guest
>>> address space.
>>
>> As I noted earlier, it think it would be advantageous for the Xen platform as whole
>> for the patching to be done in hvmloader. That way, support for extended VBT is
>> automatically added for all implementations of the DM, not just for Qemu. But the
>> downside is that for hvmloader to do the patching, it needs to know the host OpRegion
>> address, which one could argue it should not need to know. This is the only reason I
>> can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
>> avoid disclosing the host OpRegion address to the guest.
>>
>> But we trust hvmloader, don't we, to not abuse this knowledge of the host's OpRegion
>> address?
>
> No, we cannot (fully) trust hvmloader.
That is good to know.
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 13:03 ` Chuck Zmudzinski
@ 2026-08-20 14:58 ` Chuck Zmudzinski
0 siblings, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-20 14:58 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/20/2026 9:03 AM, Chuck Zmudzinski wrote:
> On 8/20/2026 3:58 AM, Jan Beulich wrote:
>> On 19.08.2026 21:09, Chuck Zmudzinski wrote:
>>> On 8/19/2026 1:49 PM, Chuck Zmudzinski wrote:
>>>> On 8/19/2026 11:47 AM, Chuck Zmudzinski wrote:
>>>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>>>> about avoiding the layering violation than anything else.
>>>>>>>
>>>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>>>
>>>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>>>> in hvmloader?
>>>>>>
>>>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>>>> restricted DM as well.
>>>>>>
>>>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>>>> treatment. Earlier on we also talked about the region not necessarily being
>>>>>> page-aligned. That poses, even with r/o exposure, the question of other
>>>>>> data on the same (leading / trailing) pages. This may imply that the
>>>>>> copying needs to be done strictly in Dom0, for both DM and guest to only
>>>>>> ever act on copies (which may then as well be r/w).
>>>>>
>>>>> Yes, I am thinking the DM should make a copy host OpRegion and never expose
>>>>> the host OpRegion to the guest but only a copy of it.
>>>>>
>>>>> The reason we need a patch like this is that with the introduction of the
>>>>> rvda/rvds fields into the OpRegion, the OpRegion is not always position-independent
>>>>> so its contents might be unsuitable in the guest address space, so in those cases
>>>>> we need to patch the copy of the OpRegion that will be exposed to the guest.
>>>>> If there is an extended VBT the DM will also get a copy of it, make a copy of
>>>>> it, and expose it to the guest by appending it contiguous with the OpRegion.
>>>>> Since in this scenario we are assuming the DM knows the contents of the OpRegion,
>>>>> then it can find the host VBT and make a copy of it without needing hvmloader
>>>>> to send the rvda and rvds values to it.
>>>>>
>>>>> Then, the remaining question is which component (DM or hvmloader) will patch it
>>>>> if it needs to be patched to make the guest's copy of it compatible with the guest
>>>>> address space.
>>>>
>>>> As I noted earlier, it think it would be advantageous for the Xen platform as whole
>>>> for the patching to be done in hvmloader. That way, support for extended VBT is
>>>> automatically added for all implementations of the DM, not just for Qemu. But the
>>>> downside is that for hvmloader to do the patching, it needs to know the host OpRegion
>>>> address, which one could argue it should not need to know. This is the only reason I
>>>> can think of to do the patching of the OpRegion in the DM instead of in hvmloader: to
>>>> avoid disclosing the host OpRegion address to the guest.
>>>
>>> Correction: Actually, with this new scenario, we need not disclose any confidential
>>> host addresses to hvmloader if the DM removes such information from the copy of
>>> the OpRegion that it exposes to hvmloader. Then, all hvmloader needs to know to
>>> ensure the OpRegion is compatible with the guest's address space is the guest
>>> address of the OpRegion. It need not know either the host OpRegion address or the
>>> host VBT address.
>>>
>>> So the guidance I need from you to do v3 of the patch is simply to answer these
>>> two questions.
>>>
>>> 1. Should I write v3 of the patch not only assuming the DM will never expose the
>>> host OpRegion to hvmloader, but also assuming that the DM is responsible for
>>> patching the OpRegion to ensure it is compatible with guest address space?
>>>
>>> Or
>>>
>>> 2. Should I write v3 of the patch assuming that hvmloader is responsible for
>>> patching the OpRegion so it is compatible with the guest address space?
>>
>> My tentative response is to use option 1, not the least because a mid to long term
>> plan is to see about removing hvmloader altogether. However, a more firm response
>> here depends on an answer to the question raised in
>> <92022f85-9a53-4db8-b489-fc91c86b413c@suse.com> (sorry, the list archive hasn't
>> caught up yet).
Ah, I see this message is the one you sent me earlier today about this patch and now
the list archive has caught up so for those who might be reading this thread here
is the link:
https://lore.kernel.org/xen-devel/92022f85-9a53-4db8-b489-fc91c86b413c@suse.com/
Well, I did try to answer this question here:
https://lore.kernel.org/xen-devel/fa497825-c8f0-4caf-94f5-b37108e31952@aol.com/
My answer is based on the fact, as far as I understand it, the ASLS register
on the real hardware is not touched when the guest writes to it because in our
case the register is fully emulated and the guest can only access and write to or
read from the emulated virtual register, not the real register on the hardware.
Also, we have this code in Qemu (hw/xen/xen_pt_config_init.c):
static XenPTRegInfo xen_pt_emu_reg_igd_opregion[] = {
/* Intel IGFX OpRegion reg */
{
.offset = 0x0,
.size = 4,
.init_val = 0,
.emu_mask = 0xFFFFFFFF,
.u.dw.read = xen_pt_intel_opregion_read,
.u.dw.write = xen_pt_intel_opregion_write,
},
Do you see that emu_mask setting of 0xFFFFFFFF? As I understand it, that means
that all 32 bits of the register are emulated, and none of the bits are passed
through to the real device.
Also, I can quote from the (admittedly outdated) spec for the OpRegion that is
available online [1] which says this about the ASLS register of the IGD PCI device
in section 5.1.2 of that document:
> This register is a software scratch register and is not used by hardware
> other than to hold the state software has set.
I think this means that even if the real hardware register on the device was exposed
to the guest and the guest wrote a different address to the register, it would
*not* "move" the host OpRegion anywhere because, as the spec says, the register is
not used by hardware but by software (the system BIOS software) to let the graphics
driver know where it can find the OpRegion. But the guest *cannot* access the real
ASLS register on the device in our implementation nor in my proposed implementation
in v2 of this patch or in any of the other ways to solve this problem that we
have discussed in this thread.
So I don't understand how the question you raise poses a serious problem.
But if you are not an expert on the PCI specification and how the PCI config space
registers can be programmed with emulated bits and passthrough bits, and if you
don't trust my understanding of it either, then I think we need to wait for
experts on the PCI specification to weigh in and answer your question before we
can move forward.
Chuck
[1] https://www.intel.com/content/www/us/en/docs/graphics-for-linux/developer-reference/1-0/opregion-specification.html
To actually see the spec, click on the "OpRegion Specification" link in the page
shown above and download the pdf file that link points to. It is still live, I
checked it today.
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 11:47 ` Chuck Zmudzinski
@ 2026-08-20 15:17 ` Jan Beulich
2026-08-20 16:53 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-20 15:17 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 20.08.2026 13:47, Chuck Zmudzinski wrote:
> On 8/20/2026 3:51 AM, Jan Beulich wrote:
>> On 19.08.2026 19:13, Chuck Zmudzinski wrote:
>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>> about avoiding the layering violation than anything else.
>>>>>
>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>
>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>> in hvmloader?
>>>>
>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>> restricted DM as well.
>>>>
>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>> treatment.
>>>
>>> Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
>>> it functions more or less like a BAR region with the devices's ASLS register
>>> at offset 0xfc in the PCI device config space of the device acting like the
>>> BAR for that region.
>>
>> That is, on real hardware a write to that register moves the OpRegion? That
>> would need following by the DM then, i.e. the DM would need to indicate the
>> original position in the register, and the guest (incl hvmloader) would
>> then be free to relocate it.
>
> Why would that "need following by the DM" when the register in the guest is
> fully emulated, [1] which means that when the guest (incl hvmloader) writes to the
> register, the register on the real hardware is not touched, nor is the OpRegion
> in the host address space moved?
You said it's BAR-like. If the guest writes to a BAR, the referenced MMIO
region moves accordingly.
> Here is how I understand how this works in the current implementation and how
> this should be done:
I'm sorry, but this is getting out of hand, at least as far as I'm concerned.
I've been trying to help, but even just reading your replies has already been
taking way more time than I would have wanted to spend here.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 15:17 ` Jan Beulich
@ 2026-08-20 16:53 ` Chuck Zmudzinski
2026-08-21 8:19 ` Jan Beulich
0 siblings, 1 reply; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-20 16:53 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/20/2026 11:17 AM, Jan Beulich wrote:
> On 20.08.2026 13:47, Chuck Zmudzinski wrote:
>> On 8/20/2026 3:51 AM, Jan Beulich wrote:
>>> On 19.08.2026 19:13, Chuck Zmudzinski wrote:
>>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>>> about avoiding the layering violation than anything else.
>>>>>>
>>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>>
>>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>>> in hvmloader?
>>>>>
>>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>>> restricted DM as well.
>>>>>
>>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>>> treatment.
>>>>
>>>> Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
>>>> it functions more or less like a BAR region with the devices's ASLS register
>>>> at offset 0xfc in the PCI device config space of the device acting like the
>>>> BAR for that region.
>>>
>>> That is, on real hardware a write to that register moves the OpRegion? That
>>> would need following by the DM then, i.e. the DM would need to indicate the
>>> original position in the register, and the guest (incl hvmloader) would
>>> then be free to relocate it.
>>
>> Why would that "need following by the DM" when the register in the guest is
>> fully emulated, [1] which means that when the guest (incl hvmloader) writes to the
>> register, the register on the real hardware is not touched, nor is the OpRegion
>> in the host address space moved?
>
> You said it's BAR-like. If the guest writes to a BAR, the referenced MMIO
> region moves accordingly.
It's BAR-like, but it is not actually a BAR (and the OpRegion is not exactly
an MMIO region either (it is actually and ACPI thing), so that is not relevant
to this patch.
Also, it is fully emulated so when the guest writes to it, the real register on the
real device is not touched, as I have said multiple times in my responses to your
question.
>
>> Here is how I understand how this works in the current implementation and how
>> this should be done:
>
> I'm sorry, but this is getting out of hand, at least as far as I'm concerned.
> I've been trying to help, but even just reading your replies has already been
> taking way more time than I would have wanted to spend here.
>
Fair enough. Thank you for the time you have spent on this patch, and also thank
you for clearly stating that you don't want to spend any more time on it. So
I consider this patch dead unless and until another maintainer shows some interest
in it.
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-20 16:53 ` Chuck Zmudzinski
@ 2026-08-21 8:19 ` Jan Beulich
2026-08-21 13:12 ` Chuck Zmudzinski
0 siblings, 1 reply; 42+ messages in thread
From: Jan Beulich @ 2026-08-21 8:19 UTC (permalink / raw)
To: Chuck Zmudzinski
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 20.08.2026 18:53, Chuck Zmudzinski wrote:
> On 8/20/2026 11:17 AM, Jan Beulich wrote:
>> On 20.08.2026 13:47, Chuck Zmudzinski wrote:
>>> On 8/20/2026 3:51 AM, Jan Beulich wrote:
>>>> On 19.08.2026 19:13, Chuck Zmudzinski wrote:
>>>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>>>> about avoiding the layering violation than anything else.
>>>>>>>
>>>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>>>
>>>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>>>> in hvmloader?
>>>>>>
>>>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>>>> restricted DM as well.
>>>>>>
>>>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>>>> treatment.
>>>>>
>>>>> Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
>>>>> it functions more or less like a BAR region with the devices's ASLS register
>>>>> at offset 0xfc in the PCI device config space of the device acting like the
>>>>> BAR for that region.
>>>>
>>>> That is, on real hardware a write to that register moves the OpRegion? That
>>>> would need following by the DM then, i.e. the DM would need to indicate the
>>>> original position in the register, and the guest (incl hvmloader) would
>>>> then be free to relocate it.
>>>
>>> Why would that "need following by the DM" when the register in the guest is
>>> fully emulated, [1] which means that when the guest (incl hvmloader) writes to the
>>> register, the register on the real hardware is not touched, nor is the OpRegion
>>> in the host address space moved?
>>
>> You said it's BAR-like. If the guest writes to a BAR, the referenced MMIO
>> region moves accordingly.
>
> It's BAR-like, but it is not actually a BAR (and the OpRegion is not exactly
> an MMIO region either (it is actually and ACPI thing), so that is not relevant
> to this patch.
>
> Also, it is fully emulated so when the guest writes to it, the real register on the
> real device is not touched, as I have said multiple times in my responses to your
> question.
No matter how often you said that, I never put that under question. I was asking
about the behavior of writes (where the behavior on bare hardware would need to
be reflected in the behavior of the emulated register).
>>> Here is how I understand how this works in the current implementation and how
>>> this should be done:
>>
>> I'm sorry, but this is getting out of hand, at least as far as I'm concerned.
>> I've been trying to help, but even just reading your replies has already been
>> taking way more time than I would have wanted to spend here.
>
> Fair enough. Thank you for the time you have spent on this patch, and also thank
> you for clearly stating that you don't want to spend any more time on it. So
> I consider this patch dead unless and until another maintainer shows some interest
> in it.
I didn't say I would not look at future versions of the patch. However, for me
to (usefully) do so, things need to be presented in a way that I can understand
without knowing all the details of IGD.
Jan
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support
2026-08-21 8:19 ` Jan Beulich
@ 2026-08-21 13:12 ` Chuck Zmudzinski
0 siblings, 0 replies; 42+ messages in thread
From: Chuck Zmudzinski @ 2026-08-21 13:12 UTC (permalink / raw)
To: Jan Beulich
Cc: qemu-devel, Andrew Cooper, Roger Pau Monné, Teddy Astie,
Tomita Moeko, xen-devel
On 8/21/2026 4:19 AM, Jan Beulich wrote:
> On 20.08.2026 18:53, Chuck Zmudzinski wrote:
>> On 8/20/2026 11:17 AM, Jan Beulich wrote:
>>> On 20.08.2026 13:47, Chuck Zmudzinski wrote:
>>>> On 8/20/2026 3:51 AM, Jan Beulich wrote:
>>>>> On 19.08.2026 19:13, Chuck Zmudzinski wrote:
>>>>>> On 8/19/2026 9:51 AM, Jan Beulich wrote:
>>>>>>> On 19.08.2026 14:36, Chuck Zmudzinski wrote:
>>>>>>>> On 8/19/2026 8:16 AM, Chuck Zmudzinski wrote:
>>>>>>>>> Yes, I agree that v3 of the patch to hvmloader should presume that the DM can get
>>>>>>>>> a copy of the OpRegion and read its contents so most of this can be done in the
>>>>>>>>> DM instead of in hvmloader. So from hvmloader's perspective, the patch will be more
>>>>>>>>> about avoiding the layering violation than anything else.
>>>>>>>>
>>>>>>>> However, there is one advantage, from the viewpoint of the Xen virtualization platform
>>>>>>>> as a whole, to do the patching of the OpRegion in hvmloader instead of in the DM.
>>>>>>>>
>>>>>>>> If we patch the OpRegion in hvmloader as v2 of this patch does, we provide a common
>>>>>>>> solution for extended VBT support for Intel IGD devices that would be compatible with
>>>>>>>> all DM implementations, not just with Qemu. So why not do the patching of the OpRegion
>>>>>>>> in hvmloader?
>>>>>>>
>>>>>>> As indicated before: If the OpRegion holds data that is needed to drive the
>>>>>>> device, and if the OpRegion is exposed writable to guests, then guest can
>>>>>>> screw up that data such that subsequent guests won't work anymore. Hence
>>>>>>> exposing to guests (which includes hvmloader) needs to be stopped, or at
>>>>>>> least be limited to r/o. That, in fact, includes exposing to any privilege-
>>>>>>> restricted DM as well.
>>>>>>>
>>>>>>> Exposing r/o may be entirely okay (i.e. may not be a layering violation),
>>>>>>> depending how exactly an OpRegion surfaces for a device (on the host). Aiui
>>>>>>> it's not addressed by any of the BARs, yet it looks like it needs similar
>>>>>>> treatment.
>>>>>>
>>>>>> Yes, the OpRegion is not one of the BARs as specified by the PCI specs, but
>>>>>> it functions more or less like a BAR region with the devices's ASLS register
>>>>>> at offset 0xfc in the PCI device config space of the device acting like the
>>>>>> BAR for that region.
>>>>>
>>>>> That is, on real hardware a write to that register moves the OpRegion? That
>>>>> would need following by the DM then, i.e. the DM would need to indicate the
>>>>> original position in the register, and the guest (incl hvmloader) would
>>>>> then be free to relocate it.
>>>>
>>>> Why would that "need following by the DM" when the register in the guest is
>>>> fully emulated, [1] which means that when the guest (incl hvmloader) writes to the
>>>> register, the register on the real hardware is not touched, nor is the OpRegion
>>>> in the host address space moved?
>>>
>>> You said it's BAR-like. If the guest writes to a BAR, the referenced MMIO
>>> region moves accordingly.
>>
>> It's BAR-like, but it is not actually a BAR (and the OpRegion is not exactly
>> an MMIO region either (it is actually and ACPI thing), so that is not relevant
>> to this patch.
>>
>> Also, it is fully emulated so when the guest writes to it, the real register on the
>> real device is not touched, as I have said multiple times in my responses to your
>> question.
>
> No matter how often you said that, I never put that under question. I was asking
> about the behavior of writes (where the behavior on bare hardware would need to
> be reflected in the behavior of the emulated register).
>
>>>> Here is how I understand how this works in the current implementation and how
>>>> this should be done:
>>>
>>> I'm sorry, but this is getting out of hand, at least as far as I'm concerned.
>>> I've been trying to help, but even just reading your replies has already been
>>> taking way more time than I would have wanted to spend here.
>>
>> Fair enough. Thank you for the time you have spent on this patch, and also thank
>> you for clearly stating that you don't want to spend any more time on it. So
>> I consider this patch dead unless and until another maintainer shows some interest
>> in it.
>
> I didn't say I would not look at future versions of the patch. However, for me
> to (usefully) do so, things need to be presented in a way that I can understand
> without knowing all the details of IGD.
Thanks for clarifying. If I do v3 I will try to present things in a way that clearly
answers the questions you have raised here about IGD and provide more information
about IGD than I did in v1/v2 for those who don't know all the details of it.
If I do a v3, you will of course be on the Cc list since I expect you will be one of
the maintainers of the affected code.
Chuck
^ permalink raw reply [flat|nested] 42+ messages in thread
end of thread, other threads:[~2026-08-21 13:12 UTC | newest]
Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260802050824.10554-1-brchuckz.ref@aol.com>
2026-08-02 5:08 ` [PATCH v2] tools/hvmloader: implement Intel IGD extended VBT support Chuck Zmudzinski
2026-08-13 10:35 ` Jan Beulich
2026-08-14 0:45 ` Chuck Zmudzinski
2026-08-14 7:35 ` Jan Beulich
2026-08-14 13:18 ` Chuck Zmudzinski
2026-08-14 13:46 ` Jan Beulich
2026-08-14 15:23 ` Chuck Zmudzinski
2026-08-14 16:18 ` Chuck Zmudzinski
2026-08-14 19:13 ` Chuck Zmudzinski
2026-08-14 17:07 ` Chuck Zmudzinski
2026-08-17 8:42 ` Jan Beulich
2026-08-17 16:04 ` Chuck Zmudzinski
2026-08-17 17:04 ` Chuck Zmudzinski
2026-08-18 7:17 ` Jan Beulich
2026-08-18 11:52 ` Chuck Zmudzinski
2026-08-18 12:18 ` Jan Beulich
2026-08-18 12:29 ` Chuck Zmudzinski
2026-08-18 17:15 ` Chuck Zmudzinski
2026-08-19 7:30 ` Jan Beulich
2026-08-19 12:16 ` Chuck Zmudzinski
2026-08-19 12:36 ` Chuck Zmudzinski
2026-08-19 13:51 ` Jan Beulich
2026-08-19 15:47 ` Chuck Zmudzinski
2026-08-19 17:49 ` Chuck Zmudzinski
2026-08-19 19:09 ` Chuck Zmudzinski
2026-08-20 7:58 ` Jan Beulich
2026-08-20 13:03 ` Chuck Zmudzinski
2026-08-20 14:58 ` Chuck Zmudzinski
2026-08-20 7:53 ` Jan Beulich
2026-08-20 13:03 ` Chuck Zmudzinski
2026-08-19 17:13 ` Chuck Zmudzinski
2026-08-20 7:51 ` Jan Beulich
2026-08-20 11:47 ` Chuck Zmudzinski
2026-08-20 15:17 ` Jan Beulich
2026-08-20 16:53 ` Chuck Zmudzinski
2026-08-21 8:19 ` Jan Beulich
2026-08-21 13:12 ` Chuck Zmudzinski
2026-08-19 12:10 ` Chuck Zmudzinski
2026-08-15 2:22 ` Chuck Zmudzinski
2026-08-17 9:11 ` Jan Beulich
2026-08-16 16:38 ` Chuck Zmudzinski
2026-08-17 9:18 ` Jan Beulich
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.