IGD ROMs are known to have wrong device IDs and bogus checksums. Toggle the rom_need_patch_id flag when the IGD has ROM BAR or custom romfile so that pci_rom_patch_ids() will correct the vendor/device IDs and checksum.
The ROM BAR availability check is extracted into vfio_pci_igd_has_rom_bar() to avoid duplicating the region info lookup. Reported-by: K S Maan <[email protected]> Signed-off-by: Tomita Moeko <[email protected]> Tested-by: K S Maan <[email protected]> --- hw/vfio/igd.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c index e091f21b6a..17437ae18d 100644 --- a/hw/vfio/igd.c +++ b/hw/vfio/igd.c @@ -509,11 +509,22 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr) QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, bdsm_quirk, next); } +static bool vfio_pci_igd_has_rom_bar(VFIOPCIDevice *vdev) +{ + struct vfio_region_info *rom = NULL; + int ret; + + ret = vfio_device_get_region_info(&vdev->vbasedev, + VFIO_PCI_ROM_REGION_INDEX, &rom); + + return !ret && rom->size; +} + static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp) { struct vfio_region_info *opregion = NULL; PCIDevice *pdev = PCI_DEVICE(vdev); - int ret, gen; + int gen; uint64_t gms_size = 0; uint64_t *bdsm_size; uint32_t gmch; @@ -556,8 +567,6 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp) * - OpRegion * - Same LPC bridge and Host bridge VID/DID/SVID/SSID as host */ - struct vfio_region_info *rom = NULL; - legacy_mode_enabled = true; info_report("IGD legacy mode enabled, " "use x-igd-legacy-mode=off to disable it if unwanted."); @@ -567,9 +576,7 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp) * there's no ROM, there's no point in setting up this quirk. * NB. We only seem to get BIOS ROMs, so UEFI VM would need CSM support. */ - ret = vfio_device_get_region_info(&vdev->vbasedev, - VFIO_PCI_ROM_REGION_INDEX, &rom); - if ((ret || !rom->size) && !pdev->romfile) { + if (!vfio_pci_igd_has_rom_bar(vdev) && !pdev->romfile) { error_setg(&err, "Device has no ROM"); goto error; } @@ -610,6 +617,14 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp) goto error; } + /* + * IGD are known to have bad checksums and wrong device ID in its rom, + * request to patch it. + */ + if (pdev->romfile || vfio_pci_igd_has_rom_bar(vdev)) { + pdev->rom_need_patch_id = true; + } + /* * ASLS (OpRegion address) is read-only, emulated * It contains HPA, guest firmware need to reprogram it with GPA. -- 2.53.0
