Chuck Zmudzinski
2022-Mar-11 05:19 UTC
[Pkg-xen-devel] Bug#988333: Bug#988333: Bug#988333: libxenmisc4.16: libxl fails to grant necessary I/O memory access for gfx_passthru of Intel IGD
On 3/8/2022 6:00 AM, Hans van Kranenburg wrote:>> On 3/7/22 18:30, Chuck Zmudzinski wrote: >>> [...] >> >> Thanks for adding all the info and researching this, Chuck! >> >> Hans > > Thanks for the encouragement. Now I am working on two things: > > 1. I want to understand the problem better so I can Improve the patch. > The patch I proposed for this bug currently adds two pages to the > permitted I/O addresses for the domain starting at 0xcc490, but I > don't know the best way to determine that memory address. Probably a > hard-coded constant address is not good enough to handle all possible > hardware affected by this bug. It might be different for different > Intel revisions of the Intel IGD, and it probably can be read from > somewhere, but where? Also, what is that memory for? I would like to > understand that before finalizing what the patch should be. I am > researching these things, and then I will have a better version of the > patch to propose for Xen upstream. I have found places where Qemu/vfio > deals with what they call Intel IGD quirks, and that information can > shed light on how to solve this bug in Xen. Hopefully upstream will > accept a patch when we have a patch to propose to them. I am fairly > sure there really is a bug that should be patched upstream to improve > support for the Intel IGD passthrough feature on Xen.I discovered that address 0xcc490 is for the Intel IGD Opregion, an area of memory that Xen's hvmloader and Qemu both know about. So I was able to propose this patch to the xen-devel mailing list. Regards, Chuck --- a/tools/libs/light/libxl_pci.c +++ b/tools/libs/light/libxl_pci.c @@ -24,6 +24,7 @@ ?#define PCI_OPTIONS??????????? "msitranslate=%d,power_mgmt=%d" ?#define PCI_BDF_XSPATH???????? "%04x-%02x-%02x-%01x" ?#define PCI_PT_QDEV_ID???????? "pci-pt-%02x_%02x.%01x" +#define PCI_INTEL_OPREGION???? 0xfc /* value defined in tools/firmware/hvmloader/pci_regs.h */ ?static unsigned int pci_encode_bdf(libxl_device_pci *pci) ?{ @@ -640,6 +641,45 @@ ?} ?/* + * This function assumes prior verification + * that pci is an Intel IGD device. + */ +static uint32_t sysfs_dev_get_igd_opregion(libxl__gc *gc, libxl_device_pci *pci) +{ +??? char *pci_device_vendor_path +??????????? GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/config", +????????????????????? pci->domain, pci->bus, pci->dev, pci->func); +??? size_t read_item; +??? uint32_t igd_opregion; + +??? FILE *f = fopen(pci_device_vendor_path, "r"); +??? if (!f) { +??????? LOGE(ERROR, +???????????? "pci device "PCI_BDF" does not have config attribute", +???????????? pci->domain, pci->bus, pci->dev, pci->func); +??????? return 0xffffffff; +??? } +??? if (fseek(f, PCI_INTEL_OPREGION, SEEK_SET)) { +??????? LOGE(ERROR, +???????????? "pci device "PCI_BDF": cannot find igd-opregion address", +???????????? pci->domain, pci->bus, pci->dev, pci->func); +??????? fclose(f); +??????? return 0xffffffff; +??? } +??? read_item = fread(&igd_opregion, 4, 1, f); +??? fclose(f); + +??? if (read_item != 1) { +??????? LOGE(ERROR, +???????????? "cannot read igd-opresgion address of pci device "PCI_BDF, +???????????? pci->domain, pci->bus, pci->dev, pci->func); +??????? return 0xffffffff; +??? } + +??? return igd_opregion; +} + +/* ? * A brief comment about slots.? I don't know what slots are for; however, ? * I have by experimentation determined: ? * - Before a device can be bound to pciback, its BDF must first be listed @@ -2531,6 +2571,34 @@ ?????????????????? domid, vga_iomem_start, (vga_iomem_start + 0x20 - 1)); ???????????? return ret; ???????? } + +??????? /* Allow access to Intel igd-opregion */ +??????? if (sysfs_dev_get_vendor(gc, pci) == 0x8086) +??????? { +??????????? uint32_t igd_opregion = sysfs_dev_get_igd_opregion(gc, pci); +??????????? if (igd_opregion == 0xffffffff) +??????????????? break; +??????????? vga_iomem_start = ((uint64_t)igd_opregion) >> XC_PAGE_SHIFT; +??????????? ret = xc_domain_iomem_permission(CTX->xch, stubdom_domid, +???????????????????????????????????????????? vga_iomem_start, 0x2, 1); +??????????? if (ret < 0) { +??????????????? LOGED(ERROR, domid, +????????????????????? "failed to give stubdom%d access to iomem range " +????????????????????? "%"PRIx64"-%"PRIx64" for IGD passthru", +????????????????????? stubdom_domid, +????????????????????? vga_iomem_start, (vga_iomem_start + 0x2 - 1)); +??????????????? return ret; +??????????? } +??????????? ret = xc_domain_iomem_permission(CTX->xch, domid, +???????????????????????????????????????????? vga_iomem_start, 0x2, 1); +??????????? if (ret < 0) { +??????????????? LOGED(ERROR, domid, +????????????????????? "failed to give dom%d access to iomem range " +????????????????????? "%"PRIx64"-%"PRIx64" for IGD passthru", +????????????????????? domid, vga_iomem_start, (vga_iomem_start + 0x2 - 1)); +??????????????? return ret; +??????????? } +??????? } ???????? break; ???? } snip ---------------------------------------------------- snip