[Pkg-xen-devel] Bug#988333: libxenmisc4.16: libxl fails to grant necessary I/O memory access for gfx_passthru of Intel IGD

Chuck Zmudzinski brchuckz at netscape.net
Mon Mar 7 15:11:29 GMT 2022


Detailed description of how I discovered the patch that fixes the bug 
and enables Intel IGD passthrough to Bullseye when using the traditional 
Qemu device model:

A long time ago, during the development of Xen 4.5 in 2014, two patches 
implemented a change to the way permission is granted for an 
unprivileged domain to access PCI/VGA-related I/O memory. Prior to this, 
AFAICT, permission was implicitly granted to access the memory the 
domain requested when a PCI device being passed to the domain was being 
configured. After the change, permission to access such memory is not 
granted without prior explicit permission being configured, and this is 
still the current behavior.

The relevant patches are:

1. 
https://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=abfb006f1ff4af1424e5b0d0589f0226377fda36

and

2. 
https://xenbits.xen.org/gitweb/?p=xen.git;a=commitdiff;h=0561e1f01e87b777bcc47971e4ae1f420314f4a0

The first of these patches intended to implement explicit granting of 
permission to access the I/O memory that is needed to support the 
gfx_passthru feature in libxl_pci.c, in the 
libxl__grant_vga_iomem_permission function. The second patch implements 
the removal of implicit permission to access the PCI/VGA-related I/O 
memory and causes requests to access such memory by a domain to be 
denied unless prior explicit permission has been configured.

Specifically, the first patch adds 32 (0x20) units (I presume bytes) of 
data starting at memory address 0xa0000 >> XC_PAGE_SHIFT to the memory 
the domain is permitted to access. XC_PAGE_SHIFT is 12, so this memory 
range shows up in the logs when running Xen 4.5 as:

memory_map:add: dom1 gfn=a0 mfn=a0 nr=20

But my testing of these old patches with added custom logging shows that 
another two units (bytes?) are needed:

memory_map:access not permitted: dom1 gfn=fdffc mfn=cc490 nr=2

On versions of Xen prior to adding these two patches the mapping succeeds:

memory_map:add: dom1 gfn=fdffc mfn=cc490 nr=2

The failure to map this memory with gfx_passthru enabled is therefore a 
bug, a regression that was introduced with the two aforementioned 
upstream patches from the development of Xen 4.5 back in 2014.

This bug still exists in current supported versions of Xen because in 
these versions of Xen, passthrough of the Haswell Intel IGD to a Linux 
domain fails with a crash of the i915 Linux kernel module in the Linux 
unprivileged domain when the traditional Qemu device model is used in 
dom0, and the Linux domain is unable to handle IRQ's from the passed 
through IGD device when the upstream QEMU device model is used in dom0. 
Prior to the addition of the aforementioned patches, passthrough of the 
Haswell Intel IGD worked with Linux domains, but not after these patches 
were added to Xen.

When passing through the Haswell Intel IGD to a Windows domain, the 
Windows domain also tries to access the same memory (gfn=fdffc mfn=cc490 
nr=2) and is also denied access just as with a Linux domain, but the 
Windows domain is able to workaround this lack of access to that memory 
and the Intel IGD functions properly without a crash of the Windows 
Intel graphics driver in the Windows domain and, AFAICT, without any 
problems handling the IRQs. I think this is because of a difference in 
the way Windows handles IRQs from the passed through Intel IGD, in 
contrast to how Linux handles IRQs from the passed through Intel IGD.

With a Windows HVM, I see the following message in the log (Xen 4.5):

irq.c:380: Dom2 callback via changed to GSI 28

With a Linux HVM, instead I see the following message in the log (Xen 4.5):

irq.c:380: Dom1 callback via changed to Direct Vector 0xf3

AFAICT, this difference is what causes IGD passthrough to work with a 
Windows domain, but not with a Linux domain, in current supported 
versions of Xen.

This also might partially explain why there are problems configuring the 
IRQ for the Linux domain when using the upstream Qemu device model in 
dom0. It seems likely that when the callback for handling the IRQ is 
direct vector, rather than gsi, the domain needs to access the memory 
that is blocked by the aforementioned patches from way back in 2014. I 
suspect the blocked memory contains essential data about the IRQ that 
the Linux domain needs, but the Windows domain does not necessarily need 
it because it uses a different callback for the IRQ. But more 
investigation is needed and there is probably another bug that needs to 
be patched for the setup to work with the upstream Qemu device model 
instead of the traditional Qemu device model.

Nevertheless, this bug defined narrowly as a failure to grant the 
necessary I/O memory access to a Linux HVM domU for gfx_passthru of the 
Intel IGD is fixed by modifying the first patch discussed above from the 
Xen 4.5 branch committed back in 2014 so it also explicitly grants 
access to the memory defined by the variables mfn=0xcc490 nr=0x2

The patch for the Xen 4.16 package for Sid, version 
4.16.0+51-g0941d6cb-1 follows:

Patch to fix passthrough of Intel IGD to Linux domU

--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -2502,6 +2502,7 @@

      for (i = 0 ; i < d_config->num_pcidevs ; i++) {
          uint64_t vga_iomem_start = 0xa0000 >> XC_PAGE_SHIFT;
+        uint64_t vga_iomem2_start = 0xcc490; /* Probably IRQ data, nr = 
0x2 */
          uint32_t stubdom_domid;
          libxl_device_pci *pci = &d_config->pcidevs[i];
          unsigned long pci_device_class;
@@ -2531,6 +2532,25 @@
                    domid, vga_iomem_start, (vga_iomem_start + 0x20 - 1));
              return ret;
          }
+        ret = xc_domain_iomem_permission(CTX->xch, stubdom_domid,
+                                         vga_iomem2_start, 0x2, 1);
+        if (ret < 0) {
+            LOGED(ERROR, domid,
+                  "failed to give stubdom%d access to iomem range "
+                  "%"PRIx64"-%"PRIx64" for VGA passthru",
+                  stubdom_domid,
+                  vga_iomem2_start, (vga_iomem2_start + 0x2 - 1));
+            return ret;
+        }
+        ret = xc_domain_iomem_permission(CTX->xch, domid,
+                                         vga_iomem2_start, 0x2, 1);
+        if (ret < 0) {
+            LOGED(ERROR, domid,
+                  "failed to give dom%d access to iomem range "
+                  "%"PRIx64"-%"PRIx64" for VGA passthru",
+                  domid, vga_iomem2_start, (vga_iomem2_start + 0x2 - 1));
+            return ret;
+        }
          break;
      }



More information about the Pkg-xen-devel mailing list