[SeaBIOS] [RFC PATCH v4] fw/pci: Add support for mapping Intel IGD via QEMU

Alex Williamson alex.williamson at redhat.com
Tue Feb 16 22:39:27 CET 2016


QEMU provides two fw_cfg files to support IGD.  The first holds the
OpRegion data which holds the Video BIOS Table (VBT).  This needs to
be copied into reserved memory and the address stored in the ASL
Storage register of the device at 0xFC offset in PCI config space.
The OpRegion is generally 8KB.  This file is named "etc/igd-opregion".

The second file tells us the required size of the stolen memory space
for the device.  This is a dummy file, it has no backing so we only
allocate the space without copying anything into it.  This space
requires 1MB alignment and is generally either 1MB or 2MB, depending
on the hardware config.  If the user has opted in QEMU to expose
additional stolen memory beyond the GTT (GGMS), the GMS may add an
additional 32MB to 512MB.  The base address of the reserved memory
allocated for this is written back to the Base Data of Stolen Memory
register (BDSM) at PCI config offset 0x5C on the device.  This file is
named "etc/igd-bdsm".

Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
---

v4: Back to a single patch thanks to Kevin's suggestion to use
    memalign_tmphigh() for larger allocations.  Now creating
    reserved space for stolen memory and writing the value to
    the BDSM register is queued off the existence of a fw_cfg
    file, just like the OpRegion.  The only difference is that
    we don't copy the contents, just use the meta data.

 src/fw/pciinit.c |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 0ed5dfb..dc2e433 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -269,6 +269,49 @@ static void ich9_smbus_setup(struct pci_device *dev, void *arg)
     pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN);
 }
 
+static void intel_igd_setup(struct pci_device *dev, void *arg)
+{
+    struct romfile_s *opregion = romfile_find("etc/igd-opregion");
+    struct romfile_s *bdsm = romfile_find("etc/igd-bdsm");
+    void *addr;
+    u16 bdf = dev->bdf;
+
+    if (opregion && opregion->size) {
+        addr = memalign_high(PAGE_SIZE, opregion->size);
+        if (!addr) {
+            warn_noalloc();
+            return;
+        }
+
+        if (opregion->copy(opregion, addr, opregion->size) < 0) {
+            free(addr);
+            return;
+        }
+
+        pci_config_writel(bdf, 0xFC, cpu_to_le32((u32)addr));
+
+        dprintf(1, "Intel IGD OpRegion enabled at 0x%08x, size %dKB, dev "
+                "%02x:%02x.%x\n", (u32)addr, opregion->size >> 10,
+                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
+    }
+
+    if (bdsm && bdsm->size) {
+        addr = memalign_tmphigh(1024 * 1024, bdsm->size);
+        if (!addr) {
+            warn_noalloc();
+            return;
+        }
+
+        e820_add((u32)addr, bdsm->size, E820_RESERVED);
+
+        pci_config_writel(bdf, 0x5C, cpu_to_le32((u32)addr));
+
+        dprintf(1, "Intel IGD BDSM enabled at 0x%08x, size %dMB, dev "
+                "%02x:%02x.%x\n", (u32)addr, bdsm->size >> 20,
+                pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
+    }
+}
+
 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,
@@ -302,6 +345,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_setup),
+
     PCI_DEVICE_END,
 };
 




More information about the SeaBIOS mailing list