Package: qemu-system-x86 Version: 6.0+dfsg-1~exp0 and 5.2+dfsg-10 Severity: normal Tags: patch upstream
Dear Maintainer, I find that when using qemu with a Windows Xen HVM DomU and also passing through the Intel integrated graphics device (IGD) to the Windows Xen HVM DomU, it is much more reliable if the Intel IGD is at PCI slot 2 in the HVM DomU. When using the ancient qemu-xen-traditional device model provided by the Xen project, the Intel IGD always grabs slot 2 when it is passed through to the Xen HVM DomU using the gfx_passthru option in xl.cfg, but not when using what the Xen project refers to as the upstream qemu device model, which is the device model provided by the qemu-system-x86 package. Intel says the IGD device needs to be at PCI slot 2 and but it will be at a different slot when using the qemu version provided by the qemu-system-x86 package. One problem that occurs is that Windows sometimes reports code 43 errors in the Windows Device Manager when the Intel IGD is not set to PCI slot 2, and this prevents IGD passthrough from working because the Windows code 43 error causes Windows to disable the affected device. Other times, the screen is a little fuzzy at first but it usually clears up later. I investigated and found out how the ancient qemu-xen-traditional model ensures the IGD grabs PCI slot 2, it is by patching the hw/pci/pci.c file, but the patch in qemu-xen-traditional is not appropriate for this version of qemu because unlike qemu-xen-traditional, this version is designed to support more configuratons than with Xen. I was able to develop a patch that causes the Intel IGD to grab slot 2 with these versions of qemu when qemu is running with xen as the accelerator and when using the xenlight (xl/libxl) toolstack to build the Xen HVM. The patch is designed to only affect Xen HVMs with IGD passthrough, that is, when using the xenlight toolstack and setting gfx_passthru to '1' or 'igd' in the Xen HVM DomU's xl.cfg file. The following patch is for the 6.0+dfsg-1~exp0 package, but it also applies to the 5.2+dfsg-10 package also with some fuzz. I used it as the last patch in the series of patches in debian/patches, and it works well. It uses CONFIG_DEVICES to only compile on platforms with CONFIG_XEN_IGD_PASSTHROUGH set by the meson build system, and it also checks and only applies at runtime if the gfx_passthru option is set, and all the patch is in the xen part of the qemu code. -------------Start of Patch-------------------------------- --- a/hw/i386/xen/xen-hvm.c 2021-04-29 13:18:58.000000000 -0400 +++ b/hw/i386/xen/xen-hvm.c 2021-06-18 09:44:58.000000000 -0400 @@ -9,6 +9,7 @@ */ #include "qemu/osdep.h" +#include CONFIG_DEVICES #include "qemu/units.h" #include "cpu.h" @@ -38,6 +39,11 @@ #include <xen/hvm/ioreq.h> #include <xen/hvm/e820.h> +#ifdef CONFIG_XEN_IGD_PASSTHROUGH +#include "hw/pci/pci_bus.h" +#include "hw/xen/xen_pt.h" +#endif + //#define DEBUG_XEN_HVM #ifdef DEBUG_XEN_HVM @@ -1530,6 +1536,21 @@ exit(1); } +#ifdef CONFIG_XEN_IGD_PASSTHROUGH +/* Reserve pci slot 2 for the Intel IGD */ +void xen_hvm_reserve_igd_slot(PCIBus *pci_bus) +{ + DPRINTF("Checking if igd-passthrough is set...\n"); + if (xen_igd_gfx_pt_enabled()) { + DPRINTF("Reserving PCI slot 0x02 for IGD...\n"); + pci_bus->slot_reserved_mask = XEN_IGD_PCI_SLOT; + } + else { + DPRINTF("IGD passthrough is not set\n"); + } +} +#endif + void destroy_hvm_domain(bool reboot) { xc_interface *xc_handle; --- a/hw/i386/pc_piix.c 2021-06-18 09:39:56.000000000 -0400 +++ b/hw/i386/pc_piix.c 2021-06-18 09:49:15.000000000 -0400 @@ -208,6 +208,13 @@ pci_memory, ram_memory); pcms->bus = pci_bus; +#ifdef CONFIG_XEN_IGD_PASSTHROUGH + /* This function checks if igd-passthru is enabled and + * if so, reserve slot 2 for it on the PCI Bus */ + if (xen_enabled()) { + xen_hvm_reserve_igd_slot(pci_bus); + } +#endif piix3 = piix3_create(pci_bus, &isa_bus); piix3->pic = x86ms->gsi; piix3_devfn = piix3->dev.devfn; --- a/include/hw/xen/xen-x86.h 2021-04-29 13:18:58.000000000 -0400 +++ b/include/hw/xen/xen-x86.h 2021-06-18 09:54:05.000000000 -0400 @@ -12,4 +12,8 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory); +#ifdef CONFIG_XEN_IGD_PASSTHROUGH +void xen_hvm_reserve_igd_slot(PCIBus *pci_bus); +#endif + #endif /* QEMU_HW_XEN_X86_H */ --- a/hw/xen/xen_pt.c 2021-04-29 13:18:58.000000000 -0400 +++ b/hw/xen/xen_pt.c 2021-06-18 10:07:42.000000000 -0400 @@ -53,6 +53,7 @@ */ #include "qemu/osdep.h" +#include CONFIG_DEVICES #include "qapi/error.h" #include <sys/ioctl.h> @@ -65,6 +66,10 @@ #include "xen_pt.h" #include "qemu/range.h" #include "exec/address-spaces.h" +#ifdef CONFIG_XEN_IGD_PASSTHROUGH +#include "hw/pci/pci_bus.h" +static void xen_pt_clear_igd_slot(DeviceState *qdev, Error **errp); +#endif static bool has_igd_gfx_passthru; @@ -961,11 +966,47 @@ PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS; } +#ifdef CONFIG_XEN_IGD_PASSTHROUGH +#define XEN_PT_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(XenPTDeviceClass, klass, TYPE_XEN_PT_DEVICE) +#define XEN_PT_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(XenPTDeviceClass, obj, TYPE_XEN_PT_DEVICE) + +typedef void (*XenPTQdevRealize)(DeviceState *qdev, Error **errp); + +typedef struct XenPTDeviceClass { + PCIDeviceClass parent_class; + XenPTQdevRealize pci_qdev_realize; +} XenPTDeviceClass; + +static void xen_pt_clear_igd_slot(DeviceState *qdev, Error **errp) +{ + PCIDevice *pci_dev = (PCIDevice *)qdev; + XenPCIPassthroughState *s = XEN_PT_DEVICE(pci_dev); + XenPTDeviceClass *xptc = XEN_PT_DEVICE_GET_CLASS(s); + PCIBus *bus = pci_get_bus(pci_dev); + + /* If this is the Intel IGD, clear the bit that reserves slot 2 */ + if (has_igd_gfx_passthru && s && (s->hostaddr.slot == 0x2) + && (s->hostaddr.function == 0)) { + bus->slot_reserved_mask &= ~XEN_IGD_PCI_SLOT; + XEN_PT_LOG(pci_dev, "Intel IGD found, slot_reserved_mask = 0x%x\n", + bus->slot_reserved_mask); + } + xptc->pci_qdev_realize(qdev, errp); +} +#endif + static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); +#ifdef CONFIG_XEN_IGD_PASSTHROUGH + XenPTDeviceClass *xptc = XEN_PT_DEVICE_CLASS(klass); + xptc->pci_qdev_realize = dc->realize; + dc->realize = xen_pt_clear_igd_slot; +#endif k->realize = xen_pt_realize; k->exit = xen_pt_unregister_device; k->config_read = xen_pt_pci_read_config; @@ -988,6 +1029,9 @@ .instance_size = sizeof(XenPCIPassthroughState), .instance_finalize = xen_pci_passthrough_finalize, .class_init = xen_pci_passthrough_class_init, +#ifdef CONFIG_XEN_IGD_PASSTHROUGH + .class_size = sizeof(XenPTDeviceClass), +#endif .instance_init = xen_pci_passthrough_instance_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, --- a/hw/xen/xen_pt.h 2021-04-29 13:18:58.000000000 -0400 +++ b/hw/xen/xen_pt.h 2021-06-18 10:13:08.000000000 -0400 @@ -33,7 +33,7 @@ /* Helper */ #define XEN_PFN(x) ((x) >> XC_PAGE_SHIFT) - +#define XEN_IGD_PCI_SLOT 0x00000004UL /* slot_reserved_mask for Intel IGD */ typedef const struct XenPTRegInfo XenPTRegInfo; typedef struct XenPTReg XenPTReg; ------------END of Patch-------------------------------- -- System Information: Debian Release: 11.0 APT prefers testing-security APT policy: (500, 'testing-security'), (500, 'testing') Architecture: amd64 (x86_64) Kernel: Linux 5.10.0-7-amd64 (SMP w/4 CPU threads) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages qemu-system-x86 depends on: pn ipxe-qemu <none> ii libaio1 0.3.112-9 ii libasound2 1.2.4-1.1 ii libbrlapi0.8 6.3+dfsg-1 ii libc6 2.31-12 ii libcacard0 1:2.8.0-3 ii libcapstone4 4.0.2-3 ii libepoxy0 1.5.5-1 ii libfdt1 1.6.0-1 ii libgbm1 20.3.4-1 ii libgcc-s1 10.2.1-6 ii libglib2.0-0 2.66.8-1 ii libgnutls30 3.7.1-3 ii libibverbs1 33.2-1 ii libjpeg62-turbo 1:2.0.6-4 ii libncursesw6 6.2+20201114-2 ii libnettle8 3.7.3-1 ii libnuma1 2.0.12-1+b1 ii libpixman-1-0 0.40.0-1 ii libpmem1 1.10-1 ii libpng16-16 1.6.37-3 ii librdmacm1 33.2-1 ii libsasl2-2 2.1.27+dfsg-2.1 ii libseccomp2 2.5.1-1 ii libslirp0 4.4.0-1 ii libspice-server1 0.14.3-2.1 ii libtinfo6 6.2+20201114-2 ii libudev1 247.3-5 ii liburing1 0.7-3 ii libusb-1.0-0 2:1.0.24-3 ii libusbredirparser1 0.8.0-1+b1 ii libvdeplug2 4.0.1-2 ii libvirglrenderer1 0.8.2-5 ii libxendevicemodel1 4.14.1+11-gb0b734a8b3-1 ii libxenevtchn1 4.14.1+11-gb0b734a8b3-1 ii libxenforeignmemory1 4.14.1+11-gb0b734a8b3-1 ii libxengnttab1 4.14.1+11-gb0b734a8b3-1 ii libxenmisc4.14 4.14.1+11-gb0b734a8b3-1 ii libxenstore3.0 4.14.1+11-gb0b734a8b3-1 ii libxentoolcore1 4.14.1+11-gb0b734a8b3-1 pn qemu-system-common <none> pn qemu-system-data <none> ii seabios 1.14.0-2 ii zlib1g 1:1.2.11.dfsg-2 Versions of packages qemu-system-x86 recommends: ii ovmf 2020.11-2 pn qemu-system-gui <none> pn qemu-utils <none> Versions of packages qemu-system-x86 suggests: pn qemu-block-extra <none> ii samba 2:4.13.5+dfsg-2 pn sgabios <none> pn vde2 <none>