[Intel-gfx] [IGDVFIO] [PATCH 3/8] RFC and help completing: Intel IGD Direct Assignment with VFIO

2014-09-24 Thread Andrew Barnes
hw/pci-host/q35.c

this patch adds:
* redirect some PCI config reads/writes to host
* memory map BSDM, BGSM, TSEG

patch
-

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index a0a3068..05348ac 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -6,6 +6,7 @@
  *   Isaku Yamahata yamahata at valinux co jp
  *   VA Linux Systems Japan K.K.
  * Copyright (C) 2012 Jason Baron jba...@redhat.com
+ *   2014 Andrew barnes a...@outsideglobe.com IGD Support
  *
  * This is based on piix_pci.c, but heavily modified.
  *
@@ -30,11 +31,26 @@
 #include hw/hw.h
 #include hw/pci-host/q35.h
 #include qapi/visitor.h
+#include hw/pci/pci.h
+#include sys/mman.h /* memory map functions */
+
+/* #define DEBUG_Q35 */
+#ifdef DEBUG_Q35
+# define Q35_DPRINTF(format, ...)   printf(Q35:  format, ##
__VA_ARGS__)
+#else
+# define Q35_DPRINTF(format, ...)   do { } while (0)
+#endif
+
+/* for intel-spec conforming config */
+/* #define CORRECT_CONFIG */

 /
  * Q35 host
  */

+/* BEWARE: only set this if you are passing IGD through */
+static bool IGD_PASSTHROUGH = true;
+
 static void q35_host_realize(DeviceState *dev, Error **errp)
 {
 PCIHostState *pci = PCI_HOST_BRIDGE(dev);
@@ -284,11 +300,193 @@ static void mch_set_smm(int smm, void *arg)
 memory_region_transaction_commit();
 }

-static void mch_write_config(PCIDevice *d,
+/* TODO: Move these variables/defines to be consistent with Q35 coding
style */
+MemoryRegion bdsm;
+uint32_t bdsm_host;
+MemoryRegion bgsm;
+uint32_t bgsm_host;
+MemoryRegion tseg;
+uint32_t tseg_host;
+#define MCH_CONFIG_BDSM 0xb0
+#define MCH_CONFIG_BGSM 0xb4
+#define MCH_CONFIG_TSEG 0xb8
+#define MCH_CONFIG_GMCH 0x50
+
+/* Setup memory map for Stolen Memory */
+static void mch_setup_bdsm(PCIDevice *d)
+{
+int fd;
+char name[64];
+void *map;
+bdsm_host =
host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_BDSM,4);
+int dsm_size;
+uint16_t gmch_host =
host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_GMCH,2);
+uint16_t gmch_dsm = (gmch_host  0xF8)  3;
+MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+Q35_DPRINTF(%s Setup BDSM: %x\n,__func__,bdsm_host);
+
+snprintf(name, sizeof(name), MCH-BDSM-mmap);
+fd = open(/dev/mem, O_RDWR);
+
+switch (gmch_dsm)
+{
+  case 0x0: dsm_size = 0; break;
+  case 0x1: dsm_size = 32; break;
+  case 0x2: dsm_size = 64; break;
+  case 0x3: dsm_size = 96; break;
+  case 0x4: dsm_size = 128; break;
+  case 0x5: dsm_size = 160; break;
+  case 0x6: dsm_size = 192; break;
+  case 0x7: dsm_size = 224; break;
+  case 0x8: dsm_size = 256; break;
+  case 0x9: dsm_size = 288; break;
+  case 0xa: dsm_size = 320; break;
+  case 0xb: dsm_size = 352; break;
+  case 0xc: dsm_size = 384; break;
+  case 0xd: dsm_size = 416; break;
+  case 0xe: dsm_size = 448; break;
+  case 0xf: dsm_size = 480; break;
+  case 0x10: dsm_size = 512; break;
+ // default: /* panic */
+}
+
+dsm_size = dsm_size * 1024 * 1024;
+map = mmap(NULL,dsm_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,(bdsm_host
 0xFFF0));
+
+if (map == MAP_FAILED)
+{
+map = NULL;
+Q35_DPRINTF(%s Setup BDSM: MAP_FAILED\n,__func__);
+}
+
+memory_region_init_ram_ptr(bdsm, OBJECT(mch), name, dsm_size, map);
+}
+
+/* this function memory maps the region of host memory assigned to Stolen
memory
+ * to the guest location provided by seabios. */
+static void mch_map_bdsm(PCIDevice *d, uint32_t bdsm_new)
+{
+MemoryRegion *guest_memory = get_system_memory();
+uint32_t bdsm_current = pci_default_read_config(d,MCH_CONFIG_BDSM,4);
+
+if ( bdsm_current != bdsm_host  bdsm_current != 0 )
+{
+// remap
+Q35_DPRINTF(%s Delete BDSM mapping: %x\n,__func__,(bdsm_current
 0xFFF0));
+memory_region_del_subregion(guest_memory, bdsm);
+}
+Q35_DPRINTF(%s Add BDSM mapping: %x -
%x\n,__func__,bdsm_host,bdsm_new);
+memory_region_add_subregion(guest_memory, (bdsm_new  0xFFF0),
bdsm);
+}
+
+/* Setup memory map for GTT Stolen Memory */
+static void mch_setup_bgsm(PCIDevice *d)
+{
+int fd;
+char name[64];
+void *map;
+bgsm_host =
host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_BGSM,4);
+int gsm_size;
+uint16_t gmch_host =
host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_GMCH,2);
+uint16_t gmch_gsm = (gmch_host  0x300)  8;
+MCHPCIState *mch = MCH_PCI_DEVICE(d);
+
+Q35_DPRINTF(%s Setup BGSM: %x\n,__func__,bgsm_host);
+
+snprintf(name, sizeof(name), MCH %04x:%02x:%02x.%x BGSM mmap,
+ 0, 0, 0, 0);
+
+fd = open(/dev/mem, O_RDWR);
+
+switch (gmch_gsm)
+{
+  case 0x2: gsm_size = 2; break;
+  case 0x1: gsm_size = 1; break;
+  case 0x0: gsm_size = 0; break;
+ // 

Re: [Intel-gfx] [IGDVFIO] [PATCH 3/8] RFC and help completing: Intel IGD Direct Assignment with VFIO

2014-09-24 Thread Alex Williamson
On Wed, 2014-09-24 at 14:20 +0100, Andrew Barnes wrote:
 hw/pci-host/q35.c
 
 this patch adds:
 * redirect some PCI config reads/writes to host
 * memory map BSDM, BGSM, TSEG
 
 patch
 -
 
 diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
 index a0a3068..05348ac 100644
 --- a/hw/pci-host/q35.c
 +++ b/hw/pci-host/q35.c
 @@ -6,6 +6,7 @@
   *   Isaku Yamahata yamahata at valinux co jp
   *   VA Linux Systems Japan K.K.
   * Copyright (C) 2012 Jason Baron jba...@redhat.com
 + *   2014 Andrew barnes a...@outsideglobe.com IGD Support
   *
   * This is based on piix_pci.c, but heavily modified.
   *
 @@ -30,11 +31,26 @@
  #include hw/hw.h
  #include hw/pci-host/q35.h
  #include qapi/visitor.h
 +#include hw/pci/pci.h
 +#include sys/mman.h /* memory map functions */
 +
 +/* #define DEBUG_Q35 */
 +#ifdef DEBUG_Q35
 +# define Q35_DPRINTF(format, ...)   printf(Q35:  format, ##
 __VA_ARGS__)
 +#else
 +# define Q35_DPRINTF(format, ...)   do { } while (0)
 +#endif
 +
 +/* for intel-spec conforming config */
 +/* #define CORRECT_CONFIG */
 
  /
   * Q35 host
   */
 
 +/* BEWARE: only set this if you are passing IGD through */
 +static bool IGD_PASSTHROUGH = true;
 +
  static void q35_host_realize(DeviceState *dev, Error **errp)
  {
  PCIHostState *pci = PCI_HOST_BRIDGE(dev);
 @@ -284,11 +300,193 @@ static void mch_set_smm(int smm, void *arg)
  memory_region_transaction_commit();
  }
 
 -static void mch_write_config(PCIDevice *d,
 +/* TODO: Move these variables/defines to be consistent with Q35 coding
 style */
 +MemoryRegion bdsm;
 +uint32_t bdsm_host;
 +MemoryRegion bgsm;
 +uint32_t bgsm_host;
 +MemoryRegion tseg;
 +uint32_t tseg_host;
 +#define MCH_CONFIG_BDSM 0xb0
 +#define MCH_CONFIG_BGSM 0xb4
 +#define MCH_CONFIG_TSEG 0xb8
 +#define MCH_CONFIG_GMCH 0x50
 +
 +/* Setup memory map for Stolen Memory */
 +static void mch_setup_bdsm(PCIDevice *d)
 +{
 +int fd;
 +char name[64];
 +void *map;
 +bdsm_host =
 host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_BDSM,4);
 +int dsm_size;
 +uint16_t gmch_host =
 host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_GMCH,2);
 +uint16_t gmch_dsm = (gmch_host  0xF8)  3;
 +MCHPCIState *mch = MCH_PCI_DEVICE(d);
 +
 +Q35_DPRINTF(%s Setup BDSM: %x\n,__func__,bdsm_host);
 +
 +snprintf(name, sizeof(name), MCH-BDSM-mmap);
 +fd = open(/dev/mem, O_RDWR);
 +
 +switch (gmch_dsm)
 +{
 +  case 0x0: dsm_size = 0; break;
 +  case 0x1: dsm_size = 32; break;
 +  case 0x2: dsm_size = 64; break;
 +  case 0x3: dsm_size = 96; break;
 +  case 0x4: dsm_size = 128; break;
 +  case 0x5: dsm_size = 160; break;
 +  case 0x6: dsm_size = 192; break;
 +  case 0x7: dsm_size = 224; break;
 +  case 0x8: dsm_size = 256; break;
 +  case 0x9: dsm_size = 288; break;
 +  case 0xa: dsm_size = 320; break;
 +  case 0xb: dsm_size = 352; break;
 +  case 0xc: dsm_size = 384; break;
 +  case 0xd: dsm_size = 416; break;
 +  case 0xe: dsm_size = 448; break;
 +  case 0xf: dsm_size = 480; break;
 +  case 0x10: dsm_size = 512; break;
 + // default: /* panic */

Certainly do something other than pass a multiple of an uninitialized
variable through to mmap.

 +}
 +
 +dsm_size = dsm_size * 1024 * 1024;
 +map = mmap(NULL,dsm_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,(bdsm_host
  0xFFF0));
 +
 +if (map == MAP_FAILED)
 +{
 +map = NULL;
 +Q35_DPRINTF(%s Setup BDSM: MAP_FAILED\n,__func__);
 +}
 +
 +memory_region_init_ram_ptr(bdsm, OBJECT(mch), name, dsm_size, map);
 +}

Presumably this is something else we'd need to provide through the vfio
device.  So we're up to

1. opregion (3 pages... wasn't it 2 before?)
2. stolen memory (up to 512M)


 +
 +/* this function memory maps the region of host memory assigned to Stolen
 memory
 + * to the guest location provided by seabios. */
 +static void mch_map_bdsm(PCIDevice *d, uint32_t bdsm_new)
 +{
 +MemoryRegion *guest_memory = get_system_memory();
 +uint32_t bdsm_current = pci_default_read_config(d,MCH_CONFIG_BDSM,4);
 +
 +if ( bdsm_current != bdsm_host  bdsm_current != 0 )
 +{
 +// remap
 +Q35_DPRINTF(%s Delete BDSM mapping: %x\n,__func__,(bdsm_current
  0xFFF0));
 +memory_region_del_subregion(guest_memory, bdsm);
 +}
 +Q35_DPRINTF(%s Add BDSM mapping: %x -
 %x\n,__func__,bdsm_host,bdsm_new);
 +memory_region_add_subregion(guest_memory, (bdsm_new  0xFFF0),
 bdsm);
 +}
 +
 +/* Setup memory map for GTT Stolen Memory */
 +static void mch_setup_bgsm(PCIDevice *d)
 +{
 +int fd;
 +char name[64];
 +void *map;
 +bgsm_host =
 host_pci_read_config(0,PCI_SLOT(d-devfn),PCI_FUNC(d-devfn),MCH_CONFIG_BGSM,4);
 +int gsm_size;
 +uint16_t gmch_host =
 

Re: [Intel-gfx] [IGDVFIO] [PATCH 3/8] RFC and help completing: Intel IGD Direct Assignment with VFIO

2014-09-24 Thread Paolo Bonzini
Il 24/09/2014 21:47, Alex Williamson ha scritto:
 So the opregion is mapped by a config write on the IGD device itself and
 the other 3 regions, that we know about so far, are mapped via writes to
 the host bridge.

AFAIU the opregion is mapped by the (host) BIOS, that writes the address
to a well-known scratch dword in the configuration space.  The host
reads from the dword and finds the opregion that way.

Paolo
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx