aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2016-05-17 14:44:32 -0600
committerGerd Hoffmann <kraxel@redhat.com>2016-06-01 11:25:01 +0200
commit8dada77beed057e93e36a1c67eb8b3dfe86398c9 (patch)
treee0909c5d2072b25cae4119cb4a82bf59ebba4361
parentd2aeb7f1c6c5cfe9ff83cc6c335f19c25ea870a1 (diff)
downloadseabios-8dada77beed057e93e36a1c67eb8b3dfe86398c9.zip
seabios-8dada77beed057e93e36a1c67eb8b3dfe86398c9.tar.gz
seabios-8dada77beed057e93e36a1c67eb8b3dfe86398c9.tar.bz2
fw/pci: Add support for mapping Intel IGD via QEMU
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 space requires 1MB alignment and is generally either 1MB to 8MB depending on hardware config, but may be hundreds of MB for user specified stolen memory. 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-size". QEMU documents these fw_cfg entries in docs/igd-assign.txt. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Message-id: 20160517203151.6996.95545.stgit@gimli.home Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> (cherry picked from commit 04259c5817edc6d23f0aed76fd20ab220efcddc6)
-rw-r--r--src/fw/pciinit.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 7896600..66e9f5a 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -275,6 +275,50 @@ static void ich9_smbus_setup(struct pci_device *dev, void *arg)
ich9_smbus_enable(dev->bdf);
}
+static void intel_igd_setup(struct pci_device *dev, void *arg)
+{
+ struct romfile_s *opregion = romfile_find("etc/igd-opregion");
+ u64 bdsm_size = le64_to_cpu(romfile_loadint("etc/igd-bdsm-size", 0));
+ void *addr;
+ u16 bdf = dev->bdf;
+
+ /* Apply OpRegion to any Intel VGA device, more than one is undefined */
+ 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));
+ }
+
+ /* Apply BDSM only to Intel VGA at 00:02.0 */
+ if (bdsm_size && (bdf == pci_to_bdf(0, 2, 0))) {
+ 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 %lldMB, dev "
+ "00:02.0\n", (u32)addr, bdsm_size >> 20);
+ }
+}
+
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,
@@ -308,6 +352,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,
};