WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [qemu-xen-unstable] passthrough: graphics passthrough cl

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [qemu-xen-unstable] passthrough: graphics passthrough cleanup
From: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
Date: Thu, 19 Aug 2010 09:50:04 -0700
Delivery-date: Thu, 19 Aug 2010 09:50:19 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
commit b2ea6374ccd134f225f0ca728c836928fb8ae25c
Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date:   Thu Aug 19 17:45:33 2010 +0100

    passthrough: graphics passthrough cleanup
    
    This patch as originally titled Calpella/Sandybridge IGD passthrough.
    In this revision, I have separated cleanup portion of the patch from
    Calpella/Sandybridge portion.  This cleanup portion incorporates
    inputs from Stephano and proposed patch from Isaku.  The main changes
    are consolidating graphics passthrough specific code into
    pt-graphics.c and removal of hardcoded intercepts for host bridge
    (device 00:00.0) accesses in pci.c.
    
    Signed-off-by: Allen Kay 
[allen.m.kay@xxxxxxxxx<mailto:allen.m.kay@xxxxxxxxx>]
    Signed-off-by: Isaku Yamahata [yamahata@xxxxxxxxxxxxx]
---
 hw/pass-through.c |  215 +++++++-----------------------------------------
 hw/pass-through.h |   14 ++-
 hw/pc.c           |    4 +
 hw/pci.c          |   31 +------
 hw/pci.h          |    6 +-
 hw/piix_pci.c     |    9 ++-
 hw/pt-graphics.c  |  240 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 xen-hooks.mak     |    2 +-
 8 files changed, 303 insertions(+), 218 deletions(-)

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 5a76e8d..f6ae4b2 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -1865,50 +1865,6 @@ static int pt_dev_is_virtfn(struct pci_dev *dev)
     return rc;
 }
 
-/*
- * register VGA resources for the domain with assigned gfx
- */
-static int register_vga_regions(struct pt_dev *real_device)
-{
-    int ret = 0;
-
-    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3B0,
-            0x3B0, 0xC, DPCI_ADD_MAPPING);
-
-    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0,
-            0x3C0, 0x20, DPCI_ADD_MAPPING);
-
-    ret |= xc_domain_memory_mapping(xc_handle, domid,
-            0xa0000 >> XC_PAGE_SHIFT,
-            0xa0000 >> XC_PAGE_SHIFT,
-            0x20,
-            DPCI_ADD_MAPPING);
-
-    return ret;
-}
-
-/*
- * unregister VGA resources for the domain with assigned gfx
- */
-static int unregister_vga_regions(struct pt_dev *real_device)
-{
-    int ret = 0;
-
-    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3B0,
-            0x3B0, 0xC, DPCI_REMOVE_MAPPING);
-
-    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0,
-            0x3C0, 0x20, DPCI_REMOVE_MAPPING);
-
-    ret |= xc_domain_memory_mapping(xc_handle, domid,
-            0xa0000 >> XC_PAGE_SHIFT,
-            0xa0000 >> XC_PAGE_SHIFT,
-            0x20,
-            DPCI_REMOVE_MAPPING);
-
-    return ret;
-}
-
 static int pt_register_regions(struct pt_dev *assigned_device)
 {
     int i = 0;
@@ -1970,17 +1926,7 @@ static int pt_register_regions(struct pt_dev 
*assigned_device)
         PT_LOG("Expansion ROM registered (size=0x%08x base_addr=0x%08x)\n",
             (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr));
     }
-
-    if ( gfx_passthru && (pci_dev->device_class == 0x0300) )
-    {
-        ret = register_vga_regions(assigned_device);
-        if ( ret != 0 )
-        {
-            PT_LOG("VGA region mapping failed\n");
-            return ret;
-        }
-    }
-
+    register_vga_regions(assigned_device);
     return 0;
 }
 
@@ -2029,13 +1975,7 @@ static void pt_unregister_regions(struct pt_dev 
*assigned_device)
         }
 
     }
-
-    if ( gfx_passthru && (assigned_device->pci_dev->device_class == 0x0300) )
-    {
-        ret = unregister_vga_regions(assigned_device);
-        if ( ret != 0 )
-            PT_LOG("VGA region unmapping failed\n");
-    }
+    unregister_vga_regions(assigned_device);
 }
 
 static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
@@ -2097,46 +2037,51 @@ static uint32_t find_ext_cap_offset(struct pci_dev 
*pci_dev, uint32_t cap)
     return 0;
 }
 
-u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr)
+static void pci_access_init(void)
 {
-    struct pci_dev *pci_dev;
-    u8 val;
+    struct pci_access *pci_access;
 
-    pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
-    if ( !pci_dev )
-        return 0;
+    if (dpci_infos.pci_access)
+        return;
 
-    val = pci_read_byte(pci_dev, addr);
-    pci_free_dev(pci_dev);
-    return val;
+    /* Initialize libpci */
+    pci_access = pci_alloc();
+    if ( pci_access == NULL ) {
+        PT_LOG("Error: pci_access is NULL\n");
+        return;
+    }
+    pci_init(pci_access);
+    pci_scan_bus(pci_access);
+    dpci_infos.pci_access = pci_access;
 }
 
-u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr)
+u32 pt_pci_host_read(int bus, int dev, int fn, u32 addr, int len)
 {
+
     struct pci_dev *pci_dev;
-    u16 val;
+    u32 val = -1;
 
+    pci_access_init();
     pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
     if ( !pci_dev )
         return 0;
 
-    val = pci_read_word(pci_dev, addr);
-    pci_free_dev(pci_dev);
+    pci_read_block(pci_dev, addr, (u8 *) &val, len);
     return val;
 }
 
-u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr)
+int pt_pci_host_write(int bus, int dev, int fn, u32 addr, u32 val, int len)
 {
     struct pci_dev *pci_dev;
-    u32 val;
+    int ret = 0;
 
+    pci_access_init();
     pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
     if ( !pci_dev )
         return 0;
 
-    val = pci_read_long(pci_dev, addr);
-    pci_free_dev(pci_dev);
-    return val;
+    ret = pci_write_block(pci_dev, addr, (u8 *) &val, len);
+    return ret;
 }
 
 /* parse BAR */
@@ -4200,92 +4145,6 @@ static int pt_pmcsr_reg_restore(struct pt_dev *ptdev,
     return 0;
 }
 
-static int get_vgabios(unsigned char *buf)
-{
-    int fd;
-    uint32_t bios_size = 0;
-    uint32_t start = 0xC0000;
-    uint16_t magic = 0;
-
-    if ( (fd = open("/dev/mem", O_RDONLY)) < 0 )
-    {
-        PT_LOG("Error: Can't open /dev/mem: %s\n", strerror(errno));
-        return 0;
-    }
-
-    /*
-     * Check if it a real bios extension.
-     * The magic number is 0xAA55.
-     */
-    if ( start != lseek(fd, start, SEEK_SET) )
-        goto out;
-    if ( read(fd, &magic, 2) != 2 )
-        goto out;
-    if ( magic != 0xAA55 )
-        goto out;
-
-    /* Find the size of the rom extension */
-    if ( start != lseek(fd, start, SEEK_SET) )
-        goto out;
-    if ( lseek(fd, 2, SEEK_CUR) != (start + 2) )
-        goto out;
-    if ( read(fd, &bios_size, 1) != 1 )
-        goto out;
-
-    /* This size is in 512 bytes */
-    bios_size *= 512;
-
-    /*
-     * Set the file to the begining of the rombios,
-     * to start the copy.
-     */
-    if ( start != lseek(fd, start, SEEK_SET) )
-        goto out;
-
-    if ( bios_size != read(fd, buf, bios_size))
-        bios_size = 0;
-
-out:
-    close(fd);
-    return bios_size;
-}
-
-static int setup_vga_pt(void)
-{
-    unsigned char *bios = NULL;
-    int bios_size = 0;
-    char *c = NULL;
-    char checksum = 0;
-    int rc = 0;
-
-    /* Allocated 64K for the vga bios */
-    if ( !(bios = malloc(64 * 1024)) )
-        return -1;
-
-    bios_size = get_vgabios(bios);
-    if ( bios_size == 0 || bios_size > 64 * 1024)
-    {
-        PT_LOG("vga bios size (0x%x) is invalid!\n", bios_size);
-        rc = -1;
-        goto out;
-    }
-
-    /* Adjust the bios checksum */
-    for ( c = (char*)bios; c < ((char*)bios + bios_size); c++ )
-        checksum += *c;
-    if ( checksum )
-    {
-        bios[bios_size - 1] -= checksum;
-        PT_LOG("vga bios checksum is adjusted!\n");
-    }
-
-    cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
-
-out:
-    free(bios);
-    return rc;
-}
-
 static struct pt_dev * register_real_device(PCIBus *e_bus,
         const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev,
         uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access,
@@ -4387,16 +4246,13 @@ static struct pt_dev * register_real_device(PCIBus 
*e_bus,
     pt_register_regions(assigned_device);
 
     /* Setup VGA bios for passthroughed gfx */
-    if ( gfx_passthru && (assigned_device->pci_dev->device_class == 0x0300) )
+    if ( setup_vga_pt(assigned_device) < 0 )
     {
-        rc = setup_vga_pt();
-        if ( rc < 0 )
-        {
-            PT_LOG("Setup VGA BIOS of passthroughed gfx failed!\n");
-            return NULL;
-        }
+        PT_LOG("Setup VGA BIOS of passthroughed gfx failed!\n");
+        return NULL;
     }
 
+
     /* reinitialize each config register to be emulated */
     rc = pt_config_init(assigned_device);
     if ( rc < 0 ) {
@@ -4548,19 +4404,8 @@ int power_on_php_devfn(int devfn)
 {
     struct php_dev *php_dev = &dpci_infos.php_devs[devfn];
     struct pt_dev *pt_dev;
-    struct pci_access *pci_access;
 
-    if (!dpci_infos.pci_access) {
-        /* Initialize libpci */
-        pci_access = pci_alloc();
-        if ( pci_access == NULL ) {
-            PT_LOG("Error: pci_access is NULL\n");
-            return -1;
-        }
-        pci_init(pci_access);
-        pci_scan_bus(pci_access);
-        dpci_infos.pci_access = pci_access;
-    }
+    pci_access_init();
 
     pt_dev =
         register_real_device(dpci_infos.e_bus,
diff --git a/hw/pass-through.h b/hw/pass-through.h
index f8a0c73..e59eb52 100644
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -406,10 +406,16 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base)
 }
 
 uint8_t pci_intx(struct pt_dev *ptdev);
-
-u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr);
-u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr);
-u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr);
+u32 pt_pci_host_read(int bus, int dev, int fn, u32 addr, int len);
+int pt_pci_host_write(int bus, int dev, int fn, u32 addr, u32 val, int len);
+void intel_pch_init(PCIBus *bus);
+int register_vga_regions(struct pt_dev *real_device);
+int unregister_vga_regions(struct pt_dev *real_device);
+int setup_vga_pt(struct pt_dev *real_device);
+PCIBus *intel_pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
+           uint16_t did, const char *name, uint16_t revision);
+void igd_pci_write(PCIDevice *pci_dev, int config_addr, uint32_t val, int len);
+uint32_t igd_pci_read(PCIDevice *pci_dev, int config_addr, int len);
 
 #endif /* __PASSTHROUGH_H__ */
 
diff --git a/hw/pc.c b/hw/pc.c
index 9375951..4c9a164 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -42,6 +42,10 @@
 #include "virtio-console.h"
 #include "hpet_emul.h"
 
+#ifdef CONFIG_PASSTHROUGH
+#include "pass-through.h"
+#endif
+
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
 
diff --git a/hw/pci.c b/hw/pci.c
index b07e5ea..ffa2c6f 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -96,7 +96,7 @@ PCIBus *pci_register_bus(pci_set_irq_fn set_irq, 
pci_map_irq_fn map_irq,
     return bus;
 }
 
-static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn 
map_irq)
+PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
 {
     PCIBus *bus;
     bus = qemu_mallocz(sizeof(PCIBus));
@@ -598,7 +598,7 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
     PCIBus *s = opaque;
     PCIDevice *pci_dev;
     int config_addr, bus_num;
-    uint32_t val;
+    uint32_t val = 0;
 
     bus_num = (addr >> 16) & 0xff;
     while (s && s->bus_num != bus_num)
@@ -624,27 +624,6 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int 
len)
     }
     config_addr = addr & 0xff;
 
-#ifdef CONFIG_PASSTHROUGH
-    /* host bridge reads for IGD passthrough */
-    if ( igd_passthru && pci_dev->devfn == 0x00 ) {
-        val = pci_dev->config_read(pci_dev, config_addr, len);
-
-        if ( config_addr == 0x00 && len == 4 )
-            val = pt_pci_host_read_long(0, 0, 0, 0x00);
-        else if ( config_addr == 0x02 ) // Device ID
-            val = pt_pci_host_read_word(0, 0, 0, 0x02);
-        else if ( config_addr == 0x52 ) // GMCH Graphics Control Register
-            val = pt_pci_host_read_word(0, 0, 0, 0x52);
-        else if ( config_addr == 0xa0 ) // GMCH Top of Memory Register
-            val = pt_pci_host_read_word(0, 0, 0, 0xa0);
-        goto done_config_read;
-    } else if ( igd_passthru && pci_dev->devfn == 0x10 &&
-              config_addr == 0xfc ) { // read on IGD device
-        val = 0;  // use SMI to communicate with the system BIOS
-        goto done_config_read;
-    }
-#endif
-
     val = pci_dev->config_read(pci_dev, config_addr, len);
 
  done_config_read:
@@ -897,7 +876,7 @@ typedef struct {
     PCIBus *bus;
 } PCIBridge;
 
-static void pci_bridge_write_config(PCIDevice *d,
+void pci_bridge_write_config(PCIDevice *d,
                              uint32_t address, uint32_t val, int len)
 {
     PCIBridge *s = (PCIBridge *)d;
@@ -935,7 +914,7 @@ PCIDevice *pci_find_device(int bus_num, int slot, int 
function)
 }
 
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
-                        pci_map_irq_fn map_irq, const char *name)
+                        uint8_t rid, pci_map_irq_fn map_irq, const char *name)
 {
     PCIBridge *s;
     s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
@@ -948,7 +927,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t 
vid, uint16_t did,
     s->dev.config[0x05] = 0x00;
     s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
     s->dev.config[0x07] = 0x00; // status = fast devsel
-    s->dev.config[0x08] = 0x00; // revision
+    s->dev.config[0x08] = rid;  // revision
     s->dev.config[0x09] = 0x00; // programming i/f
     pci_config_set_class(s->dev.config, PCI_CLASS_BRIDGE_PCI);
     s->dev.config[0x0D] = 0x10; // latency_timer
diff --git a/hw/pci.h b/hw/pci.h
index de5a4e1..f232bbe 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -254,7 +254,7 @@ int pci_assign_devaddr(const char *addr, int *domp, int 
*busp, unsigned *slotp);
 
 void pci_info(void);
 PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
-                        pci_map_irq_fn map_irq, const char *name);
+                        uint8_t rid, pci_map_irq_fn map_irq, const char *name);
 
 #define NR_PCI_FUNC          8
 #define NR_PCI_DEV           32
@@ -341,5 +341,9 @@ PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, 
pci_map_irq_fn map_irq,
 
 /* pass-through.c */
 int pt_init(PCIBus *e_bus);
+void pci_bridge_write_config(PCIDevice *d,
+                             uint32_t address, uint32_t val, int len);
+PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq);
+
 
 #endif
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 49d72b2..9c5dcf1 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -25,7 +25,9 @@
 #include "hw.h"
 #include "pc.h"
 #include "pci.h"
-
+#ifdef CONFIG_PASSTHROUGH
+#include "pass-through.h"
+#endif
 
 static void i440fx_set_irq(qemu_irq *pic, int irq_num, int level);
 static void piix3_write_config(PCIDevice *d, 
@@ -206,8 +208,13 @@ PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq 
*pic)
     register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
     register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
 
+#ifdef CONFIG_PASSTHROUGH
+    d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
+                            igd_pci_read, igd_pci_write);
+#else
     d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
                             NULL, NULL);
+#endif
 
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441);
diff --git a/hw/pt-graphics.c b/hw/pt-graphics.c
new file mode 100644
index 0000000..ce0c4a6
--- /dev/null
+++ b/hw/pt-graphics.c
@@ -0,0 +1,240 @@
+/*
+ * graphics passthrough
+ */
+
+#include "pass-through.h"
+#include "pci/header.h"
+#include "pci/pci.h"
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+
+extern int gfx_passthru;
+extern int igd_passthru;
+
+static int pch_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    PT_LOG("pch_map_irq called\n");
+    return irq_num;
+}
+
+void intel_pch_init(PCIBus *bus)
+{
+    uint16_t vid, did;
+    uint8_t  rid;
+
+    if ( !gfx_passthru )
+        return;
+
+    vid = pt_pci_host_read(0, 0x1f, 0, 0, 2);
+    did = pt_pci_host_read(0, 0x1f, 0, 2, 2);
+    rid = pt_pci_host_read(0, 0x1f, 0, 8, 1);
+
+    pci_bridge_init(bus, PCI_DEVFN(0x1f, 0), vid, did, rid,
+                    pch_map_irq, "intel_bridge_1f");
+}
+
+void igd_pci_write(PCIDevice *pci_dev, int config_addr, uint32_t val, int len)
+{
+    assert(pci_dev->devfn == 0x00);
+    if ( !igd_passthru ) {
+        pci_default_write_config(pci_dev, config_addr, val, len);
+        return;
+    }
+
+    switch (config_addr)
+    {
+        case 0x58:        // PAVPC Offset
+            pt_pci_host_write(0, 0, 0, config_addr, val, len);
+            PT_LOG("pci_config_write: %x:%x.%x: addr=%x len=%x val=%x\n",
+                   pci_bus_num(pci_dev->bus), PCI_SLOT(pci_dev->devfn),
+                   PCI_FUNC(pci_dev->devfn), config_addr, len, val);
+            break;
+        default:
+            pci_default_write_config(pci_dev, config_addr, val, len);
+    }
+}
+
+uint32_t igd_pci_read(PCIDevice *pci_dev, int config_addr, int len)
+{
+    uint32_t val;
+
+    assert(pci_dev->devfn == 0x00);
+    if ( !igd_passthru ) {
+        return pci_default_read_config(pci_dev, config_addr, len);
+    }
+
+    switch (config_addr)
+    {
+        case 0x00:        /* vendor id */
+        case 0x02:        /* device id */
+        case 0x52:        /* processor graphics control register */
+        case 0xa0:        /* top of memory */
+        case 0xb0:        /* ILK: BSM: should read from dev 2 offset 0x5c */
+        case 0x58:        /* SNB: PAVPC Offset */
+        case 0xa4:        /* SNB: graphics base of stolen memory */
+        case 0xa8:        /* SNB: base of GTT stolen memory */
+            val = pt_pci_host_read(0, PCI_SLOT(pci_dev->devfn),
+                                   0, config_addr, len);
+            PT_LOG("pci_config_read: %x:%x.%x: addr=%x len=%x val=%x\n",
+                   pci_bus_num(pci_dev->bus), PCI_SLOT(pci_dev->devfn),
+                   PCI_FUNC(pci_dev->devfn), config_addr, len, val);
+            break;
+        default:
+            val = pci_default_read_config(pci_dev, config_addr, len);
+    }
+    return val;
+}
+
+/*
+ * register VGA resources for the domain with assigned gfx
+ */
+int register_vga_regions(struct pt_dev *real_device)
+{
+    int ret = 0;
+
+    if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
+        return ret;
+
+    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3B0,
+            0x3B0, 0xC, DPCI_ADD_MAPPING);
+
+    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0,
+            0x3C0, 0x20, DPCI_ADD_MAPPING);
+
+    ret |= xc_domain_memory_mapping(xc_handle, domid,
+            0xa0000 >> XC_PAGE_SHIFT,
+            0xa0000 >> XC_PAGE_SHIFT,
+            0x20,
+            DPCI_ADD_MAPPING);
+
+    if ( ret != 0 )
+        PT_LOG("VGA region mapping failed\n");
+
+    return ret;
+}
+
+/*
+ * unregister VGA resources for the domain with assigned gfx
+ */
+int unregister_vga_regions(struct pt_dev *real_device)
+{
+    u32 igd_opregion, igd_bsm;
+    int ret = 0;
+
+    if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
+        return ret;
+
+    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3B0,
+            0x3B0, 0xC, DPCI_REMOVE_MAPPING);
+
+    ret |= xc_domain_ioport_mapping(xc_handle, domid, 0x3C0,
+            0x3C0, 0x20, DPCI_REMOVE_MAPPING);
+
+    ret |= xc_domain_memory_mapping(xc_handle, domid,
+            0xa0000 >> XC_PAGE_SHIFT,
+            0xa0000 >> XC_PAGE_SHIFT,
+            20,
+            DPCI_REMOVE_MAPPING);
+
+    igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4);
+    ret |= xc_domain_memory_mapping(xc_handle, domid,
+            igd_opregion >> XC_PAGE_SHIFT,
+            igd_opregion >> XC_PAGE_SHIFT,
+            2,
+            DPCI_REMOVE_MAPPING);
+
+    if ( ret != 0 )
+        PT_LOG("VGA region unmapping failed\n");
+
+    return ret;
+}
+
+static int get_vgabios(unsigned char *buf)
+{
+    int fd;
+    uint32_t bios_size = 0;
+    uint32_t start = 0xC0000;
+    uint16_t magic = 0;
+
+    if ( (fd = open("/dev/mem", O_RDONLY)) < 0 )
+    {
+        PT_LOG("Error: Can't open /dev/mem: %s\n", strerror(errno));
+        return 0;
+    }
+
+    /*
+     * Check if it a real bios extension.
+     * The magic number is 0xAA55.
+     */
+    if ( start != lseek(fd, start, SEEK_SET) )
+        goto out;
+    if ( read(fd, &magic, 2) != 2 )
+        goto out;
+    if ( magic != 0xAA55 )
+        goto out;
+
+    /* Find the size of the rom extension */
+    if ( start != lseek(fd, start, SEEK_SET) )
+        goto out;
+    if ( lseek(fd, 2, SEEK_CUR) != (start + 2) )
+        goto out;
+    if ( read(fd, &bios_size, 1) != 1 )
+        goto out;
+
+    /* This size is in 512 bytes */
+    bios_size *= 512;
+
+    /*
+     * Set the file to the begining of the rombios,
+     * to start the copy.
+     */
+    if ( start != lseek(fd, start, SEEK_SET) )
+        goto out;
+
+    if ( bios_size != read(fd, buf, bios_size))
+        bios_size = 0;
+
+out:
+    close(fd);
+    return bios_size;
+}
+
+int setup_vga_pt(struct pt_dev *real_device)
+{
+    unsigned char *bios = NULL;
+    int bios_size = 0;
+    char *c = NULL;
+    char checksum = 0;
+    int rc = 0;
+
+    if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
+        return rc;
+
+    /* Allocated 64K for the vga bios */
+    if ( !(bios = malloc(64 * 1024)) )
+        return -1;
+
+    bios_size = get_vgabios(bios);
+    if ( bios_size == 0 || bios_size > 64 * 1024)
+    {
+        PT_LOG("vga bios size (0x%x) is invalid!\n", bios_size);
+        rc = -1;
+        goto out;
+    }
+
+    /* Adjust the bios checksum */
+    for ( c = (char*)bios; c < ((char*)bios + bios_size); c++ )
+        checksum += *c;
+    if ( checksum )
+    {
+        bios[bios_size - 1] -= checksum;
+        PT_LOG("vga bios checksum is adjusted!\n");
+    }
+
+    cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
+out:
+    free(bios);
+    return rc;
+}
diff --git a/xen-hooks.mak b/xen-hooks.mak
index 211416e..93f4402 100644
--- a/xen-hooks.mak
+++ b/xen-hooks.mak
@@ -61,7 +61,7 @@ CONFIG_PASSTHROUGH=1
 endif
 
 ifdef CONFIG_PASSTHROUGH
-OBJS+= pass-through.o pt-msi.o
+OBJS+= pass-through.o pt-msi.o pt-graphics.o
 LIBS += -lpci
 CFLAGS += -DCONFIG_PASSTHROUGH 
 $(info === PCI passthrough capability has been enabled ===)
--
generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [qemu-xen-unstable] passthrough: graphics passthrough cleanup, Ian Jackson <=