@@ -257,6 +257,52 @@ static void ich9_smbus_setup(struct pci_device *dev, void *
pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN);
}
+static void intel_igd_opregion_setup(struct pci_device *dev, void *arg)
+{
+ u16 bdf = dev->bdf;
+ u32 orig;
+ void *opregion;
+ int size = 8;
+
+ if (!CONFIG_QEMU)
+ return;
+
+ orig = pci_config_readl(bdf, 0xFC);
+
+realloc:
+ opregion = malloc_high(size * 1024);
+ if (!opregion) {
+ warn_noalloc();
+ return;
+ }
+
+ /*
+ * QEMU maps the OpRegion into system memory at the address written here,
+ * this overlaps our malloc, which marks the range e820 reserved.
+ */
+ pci_config_writel(bdf, 0xFC, cpu_to_le32((u32)opregion));
+
+ if (memcmp(opregion, "IntelGraphicsMem", 16)) {
+ pci_config_writel(bdf, 0xFC, orig);
+ free(opregion);
+ return; /* the opregion didn't magically appear, not supported */
+ }
+
+ if (size == le32_to_cpu(*(u32 *)(opregion + 16))) {
+ dprintf(1, "Intel IGD OpRegion enabled on %02x:%02x.%x\n",
+ pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
+ return; /* success! */
+ }
+
+ pci_config_writel(bdf, 0xFC, orig);
+ free(opregion);
+
+ if (size == 8) { /* try once more with a new size */
+ size = le32_to_cpu(*(u32 *)(opregion + 16));
+ goto realloc;
+ }
+}
+
static const struct pci_device_id pci_device_tbl[] = {
/* PIIX3/PIIX4 PCI to ISA bridge */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
@@ -290,6 +336,10 @@ static const struct pci_device_id pci_device_tbl[] = {
PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_setup),
PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_setup),
+ /* Intel IGD OpRegion setup */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA,
+ intel_igd_opregion_setup),
+
PCI_DEVICE_END,
};