Han, Weidong
2009-Sep-28 10:22 UTC
[Xen-devel] [PATCH] Support Integrated graphics passthrough
>From e2e2b6091b6d0075bc1d94472771571f69b451cd Mon Sep 17 00:00:00 2001From: Weidong Han <weidong.han@intel.com> Date: Fri, 25 Sep 2009 18:01:30 +0800 Subject: [PATCH] support Intel integrated graphics passthrough This patch supports passthrough Intel integrated graphics (IGD) to guest. It needs to passthrough some registers of physical IGD and physical host bridge for passthroughed IGD in guest. Passthroughed IGD must use 00:02.0 in guest like in native, otherwise the driver may fail to operate the IGD. This patch reserves the 00:02.0 in guest and assigns it IGD automatically. Signed-off-by: Weidong Han <weidong.han@intel.com> --- hw/pass-through.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++- hw/pass-through.h | 7 ++++ hw/pci.c | 26 ++++++++++++++++- qemu-xen.h | 4 ++ vl.c | 6 ++++ xenstore.c | 47 +++++++++++++++++++++++++++++++ 6 files changed, 168 insertions(+), 2 deletions(-) diff --git a/hw/pass-through.c b/hw/pass-through.c index a97368a..feaf49e 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -94,6 +94,7 @@ #include <sys/ioctl.h> extern int gfx_passthru; +int igd_passthru = 0; struct php_dev { struct pt_dev *pt_dev; @@ -940,7 +941,15 @@ static int __insert_to_pci_devfn(int bus, int dev, int func, int devfn, PCIBus *e_bus = dpci_infos.e_bus; int vslot; - if ( devfn & AUTO_PHP_SLOT ) + if ( igd_passthru && bus == 0x0 && dev == 0x2 && func == 0x0 ) + { + /* passthroughed IGD must use 00:02.0 in guest */ + if ( devfn != 0x10 ) + devfn = 0x10; + 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) @@ -2015,6 +2024,48 @@ 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) +{ + 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) @@ -4531,3 +4582,30 @@ uint8_t pci_intx(struct pt_dev *ptdev) return 0; return pci_read_intx(ptdev); } + +/* + * Check if it''s IGD passthrough + * This function will be called after xenstore initializion in qemu and + * before qemu device initialization + */ +void check_igd_passthrough(void) +{ + int num = xenstore_get_assigned_device_num(); + int seg, bus, dev, func, devfn; + char *bdf_str = NULL, *opt; + int i; + + if ( !gfx_passthru ) + return; + + for ( i = 0; i < num; i++ ) + { + bdf_str = xenstore_get_assigned_device(i); + + if ( !parse_bdf(&bdf_str, &seg, &bus, &dev, &func, &opt, &devfn) ) + exit(1); + + if ( bus == 0x00 && dev == 0x02 && func == 0x00 ) + igd_passthru = 1; + } +} diff --git a/hw/pass-through.h b/hw/pass-through.h index 028a03e..c0cdb90 100644 --- a/hw/pass-through.h +++ b/hw/pass-through.h @@ -404,5 +404,12 @@ 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); + +extern int igd_passthru; +void check_igd_passthrough(void); + #endif /* __PASSTHROUGH_H__ */ diff --git a/hw/pci.c b/hw/pci.c index d7c516e..ccf12a7 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -30,6 +30,7 @@ #include "exec-all.h" #include "qemu-xen.h" +#include "pass-through.h" //#define DEBUG_PCI @@ -230,6 +231,9 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, if (devfn < 0) { for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { + /* reserve 00:02.0 for passthroughed IGD */ + if ( igd_passthru && devfn == 0x10 ) + continue; if ( !pci_devfn_in_use(bus, devfn) ) goto found; } @@ -611,7 +615,27 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len) goto the_end; } config_addr = addr & 0xff; - val = pci_dev->config_read(pci_dev, config_addr, len); + + /* 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); + } + 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 + else + val = pci_dev->config_read(pci_dev, config_addr, len); + #if defined(DEBUG_PCI) printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len); diff --git a/qemu-xen.h b/qemu-xen.h index 29b8161..1d48a4f 100644 --- a/qemu-xen.h +++ b/qemu-xen.h @@ -123,6 +123,10 @@ char *xenstore_read_battery_data(int battery_status); int xenstore_refresh_battery_status(void); int xenstore_pv_driver_build_blacklisted(uint16_t product_number, uint32_t build_nr); +#ifdef CONFIG_PASSTHROUGH +int xenstore_get_assigned_device_num(void); +char *xenstore_get_assigned_device(int index); +#endif /* xenfbfront.c */ int xenfb_pv_display_init(DisplayState *ds); diff --git a/vl.c b/vl.c index e916561..579fc2c 100644 --- a/vl.c +++ b/vl.c @@ -48,6 +48,7 @@ #include <stdlib.h> #include "qemu-xen.h" +#include "hw/pass-through.h" #include <unistd.h> #include <fcntl.h> @@ -5740,6 +5741,11 @@ int main(int argc, char **argv, char **envp) xenstore_parse_domain_config(domid); #endif /* CONFIG_STUBDOM */ +#ifdef CONFIG_PASSTHROUGH + if ( gfx_passthru ) + check_igd_passthrough(); +#endif + /* we always create the cdrom drive, even if no disk is there */ #ifndef CONFIG_DM diff --git a/xenstore.c b/xenstore.c index e091259..b6e89f7 100644 --- a/xenstore.c +++ b/xenstore.c @@ -347,6 +347,53 @@ static const char *xenstore_get_guest_uuid(void) return already_computed; } +#ifdef CONFIG_PASSTHROUGH +int xenstore_get_assigned_device_num(void) +{ + char *path = NULL, *num_str = NULL; + int num_devs = 0; + unsigned int len; + + if (pasprintf(&path, + "/local/domain/0/backend/pci/%u/0/num_devs", domid) == -1) { + fprintf(logfile, "get num_devs: out of memory.\n"); + goto out; + } + + num_str = xs_read(xsh, XBT_NULL, path, &len); + if (num_str == NULL) { + fprintf(logfile, "xs_read(): fail to get num_devs. %s.\n", path); + goto out; + } + + num_devs = strtol(num_str, NULL, 16); + +out: + return num_devs; +} + +char *xenstore_get_assigned_device(int index) +{ + char *path = NULL, *bdf_str = NULL; + unsigned int len; + + if (pasprintf(&path, "/local/domain/0/backend/pci/%u/0/dev-%i", + domid, index) == -1) { + fprintf(logfile, "get assigned device: out of memory.\n"); + goto out; + } + + bdf_str = xs_read(xsh, XBT_NULL, path, &len); + if (bdf_str == NULL) { + fprintf(logfile, "xs_read(): fail to get assigned device. %s.\n", path); + goto out; + } + +out: + return bdf_str; +} +#endif + #define PT_PCI_MSITRANSLATE_DEFAULT 1 #define PT_PCI_POWER_MANAGEMENT_DEFAULT 0 int direct_pci_msitranslate; -- 1.6.0.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Jackson
2009-Oct-07 15:29 UTC
Re: [Xen-devel] [PATCH] Support Integrated graphics passthrough
Han, Weidong writes ("[Xen-devel] [PATCH] Support Integrated graphics passthrough"):> Passthroughed IGD must use 00:02.0 in guest like in native, otherwise > the driver may fail to operate the IGD. This patch reserves the > 00:02.0 in guest and assigns it IGD automatically.This breaks the build if passthrough is disabled due to pciutils-dev being missing: Ian. get-path: will use #!/usr/bin/python2.5 for python programs xen-hooks.mak:56: === pciutils-dev package not found - missing /usr/include/pci xen-hooks.mak:57: === PCI passthrough capability has been disabled get-path: will use #!/usr/bin/python2.5 for python programs make[1]: Entering directory `/u/iwj/work/1/qemu-iwj.git/i386-dm'' ../xen-hooks.mak:56: === pciutils-dev package not found - missing /usr/include/pci ../xen-hooks.mak:57: === PCI passthrough capability has been disabled ../xen-hooks.mak:56: === pciutils-dev package not found - missing /usr/include/pci ../xen-hooks.mak:57: === PCI passthrough capability has been disabled CC i386-dm/vl.o CC i386-dm/pci.o CC i386-dm/xenstore.o In file included from /u/iwj/work/1/qemu-iwj.git/hw/pci.c:33: /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:23:24: error: pci/header.h: No such file or directory /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:24:21: error: pci/pci.h: No such file or directory In file included from /u/iwj/work/1/qemu-iwj.git/hw/pci.c:33: /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:397: error: expected ''='', '','', '';'', ''asm'' or ''__attribute__'' before ''pt_pci_base_addr'' /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:407: error: expected ''='', '','', '';'', ''asm'' or ''__attribute__'' before ''pt_pci_host_read_byte'' /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:408: error: expected ''='', '','', '';'', ''asm'' or ''__attribute__'' before ''pt_pci_host_read_word'' [etc] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Han, Weidong
2009-Oct-12 07:19 UTC
RE: [Xen-devel] [PATCH] Support Integrated graphics passthrough
Hi Ian, Thanks for pointing it out. pass-through.h references files of pciutils-dev package, so it shouldn''t be included when pciutils-dev is not installed. Fixed it by checking CONFIG_PASSTHROUGH before including pass-through.h. Attached the updated patch. Thanks. Regards, Weidong Ian Jackson wrote:> Han, Weidong writes ("[Xen-devel] [PATCH] Support Integrated graphics > passthrough"): >> Passthroughed IGD must use 00:02.0 in guest like in native, otherwise >> the driver may fail to operate the IGD. This patch reserves the >> 00:02.0 in guest and assigns it IGD automatically. > > This breaks the build if passthrough is disabled due to pciutils-dev > being missing: > > Ian. > > get-path: will use #!/usr/bin/python2.5 for python programs > xen-hooks.mak:56: === pciutils-dev package not found - missing > /usr/include/pci > xen-hooks.mak:57: === PCI passthrough capability has been disabled > get-path: will use #!/usr/bin/python2.5 for python programs > make[1]: Entering directory `/u/iwj/work/1/qemu-iwj.git/i386-dm'' > ../xen-hooks.mak:56: === pciutils-dev package not found - missing > /usr/include/pci ../xen-hooks.mak:57: === PCI passthrough capability > has been disabled ../xen-hooks.mak:56: === pciutils-dev package not > found - missing /usr/include/pci ../xen-hooks.mak:57: === PCI > passthrough capability has been disabled CC i386-dm/vl.o > CC i386-dm/pci.o > CC i386-dm/xenstore.o > In file included from /u/iwj/work/1/qemu-iwj.git/hw/pci.c:33: > /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:23:24: error: > pci/header.h: No such file or directory > /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:24:21: error: pci/pci.h: > No such file or directory > In file included from /u/iwj/work/1/qemu-iwj.git/hw/pci.c:33: > /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:397: error: expected > ''='', '','', '';'', ''asm'' or ''__attribute__'' before ''pt_pci_base_addr'' > /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:407: error: expected > ''='', '','', '';'', ''asm'' or ''__attribute__'' before > ''pt_pci_host_read_byte'' > /u/iwj/work/1/qemu-iwj.git/hw/pass-through.h:408: error: expected > ''='', '','', '';'', ''asm'' or ''__attribute__'' before > ''pt_pci_host_read_word'' [etc]_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel