[Intel-gfx] [IGDVFIO] [PATCH 3/8] RFC and help completing: Intel IGD Direct Assignment with VFIO
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
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
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