#include <sys/ioctl.h>
extern int gfx_passthru;
+int igd_passthru = 0;
struct php_dev {
struct pt_dev *pt_dev;
for ( slot = 0; slot < NR_PCI_DEV; slot++ )
{
+ if ( gfx_passthru && slot == 0x2 )
+ continue;
for ( func = 0; func < NR_PCI_FUNC; func++ )
{
devfn = PCI_DEVFN(slot, func);
PCIBus *e_bus = dpci_infos.e_bus;
int vslot;
- if ( devfn & AUTO_PHP_SLOT )
+ if ( gfx_passthru && bus == 0x0 && dev == 0x2 )
+ {
+ igd_passthru = 1;
+
+ /* make virtual BDF of Intel IGD in guest is same with host */
+ devfn = PCI_DEVFN(dev, func);
+ if ( test_pci_devfn(devfn) || pci_devfn_in_use(e_bus, devfn) )
+ return -2;
+ }
+ else if ( devfn & AUTO_PHP_SLOT )
{
vslot = find_free_vslot();
if (vslot < 0)
return 0;
}
+u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr)
+{
+ struct pci_dev *pci_dev;
+ u8 val;
+
+ pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
+ if ( !pci_dev )
+ return 0;
+
+ val = pci_read_byte(pci_dev, addr);
+ pci_free_dev(pci_dev);
+ return val;
+}
+
+u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr)
+{
+ struct pci_dev *pci_dev;
+ u16 val;
+
+ 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);
+ return val;
+}
+
+u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr)
+{
+ struct pci_dev *pci_dev;
+ u32 val;
+
+ 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;
+}
+
/* parse BAR */
static int pt_bar_reg_parse(
struct pt_dev *ptdev, struct pt_reg_info_tbl *reg)
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);
+
#endif /* __PASSTHROUGH_H__ */
#include "exec-all.h"
#include "qemu-xen.h"
+extern int igd_passthru;
+
//#define DEBUG_PCI
struct PCIBus {
if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
+#ifdef CONFIG_PASSTHROUGH
+ /* reserve 00:02.0, because some BIOSs and drivers assume
+ * 00:02.0 for Intel IGD */
+ if ( gfx_passthru && devfn == 0x10 )
+ continue;
+#endif
if ( !pci_devfn_in_use(bus, devfn) )
goto found;
}
goto the_end;
}
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:
#if defined(DEBUG_PCI)
printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
pci_dev->name, config_addr, val, len);