static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)

{

    struct vfio_region_info *rom = NULL, *opregion = NULL,

                            *host = NULL, *lpc = NULL;

    VFIOQuirk *quirk;

    VFIOIGDQuirk *igd;

    PCIDevice *lpc_bridge;

    int i, ret, ggms_mb, gms_mb = 0, gen;

    uint64_t *bdsm_size;

    uint32_t gmch;

    uint16_t cmd_orig, cmd;

    Error *err = NULL;



    /* This must be an Intel VGA device. */

    if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||

        !vfio_is_vga(vdev) || nr != 4) {

        return;

    }



    /*

     * IGD is not a standard, they like to change their specs often.  We

     * only attempt to support back to SandBridge and we hope that newer

     * devices maintain compatibility with generation 8.

     */

    gen = igd_gen(vdev);

    if (gen != 6 && gen != 8) {

        error_report("IGD device %s is unsupported by IGD quirks, "

                     "try SandyBridge or newer", vdev->vbasedev.name);

        return;

    }



    /*

     * Regardless of running in UPT or legacy mode, the guest graphics

     * driver may attempt to use stolen memory, however only legacy mode

     * has BIOS support for reserving stolen memory in the guest VM.

     * Emulate the GMCH register in all cases and zero out the stolen

     * memory size here. Legacy mode may request allocation and re-write

     * this below.

     */

    gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);

    gmch &= ~((gen < 8 ? 0x1f : 0xff) << (gen < 8 ? 3 : 8));



    /* GMCH is read-only, emulated */

    pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);

    pci_set_long(vdev->pdev.wmask + IGD_GMCH, 0);

    pci_set_long(vdev->emulated_config_bits + IGD_GMCH, ~0);



    /*

     * This must be at address 00:02.0 for us to even onsider enabling

     * legacy mode.  The vBIOS has dependencies on the PCI bus address.

     */

    if (&vdev->pdev != pci_find_device(pci_device_root_bus(&vdev->pdev),

                                       0, PCI_DEVFN(0x2, 0))) {

        return;

    }



    /*

     * We need to create an LPC/ISA bridge at PCI bus address 00:1f.0 that we

     * can stuff host values into, so if there's already one there and it's not

     * one we can hack on, legacy mode is no-go.  Sorry Q35.

     */

    lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),

                                 0, PCI_DEVFN(0x1f, 0));

    if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),

                                           "vfio-pci-igd-lpc-bridge")) {

        error_report("IGD device %s cannot support legacy mode due to existing "

                     "devices at address 1f.0", vdev->vbasedev.name);

        return;

    }



    /*

     * Most of what we're doing here is to enable the ROM to run, so if

     * there's no ROM, there's no point in setting up this quirk.

     * NB. We only seem to get BIOS ROMs, so a UEFI VM would need CSM support.

     */

    ret = vfio_get_region_info(&vdev->vbasedev,

                               VFIO_PCI_ROM_REGION_INDEX, &rom);

    if ((ret || !rom->size) && !vdev->pdev.romfile) {

        error_report("IGD device %s has no ROM, legacy mode disabled",

                     vdev->vbasedev.name);

        goto out;

    }



    /*

     * Ignore the hotplug corner case, mark the ROM failed, we can't

     * create the devices we need for legacy mode in the hotplug scenario.

     */

    if (vdev->pdev.qdev.hotplugged) {

        error_report("IGD device %s hotplugged, ROM disabled, "

                     "legacy mode disabled", vdev->vbasedev.name);

        vdev->rom_read_failed = true;

        goto out;

    }



    /*

     * Check whether we have all the vfio device specific regions to

     * support legacy mode (added in Linux v4.6).  If not, bail.

     */

    ret = vfio_get_dev_region_info(&vdev->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);

    if (ret) {

        error_report("IGD device %s does not support OpRegion access,"

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    ret = vfio_get_dev_region_info(&vdev->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &host);

    if (ret) {

        error_report("IGD device %s does not support host bridge access,"

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    ret = vfio_get_dev_region_info(&vdev->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG, &lpc);

    if (ret) {

        error_report("IGD device %s does not support LPC bridge access,"

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    /*

     * If IGD VGA Disable is clear (expected) and VGA is not already enabled,

     * try to enable it.  Probably shouldn't be using legacy mode without VGA,

     * but also no point in us enabling VGA if disabled in hardware.

     */

    if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev, &err)) {

        error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name);

        error_report("IGD device %s failed to enable VGA access, "

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    /* Create our LPC/ISA bridge */

    ret = vfio_pci_igd_lpc_init(vdev, lpc);

    if (ret) {

        error_report("IGD device %s failed to create LPC bridge, "

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    /* Stuff some host values into the VM PCI host bridge */

    ret = vfio_pci_igd_host_init(vdev, host);

    if (ret) {

        error_report("IGD device %s failed to modify host bridge, "

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    /* Setup OpRegion access */

    ret = vfio_pci_igd_opregion_init(vdev, opregion, &err);

    if (ret) {

        error_append_hint(&err, "IGD legacy mode disabled\n");

        error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name);

        goto out;

    }



    /* Setup our quirk to munge GTT addresses to the VM allocated buffer */

    quirk = g_malloc0(sizeof(*quirk));

    quirk->mem = g_new0(MemoryRegion, 2);

    quirk->nr_mem = 2;

    igd = quirk->data = g_malloc0(sizeof(*igd));

    igd->vdev = vdev;

    igd->index = ~0;

    igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM, 4);

    igd->bdsm &= ~((1 << 20) - 1); /* 1MB aligned */



    memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_index_quirk,

                          igd, "vfio-igd-index-quirk", 4);

    memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,

                                        0, &quirk->mem[0], 1);



    memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_igd_data_quirk,

                          igd, "vfio-igd-data-quirk", 4);

    memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,

                                        4, &quirk->mem[1], 1);



    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);



    /* Determine the size of stolen memory needed for GTT */

    ggms_mb = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;

    if (gen > 6) {

        ggms_mb = 1 << ggms_mb;

    }



    /*

     * Assume we have no GMS memory, but allow it to be overrided by device

     * option (experimental).  The spec doesn't actually allow zero GMS when

     * when IVD (IGD VGA Disable) is clear, but the claim is that it's unused,

     * so let's not waste VM memory for it.

     */

    if (vdev->igd_gms) {

        if (vdev->igd_gms <= 0x10) {

            gms_mb = vdev->igd_gms * 32;

            gmch |= vdev->igd_gms << (gen < 8 ? 3 : 8);

            pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);

        } else {

            error_report("Unsupported IGD GMS value 0x%x", vdev->igd_gms);

            vdev->igd_gms = 0;

        }

    }



    /*

     * Request reserved memory for stolen memory via fw_cfg.  VM firmware

     * must allocate a 1MB aligned reserved memory region below 4GB with

     * the requested size (in bytes) for use by the Intel PCI class VGA

     * device at VM address 00:02.0.  The base address of this reserved

     * memory region must be written to the device BDSM regsiter at PCI

     * config offset 0x5C.

     */

    bdsm_size = g_malloc(sizeof(*bdsm_size));

    *bdsm_size = cpu_to_le64((ggms_mb + gms_mb) * 1024 * 1024);

    fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",

                    bdsm_size, sizeof(*bdsm_size));



    /* BDSM is read-write, emulated.  The BIOS needs to be able to write it */

    pci_set_long(vdev->pdev.config + IGD_BDSM, 0);

    pci_set_long(vdev->pdev.wmask + IGD_BDSM, ~0);

    pci_set_long(vdev->emulated_config_bits + IGD_BDSM, ~0);



    /*

     * This IOBAR gives us access to GTTADR, which allows us to write to

     * the GTT itself.  So let's go ahead and write zero to all the GTT

     * entries to avoid spurious DMA faults.  Be sure I/O access is enabled

     * before talking to the device.

     */

    if (pread(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),

              vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {

        error_report("IGD device %s - failed to read PCI command register",

                     vdev->vbasedev.name);

    }



    cmd = cmd_orig | PCI_COMMAND_IO;



    if (pwrite(vdev->vbasedev.fd, &cmd, sizeof(cmd),

               vdev->config_offset + PCI_COMMAND) != sizeof(cmd)) {

        error_report("IGD device %s - failed to write PCI command register",

                     vdev->vbasedev.name);

    }



    for (i = 1; i < vfio_igd_gtt_max(vdev); i += 4) {

        vfio_region_write(&vdev->bars[4].region, 0, i, 4);

        vfio_region_write(&vdev->bars[4].region, 4, 0, 4);

    }



    if (pwrite(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),

               vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {

        error_report("IGD device %s - failed to restore PCI command register",

                     vdev->vbasedev.name);

    }



    trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb);



out:

    g_free(rom);

    g_free(opregion);

    g_free(host);

    g_free(lpc);

}

static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)

{

    struct vfio_region_info *rom = NULL, *opregion = NULL,

                            *host = NULL, *lpc = NULL;

    VFIOQuirk *quirk;

    VFIOIGDQuirk *igd;

    PCIDevice *lpc_bridge;

    int i, ret, ggms_mb, gms_mb = 0, gen;

    uint64_t *bdsm_size;

    uint32_t gmch;

    uint16_t cmd_orig, cmd;

    Error *err = NULL;



    

    if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||

        !vfio_is_vga(vdev) || nr != 4) {

        return;

    }



    









    gen = igd_gen(vdev);

    if (gen != 6 && gen != 8) {

        error_report("IGD device %s is unsupported by IGD quirks, "

                     "try SandyBridge or newer", vdev->vbasedev.name);

        return;

    }



    















    gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);

    gmch &= ~((gen < 8 ? 0x1f : 0xff) << (gen < 8 ? 3 : 8));



    

    pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);

    pci_set_long(vdev->pdev.wmask + IGD_GMCH, 0);

    pci_set_long(vdev->emulated_config_bits + IGD_GMCH, ~0);



    







    if (&vdev->pdev != pci_find_device(pci_device_root_bus(&vdev->pdev),

                                       0, PCI_DEVFN(0x2, 0))) {

        return;

    }



    









    lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),

                                 0, PCI_DEVFN(0x1f, 0));

    if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),

                                           "vfio-pci-igd-lpc-bridge")) {

        error_report("IGD device %s cannot support legacy mode due to existing "

                     "devices at address 1f.0", vdev->vbasedev.name);

        return;

    }



    









    ret = vfio_get_region_info(&vdev->vbasedev,

                               VFIO_PCI_ROM_REGION_INDEX, &rom);

    if ((ret || !rom->size) && !vdev->pdev.romfile) {

        error_report("IGD device %s has no ROM, legacy mode disabled",

                     vdev->vbasedev.name);

        goto out;

    }



    







    if (vdev->pdev.qdev.hotplugged) {

        error_report("IGD device %s hotplugged, ROM disabled, "

                     "legacy mode disabled", vdev->vbasedev.name);

        vdev->rom_read_failed = true;

        goto out;

    }



    







    ret = vfio_get_dev_region_info(&vdev->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);

    if (ret) {

        error_report("IGD device %s does not support OpRegion access,"

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    ret = vfio_get_dev_region_info(&vdev->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &host);

    if (ret) {

        error_report("IGD device %s does not support host bridge access,"

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    ret = vfio_get_dev_region_info(&vdev->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG, &lpc);

    if (ret) {

        error_report("IGD device %s does not support LPC bridge access,"

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    









    if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev, &err)) {

        error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name);

        error_report("IGD device %s failed to enable VGA access, "

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    

    ret = vfio_pci_igd_lpc_init(vdev, lpc);

    if (ret) {

        error_report("IGD device %s failed to create LPC bridge, "

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    

    ret = vfio_pci_igd_host_init(vdev, host);

    if (ret) {

        error_report("IGD device %s failed to modify host bridge, "

                     "legacy mode disabled", vdev->vbasedev.name);

        goto out;

    }



    

    ret = vfio_pci_igd_opregion_init(vdev, opregion, &err);

    if (ret) {

        error_append_hint(&err, "IGD legacy mode disabled\n");

        error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name);

        goto out;

    }



    

    quirk = g_malloc0(sizeof(*quirk));

    quirk->mem = g_new0(MemoryRegion, 2);

    quirk->nr_mem = 2;

    igd = quirk->data = g_malloc0(sizeof(*igd));

    igd->vdev = vdev;

    igd->index = ~0;

    igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM, 4);

    igd->bdsm &= ~((1 << 20) - 1); 



    memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_index_quirk,

                          igd, "vfio-igd-index-quirk", 4);

    memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,

                                        0, &quirk->mem[0], 1);



    memory_region_init_io(&quirk->mem[1], OBJECT(vdev), &vfio_igd_data_quirk,

                          igd, "vfio-igd-data-quirk", 4);

    memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,

                                        4, &quirk->mem[1], 1);



    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);



    

    ggms_mb = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;

    if (gen > 6) {

        ggms_mb = 1 << ggms_mb;

    }



    











    if (vdev->igd_gms) {

        if (vdev->igd_gms <= 0x10) {

            gms_mb = vdev->igd_gms * 32;

            gmch |= vdev->igd_gms << (gen < 8 ? 3 : 8);

            pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);

        } else {

            error_report("Unsupported IGD GMS value 0x%x", vdev->igd_gms);

            vdev->igd_gms = 0;

        }

    }



    















    bdsm_size = g_malloc(sizeof(*bdsm_size));

    *bdsm_size = cpu_to_le64((ggms_mb + gms_mb) * 1024 * 1024);

    fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",

                    bdsm_size, sizeof(*bdsm_size));



    

    pci_set_long(vdev->pdev.config + IGD_BDSM, 0);

    pci_set_long(vdev->pdev.wmask + IGD_BDSM, ~0);

    pci_set_long(vdev->emulated_config_bits + IGD_BDSM, ~0);



    











    if (pread(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),

              vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {

        error_report("IGD device %s - failed to read PCI command register",

                     vdev->vbasedev.name);

    }



    cmd = cmd_orig | PCI_COMMAND_IO;



    if (pwrite(vdev->vbasedev.fd, &cmd, sizeof(cmd),

               vdev->config_offset + PCI_COMMAND) != sizeof(cmd)) {

        error_report("IGD device %s - failed to write PCI command register",

                     vdev->vbasedev.name);

    }



    for (i = 1; i < vfio_igd_gtt_max(vdev); i += 4) {

        vfio_region_write(&vdev->bars[4].region, 0, i, 4);

        vfio_region_write(&vdev->bars[4].region, 4, 0, 4);

    }



    if (pwrite(vdev->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),

               vdev->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {

        error_report("IGD device %s - failed to restore PCI command register",

                     vdev->vbasedev.name);

    }



    trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb);



out:

    g_free(rom);

    g_free(opregion);

    g_free(host);

    g_free(lpc);

}

static void FUNC_0(VFIOPCIDevice *VAR_0, int VAR_1)

{

    struct vfio_region_info *VAR_2 = NULL, *VAR_3 = NULL,

                            *VAR_4 = NULL, *VAR_5 = NULL;

    VFIOQuirk *quirk;

    VFIOIGDQuirk *igd;

    PCIDevice *lpc_bridge;

    int VAR_6, VAR_7, VAR_8, VAR_9 = 0, VAR_10;

    uint64_t *bdsm_size;

    uint32_t gmch;

    uint16_t cmd_orig, cmd;

    Error *err = NULL;



    

    if (!vfio_pci_is(VAR_0, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||

        !vfio_is_vga(VAR_0) || VAR_1 != 4) {

        return;

    }



    









    VAR_10 = igd_gen(VAR_0);

    if (VAR_10 != 6 && VAR_10 != 8) {

        error_report("IGD device %s is unsupported by IGD quirks, "

                     "try SandyBridge or newer", VAR_0->vbasedev.name);

        return;

    }



    















    gmch = vfio_pci_read_config(&VAR_0->pdev, IGD_GMCH, 4);

    gmch &= ~((VAR_10 < 8 ? 0x1f : 0xff) << (VAR_10 < 8 ? 3 : 8));



    

    pci_set_long(VAR_0->pdev.config + IGD_GMCH, gmch);

    pci_set_long(VAR_0->pdev.wmask + IGD_GMCH, 0);

    pci_set_long(VAR_0->emulated_config_bits + IGD_GMCH, ~0);



    







    if (&VAR_0->pdev != pci_find_device(pci_device_root_bus(&VAR_0->pdev),

                                       0, PCI_DEVFN(0x2, 0))) {

        return;

    }



    









    lpc_bridge = pci_find_device(pci_device_root_bus(&VAR_0->pdev),

                                 0, PCI_DEVFN(0x1f, 0));

    if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),

                                           "vfio-pci-igd-VAR_5-bridge")) {

        error_report("IGD device %s cannot support legacy mode due to existing "

                     "devices at address 1f.0", VAR_0->vbasedev.name);

        return;

    }



    









    VAR_7 = vfio_get_region_info(&VAR_0->vbasedev,

                               VFIO_PCI_ROM_REGION_INDEX, &VAR_2);

    if ((VAR_7 || !VAR_2->size) && !VAR_0->pdev.romfile) {

        error_report("IGD device %s has no ROM, legacy mode disabled",

                     VAR_0->vbasedev.name);

        goto out;

    }



    







    if (VAR_0->pdev.qdev.hotplugged) {

        error_report("IGD device %s hotplugged, ROM disabled, "

                     "legacy mode disabled", VAR_0->vbasedev.name);

        VAR_0->rom_read_failed = true;

        goto out;

    }



    







    VAR_7 = vfio_get_dev_region_info(&VAR_0->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &VAR_3);

    if (VAR_7) {

        error_report("IGD device %s does not support OpRegion access,"

                     "legacy mode disabled", VAR_0->vbasedev.name);

        goto out;

    }



    VAR_7 = vfio_get_dev_region_info(&VAR_0->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &VAR_4);

    if (VAR_7) {

        error_report("IGD device %s does not support VAR_4 bridge access,"

                     "legacy mode disabled", VAR_0->vbasedev.name);

        goto out;

    }



    VAR_7 = vfio_get_dev_region_info(&VAR_0->vbasedev,

                        VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,

                        VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG, &VAR_5);

    if (VAR_7) {

        error_report("IGD device %s does not support LPC bridge access,"

                     "legacy mode disabled", VAR_0->vbasedev.name);

        goto out;

    }



    









    if (!(gmch & 0x2) && !VAR_0->vga && vfio_populate_vga(VAR_0, &err)) {

        error_reportf_err(err, ERR_PREFIX, VAR_0->vbasedev.name);

        error_report("IGD device %s failed to enable VGA access, "

                     "legacy mode disabled", VAR_0->vbasedev.name);

        goto out;

    }



    

    VAR_7 = vfio_pci_igd_lpc_init(VAR_0, VAR_5);

    if (VAR_7) {

        error_report("IGD device %s failed to create LPC bridge, "

                     "legacy mode disabled", VAR_0->vbasedev.name);

        goto out;

    }



    

    VAR_7 = vfio_pci_igd_host_init(VAR_0, VAR_4);

    if (VAR_7) {

        error_report("IGD device %s failed to modify VAR_4 bridge, "

                     "legacy mode disabled", VAR_0->vbasedev.name);

        goto out;

    }



    

    VAR_7 = vfio_pci_igd_opregion_init(VAR_0, VAR_3, &err);

    if (VAR_7) {

        error_append_hint(&err, "IGD legacy mode disabled\n");

        error_reportf_err(err, ERR_PREFIX, VAR_0->vbasedev.name);

        goto out;

    }



    

    quirk = g_malloc0(sizeof(*quirk));

    quirk->mem = g_new0(MemoryRegion, 2);

    quirk->nr_mem = 2;

    igd = quirk->data = g_malloc0(sizeof(*igd));

    igd->VAR_0 = VAR_0;

    igd->index = ~0;

    igd->bdsm = vfio_pci_read_config(&VAR_0->pdev, IGD_BDSM, 4);

    igd->bdsm &= ~((1 << 20) - 1); 



    memory_region_init_io(&quirk->mem[0], OBJECT(VAR_0), &vfio_igd_index_quirk,

                          igd, "vfio-igd-index-quirk", 4);

    memory_region_add_subregion_overlap(VAR_0->bars[VAR_1].region.mem,

                                        0, &quirk->mem[0], 1);



    memory_region_init_io(&quirk->mem[1], OBJECT(VAR_0), &vfio_igd_data_quirk,

                          igd, "vfio-igd-data-quirk", 4);

    memory_region_add_subregion_overlap(VAR_0->bars[VAR_1].region.mem,

                                        4, &quirk->mem[1], 1);



    QLIST_INSERT_HEAD(&VAR_0->bars[VAR_1].quirks, quirk, next);



    

    VAR_8 = (gmch >> (VAR_10 < 8 ? 8 : 6)) & 0x3;

    if (VAR_10 > 6) {

        VAR_8 = 1 << VAR_8;

    }



    











    if (VAR_0->igd_gms) {

        if (VAR_0->igd_gms <= 0x10) {

            VAR_9 = VAR_0->igd_gms * 32;

            gmch |= VAR_0->igd_gms << (VAR_10 < 8 ? 3 : 8);

            pci_set_long(VAR_0->pdev.config + IGD_GMCH, gmch);

        } else {

            error_report("Unsupported IGD GMS value 0x%x", VAR_0->igd_gms);

            VAR_0->igd_gms = 0;

        }

    }



    















    bdsm_size = g_malloc(sizeof(*bdsm_size));

    *bdsm_size = cpu_to_le64((VAR_8 + VAR_9) * 1024 * 1024);

    fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",

                    bdsm_size, sizeof(*bdsm_size));



    

    pci_set_long(VAR_0->pdev.config + IGD_BDSM, 0);

    pci_set_long(VAR_0->pdev.wmask + IGD_BDSM, ~0);

    pci_set_long(VAR_0->emulated_config_bits + IGD_BDSM, ~0);



    











    if (pread(VAR_0->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),

              VAR_0->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {

        error_report("IGD device %s - failed to read PCI command register",

                     VAR_0->vbasedev.name);

    }



    cmd = cmd_orig | PCI_COMMAND_IO;



    if (pwrite(VAR_0->vbasedev.fd, &cmd, sizeof(cmd),

               VAR_0->config_offset + PCI_COMMAND) != sizeof(cmd)) {

        error_report("IGD device %s - failed to write PCI command register",

                     VAR_0->vbasedev.name);

    }



    for (VAR_6 = 1; VAR_6 < vfio_igd_gtt_max(VAR_0); VAR_6 += 4) {

        vfio_region_write(&VAR_0->bars[4].region, 0, VAR_6, 4);

        vfio_region_write(&VAR_0->bars[4].region, 4, 0, 4);

    }



    if (pwrite(VAR_0->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),

               VAR_0->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) {

        error_report("IGD device %s - failed to restore PCI command register",

                     VAR_0->vbasedev.name);

    }



    trace_vfio_pci_igd_bdsm_enabled(VAR_0->vbasedev.name, VAR_8 + VAR_9);



out:

    g_free(VAR_2);

    g_free(VAR_3);

    g_free(VAR_4);

    g_free(VAR_5);

}

static void FUNC_0(VFIOPCIDevice *VAR_0, int VAR_1)
{ struct vfio_region_info *VAR_2 = NULL, *VAR_3 = NULL,
*VAR_4 = NULL, *VAR_5 = NULL; VFIOQuirk *quirk; VFIOIGDQuirk *igd; PCIDevice *lpc_bridge; int VAR_6, VAR_7, VAR_8, VAR_9 = 0, VAR_10; uint64_t *bdsm_size; uint32_t gmch; uint16_t cmd_orig, cmd; Error *err = NULL; if (!vfio_pci_is(VAR_0, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
!vfio_is_vga(VAR_0) || VAR_1 != 4) { return; } VAR_10 = igd_gen(VAR_0); if (VAR_10 != 6 && VAR_10 != 8) { error_report("IGD device %s is unsupported by IGD quirks, "
"try SandyBridge or newer", VAR_0->vbasedev.name); return; } gmch = vfio_pci_read_config(&VAR_0->pdev, IGD_GMCH, 4); gmch &= ~((VAR_10 < 8 ? 0x1f : 0xff) << (VAR_10 < 8 ? 3 : 8)); pci_set_long(VAR_0->pdev.config + IGD_GMCH, gmch); pci_set_long(VAR_0->pdev.wmask + IGD_GMCH, 0); pci_set_long(VAR_0->emulated_config_bits + IGD_GMCH, ~0); if (&VAR_0->pdev != pci_find_device(pci_device_root_bus(&VAR_0->pdev),
0, PCI_DEVFN(0x2, 0))) { return; } lpc_bridge = pci_find_device(pci_device_root_bus(&VAR_0->pdev),
0, PCI_DEVFN(0x1f, 0)); if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),
"vfio-pci-igd-VAR_5-bridge")) { error_report("IGD device %s cannot support legacy mode due to existing "
"devices at address 1f.0", VAR_0->vbasedev.name); return; } VAR_7 = vfio_get_region_info(&VAR_0->vbasedev,
VFIO_PCI_ROM_REGION_INDEX, &VAR_2); if ((VAR_7 || !VAR_2->size) && !VAR_0->pdev.romfile) { error_report("IGD device %s has no ROM, legacy mode disabled",
VAR_0->vbasedev.name); goto out; } if (VAR_0->pdev.qdev.hotplugged) { error_report("IGD device %s hotplugged, ROM disabled, "
"legacy mode disabled", VAR_0->vbasedev.name); VAR_0->rom_read_failed = true; goto out; } VAR_7 = vfio_get_dev_region_info(&VAR_0->vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &VAR_3); if (VAR_7) { error_report("IGD device %s does not support OpRegion access,"
"legacy mode disabled", VAR_0->vbasedev.name); goto out; } VAR_7 = vfio_get_dev_region_info(&VAR_0->vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG, &VAR_4); if (VAR_7) { error_report("IGD device %s does not support VAR_4 bridge access,"
"legacy mode disabled", VAR_0->vbasedev.name); goto out; } VAR_7 = vfio_get_dev_region_info(&VAR_0->vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG, &VAR_5); if (VAR_7) { error_report("IGD device %s does not support LPC bridge access,"
"legacy mode disabled", VAR_0->vbasedev.name); goto out; } if (!(gmch & 0x2) && !VAR_0->vga && vfio_populate_vga(VAR_0, &err)) { error_reportf_err(err, ERR_PREFIX, VAR_0->vbasedev.name); error_report("IGD device %s failed to enable VGA access, "
"legacy mode disabled", VAR_0->vbasedev.name); goto out; } VAR_7 = vfio_pci_igd_lpc_init(VAR_0, VAR_5); if (VAR_7) { error_report("IGD device %s failed to create LPC bridge, "
"legacy mode disabled", VAR_0->vbasedev.name); goto out; } VAR_7 = vfio_pci_igd_host_init(VAR_0, VAR_4); if (VAR_7) { error_report("IGD device %s failed to modify VAR_4 bridge, "
"legacy mode disabled", VAR_0->vbasedev.name); goto out; } VAR_7 = vfio_pci_igd_opregion_init(VAR_0, VAR_3, &err); if (VAR_7) { error_append_hint(&err, "IGD legacy mode disabled\n"); error_reportf_err(err, ERR_PREFIX, VAR_0->vbasedev.name); goto out; } quirk = g_malloc0(sizeof(*quirk)); quirk->mem = g_new0(MemoryRegion, 2); quirk->nr_mem = 2; igd = quirk->data = g_malloc0(sizeof(*igd)); igd->VAR_0 = VAR_0; igd->index = ~0; igd->bdsm = vfio_pci_read_config(&VAR_0->pdev, IGD_BDSM, 4); igd->bdsm &= ~((1 << 20) - 1); memory_region_init_io(&quirk->mem[0], OBJECT(VAR_0), &vfio_igd_index_quirk,
igd, "vfio-igd-index-quirk", 4); memory_region_add_subregion_overlap(VAR_0->bars[VAR_1].region.mem,
0, &quirk->mem[0], 1); memory_region_init_io(&quirk->mem[1], OBJECT(VAR_0), &vfio_igd_data_quirk,
igd, "vfio-igd-data-quirk", 4); memory_region_add_subregion_overlap(VAR_0->bars[VAR_1].region.mem,
4, &quirk->mem[1], 1); QLIST_INSERT_HEAD(&VAR_0->bars[VAR_1].quirks, quirk, next); VAR_8 = (gmch >> (VAR_10 < 8 ? 8 : 6)) & 0x3; if (VAR_10 > 6) { VAR_8 = 1 << VAR_8; } if (VAR_0->igd_gms) { if (VAR_0->igd_gms <= 0x10) { VAR_9 = VAR_0->igd_gms * 32; gmch |= VAR_0->igd_gms << (VAR_10 < 8 ? 3 : 8); pci_set_long(VAR_0->pdev.config + IGD_GMCH, gmch); } else { error_report("Unsupported IGD GMS value 0x%x", VAR_0->igd_gms); VAR_0->igd_gms = 0; } } bdsm_size = g_malloc(sizeof(*bdsm_size)); *bdsm_size = cpu_to_le64((VAR_8 + VAR_9) * 1024 * 1024); fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",
bdsm_size, sizeof(*bdsm_size)); pci_set_long(VAR_0->pdev.config + IGD_BDSM, 0); pci_set_long(VAR_0->pdev.wmask + IGD_BDSM, ~0); pci_set_long(VAR_0->emulated_config_bits + IGD_BDSM, ~0); if (pread(VAR_0->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),
VAR_0->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) { error_report("IGD device %s - failed to read PCI command register",
VAR_0->vbasedev.name); } cmd = cmd_orig | PCI_COMMAND_IO; if (pwrite(VAR_0->vbasedev.fd, &cmd, sizeof(cmd),
VAR_0->config_offset + PCI_COMMAND) != sizeof(cmd)) { error_report("IGD device %s - failed to write PCI command register",
VAR_0->vbasedev.name); } for (VAR_6 = 1; VAR_6 < vfio_igd_gtt_max(VAR_0); VAR_6 += 4) { vfio_region_write(&VAR_0->bars[4].region, 0, VAR_6, 4); vfio_region_write(&VAR_0->bars[4].region, 4, 0, 4); } if (pwrite(VAR_0->vbasedev.fd, &cmd_orig, sizeof(cmd_orig),
VAR_0->config_offset + PCI_COMMAND) != sizeof(cmd_orig)) { error_report("IGD device %s - failed to restore PCI command register",
VAR_0->vbasedev.name); } trace_vfio_pci_igd_bdsm_enabled(VAR_0->vbasedev.name, VAR_8 + VAR_9); out:
g_free(VAR_2); g_free(VAR_3); g_free(VAR_4); g_free(VAR_5); }