[RFC,v4] fw/pci: Add support for mapping Intel IGD via QEMU
diff mbox

Message ID 20160216213540.14607.97134.stgit@gimli.home
State New
Headers show

Commit Message

Alex Williamson Feb. 16, 2016, 9:39 p.m. UTC
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@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(+)

Comments

Tian, Kevin Feb. 17, 2016, 11:09 a.m. UTC | #1
> From: Alex Williamson

> Sent: Wednesday, February 17, 2016 5:39 AM

> 

> 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".


What would happen if guest tries to access this range while there is
no actual memory behind? Isn't it more clear to hide stolen memory
at all instead of reporting a dummy range?

Thanks
Kevin
Alex Williamson Feb. 17, 2016, 1:49 p.m. UTC | #2
On Wed, 17 Feb 2016 11:09:49 +0000
"Tian, Kevin" <kevin.tian@intel.com> wrote:

> > From: Alex Williamson
> > Sent: Wednesday, February 17, 2016 5:39 AM
> > 
> > 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".  
> 
> What would happen if guest tries to access this range while there is
> no actual memory behind? Isn't it more clear to hide stolen memory
> at all instead of reporting a dummy range?

It's a fw_cfg file, it's not exposed to the guest, the purpose is to
convey the size of stolen memory, which the BIOS then allocates as
reserved memory and writes back to the BDSM register.  It would be more
clean to ignore stolen memory, but in cases where we need the vBIOS,
such as laptops, where my LCD panel won't turn on without it, we don't
have that luxury.  The vBIOS programs the device to use stolen memory,
at least 1MB, I assume for GTT purposes, and makes use of that for VESA
modes.  So, we need the vBIOS to support laptop panels, the vBIOS needs
stolen memory for GTT space, therefore we need to provide some stolen
memory.

This support is enabled in QEMU by using a vBIOS, I assume vGPUs won't
expose a ROM BAR and therefore won't enable this.  Additionally for
BDW/SKL+ (gen8+) GPUs, if the user specifies rombar=0 then all of this
is disabled, including the hostbridge and ISA bridge manipulation in
order to support UPT mode.  Thanks,

Alex
Tian, Kevin Feb. 18, 2016, 6:43 a.m. UTC | #3
> From: Alex Williamson [mailto:alex.williamson@redhat.com]
> Sent: Wednesday, February 17, 2016 9:50 PM
> 
> On Wed, 17 Feb 2016 11:09:49 +0000
> "Tian, Kevin" <kevin.tian@intel.com> wrote:
> 
> > > From: Alex Williamson
> > > Sent: Wednesday, February 17, 2016 5:39 AM
> > >
> > > 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".
> >
> > What would happen if guest tries to access this range while there is
> > no actual memory behind? Isn't it more clear to hide stolen memory
> > at all instead of reporting a dummy range?
> 
> It's a fw_cfg file, it's not exposed to the guest, the purpose is to
> convey the size of stolen memory, which the BIOS then allocates as
> reserved memory and writes back to the BDSM register.  It would be more
> clean to ignore stolen memory, but in cases where we need the vBIOS,
> such as laptops, where my LCD panel won't turn on without it, we don't
> have that luxury.  The vBIOS programs the device to use stolen memory,
> at least 1MB, I assume for GTT purposes, and makes use of that for VESA
> modes.  So, we need the vBIOS to support laptop panels, the vBIOS needs
> stolen memory for GTT space, therefore we need to provide some stolen
> memory.

Thanks for explaining the rationale. It's a bit surprise to me but anyway
since you do observe the effect. Allen might help confirm whether your
assumption makes sense. :-)

> 
> This support is enabled in QEMU by using a vBIOS, I assume vGPUs won't
> expose a ROM BAR and therefore won't enable this.  Additionally for
> BDW/SKL+ (gen8+) GPUs, if the user specifies rombar=0 then all of this
> is disabled, including the hostbridge and ISA bridge manipulation in
> order to support UPT mode.  Thanks,
> 

Correct. vGPU doesn't use a host vBIOS. We just leverage existing
Seabios for early booting.

Thanks
Kevin
Kevin O'Connor Feb. 23, 2016, 3:22 p.m. UTC | #4
On Tue, Feb 16, 2016 at 02:39:27PM -0700, Alex Williamson wrote:
> 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".

Thanks.  I'd be interested in seeing how the discussion with Michael
and Igor works out (wrt using a standardized interface for
communicating addresses between qemu and firmware) before adopting
this interface in SeaBIOS.

-Kevin
Alex Williamson May 10, 2016, 3:19 p.m. UTC | #5
On Tue, 23 Feb 2016 10:22:33 -0500
"Kevin O'Connor" <kevin@koconnor.net> wrote:

> On Tue, Feb 16, 2016 at 02:39:27PM -0700, Alex Williamson wrote:
> > 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".  
> 
> Thanks.  I'd be interested in seeing how the discussion with Michael
> and Igor works out (wrt using a standardized interface for
> communicating addresses between qemu and firmware) before adopting
> this interface in SeaBIOS.

Apologies if I missed it, but I haven't seen any work in this
direction, please point me to it if I'm wrong.  Now that QEMU 2.6 is
wrapping up, I'd like to get IGD assignment support in for 2.7, but we
can't do that without BIOS support.  How shall we proceed?  Thanks,

Alex
Igor Mammedov May 11, 2016, 10:07 a.m. UTC | #6
On Tue, 10 May 2016 09:19:52 -0600
Alex Williamson <alex.williamson@redhat.com> wrote:

> On Tue, 23 Feb 2016 10:22:33 -0500
> "Kevin O'Connor" <kevin@koconnor.net> wrote:
> 
> > On Tue, Feb 16, 2016 at 02:39:27PM -0700, Alex Williamson wrote:  
> > > 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".    
> > 
> > Thanks.  I'd be interested in seeing how the discussion with Michael
> > and Igor works out (wrt using a standardized interface for
> > communicating addresses between qemu and firmware) before adopting
> > this interface in SeaBIOS.  
> 
> Apologies if I missed it, but I haven't seen any work in this
> direction, please point me to it if I'm wrong.  Now that QEMU 2.6 is
As far as I know it was only Michael's suggestion but I've not seen
actual patches either.
As for me, I'm not planning to look at it in near future.

> wrapping up, I'd like to get IGD assignment support in for 2.7, but we
> can't do that without BIOS support.  How shall we proceed?  Thanks,
> 
> Alex
>
Kevin O'Connor May 11, 2016, 3:19 p.m. UTC | #7
On Tue, May 10, 2016 at 09:19:52AM -0600, Alex Williamson wrote:
> On Tue, 23 Feb 2016 10:22:33 -0500
> "Kevin O'Connor" <kevin@koconnor.net> wrote:
> 
> > On Tue, Feb 16, 2016 at 02:39:27PM -0700, Alex Williamson wrote:
> > > 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".  
> > 
> > Thanks.  I'd be interested in seeing how the discussion with Michael
> > and Igor works out (wrt using a standardized interface for
> > communicating addresses between qemu and firmware) before adopting
> > this interface in SeaBIOS.
> 
> Apologies if I missed it, but I haven't seen any work in this
> direction, please point me to it if I'm wrong.  Now that QEMU 2.6 is
> wrapping up, I'd like to get IGD assignment support in for 2.7, but we
> can't do that without BIOS support.  How shall we proceed?  Thanks,

If there's no consensus on standardizing the qemu/firmware interface
for addresses then I'm okay with the custom solution you last
proposed.  So, I'd say submit your patches and if they are accepted in
QEMU then I will follow suit and apply them to SeaBIOS.

-Kevin
Alex Williamson May 11, 2016, 6:39 p.m. UTC | #8
On Wed, 11 May 2016 11:19:25 -0400
"Kevin O'Connor" <kevin@koconnor.net> wrote:

> On Tue, May 10, 2016 at 09:19:52AM -0600, Alex Williamson wrote:
> > On Tue, 23 Feb 2016 10:22:33 -0500
> > "Kevin O'Connor" <kevin@koconnor.net> wrote:
> >   
> > > On Tue, Feb 16, 2016 at 02:39:27PM -0700, Alex Williamson wrote:  
> > > > 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".    
> > > 
> > > Thanks.  I'd be interested in seeing how the discussion with Michael
> > > and Igor works out (wrt using a standardized interface for
> > > communicating addresses between qemu and firmware) before adopting
> > > this interface in SeaBIOS.  
> > 
> > Apologies if I missed it, but I haven't seen any work in this
> > direction, please point me to it if I'm wrong.  Now that QEMU 2.6 is
> > wrapping up, I'd like to get IGD assignment support in for 2.7, but we
> > can't do that without BIOS support.  How shall we proceed?  Thanks,  
> 
> If there's no consensus on standardizing the qemu/firmware interface
> for addresses then I'm okay with the custom solution you last
> proposed.  So, I'd say submit your patches and if they are accepted in
> QEMU then I will follow suit and apply them to SeaBIOS.


Thanks Kevin, I'll post the proposed fw_cfg files as a separate RFC to
QEMU to make sure they get eyes on them rather than just having them
buried in a patch and we'll go from there.  Thanks,

Alex

Patch
diff mbox

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,
 };