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
|