* [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 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 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 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-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-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 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 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: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 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-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-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-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 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-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 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
* 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-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-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-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-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
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.