xen: add Intel IGD passthrough support
v3 cover xen: add Intel IGD passthrough support
v3:
* In this case, as we discussed we will give priority to devices to reserve a specific devfn by passing "device_model_args_hvm = ['-device', 'xen-platform,addr=0x3']" and "vga=none", so withdraw patch #1, #2 and #4.
* Fix some typos.
* Add more comments to make that readable.
* To unmap igd_opregion when call xen_pt_unregister_vga_regions().
* Improve some return paths.
* Force to convert igd_guest/host_opoegion as an unsigned long type while calling xc_domain_memory_mapping().
* We need to map 3 pages for opregion as hvmloader set.
v2:
* rebase on current qemu tree.
* retrieve VGA bios from sysfs properly.
* redefine some function name.
* introduce bitmap to manage registe/runregister pci dev, and provide a common way to reserve some specific devfn.
* introduce is_igd_passthrough() to make sure we touch physical host bridge only in IGD case.
* We should return zero as an invalid address value while calling igd_read_opregion().
Additionally, now its also not necessary to recompile seabios with some extra steps like v1.
The following patches are ported partially from Xen Qemu-traditional branch which are adding Intel IGD passthrough supporting to Qemu upstream.
To pass through IGD to guest, user need to add following lines in Xen config file:
gfx_passthru=1
pci=['00:02.0 <at> 2']
Now successfully boot Ubuntu 14.04 guests with IGD assigned in Haswell desktop with Latest Xen + Qemu upstream.
----------------------------------------------------------------
Tiejun Chen (2):
xen, gfx passthrough: create intel isa bridge xen, gfx passthrough: create host bridge to passthrough
Yang Zhang (3):
xen, gfx passthrough: basic graphics passthrough support xen, gfx passthrough: support Intel IGD passthrough with VT-D xen, gfx passthrough: add opregion mapping
hw/pci-host/piix.c | 56 +++++++++++++- hw/xen/Makefile.objs | 2 +- hw/xen/xen-host-pci-device.c | 5 ++ hw/xen/xen-host-pci-device.h | 1 + hw/xen/xen_pt.c | 10 +++ hw/xen/xen_pt.h | 12 ++- hw/xen/xen_pt_config_init.c | 50 ++++++++++++- hw/xen/xen_pt_graphics.c | 518 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 9 +++ vl.c | 11 ++- 10 files changed, 668 insertions(+), 6 deletions(-) create mode 100644 hw/xen/xen_pt_graphics.c
Thanks
Tiejun
PATCH v3 1/5 xen, gfx passthrough: basic graphics passthrough support
basic gfx passthrough support:
- add a vga type for gfx passthrough
- retrieve VGA bios from sysfs, then load it to guest 0xC0000
- register/unregister legacy VGA I/O ports and MMIOs for passthroughed gfx
The original patch is from Weidong Han <[email protected]>
---
v3:
* Fix some typos.
* Add more comments to make that readable.
* Improve some return paths.
v2:
* retrieve VGA bios from sysfs properly.
* redefine some function name.
hw/xen/Makefile.objs | 2 +- hw/xen/xen-host-pci-device.c | 5 + hw/xen/xen-host-pci-device.h | 1 + hw/xen/xen_pt.c | 10 ++ hw/xen/xen_pt.h | 4 + hw/xen/xen_pt_graphics.c | 232 +++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 9 ++ vl.c | 11 +- 8 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 hw/xen/xen_pt_graphics.c
hw/xen/Makefile.objs +1 -1
@@ -2,4 +2,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o +obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_pt_graphics.o
hw/xen/xen-host-pci-device.c +5 -0
@@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain, goto error; } d->irq = v; + rc =xen_host_pci_get_hex_value (d,"class" , &v); +if (rc) { + goto error; + } + d->class_code = v; d->is_virtfn =xen_host_pci_dev_is_virtfn (d);return 0 ;
hw/xen/xen-host-pci-device.h +1 -0
@@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {uint16_t vendor_id;uint16_t device_id; +uint32_t class_code;int irq;XenHostPCIIORegion io_regions[PCI_NUM_REGIONS -1 ];
hw/xen/xen_pt.c +10 -0
@@ -450,6 +450,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) d->rom.size, d->rom.base_addr); } +xen_pt_register_vga_regions (d);return 0 ; }
@@ -470,6 +471,8 @@ static void xen_pt_unregister_regions(XenPCIPassthroughState *s)if (d->rom.base_addr && d->rom.size) {memory_region_destroy (&s->rom); } + +xen_pt_unregister_vga_regions (d); }/* region mapping */
@@ -693,6 +696,13 @@ static int xen_pt_initfn(PCIDevice *d)/* Handle real device's MMIO/PIO BARs */ xen_pt_register_regions (s); +/* Setup VGA bios for passthroughed gfx */ +if (xen_pt_setup_vga (&s->real_device) <0 ) { +XEN_PT_ERR (d,"Setup VGA BIOS of passthroughed gfx failed!\n" ); +xen_host_pci_device_put (&s->real_device); +return -1 ; + } +/* reinitialize each config register to be emulated */ if (xen_pt_config_init (s)) {XEN_PT_ERR (d,"PCI Config space initialisation failed.\n" );
hw/xen/xen_pt.h +4 -0
@@ -298,5 +298,9 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar) return s->msix && s->msix->bar_index == bar; } +extern int xen_has_gfx_passthru; +int xen_pt_register_vga_regions (XenHostPCIDevice *dev); +int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev); +int xen_pt_setup_vga (XenHostPCIDevice *dev);#endif /* !XEN_PT_H */
hw/xen/xen_pt_graphics.c new file +232 -0
232 lines not on this page · raw message
qemu-options.hx +9 -0
@@ -1053,6 +1053,15 @@ STEXI Rotate graphical output some deg left (only PXA LCD). ETEXI +DEF("gfx_passthru", 0, QEMU_OPTION_gfx_passthru, + "-gfx_passthru enable Intel IGD passthrough by XEN\n", + QEMU_ARCH_ALL) +STEXI +@item -gfx_passthru +@findex -gfx_passthru +Enable Intel IGD passthrough by XEN +ETEXI + DEF("vga", HAS_ARG, QEMU_OPTION_vga, "-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|none]\n" " select video card type\n", QEMU_ARCH_ALL)
vl.c +10 -1
@@ -1438,6 +1438,13 @@ static void smp_parse(QemuOpts *opts) } +/* We still need this for compatibility with XEN. */ +int xen_has_gfx_passthru; +static void xen_gfx_passthru (const char *optarg) +{ + xen_has_gfx_passthru =1 ; +} +static void configure_realtime (QemuOpts *opts) {bool enable_mlock;
@@ -2990,7 +2997,6 @@ int main(int argc, char **argv, char **envp)const char *trace_file =NULL ;const ram_addr_t default_ram_size = (ram_addr_t )DEFAULT_RAM_SIZE *1024 *1024 ; -atexit (qemu_run_exit_notifiers);error_set_progname (argv[0 ]);qemu_init_exec_dir (argv[0 ]);
@@ -3957,6 +3963,9 @@ int main(int argc, char **argv, char **envp) }configure_msg (opts);break ; +case QEMU_OPTION_gfx_passthru: +xen_gfx_passthru (optarg); +break ;default :os_parse_cmd_args (popt->index, optarg); }
Signature · 1 line
1.9.1
Re: [Xen-devel] [v3][PATCH 1/5] xen, gfx passthrough: basic graphics passthrough support
Quoted 3 lines · Tiejun Chen
basic gfx passthrough support:
- add a vga type for gfx passthrough
- retrieve VGA bios from sysfs, then load it to guest0xC0000
s/guest/guest at/
Quoted 1 line
- register/unregister legacy VGA I/O ports and MMIOs for passthroughed gfx
s/passthrouged gfx/passthrough GFX/
Quoted 89 lines
The original patch is from Weidong Han <[email protected]>
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Weidong Han <[email protected]>---
v3:* Fix some typos.
* Add more comments to make that readable.
* Improve some return paths.v2:
* retrieve VGA bios from sysfs properly.
* redefine some function name.hw/xen/Makefile.objs | 2 +- hw/xen/xen-host-pci-device.c | 5 + hw/xen/xen-host-pci-device.h | 1 + hw/xen/xen_pt.c | 10 ++ hw/xen/xen_pt.h | 4 + hw/xen/xen_pt_graphics.c | 232 +++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 9 ++ vl.c | 11 +- 8 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 hw/xen/xen_pt_graphics.chw/xen/Makefile.objs +1
-1@@ -2,4 +2,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o +obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_pt_graphics.ohw/xen/xen-host-pci-device.c +5
-0@@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain, goto error; } d->irq = v; + rc =xen_host_pci_get_hex_value (d,"class" , &v); +if (rc) { + goto error; + } + d->class_code = v; d->is_virtfn =xen_host_pci_dev_is_virtfn (d);return 0 ;hw/xen/xen-host-pci-device.h +1
-0@@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {uint16_t vendor_id;uint16_t device_id; +uint32_t class_code;int irq;XenHostPCIIORegion io_regions[PCI_NUM_REGIONS -1 ];hw/xen/xen_pt.c +3
-0@@ -450,6 +450,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) d->rom.size, d->rom.base_addr); } +xen_pt_register_vga_regions (d);return 0 ; }@@ -470,6 +471,8 @@ static void xen_pt_unregister_regions(XenPCIPassthroughState *s)if (d->rom.base_addr && d->rom.size) {memory_region_destroy (&s->rom); } + +xen_pt_unregister_vga_regions (d); }/* region mapping */
hw/xen/xen_pt.c static int xen_pt_initfn(PCIDevice *d) · line 699
Quoted 4 lines
hw/xen/xen_pt.c +1
-0@@ -693,6 +696,13 @@ static int xen_pt_initfn(PCIDevice *d)/* Handle real device's MMIO/PIO BARs */ xen_pt_register_regions (s); +/* Setup VGA bios for passthroughed gfx */
Ditto
hw/xen/xen_pt.c static int xen_pt_initfn(PCIDevice *d) · line 701
Quoted 2 lines
hw/xen/xen_pt.c +2
-0+if (xen_pt_setup_vga (&s->real_device) <0 ) { +XEN_PT_ERR (d,"Setup VGA BIOS of passthroughed gfx failed!\n" );
Ditto
Quoted 323 lines
hw/xen/xen_pt.c +4
-0+xen_host_pci_device_put (&s->real_device); +return -1 ; + } +/* reinitialize each config register to be emulated */ if (xen_pt_config_init (s)) {XEN_PT_ERR (d,"PCI Config space initialisation failed.\n" );hw/xen/xen_pt.h +4
-0@@ -298,5 +298,9 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar) return s->msix && s->msix->bar_index == bar; } +extern int xen_has_gfx_passthru; +int xen_pt_register_vga_regions (XenHostPCIDevice *dev); +int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev); +int xen_pt_setup_vga (XenHostPCIDevice *dev);#endif /* !XEN_PT_H */ hw/xen/xen_pt_graphics.c new file +232
-0@@ -0,0 +1,232 @@ +/* +* graphics passthrough +*/ +#include "xen_pt.h" +#include "xen-host-pci-device.h" +#include "hw/xen/xen_backend.h" + +static int is_vga_passthrough (XenHostPCIDevice *dev) +{ +return (xen_has_gfx_passthru + && ((dev->class_code >>0x8 ) ==PCI_CLASS_DISPLAY_VGA )); +} + +typedef struct VGARegion { +int type;/* Memory or port I/O */ +uint64_t guest_base_addr; +uint64_t machine_base_addr; +uint64_t size;/* size of the region */ +int rc; +}VGARegion ; + +#define IORESOURCE_IO 0x00000100 +#define IORESOURCE_MEM 0x00000200 + +static struct VGARegion vga_args[] = { + { + .type =IORESOURCE_IO , + .guest_base_addr =0x3B0 , + .machine_base_addr =0x3B0 , + .size =0xC , + .rc =-1 , + }, + { + .type =IORESOURCE_IO , + .guest_base_addr =0x3C0 , + .machine_base_addr =0x3C0 , + .size =0x20 , + .rc =-1 , + }, + { + .type =IORESOURCE_MEM , + .guest_base_addr =0xa0000 >>XC_PAGE_SHIFT , + .machine_base_addr =0xa0000 >>XC_PAGE_SHIFT , + .size =0x20 , + .rc =-1 , + }, +}; + +/* +* register VGA resources for the domain with assigned gfx +*/ +int xen_pt_register_vga_regions (XenHostPCIDevice *dev) +{ +int i =0 ; + +if (!is_vga_passthrough (dev)) { +return -1 ; + } + +for (i =0 ; i <ARRAY_SIZE (vga_args); i++) { +if (vga_args[i].type ==IORESOURCE_IO ) { + vga_args[i].rc =xc_domain_ioport_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_ADD_MAPPING ); + }else { + vga_args[i].rc =xc_domain_memory_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_ADD_MAPPING ); + } + +if (vga_args[i].rc) { +XEN_PT_ERR (NULL ,"VGA %s mapping failed! (rc: %i)\n" , + vga_args[i].type ==IORESOURCE_IO ?"ioport" :"memory" , + vga_args[i].rc); +return vga_args[i].rc; + } + } + +return 0 ; +} + +/* +* unregister VGA resources for the domain with assigned gfx +*/ +int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev) +{ +int i =0 ; + +if (!is_vga_passthrough (dev)) { +return -1 ; + } + +for (i =0 ; i <ARRAY_SIZE (vga_args); i++) { +if (vga_args[i].type ==IORESOURCE_IO ) { + vga_args[i].rc =xc_domain_ioport_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_REMOVE_MAPPING ); + }else { + vga_args[i].rc =xc_domain_memory_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_REMOVE_MAPPING ); + } + +if (vga_args[i].rc) { +XEN_PT_ERR (NULL ,"VGA %s unmapping failed! (rc: %i)\n" , + vga_args[i].type ==IORESOURCE_IO ?"ioport" :"memory" , + vga_args[i].rc); +return vga_args[i].rc; + } + } + +return 0 ; +} + +static int get_vgabios (unsigned char *buf,XenHostPCIDevice *dev) +{ +char rom_file[64 ]; +FILE *fp; +uint8_t val; +struct stat st; +uint16_t magic =0 ; +int ret =0 ; + +snprintf (rom_file,sizeof (rom_file), +"/sys/bus/pci/devices/%04x:%02x:%02x.%d/rom" , + dev->domain, dev->bus, dev->dev, + dev->func); + +if (stat (rom_file, &st)) { +return -ENODEV ; + } + +if (access (rom_file,F_OK )) { +XEN_PT_ERR (NULL ,"pci-assign: Insufficient privileges for %s" , + rom_file); +return -ENODEV ; + } + +/* Write "1" to the ROM file to enable it */ + fp =fopen (rom_file,"r+" ); +if (fp ==NULL ) { +return -EACCES ; + } + val =1 ; +if (fwrite (&val,1 ,1 , fp) !=1 ) { +XEN_PT_LOG ("%s\n" ,"Failed to enable pci-sysfs rom file" ); + ret = -EIO ; + goto close_rom; + } +fseek (fp,0 ,SEEK_SET ); + +/* +* Check if it a real bios extension. +* The magic number is 0xAA55. +*/ +if (!fread (&magic,sizeof (magic),1 , fp)) { +XEN_PT_ERR (NULL ,"VGA: can't get magic.\n" ); + ret = -ENODEV ; + goto close_rom; + } +if (magic !=0xAA55 ) { +XEN_PT_ERR (NULL ,"VGA: wrong magic %x.\n" , magic); + ret = -ENODEV ; + goto close_rom; + } +fseek (fp,0 ,SEEK_SET ); + +if (!fread (buf,1 , st.st_size, fp)) { +XEN_PT_ERR (NULL ,"VGA: pci-assign: Cannot read from host %s" , rom_file); +XEN_PT_LOG (NULL ,"VGA: Device option ROM contents are probably invalid " +"(check dmesg).\nSkip option ROM probe with rombar=0, " +"or load from file with romfile=\n" ); + } + +close_rom: +/* Write "0" to disable ROM */ +fseek (fp,0 ,SEEK_SET ); + val =0 ; +if (!fwrite (&val,1 ,1 , fp)) { + ret = -EIO ; +XEN_PT_LOG ("%s\n" ,"Failed to disable pci-sysfs rom file" ); + } +fclose (fp); +return ret; +} + +/* Allocated 128K for the vga bios */ +#define VGA_BIOS_DEFAULT_SIZE (0x20000) + +int xen_pt_setup_vga (XenHostPCIDevice *dev) +{ +unsigned char *bios =NULL ; +int bios_size =0 ; +char *c =NULL ; +char checksum =0 ; +int rc =0 ; + +if (!is_vga_passthrough (dev)) { +return rc; + } + + bios =g_malloc0 (VGA_BIOS_DEFAULT_SIZE ); + + bios_size =get_vgabios (bios, dev); +if (bios_size) { +XEN_PT_ERR (NULL ,"VGA: Error %d getting VBIOS!\n" , bios_size); +if (bios_size <0 ) { +XEN_PT_ERR (NULL ,"VGA: Error (%s).\n" ,strerror (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; +XEN_PT_LOG (NULL ,"vga bios checksum is adjusted!\n" ); + } + +/* Currently we fixed this address as a primary. */ +cpu_physical_memory_rw (0xc0000 , bios, bios_size,1 ); +out: +g_free (bios); +return rc; +}qemu-options.hx +9
-0@@ -1053,6 +1053,15 @@ STEXI Rotate graphical output some deg left (only PXA LCD). ETEXI +DEF("gfx_passthru", 0, QEMU_OPTION_gfx_passthru, + "-gfx_passthru enable Intel IGD passthrough by XEN\n", + QEMU_ARCH_ALL) +STEXI +@item -gfx_passthru +@findex -gfx_passthru +Enable Intel IGD passthrough by XEN +ETEXI + DEF("vga", HAS_ARG, QEMU_OPTION_vga, "-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|none]\n" " select video card type\n", QEMU_ARCH_ALL)vl.c +10
-1@@ -1438,6 +1438,13 @@ static void smp_parse(QemuOpts *opts) } +/* We still need this for compatibility with XEN. */ +int xen_has_gfx_passthru; +static void xen_gfx_passthru (const char *optarg) +{ + xen_has_gfx_passthru =1 ; +} +static void configure_realtime (QemuOpts *opts) {bool enable_mlock;@@ -2990,7 +2997,6 @@ int main(int argc, char **argv, char **envp)const char *trace_file =NULL ;const ram_addr_t default_ram_size = (ram_addr_t )DEFAULT_RAM_SIZE *1024 *1024 ; -atexit (qemu_run_exit_notifiers);error_set_progname (argv[0 ]);qemu_init_exec_dir (argv[0 ]);@@ -3957,6 +3963,9 @@ int main(int argc, char **argv, char **envp) }configure_msg (opts);break ; +case QEMU_OPTION_gfx_passthru: +xen_gfx_passthru (optarg); +break ;default :os_parse_cmd_args (popt->index, optarg); }Signature · 7 lines
1.9.1 _______________________________________________ Xen-devel mailing list [email protected] http://lists.xen.org/xen-devel
Re: [Xen-devel] [v3][PATCH 1/5] xen, gfx passthrough: basic graphics passthrough support
Quoted 11 lines
-----Original Message-----
From: Konrad Rzeszutek Wilk [mailto:[email protected]]
Sent: Tuesday, May 27, 2014 10:55 PM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; [email protected]; [email protected]; Zhang, Yang Z
Subject: Re: [Xen-devel] [v3][PATCH 1/5] xen, gfx passthrough: basic graphics passthrough support
Quoted 6 lines
Quoted 3 lines · Tiejun Chen
basic gfx passthrough support:
- add a vga type for gfx passthrough
- retrieve VGA bios from sysfs, then load it to guest0xC0000s/guest/guest at/
Fixed.
Quoted 4 lines
Quoted 2 lines
- register/unregister legacy VGA I/O ports and MMIOs for passthroughed gfx
s/passthrouged gfx/passthrough GFX/
Fixed.
Quoted 92 lines
Quoted 18 lines
The original patch is from Weidong Han <[email protected]>
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Weidong Han <[email protected]>---
v3:* Fix some typos.
* Add more comments to make that readable.
* Improve some return paths.v2:
* retrieve VGA bios from sysfs properly.
* redefine some function name.Quoted 6 lines
hw/xen/Makefile.objs | 2 +- hw/xen/xen-host-pci-device.c | 5 + hw/xen/xen-host-pci-device.h | 1 + hw/xen/xen_pt.c | 10 ++ hw/xen/xen_pt.h | 4 + hw/xen/xen_pt_graphics.c | 232+++++++++++++++++++++++++++++++++++++++++++
hw/xen/xen-host-pci-device.c int xen_host_pci_device_get(XenHostPCIDevice *d,
Quoted 22 lines
qemu-options.hx | 9 ++ vl.c | 11 +- 8 files changed, 272 insertions(+), 2 deletions(-) create mode100644
hw/xen/xen_pt_graphics.chw/xen/Makefile.objs index renamed from hw/xen/Makefile.objs +0
-0a0ca0aa..77b7dae 100644
hw/xen/Makefile.objs +0
-1@@ -2,4 +2,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.oxen_pt_msi.o
hw/xen/Makefile.objs +2
-0+obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o +xen_pt_msi.o xen_pt_graphics.o(quoted diff) +0
-0
b/hw/xen/xen-host-pci-device.cindex 743b37b..a54b7de 100644hw/xen/xen-host-pci-device.c +0
-0@@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d,
uint16_tdomain,hw/xen/xen_pt.c static int
Quoted 27 lines
hw/xen/xen-host-pci-device.c +5
-0goto error; } d->irq = v; + rc =xen_host_pci_get_hex_value (d,"class" , &v); +if (rc) { + goto error; + } + d->class_code = v; d->is_virtfn =xen_host_pci_dev_is_virtfn (d);return 0 ;(quoted diff) +0
-0
b/hw/xen/xen-host-pci-device.hindex c2486f0..f1e1c30 100644hw/xen/xen-host-pci-device.h +1
-0@@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {uint16_t vendor_id;uint16_t device_id; +uint32_t class_code;int irq; XenHostPCIIORegion io_regions[PCI_NUM_REGIONS - 1]; diff --git
a/hw/xen/xen_pt.cb/hw/xen/xen_pt.cindex be4220b..a0113ea 100644hw/xen/xen_pt.c +0
-0@@ -450,6 +450,7 @@ static int
xen_pt_register_regions(XenPCIPassthroughState *s)hw/xen/xen_pt.c static void
Quoted 8 lines
hw/xen/xen_pt.c +1
-0d->rom.size, d->rom.base_addr); } +xen_pt_register_vga_regions (d);return 0 ; }@@ -470,6 +471,8 @@ static void
xen_pt_unregister_regions(XenPCIPassthroughState *s)Quoted 7 lines
hw/xen/xen_pt.c +2
-0if (d->rom.base_addr && d->rom.size) {memory_region_destroy (&s->rom); } + +xen_pt_unregister_vga_regions (d); }
Quoted 9 lines
hw/xen/xen_pt.c static int xen_pt_initfn(PCIDevice *d) · line 699
Quoted 6 lines
hw/xen/xen_pt.c +1
-0/* region mapping */ @@ -693,6 +696,13 @@ static int xen_pt_initfn(PCIDevice *d)/* Handle real device's MMIO/PIO BARs */ xen_pt_register_regions (s); +/* Setup VGA bios for passthroughed gfx */ Ditto
Fixed.
Quoted 6 lines
hw/xen/xen_pt.c static int xen_pt_initfn(PCIDevice *d) · line 702
Quoted 3 lines
hw/xen/xen_pt.c +3
-0+if (xen_pt_setup_vga (&s->real_device) <0 ) { +XEN_PT_ERR (d,"Setup VGA BIOS of passthroughed gfx + failed!\n");Ditto
Fixed.
Thanks
Tiejun
Re: [v3][PATCH 1/5] xen, gfx passthrough: basic graphics passthrough support
In reply to Tiejun ChenQuoted 173 lines · Tiejun Chen
basic gfx passthrough support:
- add a vga type for gfx passthrough
- retrieve VGA bios from sysfs, then load it to guest0xC0000
- register/unregister legacy VGA I/O ports and MMIOs for passthroughed gfxThe original patch is from Weidong Han <[email protected]>
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Weidong Han <[email protected]>---
v3:* Fix some typos.
* Add more comments to make that readable.
* Improve some return paths.v2:
* retrieve VGA bios from sysfs properly.
* redefine some function name.hw/xen/Makefile.objs | 2 +- hw/xen/xen-host-pci-device.c | 5 + hw/xen/xen-host-pci-device.h | 1 + hw/xen/xen_pt.c | 10 ++ hw/xen/xen_pt.h | 4 + hw/xen/xen_pt_graphics.c | 232 +++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 9 ++ vl.c | 11 +- 8 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 hw/xen/xen_pt_graphics.chw/xen/Makefile.objs +1
-1@@ -2,4 +2,4 @@ common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o -obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o +obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_pt_graphics.ohw/xen/xen-host-pci-device.c +5
-0@@ -376,6 +376,11 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain, goto error; } d->irq = v; + rc =xen_host_pci_get_hex_value (d,"class" , &v); +if (rc) { + goto error; + } + d->class_code = v; d->is_virtfn =xen_host_pci_dev_is_virtfn (d);return 0 ;hw/xen/xen-host-pci-device.h +1
-0@@ -25,6 +25,7 @@ typedef struct XenHostPCIDevice {uint16_t vendor_id;uint16_t device_id; +uint32_t class_code;int irq;XenHostPCIIORegion io_regions[PCI_NUM_REGIONS -1 ];hw/xen/xen_pt.c +10
-0@@ -450,6 +450,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) d->rom.size, d->rom.base_addr); } +xen_pt_register_vga_regions (d);return 0 ; }@@ -470,6 +471,8 @@ static void xen_pt_unregister_regions(XenPCIPassthroughState *s)if (d->rom.base_addr && d->rom.size) {memory_region_destroy (&s->rom); } + +xen_pt_unregister_vga_regions (d); }/* region mapping */ @@ -693,6 +696,13 @@ static int xen_pt_initfn(PCIDevice *d)/* Handle real device's MMIO/PIO BARs */ xen_pt_register_regions (s); +/* Setup VGA bios for passthroughed gfx */ +if (xen_pt_setup_vga (&s->real_device) <0 ) { +XEN_PT_ERR (d,"Setup VGA BIOS of passthroughed gfx failed!\n" ); +xen_host_pci_device_put (&s->real_device); +return -1 ; + } +/* reinitialize each config register to be emulated */ if (xen_pt_config_init (s)) {XEN_PT_ERR (d,"PCI Config space initialisation failed.\n" );hw/xen/xen_pt.h +4
-0@@ -298,5 +298,9 @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar) return s->msix && s->msix->bar_index == bar; } +extern int xen_has_gfx_passthru; +int xen_pt_register_vga_regions (XenHostPCIDevice *dev); +int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev); +int xen_pt_setup_vga (XenHostPCIDevice *dev);#endif /* !XEN_PT_H */ hw/xen/xen_pt_graphics.c new file +47
-0@@ -0,0 +1,232 @@ +/* +* graphics passthrough +*/ +#include "xen_pt.h" +#include "xen-host-pci-device.h" +#include "hw/xen/xen_backend.h" + +static int is_vga_passthrough (XenHostPCIDevice *dev) +{ +return (xen_has_gfx_passthru + && ((dev->class_code >>0x8 ) ==PCI_CLASS_DISPLAY_VGA )); +} + +typedef struct VGARegion { +int type;/* Memory or port I/O */ +uint64_t guest_base_addr; +uint64_t machine_base_addr; +uint64_t size;/* size of the region */ +int rc; +}VGARegion ; + +#define IORESOURCE_IO 0x00000100 +#define IORESOURCE_MEM 0x00000200 + +static struct VGARegion vga_args[] = { + { + .type =IORESOURCE_IO , + .guest_base_addr =0x3B0 , + .machine_base_addr =0x3B0 , + .size =0xC , + .rc =-1 , + }, + { + .type =IORESOURCE_IO , + .guest_base_addr =0x3C0 , + .machine_base_addr =0x3C0 , + .size =0x20 , + .rc =-1 , + }, + { + .type =IORESOURCE_MEM , + .guest_base_addr =0xa0000 >>XC_PAGE_SHIFT , + .machine_base_addr =0xa0000 >>XC_PAGE_SHIFT , + .size =0x20 , + .rc =-1 , + }, +};
hw/xen/xen_pt_graphics.c line 57
Quoted 10 lines
hw/xen/xen_pt_graphics.c new file +10
-0+ +/* +* register VGA resources for the domain with assigned gfx +*/ +int xen_pt_register_vga_regions (XenHostPCIDevice *dev) +{ +int i =0 ; + +if (!is_vga_passthrough (dev)) { +return -1 ;
Given that xen_pt_register_vga_regions is called unconditionally, this is not an error condition, isn't it? It should return 0.
Quoted 25 lines
hw/xen/xen_pt_graphics.c new file +25
-0+ } + +for (i =0 ; i <ARRAY_SIZE (vga_args); i++) { +if (vga_args[i].type ==IORESOURCE_IO ) { + vga_args[i].rc =xc_domain_ioport_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_ADD_MAPPING ); + }else { + vga_args[i].rc =xc_domain_memory_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_ADD_MAPPING ); + } + +if (vga_args[i].rc) { +XEN_PT_ERR (NULL ,"VGA %s mapping failed! (rc: %i)\n" , + vga_args[i].type ==IORESOURCE_IO ?"ioport" :"memory" , + vga_args[i].rc); +return vga_args[i].rc; + } + } + +return 0 ; +}
hw/xen/xen_pt_graphics.c line 92
Quoted 10 lines
hw/xen/xen_pt_graphics.c new file +10
-0+ +/* +* unregister VGA resources for the domain with assigned gfx +*/ +int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev) +{ +int i =0 ; + +if (!is_vga_passthrough (dev)) { +return -1 ;
same here
Quoted 179 lines
hw/xen/xen_pt_graphics.c new file +140
-0+ } + +for (i =0 ; i <ARRAY_SIZE (vga_args); i++) { +if (vga_args[i].type ==IORESOURCE_IO ) { + vga_args[i].rc =xc_domain_ioport_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_REMOVE_MAPPING ); + }else { + vga_args[i].rc =xc_domain_memory_mapping (xen_xc, xen_domid, + vga_args[i].guest_base_addr, + vga_args[i].machine_base_addr, + vga_args[i].size,DPCI_REMOVE_MAPPING ); + } + +if (vga_args[i].rc) { +XEN_PT_ERR (NULL ,"VGA %s unmapping failed! (rc: %i)\n" , + vga_args[i].type ==IORESOURCE_IO ?"ioport" :"memory" , + vga_args[i].rc); +return vga_args[i].rc; + } + } + +return 0 ; +} + +static int get_vgabios (unsigned char *buf,XenHostPCIDevice *dev) +{ +char rom_file[64 ]; +FILE *fp; +uint8_t val; +struct stat st; +uint16_t magic =0 ; +int ret =0 ; + +snprintf (rom_file,sizeof (rom_file), +"/sys/bus/pci/devices/%04x:%02x:%02x.%d/rom" , + dev->domain, dev->bus, dev->dev, + dev->func); + +if (stat (rom_file, &st)) { +return -ENODEV ; + } + +if (access (rom_file,F_OK )) { +XEN_PT_ERR (NULL ,"pci-assign: Insufficient privileges for %s" , + rom_file); +return -ENODEV ; + } + +/* Write "1" to the ROM file to enable it */ + fp =fopen (rom_file,"r+" ); +if (fp ==NULL ) { +return -EACCES ; + } + val =1 ; +if (fwrite (&val,1 ,1 , fp) !=1 ) { +XEN_PT_LOG ("%s\n" ,"Failed to enable pci-sysfs rom file" ); + ret = -EIO ; + goto close_rom; + } +fseek (fp,0 ,SEEK_SET ); + +/* +* Check if it a real bios extension. +* The magic number is 0xAA55. +*/ +if (!fread (&magic,sizeof (magic),1 , fp)) { +XEN_PT_ERR (NULL ,"VGA: can't get magic.\n" ); + ret = -ENODEV ; + goto close_rom; + } +if (magic !=0xAA55 ) { +XEN_PT_ERR (NULL ,"VGA: wrong magic %x.\n" , magic); + ret = -ENODEV ; + goto close_rom; + } +fseek (fp,0 ,SEEK_SET ); + +if (!fread (buf,1 , st.st_size, fp)) { +XEN_PT_ERR (NULL ,"VGA: pci-assign: Cannot read from host %s" , rom_file); +XEN_PT_LOG (NULL ,"VGA: Device option ROM contents are probably invalid " +"(check dmesg).\nSkip option ROM probe with rombar=0, " +"or load from file with romfile=\n" ); + } + +close_rom: +/* Write "0" to disable ROM */ +fseek (fp,0 ,SEEK_SET ); + val =0 ; +if (!fwrite (&val,1 ,1 , fp)) { + ret = -EIO ; +XEN_PT_LOG ("%s\n" ,"Failed to disable pci-sysfs rom file" ); + } +fclose (fp); +return ret; +} + +/* Allocated 128K for the vga bios */ +#define VGA_BIOS_DEFAULT_SIZE (0x20000) + +int xen_pt_setup_vga (XenHostPCIDevice *dev) +{ +unsigned char *bios =NULL ; +int bios_size =0 ; +char *c =NULL ; +char checksum =0 ; +int rc =0 ; + +if (!is_vga_passthrough (dev)) { +return rc; + } + + bios =g_malloc0 (VGA_BIOS_DEFAULT_SIZE ); + + bios_size =get_vgabios (bios, dev); +if (bios_size) { +XEN_PT_ERR (NULL ,"VGA: Error %d getting VBIOS!\n" , bios_size); +if (bios_size <0 ) { +XEN_PT_ERR (NULL ,"VGA: Error (%s).\n" ,strerror (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; +XEN_PT_LOG (NULL ,"vga bios checksum is adjusted!\n" ); + } + +/* Currently we fixed this address as a primary. */ +cpu_physical_memory_rw (0xc0000 , bios, bios_size,1 ); +out: +g_free (bios); +return rc; +}qemu-options.hx +9
-0@@ -1053,6 +1053,15 @@ STEXI Rotate graphical output some deg left (only PXA LCD). ETEXI +DEF("gfx_passthru", 0, QEMU_OPTION_gfx_passthru, + "-gfx_passthru enable Intel IGD passthrough by XEN\n", + QEMU_ARCH_ALL) +STEXI +@item -gfx_passthru +@findex -gfx_passthru +Enable Intel IGD passthrough by XEN +ETEXI + DEF("vga", HAS_ARG, QEMU_OPTION_vga, "-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|none]\n" " select video card type\n", QEMU_ARCH_ALL)vl.c +7
-0@@ -1438,6 +1438,13 @@ static void smp_parse(QemuOpts *opts) } +/* We still need this for compatibility with XEN. */ +int xen_has_gfx_passthru; +static void xen_gfx_passthru (const char *optarg) +{ + xen_has_gfx_passthru =1 ; +} +static void configure_realtime (QemuOpts *opts) {bool enable_mlock;
vl.c int main(int argc, char **argv, char **envp) · line 2993
Quoted 4 lines
vl.c +0
-1@@ -2990,7 +2997,6 @@ int main(int argc, char **argv, char **envp)const char *trace_file =NULL ;const ram_addr_t default_ram_size = (ram_addr_t )DEFAULT_RAM_SIZE *1024 *1024 ; -
Spurious change
Quoted 16 lines
vl.c +3
-0atexit (qemu_run_exit_notifiers);error_set_progname (argv[0 ]);qemu_init_exec_dir (argv[0 ]);@@ -3957,6 +3963,9 @@ int main(int argc, char **argv, char **envp) }configure_msg (opts);break ; +case QEMU_OPTION_gfx_passthru: +xen_gfx_passthru (optarg); +break ;default :os_parse_cmd_args (popt->index, optarg); }Signature · 1 line
1.9.1
Re: [v3][PATCH 1/5] xen, gfx passthrough: basic graphics passthrough support
Quoted 11 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 1:48 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: Re: [v3][PATCH 1/5] xen, gfx passthrough: basic graphics passthrough support
[snip]
Quoted 9 lines
hw/xen/xen_pt_graphics.c line 57
Quoted 6 lines
+ * register VGA resources for the domain with assigned gfx */ int
hw/xen/xen_pt_graphics.c new file +5
-0+xen_pt_register_vga_regions(XenHostPCIDevice *dev) { +int i =0 ; + +if (!is_vga_passthrough (dev)) { +return -1 ;Given that
xen_pt_register_vga_regionsis called unconditionally, this is not an error condition, isn't it? It should return 0.
Okay.
Quoted 1 line
[snip]
Quoted 9 lines
hw/xen/xen_pt_graphics.c line 57
Quoted 6 lines
+ * unregister VGA resources for the domain with assigned gfx */ int
hw/xen/xen_pt_graphics.c new file +5
-0+xen_pt_unregister_vga_regions(XenHostPCIDevice *dev) { +int i =0 ; + +if (!is_vga_passthrough (dev)) { +return -1 ;same here
Fixed.
Quoted 1 line
[snip]
Quoted 7 lines
Quoted 1 line
const
ram_addr_tdefault_ram_size=(ram_addr_t)DEFAULT_RAM_SIZE *
Quoted 2 lines
1024 * 1024;-
Spurious change
Removed.
Thanks
Tiejun
PATCH v3 2/5 xen, gfx passthrough: create intel isa bridge
In reply to Tiejun ChenISA bridge is needed since Intel gfx drive will probe it instead of Dev31:Fun0 to make graphics device passthrough work easy for VMM, that only need to expose ISA bridge to let driver know the real hardware underneath.
The original patch is from Allen Kay [[email protected]]
---
v3:
* Fix some typos.
* Improve some return paths.
v2:
* Nothing is changed.
hw/xen/xen_pt_graphics.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)
hw/xen/xen_pt_graphics.c +63 -0
@@ -230,3 +230,66 @@ out:g_free (bios);return rc; } + +static uint32_t isa_bridge_read_config (PCIDevice *d,uint32_t addr,int len) +{ +return pci_default_read_config (d, addr, len); +} + +static void isa_bridge_write_config (PCIDevice *d,uint32_t addr,uint32_t v, +int len) +{ +pci_default_write_config (d, addr, v, len); + +return ; +} + +static void isa_bridge_class_init (ObjectClass *klass,void *data) +{ +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->config_read = isa_bridge_read_config; + k->config_write = isa_bridge_write_config; + +return ; +}; + +typedef struct { +PCIDevice dev; +}ISABridgeState ; + +static TypeInfo isa_bridge_info = { + .name ="intel-pch-isa-bridge" , + .parent =TYPE_PCI_DEVICE , + .instance_size =sizeof (ISABridgeState), + .class_init = isa_bridge_class_init, +}; + +static void xen_pt_graphics_register_types (void ) +{ +type_register_static (&isa_bridge_info); +} + +type_init (xen_pt_graphics_register_types) + +static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) +{ +struct PCIDevice *dev; + +char rid; + + dev =pci_create (bus,PCI_DEVFN (0x1f ,0 ),"intel-pch-isa-bridge" ); + +qdev_init_nofail (&dev->qdev); + +pci_config_set_vendor_id (dev->config, hdev->vendor_id); +pci_config_set_device_id (dev->config, hdev->device_id); + +xen_host_pci_get_block (hdev,PCI_REVISION_ID , (uint8_t *)&rid,1 ); + +pci_config_set_revision (dev->config, rid); +pci_config_set_class (dev->config,PCI_CLASS_BRIDGE_ISA ); + +XEN_PT_LOG (dev,"Intel PCH ISA bridge created.\n" ); +return 0 ; +}
Signature · 1 line
1.9.1
Re: [Xen-devel] [v3][PATCH 2/5] xen, gfx passthrough: create intel isa bridge
Quoted 32 lines · Tiejun Chen
ISA bridge is needed since Intel gfx drive will probe it instead of Dev31:Fun0 to make graphics device passthrough work easy for VMM, that only need to expose ISA bridge to let driver know the real hardware underneath.
The original patch is from Allen Kay [[email protected]]
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Allen Kay <[email protected]>---
v3:* Fix some typos.
* Improve some return paths.v2:
* Nothing is changed.
hw/xen/xen_pt_graphics.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)hw/xen/xen_pt_graphics.c +2
-0@@ -230,3 +230,66 @@ out:g_free (bios);return rc; } + +static uint32_t isa_bridge_read_config (PCIDevice *d,uint32_t addr,int len)
hw/xen/xen_pt_graphics.c out: · line 244
Quoted 10 lines
hw/xen/xen_pt_graphics.c +10
-0+{ +return pci_default_read_config (d, addr, len); +} + +static void isa_bridge_write_config (PCIDevice *d,uint32_t addr,uint32_t v, +int len) +{ +pci_default_write_config (d, addr, v, len); + +return ;
You don't need the return there.
hw/xen/xen_pt_graphics.c out: · line 254
Quoted 10 lines
hw/xen/xen_pt_graphics.c +10
-0+} + +static void isa_bridge_class_init (ObjectClass *klass,void *data) +{ +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->config_read = isa_bridge_read_config; + k->config_write = isa_bridge_write_config; + +return ;
Ditto
Quoted 49 lines
hw/xen/xen_pt_graphics.c +41
-0+}; + +typedef struct { +PCIDevice dev; +}ISABridgeState ; + +static TypeInfo isa_bridge_info = { + .name ="intel-pch-isa-bridge" , + .parent =TYPE_PCI_DEVICE , + .instance_size =sizeof (ISABridgeState), + .class_init = isa_bridge_class_init, +}; + +static void xen_pt_graphics_register_types (void ) +{ +type_register_static (&isa_bridge_info); +} + +type_init (xen_pt_graphics_register_types) + +static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) +{ +struct PCIDevice *dev; + +char rid; + + dev =pci_create (bus,PCI_DEVFN (0x1f ,0 ),"intel-pch-isa-bridge" ); + +qdev_init_nofail (&dev->qdev); + +pci_config_set_vendor_id (dev->config, hdev->vendor_id); +pci_config_set_device_id (dev->config, hdev->device_id); + +xen_host_pci_get_block (hdev,PCI_REVISION_ID , (uint8_t *)&rid,1 ); + +pci_config_set_revision (dev->config, rid); +pci_config_set_class (dev->config,PCI_CLASS_BRIDGE_ISA ); + +XEN_PT_LOG (dev,"Intel PCH ISA bridge created.\n" ); +return 0 ; +}Signature · 7 lines
1.9.1 _______________________________________________ Xen-devel mailing list [email protected] http://lists.xen.org/xen-devel
Re: [Xen-devel] [v3][PATCH 2/5] xen, gfx passthrough: create intel isa bridge
Quoted 45 lines · Konrad Rzeszutek Wilk
Quoted 32 lines · Tiejun Chen
ISA bridge is needed since Intel gfx drive will probe it instead of Dev31:Fun0 to make graphics device passthrough work easy for VMM, that only need to expose ISA bridge to let driver know the real hardware underneath.
The original patch is from Allen Kay [[email protected]]
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Allen Kay <[email protected]>---
v3:* Fix some typos.
* Improve some return paths.v2:
* Nothing is changed.
hw/xen/xen_pt_graphics.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)hw/xen/xen_pt_graphics.c +2
-0@@ -230,3 +230,66 @@ out:g_free (bios);return rc; } + +static uint32_t isa_bridge_read_config (PCIDevice *d,uint32_t addr,int len)hw/xen/xen_pt_graphics.c out: · line 244
Quoted 10 lines
hw/xen/xen_pt_graphics.c +10
-0+{ +return pci_default_read_config (d, addr, len); +} + +static void isa_bridge_write_config (PCIDevice *d,uint32_t addr,uint32_t v, +int len) +{ +pci_default_write_config (d, addr, v, len); + +return ;You don't need the return there.
Quoted 12 lines
hw/xen/xen_pt_graphics.c out: · line 254
Quoted 10 lines
hw/xen/xen_pt_graphics.c +10
-0+} + +static void isa_bridge_class_init (ObjectClass *klass,void *data) +{ +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->config_read = isa_bridge_read_config; + k->config_write = isa_bridge_write_config; + +return ;Ditto
Aside from these 2 minor changes, the patch looks good to me.
Quoted 50 lines
Quoted 49 lines
hw/xen/xen_pt_graphics.c +41
-0+}; + +typedef struct { +PCIDevice dev; +}ISABridgeState ; + +static TypeInfo isa_bridge_info = { + .name ="intel-pch-isa-bridge" , + .parent =TYPE_PCI_DEVICE , + .instance_size =sizeof (ISABridgeState), + .class_init = isa_bridge_class_init, +}; + +static void xen_pt_graphics_register_types (void ) +{ +type_register_static (&isa_bridge_info); +} + +type_init (xen_pt_graphics_register_types) + +static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) +{ +struct PCIDevice *dev; + +char rid; + + dev =pci_create (bus,PCI_DEVFN (0x1f ,0 ),"intel-pch-isa-bridge" ); + +qdev_init_nofail (&dev->qdev); + +pci_config_set_vendor_id (dev->config, hdev->vendor_id); +pci_config_set_device_id (dev->config, hdev->device_id); + +xen_host_pci_get_block (hdev,PCI_REVISION_ID , (uint8_t *)&rid,1 ); + +pci_config_set_revision (dev->config, rid); +pci_config_set_class (dev->config,PCI_CLASS_BRIDGE_ISA ); + +XEN_PT_LOG (dev,"Intel PCH ISA bridge created.\n" ); +return 0 ; +}Signature · 7 lines
1.9.1 _______________________________________________ Xen-devel mailing list [email protected] http://lists.xen.org/xen-devel
Re: [Xen-devel] [v3][PATCH 2/5] xen, gfx passthrough: create intel isa bridge
Quoted 70 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 1:52 AM
To: Konrad Rzeszutek Wilk
Cc: Chen, Tiejun; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; [email protected]; [email protected]; Zhang, Yang Z
Subject: Re: [Xen-devel] [v3][PATCH 2/5] xen, gfx passthrough: create intel isa bridgeQuoted 4 lines · Konrad Rzeszutek Wilk
Quoted 3 lines · Tiejun Chen
ISA bridge is needed since Intel gfx drive will probe it instead of Dev31:Fun0 to make graphics device passthrough work easy for VMM, that only need to expose ISA bridge to let driver know the real hardware
underneath.
Quoted 20 lines
Quoted 20 lines
The original patch is from Allen Kay [[email protected]]
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Allen Kay <[email protected]>---
v3:* Fix some typos.
* Improve some return paths.v2:
* Nothing is changed.
hw/xen/xen_pt_graphics.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)Quoted 14 lines
Quoted 5 lines
hw/xen/xen_pt_graphics.c +0
-0hw/xen/xen_pt_graphics.c out: · line 238
Quoted 9 lines
hw/xen/xen_pt_graphics.c +6
-0@@ -230,3 +230,66 @@ out:g_free (bios);return rc; } + +static uint32_t isa_bridge_read_config (PCIDevice *d,uint32_t addr, +int len) { +return pci_default_read_config (d, addr, len); } + +static void isa_bridge_write_config(PCIDevice *d, uint32_t addr, uint32_tv,
Quoted 6 lines
hw/xen/xen_pt_graphics.c out: · line 244
Quoted 4 lines
hw/xen/xen_pt_graphics.c +4
-0+ int len) { +pci_default_write_config (d, addr, v, len); + +return ;You don't need the return there.
Quoted 11 lines
hw/xen/xen_pt_graphics.c out: · line 254
Quoted 9 lines
hw/xen/xen_pt_graphics.c +9
-0+} + +static void isa_bridge_class_init (ObjectClass *klass,void *data) { +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->config_read = isa_bridge_read_config; + k->config_write = isa_bridge_write_config; + +return ;Ditto
Quoted 2 lines
Aside from these 2 minor changes, the patch looks good to me.
Already addressed
Thanks
Tiejun
Re: [Xen-devel] [v3][PATCH 2/5] xen, gfx passthrough: create intel isa bridge
In reply to Konrad Rzeszutek WilkQuoted 48 lines
-----Original Message-----
From: Konrad Rzeszutek Wilk [mailto:[email protected]]
Sent: Tuesday, May 27, 2014 10:56 PM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; [email protected]; [email protected]; Zhang, Yang Z
Subject: Re: [Xen-devel] [v3][PATCH 2/5] xen, gfx passthrough: create intel isa bridgeQuoted 3 lines · Tiejun Chen
ISA bridge is needed since Intel gfx drive will probe it instead of Dev31:Fun0 to make graphics device passthrough work easy for VMM, that only need to expose ISA bridge to let driver know the real hardware
underneath.
Quoted 32 lines
The original patch is from Allen Kay [[email protected]]
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Allen Kay <[email protected]>---
v3:* Fix some typos.
* Improve some return paths.v2:
* Nothing is changed.
hw/xen/xen_pt_graphics.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)hw/xen/xen_pt_graphics.c index renamed from hw/xen/xen_pt_graphics.c +0
-0e63bd6f..51b174f 100644
hw/xen/xen_pt_graphics.c +4
-0@@ -230,3 +230,66 @@ out:g_free (bios);return rc; } + +static uint32_t isa_bridge_read_config (PCIDevice *d,uint32_t addr, +int len) { +return pci_default_read_config (d, addr, len); }
Quoted 8 lines
hw/xen/xen_pt_graphics.c out: · line 244
Quoted 6 lines
hw/xen/xen_pt_graphics.c +6
-0+ +static void isa_bridge_write_config (PCIDevice *d,uint32_t addr,uint32_t v, +int len) { +pci_default_write_config (d, addr, v, len); + +return ;You don't need the return there.
Fixed.
Quoted 11 lines
hw/xen/xen_pt_graphics.c out: · line 254
Quoted 9 lines
hw/xen/xen_pt_graphics.c +9
-0+} + +static void isa_bridge_class_init (ObjectClass *klass,void *data) { +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->config_read = isa_bridge_read_config; + k->config_write = isa_bridge_write_config; + +return ;Ditto
Fixed.
Thanks
Tiejun
PATCH v3 3/5 xen, gfx passthrough: support Intel IGD passthrough with VT-D
In reply to Tiejun ChenSome registers of Intel IGD are mapped in host bridge, so it needs to passthrough these registers of physical host bridge to guest because emulated host bridge in guest doesn't have these mappings.
The original patch is from Weidong Han < weidong.han @ intel.com >
---
v3:
* Improve comments to make that readable.
v2:
* To introduce is_igd_passthrough() to make sure we touch physical host bridge only in IGD case.
hw/xen/xen_pt.h | 4 ++ hw/xen/xen_pt_graphics.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+)
hw/xen/xen_pt.h +4 -0
@@ -302,5 +302,9 @@ extern int xen_has_gfx_passthru;int xen_pt_register_vga_regions (XenHostPCIDevice *dev);int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev);int xen_pt_setup_vga (XenHostPCIDevice *dev); +int pci_create_pch (PCIBus *bus); +void igd_pci_write (PCIDevice *pci_dev,uint32_t config_addr, +uint32_t val,int len); +uint32_t igd_pci_read (PCIDevice *pci_dev,uint32_t config_addr,int len);#endif /* !XEN_PT_H */
hw/xen/xen_pt_graphics.c +159 -0
168 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-D
Quoted 51 lines · Tiejun Chen
Some registers of Intel IGD are mapped in host bridge, so it needs to passthrough these registers of physical host bridge to guest because emulated host bridge in guest doesn't have these mappings.
The original patch is from Weidong Han < weidong.han @ intel.com >
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Weidong Han <[email protected]>---
v3:* Improve comments to make that readable.
v2:
* To introduce
is_igd_passthrough()to make sure we touch physical host bridge only in IGD case.hw/xen/xen_pt.h | 4 ++ hw/xen/xen_pt_graphics.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+)hw/xen/xen_pt.h +4
-0@@ -302,5 +302,9 @@ extern int xen_has_gfx_passthru;int xen_pt_register_vga_regions (XenHostPCIDevice *dev);int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev);int xen_pt_setup_vga (XenHostPCIDevice *dev); +int pci_create_pch (PCIBus *bus); +void igd_pci_write (PCIDevice *pci_dev,uint32_t config_addr, +uint32_t val,int len); +uint32_t igd_pci_read (PCIDevice *pci_dev,uint32_t config_addr,int len);#endif /* !XEN_PT_H */ hw/xen/xen_pt_graphics.c +1
-0@@ -4,6 +4,7 @@#include "xen_pt.h" #include "xen-host-pci-device.h" #include "hw/xen/xen_backend.h" +#include "hw/pci/pci_bus.h" static int is_vga_passthrough (XenHostPCIDevice *dev) {@@ -293,3 +294,161 @@ static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev)XEN_PT_LOG (dev,"Intel PCH ISA bridge created.\n" );
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 304
Quoted 10 lines
hw/xen/xen_pt_graphics.c +8
-0return 0 ; } + +int pci_create_pch (PCIBus *bus) +{ +XenHostPCIDevice hdev; +int r =0 ; + +if (!xen_has_gfx_passthru) { +return -1 ;
If this function ends up being called unconditionally, then this should return 0;
Quoted 19 lines
hw/xen/xen_pt_graphics.c +19
-0+ } + + r =xen_host_pci_device_get (&hdev,0 ,0 ,0x1f ,0 ); +if (r) { +XEN_PT_ERR (NULL ,"Failed to find Intel PCH on host\n" ); + goto err; + } + +if (hdev.vendor_id ==PCI_VENDOR_ID_INTEL ) { + r =create_pch_isa_bridge (bus, &hdev); +if (r) { +XEN_PT_ERR (NULL ,"Failed to create PCH ISA bridge.\n" ); + goto err; + } + } + +xen_host_pci_device_put (&hdev); + +err:
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 333
Quoted 10 lines
hw/xen/xen_pt_graphics.c +10
-0+return r; +} + +/* +* Currently we just pass this physical host bridge for IGD, 00:02.0. +*/ +static int is_igd_passthrough (PCIDevice *pci_dev) +{ +PCIDevice *f = pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]; +if (pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]) {
Isn't the purpose of this function to check that the *current* device is the graphic passthrough device?
In that case, shouldn't it just be:
if (pci_dev) {
Quoted 124 lines
hw/xen/xen_pt_graphics.c +120
-0+XenPCIPassthroughState *s =DO_UPCAST (XenPCIPassthroughState, dev, f); +return (is_vga_passthrough (&s->real_device) + && (s->real_device.vendor_id ==PCI_VENDOR_ID_INTEL )); + }else { +return 0 ; + } +} +void igd_pci_write (PCIDevice *pci_dev,uint32_t config_addr, +uint32_t val,int len) +{ +XenHostPCIDevice dev; +int r; + +/* IGD read/write is through the host bridge. +* ISA bridge is only for detect purpose. In i915 driver it will +* probe ISA bridge to discover the IGD, see comment in i915_drv.c: +* intel_detect_pch(): +* The reason to probe ISA bridge instead of Dev31:Fun0 is to +* make graphics device passthrough work easy for VMM, that only +* need to expose ISA bridge to let driver know the real hardware +* underneath. This is a requirement from virtualization team. +*/ + +assert (pci_dev->devfn ==0x00 ); + +if (!is_igd_passthrough (pci_dev)) { + goto write_default; + } + +switch (config_addr) { +case 0x58 :/* PAVPC Offset */ +break ; +default : +/* Just sets the emulated values. */ + goto write_default; + } + +/* Host write */ + r =xen_host_pci_device_get (&dev,0 ,0 ,0 ,0 ); +if (r) { +XEN_PT_ERR (pci_dev,"Can't get pci_dev_host_bridge\n" ); +abort (); + } + + r =xen_host_pci_set_block (&dev, config_addr, (uint8_t *)&val, len); +if (r) { +XEN_PT_ERR (pci_dev,"Can't get pci_dev_host_bridge\n" ); +abort (); + } + +xen_host_pci_device_put (&dev); + +return ; + +write_default: +pci_default_write_config (pci_dev, config_addr, val, len); +} + +uint32_t igd_pci_read (PCIDevice *pci_dev,uint32_t config_addr,int len) +{ +XenHostPCIDevice dev; +uint32_t val; +int r; + +/* IGD read/write is through the host bridge. +* ISA bridge is only for detect purpose. In i915 driver it will +* probe ISA bridge to discover the IGD, see comment in i915_drv.c: +* intel_detect_pch(): +* The reason to probe ISA bridge instead of Dev31:Fun0 is to +* make graphics device passthrough work easy for VMM, that only +* need to expose ISA bridge to let driver know the real hardware +* underneath. This is a requirement from virtualization team. +*/ +assert (pci_dev->devfn ==0x00 ); + +if (!is_igd_passthrough (pci_dev)) { + goto read_default; + } + +switch (config_addr) { +case 0x00 :/* vendor id */ +case 0x02 :/* device id */ +case 0x08 :/* revision id */ +case 0x2c :/* sybsystem vendor id */ +case 0x2e :/* sybsystem id */ +case 0x50 :/* SNB: processor graphics control register */ +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 */ +break ; +default : +/* Just gets the emulated values. */ + goto read_default; + } + +/* Host read */ + r =xen_host_pci_device_get (&dev,0 ,0 ,0 ,0 ); +if (r) { + goto err_out; + } + + r =xen_host_pci_get_block (&dev, config_addr, (uint8_t *)&val, len); +if (r) { + goto err_out; + } + +xen_host_pci_device_put (&dev); + +return val; + +read_default: +return pci_default_read_config (pci_dev, config_addr, len); + +err_out: +XEN_PT_ERR (pci_dev,"Can't get pci_dev_host_bridge\n" ); +return -1 ; +}Signature · 1 line
1.9.1
Re: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-D
Quoted 32 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 2:02 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: Re: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-DQuoted 12 lines · Tiejun Chen
Some registers of Intel IGD are mapped in host bridge, so it needs to passthrough these registers of physical host bridge to guest because emulated host bridge in guest doesn't have these mappings.
The original patch is from Weidong Han < weidong.han @ intel.com >
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]> Cc:Weidong Han<[email protected]>
---
v3:Quoted 5 lines
* Improve comments to make that readable.
v2:
* To introduce
is_igd_passthrough()to make sure we touch physical hostbridge
Quoted 2 lines
only in IGD case.
[snip]
Quoted 10 lines
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 304
Quoted 7 lines
hw/xen/xen_pt_graphics.c +7
-0+int pci_create_pch (PCIBus *bus) +{ +XenHostPCIDevice hdev; +int r =0 ; + +if (!xen_has_gfx_passthru) { +return -1 ;If this function ends up being called unconditionally, then this should return 0;
Fixed.
Quoted 24 lines
Quoted 24 lines
hw/xen/xen_pt_graphics.c +23
-0+ } + + r =xen_host_pci_device_get (&hdev,0 ,0 ,0x1f ,0 ); +if (r) { +XEN_PT_ERR (NULL ,"Failed to find Intel PCH on host\n" ); + goto err; + } + +if (hdev.vendor_id ==PCI_VENDOR_ID_INTEL ) { + r =create_pch_isa_bridge (bus, &hdev); +if (r) { +XEN_PT_ERR (NULL ,"Failed to create PCH ISA bridge.\n" ); + goto err; + } + } + +xen_host_pci_device_put (&hdev); + +err: +return r; +} + +/*
Quoted 8 lines
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 333
Quoted 5 lines
+ * Currently we just pass this physical host bridge for IGD, 00:02.0.
+ */hw/xen/xen_pt_graphics.c +3
-0+static int is_igd_passthrough (PCIDevice *pci_dev) { +PCIDevice *f = pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]; +if (pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]) {Isn't the purpose of this function to check that the *current* device is the graphic passthrough device?
No.
Quoted 4 lines
In that case, shouldn't it just be:
if (
pci_dev) {
Here pci_dev is just that host bridge, so here we have to get that real passthrough device by that given devfn to further confirm.
Thanks
Tiejun
Re: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-D
Quoted 81 lines · Tiejun
Quoted 32 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 2:02 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: Re: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-DQuoted 12 lines · Tiejun Chen
Some registers of Intel IGD are mapped in host bridge, so it needs to passthrough these registers of physical host bridge to guest because emulated host bridge in guest doesn't have these mappings.
The original patch is from Weidong Han < weidong.han @ intel.com >
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]> Cc:Weidong Han<[email protected]>
---
v3:Quoted 5 lines
* Improve comments to make that readable.
v2:
* To introduce
is_igd_passthrough()to make sure we touch physical hostbridge
Quoted 2 lines
only in IGD case.
[snip]
Quoted 10 lines
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 304
Quoted 7 lines
hw/xen/xen_pt_graphics.c +7
-0+int pci_create_pch (PCIBus *bus) +{ +XenHostPCIDevice hdev; +int r =0 ; + +if (!xen_has_gfx_passthru) { +return -1 ;If this function ends up being called unconditionally, then this should return 0;
Fixed.
Quoted 24 lines
Quoted 24 lines
hw/xen/xen_pt_graphics.c +23
-0+ } + + r =xen_host_pci_device_get (&hdev,0 ,0 ,0x1f ,0 ); +if (r) { +XEN_PT_ERR (NULL ,"Failed to find Intel PCH on host\n" ); + goto err; + } + +if (hdev.vendor_id ==PCI_VENDOR_ID_INTEL ) { + r =create_pch_isa_bridge (bus, &hdev); +if (r) { +XEN_PT_ERR (NULL ,"Failed to create PCH ISA bridge.\n" ); + goto err; + } + } + +xen_host_pci_device_put (&hdev); + +err: +return r; +} + +/* Quoted 8 lines
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 333
Quoted 5 lines
+ * Currently we just pass this physical host bridge for IGD, 00:02.0.
+ */hw/xen/xen_pt_graphics.c +3
-0+static int is_igd_passthrough (PCIDevice *pci_dev) { +PCIDevice *f = pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]; +if (pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]) {Isn't the purpose of this function to check that the *current* device is the graphic passthrough device?
Quoted 8 lines
No.
Quoted 4 lines
In that case, shouldn't it just be:
if (
pci_dev) {Here
pci_devis just that host bridge, so here we have to get that real passthrough device by that given devfn to further confirm.
I understand now, thanks for the explanation. Maybe you want to expand the comment on top of is_igd_passthrough.
Cheers,
Stefano
Re: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-D
Quoted 11 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 8:30 PM
To: Chen, Tiejun
Cc: Stefano Stabellini; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: RE: [v3][PATCH 3/5] xen, gfx passthrough: support Intel IGD passthrough with VT-D
[snip]
Quoted 14 lines
Quoted 14 lines
Quoted 9 lines
hw/xen/xen_pt_graphics.c static int create_pch_isa_bridge(PCIBus *bus, XenHostPCIDevice *hdev) · line 333
Quoted 6 lines
hw/xen/xen_pt_graphics.c +6
-0+/* +* Currently we just pass this physical host bridge for IGD, 00:02.0. +*/ +static int is_igd_passthrough (PCIDevice *pci_dev) { +PCIDevice *f = pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]; +if (pci_dev->bus->devices[PCI_DEVFN (2 ,0 )]) {Isn't the purpose of this function to check that the *current* device is the graphic passthrough device?
No.
Quoted 2 lines
In that case, shouldn't it just be:
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
if (
pci_dev) {Here
pci_devis just that host bridge, so here we have to get that realpassthrough device by that given devfn to further confirm.
I understand now, thanks for the explanation. Maybe you want to expand the comment on top of
is_igd_passthrough.
Sure, its easy to do :)
Thanks
Tiejun
PATCH v3 4/5 xen, gfx passthrough: create host bridge to passthrough
In reply to Tiejun ChenImplement that pci host bridge to specific to passthrough. Actually thsi just inherit the standard one.
---
v3:
* Just fix this patch head description typo.
v2:
* New patch.
hw/pci-host/piix.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-)
hw/pci-host/piix.c +54 -2
@@ -34,6 +34,7 @@#include "sysemu/sysemu.h" #include "hw/i386/ioapic.h" #include "qapi/visitor.h" +#include "hw/xen/xen_pt.h" /* * I440FX chipset data sheet.
@@ -95,6 +96,10 @@ typedef struct PIIX3State {#define I440FX_PCI_DEVICE (obj) \ OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) +#define TYPE_I440FX_XEN_PCI_DEVICE "i440FX-xen" +#define I440FX_XEN_PCI_DEVICE (obj) \ + OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_XEN_PCI_DEVICE) +struct PCII440FXState {/*< private >*/ PCIDevice parent_obj;
@@ -305,6 +310,16 @@ static int i440fx_initfn(PCIDevice *dev)return 0 ; } +static int i440fx_xen_initfn (PCIDevice *dev) +{ +PCII440FXState *d =I440FX_XEN_PCI_DEVICE (dev); + + dev->config[I440FX_SMRAM ] =0x02 ; + +cpu_smm_register (&i440fx_set_smm, d); +return 0 ; +} + PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, ISABus **isa_bus, qemu_irq *pic,
@@ -333,8 +348,15 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,object_property_add_child (qdev_get_machine (),"i440fx" ,OBJECT (dev),NULL );qdev_init_nofail (dev); - d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); - *pi440fx_state =I440FX_PCI_DEVICE (d); +if (xen_enabled ()) { + d =pci_create_simple (b,0 ,TYPE_I440FX_XEN_PCI_DEVICE ); + *pi440fx_state =I440FX_XEN_PCI_DEVICE (d); +pci_create_pch (b); + }else { + d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); + *pi440fx_state =I440FX_PCI_DEVICE (d); + } + f = *pi440fx_state; f->system_memory = address_space_mem; f->pci_address_space = pci_address_space;
@@ -705,6 +727,35 @@ static const TypeInfo i440fx_info = { .class_init = i440fx_class_init, }; +static void i440fx_xen_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->init = i440fx_xen_initfn; + k->config_write = igd_pci_write; + k->config_read = igd_pci_read; + k->vendor_id =PCI_VENDOR_ID_INTEL ; + k->device_id =PCI_DEVICE_ID_INTEL_82441 ; + k->revision =0x02 ; + k->class_id =PCI_CLASS_BRIDGE_ISA ; + dc->desc ="XEN Host bridge" ; + dc->vmsd = &vmstate_i440fx; +/* +* PCI-facing part of the host bridge, not usable without the +* host-facing part, which can't be device_add'ed, yet. +*/ + dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; +} + +static const TypeInfo i440fx_xen_info = { + .name =TYPE_I440FX_XEN_PCI_DEVICE , + .parent =TYPE_PCI_DEVICE , + .instance_size =sizeof (PCII440FXState), + .class_init = i440fx_xen_class_init, +}; +static const char *i440fx_pcihost_root_bus_path (PCIHostState *host_bridge,PCIBus *rootbus) {
@@ -746,6 +797,7 @@ static const TypeInfo i440fx_pcihost_info = {static void i440fx_register_types (void ) {type_register_static (&i440fx_info); +type_register_static (&i440fx_xen_info);type_register_static (&piix3_info);type_register_static (&piix3_xen_info);type_register_static (&i440fx_pcihost_info);
Signature · 1 line
1.9.1
Re: [Xen-devel] [v3][PATCH 4/5] xen, gfx passthrough: create host bridge to passthrough
Quoted 2 lines · Tiejun Chen
Implement that pci host bridge to specific to passthrough. Actually thsi just inherit the standard one.
s/thsi/this
Quoted 124 lines
Signed-off-by Tiejun Chen <[email protected]>---
v3:* Just fix this patch head description typo.
v2:
* New patch.
hw/pci-host/piix.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-)hw/pci-host/piix.c +54
-2@@ -34,6 +34,7 @@#include "sysemu/sysemu.h" #include "hw/i386/ioapic.h" #include "qapi/visitor.h" +#include "hw/xen/xen_pt.h" /* * I440FX chipset data sheet. @@ -95,6 +96,10 @@ typedef struct PIIX3State {#define I440FX_PCI_DEVICE (obj) \ OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) +#define TYPE_I440FX_XEN_PCI_DEVICE "i440FX-xen" +#define I440FX_XEN_PCI_DEVICE (obj) \ + OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_XEN_PCI_DEVICE) +struct PCII440FXState {/*< private >*/ PCIDevice parent_obj;@@ -305,6 +310,16 @@ static int i440fx_initfn(PCIDevice *dev)return 0 ; } +static int i440fx_xen_initfn (PCIDevice *dev) +{ +PCII440FXState *d =I440FX_XEN_PCI_DEVICE (dev); + + dev->config[I440FX_SMRAM ] =0x02 ; + +cpu_smm_register (&i440fx_set_smm, d); +return 0 ; +} + PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, ISABus **isa_bus, qemu_irq *pic,@@ -333,8 +348,15 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,object_property_add_child (qdev_get_machine (),"i440fx" ,OBJECT (dev),NULL );qdev_init_nofail (dev); - d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); - *pi440fx_state =I440FX_PCI_DEVICE (d); +if (xen_enabled ()) { + d =pci_create_simple (b,0 ,TYPE_I440FX_XEN_PCI_DEVICE ); + *pi440fx_state =I440FX_XEN_PCI_DEVICE (d); +pci_create_pch (b); + }else { + d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); + *pi440fx_state =I440FX_PCI_DEVICE (d); + } + f = *pi440fx_state; f->system_memory = address_space_mem; f->pci_address_space = pci_address_space;@@ -705,6 +727,35 @@ static const TypeInfo i440fx_info = { .class_init = i440fx_class_init, }; +static void i440fx_xen_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->init = i440fx_xen_initfn; + k->config_write = igd_pci_write; + k->config_read = igd_pci_read; + k->vendor_id =PCI_VENDOR_ID_INTEL ; + k->device_id =PCI_DEVICE_ID_INTEL_82441 ; + k->revision =0x02 ; + k->class_id =PCI_CLASS_BRIDGE_ISA ; + dc->desc ="XEN Host bridge" ; + dc->vmsd = &vmstate_i440fx; +/* +* PCI-facing part of the host bridge, not usable without the +* host-facing part, which can't be device_add'ed, yet. +*/ + dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; +} + +static const TypeInfo i440fx_xen_info = { + .name =TYPE_I440FX_XEN_PCI_DEVICE , + .parent =TYPE_PCI_DEVICE , + .instance_size =sizeof (PCII440FXState), + .class_init = i440fx_xen_class_init, +}; +static const char *i440fx_pcihost_root_bus_path (PCIHostState *host_bridge,PCIBus *rootbus) {@@ -746,6 +797,7 @@ static const TypeInfo i440fx_pcihost_info = {static void i440fx_register_types (void ) {type_register_static (&i440fx_info); +type_register_static (&i440fx_xen_info);type_register_static (&piix3_info);type_register_static (&piix3_xen_info);type_register_static (&i440fx_pcihost_info);Signature · 7 lines
1.9.1 _______________________________________________ Xen-devel mailing list [email protected] http://lists.xen.org/xen-devel
Re: [Xen-devel] [v3][PATCH 4/5] xen, gfx passthrough: create host bridge to passthrough
Quoted 11 lines
-----Original Message-----
From: Konrad Rzeszutek Wilk [mailto:[email protected]]
Sent: Tuesday, May 27, 2014 10:48 PM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; [email protected]; [email protected]; Zhang, Yang Z
Subject: Re: [Xen-devel] [v3][PATCH 4/5] xen, gfx passthrough: create host bridge to passthrough
Quoted 6 lines
Quoted 2 lines · Tiejun Chen
Implement that pci host bridge to specific to passthrough. Actually thsi just inherit the standard one.
s/thsi/this
Fixed.
Thanks
Tiejun
Re: [v3][PATCH 4/5] xen, gfx passthrough: create host bridge to passthrough
In reply to Tiejun ChenQuoted 57 lines · Tiejun Chen
Implement that pci host bridge to specific to passthrough. Actually thsi just inherit the standard one.
Signed-off-by Tiejun Chen <[email protected]>---
v3:* Just fix this patch head description typo.
v2:
* New patch.
hw/pci-host/piix.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-)hw/pci-host/piix.c +15
-0@@ -34,6 +34,7 @@#include "sysemu/sysemu.h" #include "hw/i386/ioapic.h" #include "qapi/visitor.h" +#include "hw/xen/xen_pt.h" /* * I440FX chipset data sheet. @@ -95,6 +96,10 @@ typedef struct PIIX3State {#define I440FX_PCI_DEVICE (obj) \ OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE) +#define TYPE_I440FX_XEN_PCI_DEVICE "i440FX-xen" +#define I440FX_XEN_PCI_DEVICE (obj) \ + OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_XEN_PCI_DEVICE) +struct PCII440FXState {/*< private >*/ PCIDevice parent_obj;@@ -305,6 +310,16 @@ static int i440fx_initfn(PCIDevice *dev)return 0 ; } +static int i440fx_xen_initfn (PCIDevice *dev) +{ +PCII440FXState *d =I440FX_XEN_PCI_DEVICE (dev); + + dev->config[I440FX_SMRAM ] =0x02 ; + +cpu_smm_register (&i440fx_set_smm, d); +return 0 ; +} + PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, ISABus **isa_bus, qemu_irq *pic,
hw/pci-host/piix.c PCIBus *i440fx_init(PCII440FXState **pi440fx_state, · line 351
Quoted 6 lines
hw/pci-host/piix.c +1
-2@@ -333,8 +348,15 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,object_property_add_child (qdev_get_machine (),"i440fx" ,OBJECT (dev),NULL );qdev_init_nofail (dev); - d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); - *pi440fx_state =I440FX_PCI_DEVICE (d); +if (xen_enabled ()) {
if (xen_enabled() && xen_has_gfx_passthru) ?
Quoted 58 lines
hw/pci-host/piix.c +38
-0+ d =pci_create_simple (b,0 ,TYPE_I440FX_XEN_PCI_DEVICE ); + *pi440fx_state =I440FX_XEN_PCI_DEVICE (d); +pci_create_pch (b); + }else { + d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); + *pi440fx_state =I440FX_PCI_DEVICE (d); + } + f = *pi440fx_state; f->system_memory = address_space_mem; f->pci_address_space = pci_address_space;@@ -705,6 +727,35 @@ static const TypeInfo i440fx_info = { .class_init = i440fx_class_init, }; +static void i440fx_xen_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +PCIDeviceClass *k =PCI_DEVICE_CLASS (klass); + + k->init = i440fx_xen_initfn; + k->config_write = igd_pci_write; + k->config_read = igd_pci_read; + k->vendor_id =PCI_VENDOR_ID_INTEL ; + k->device_id =PCI_DEVICE_ID_INTEL_82441 ; + k->revision =0x02 ; + k->class_id =PCI_CLASS_BRIDGE_ISA ; + dc->desc ="XEN Host bridge" ; + dc->vmsd = &vmstate_i440fx; +/* +* PCI-facing part of the host bridge, not usable without the +* host-facing part, which can't be device_add'ed, yet. +*/ + dc->cannot_instantiate_with_device_add_yet = true; + dc->hotpluggable = false; +} + +static const TypeInfo i440fx_xen_info = { + .name =TYPE_I440FX_XEN_PCI_DEVICE , + .parent =TYPE_PCI_DEVICE , + .instance_size =sizeof (PCII440FXState), + .class_init = i440fx_xen_class_init, +}; +static const char *i440fx_pcihost_root_bus_path (PCIHostState *host_bridge,PCIBus *rootbus) {@@ -746,6 +797,7 @@ static const TypeInfo i440fx_pcihost_info = {static void i440fx_register_types (void ) {type_register_static (&i440fx_info); +type_register_static (&i440fx_xen_info);type_register_static (&piix3_info);type_register_static (&piix3_xen_info);type_register_static (&i440fx_pcihost_info);Signature · 1 line
1.9.1
Re: [v3][PATCH 4/5] xen, gfx passthrough: create host bridge to passthrough
Quoted 27 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Stefano Stabellini
Sent: Wednesday, May 28, 2014 2:05 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; [email protected]; [email protected]; Zhang, Yang Z; [email protected]; [email protected]
Subject: Re: [Qemu-devel] [v3][PATCH 4/5] xen, gfx passthrough: create host bridge to passthroughQuoted 13 lines · Tiejun Chen
Implement that pci host bridge to specific to passthrough. Actually thsi just inherit the standard one.
Signed-off-by Tiejun Chen <[email protected]>---
v3:* Just fix this patch head description typo.
v2:
* New patch.
[snip]
Quoted 5 lines
Quoted 5 lines
PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
int *piix3_devfn, ISABus **isa_bus, qemu_irq *pic, @@ -333,8 +348,15 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, object_property_add_child(qdev_get_machine(), "i440fx",
Quoted 9 lines
OBJECT(dev), NULL);
hw/pci-host/piix.c PCIBus *i440fx_init(PCII440FXState **pi440fx_state, · line 351
Quoted 5 lines
qdev_init_nofail(dev);hw/pci-host/piix.c +1
-2- d =pci_create_simple (b,0 ,TYPE_I440FX_PCI_DEVICE ); - *pi440fx_state =I440FX_PCI_DEVICE (d); +if (xen_enabled ()) {if (
xen_enabled()&&xen_has_gfx_passthru) ?
Fine.
Thanks
Tiejun
PATCH v3 5/5 xen, gfx passthrough: add opregion mapping
In reply to Tiejun ChenThe OpRegion shouldn't be mapped 1:1 because the address in the host can't be used in the guest directly.
This patch traps read and write access to the opregion of the Intel GPU config space (offset 0xfc).
The original patch is from Jean Guyader <[email protected]>
---
v3:
* Fix some typos.
* Add more comments to make that readable.
* To unmap igd_opregion when call xen_pt_unregister_vga_regions().
* Improve some return paths.
* We need to map 3 pages for opregion as hvmloader set.
* Force to convert igd_guest/host_opoegion as an unsigned long type while calling xc_domain_memory_mapping().
v2:
* We should return zero as an invalid address value while calling igd_read_opregion().
hw/xen/xen_pt.h | 4 ++- hw/xen/xen_pt_config_init.c | 50 ++++++++++++++++++++++++++++++++++- hw/xen/xen_pt_graphics.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-)
hw/xen/xen_pt.h +3 -1
@@ -63,7 +63,7 @@ typedef int (*xen_pt_conf_byte_read)#define XEN_PT_BAR_UNMAPPED (-1)#define PCI_CAP_MAX 48 - +#define PCI_INTEL_OPREGION 0xfc typedef enum { XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */
@@ -306,5 +306,7 @@ int pci_create_pch(PCIBus *bus);void igd_pci_write (PCIDevice *pci_dev,uint32_t config_addr,uint32_t val,int len);uint32_t igd_pci_read (PCIDevice *pci_dev,uint32_t config_addr,int len); +uint32_t igd_read_opregion (XenPCIPassthroughState *s); +void igd_write_opregion (XenPCIPassthroughState *s,uint32_t val);#endif /* !XEN_PT_H */
hw/xen/xen_pt_config_init.c +49 -1
80 lines not on this page · raw message
hw/xen/xen_pt_graphics.c +64 -0
85 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mapping
Quoted 183 lines · Tiejun Chen
The OpRegion shouldn't be mapped 1:1 because the address in the host can't be used in the guest directly.
This patch traps read and write access to the opregion of the Intel GPU config space (offset
0xfc).The original patch is from Jean Guyader <[email protected]>
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Jean Guyader <[email protected]>---
v3:* Fix some typos.
* Add more comments to make that readable.
* To unmapigd_opregionwhen callxen_pt_unregister_vga_regions().
* Improve some return paths.
* We need to map 3 pages for opregion as hvmloader set.
* Force to convert igd_guest/host_opoegion as an unsigned long type while callingxc_domain_memory_mapping().v2:
* We should return zero as an invalid address value while calling
igd_read_opregion().hw/xen/xen_pt.h | 4 ++- hw/xen/xen_pt_config_init.c | 50 ++++++++++++++++++++++++++++++++++- hw/xen/xen_pt_graphics.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-)hw/xen/xen_pt.h +3
-1@@ -63,7 +63,7 @@ typedef int (*xen_pt_conf_byte_read)#define XEN_PT_BAR_UNMAPPED (-1)#define PCI_CAP_MAX 48 - +#define PCI_INTEL_OPREGION 0xfc typedef enum { XEN_PT_GRP_TYPE_HARDWIRED = 0, /* 0 Hardwired reg group */@@ -306,5 +306,7 @@ int pci_create_pch(PCIBus *bus);void igd_pci_write (PCIDevice *pci_dev,uint32_t config_addr,uint32_t val,int len);uint32_t igd_pci_read (PCIDevice *pci_dev,uint32_t config_addr,int len); +uint32_t igd_read_opregion (XenPCIPassthroughState *s); +void igd_write_opregion (XenPCIPassthroughState *s,uint32_t val);#endif /* !XEN_PT_H */ hw/xen/xen_pt_config_init.c +49
-1@@ -575,6 +575,22 @@ static int xen_pt_exp_rom_bar_reg_write(XenPCIPassthroughState *s,return 0 ; } +static int xen_pt_intel_opregion_read (XenPCIPassthroughState *s, +XenPTReg *cfg_entry, +uint32_t *value,uint32_t valid_mask) +{ + *value =igd_read_opregion (s); +return 0 ; +} + +static int xen_pt_intel_opregion_write (XenPCIPassthroughState *s, +XenPTReg *cfg_entry,uint32_t *value, +uint32_t dev_value,uint32_t valid_mask) +{ +igd_write_opregion (s, *value); +return 0 ; +} +/* Header Type0 reg static information table */ static XenPTRegInfo xen_pt_emu_reg_header0[] = {/* Vendor ID reg */ @@ -1440,6 +1456,20 @@ static XenPTRegInfo xen_pt_emu_reg_msix[] = { }, }; +static XenPTRegInfo xen_pt_emu_reg_igd_opregion[] = { +/* Intel IGFX OpRegion reg */ + { + .offset =0x0 , + .size =4 , + .init_val =0 , + .no_wb =1 , + .u.dw.read = xen_pt_intel_opregion_read, + .u.dw.write = xen_pt_intel_opregion_write, + }, + { + .size =0 , + }, +};/**************************** * Capabilities @@ -1677,6 +1707,14 @@ static const XenPTRegGroupInfo xen_pt_emu_reg_grps[] = { .size_init = xen_pt_msix_size_init, .emu_regs = xen_pt_emu_reg_msix, }, +/* Intel IGD Opregion group */ + { + .grp_id = PCI_INTEL_OPREGION, + .grp_type = XEN_PT_GRP_TYPE_EMU, + .grp_size = 0x4, + .size_init = xen_pt_reg_grp_size_init, + .emu_regs = xen_pt_emu_reg_igd_opregion, + }, { .grp_size = 0, },@@ -1806,7 +1844,8 @@ int xen_pt_config_init(XenPCIPassthroughState *s)uint32_t reg_grp_offset =0 ;XenPTRegGroup *reg_grp_entry =NULL ; -if (xen_pt_emu_reg_grps[i].grp_id !=0xFF ) { +if (xen_pt_emu_reg_grps[i].grp_id !=0xFF + && xen_pt_emu_reg_grps[i].grp_id !=PCI_INTEL_OPREGION ) {if (xen_pt_hide_dev_cap (&s->real_device, xen_pt_emu_reg_grps[i].grp_id)) {continue ;@@ -1819,6 +1858,15 @@ int xen_pt_config_init(XenPCIPassthroughState *s) } } +/* +* By default we will trap up to 0x40 in the cfg space. +* If an intel device is pass through we need to trap 0xfc, +* therefore the size should be 0xff. +*/ +if (xen_pt_emu_reg_grps[i].grp_id ==PCI_INTEL_OPREGION ) { + reg_grp_offset =PCI_INTEL_OPREGION ; + } + reg_grp_entry =g_new0 (XenPTRegGroup,1 );QLIST_INIT (®_grp_entry->reg_tbl_list);QLIST_INSERT_HEAD (&s->reg_grps, reg_grp_entry, entries);hw/xen/xen_pt_graphics.c +15
-0@@ -6,6 +6,9 @@#include "hw/xen/xen_backend.h" #include "hw/pci/pci_bus.h" +static unsigned long igd_guest_opregion; +static unsigned long igd_host_opregion; +static int is_vga_passthrough (XenHostPCIDevice *dev) { return (xen_has_gfx_passthru@@ -88,6 +91,7 @@ int xen_pt_register_vga_regions(XenHostPCIDevice *dev)int xen_pt_unregister_vga_regions (XenHostPCIDevice *dev) {int i =0 ; +int ret =0 ;if (!is_vga_passthrough (dev)) {return -1 ;@@ -114,6 +118,17 @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev) } } +if (igd_guest_opregion) { + ret =xc_domain_memory_mapping (xen_xc, xen_domid, + (unsigned long )(igd_guest_opregion >>XC_PAGE_SHIFT ), + (unsigned long )(igd_host_opregion >>XC_PAGE_SHIFT ), +3 , +DPCI_REMOVE_MAPPING ); +if (ret) { +return ret; + } + } +return 0 ; }
hw/xen/xen_pt_graphics.c err_out: · line 476
Quoted 10 lines
hw/xen/xen_pt_graphics.c +7
-0@@ -452,3 +467,52 @@ err_out:XEN_PT_ERR (pci_dev,"Can't get pci_dev_host_bridge\n" );return -1 ; } + +uint32_t igd_read_opregion (XenPCIPassthroughState *s) +{ +uint32_t val =0 ; + +if (igd_guest_opregion ==0 ) { +return val;
Sorry for not having spotted it before, but isn't this supposed to return an error? The old code returns -1 in this case.
Quoted 17 lines
hw/xen/xen_pt_graphics.c +17
-0+ } + + val = igd_guest_opregion; + +XEN_PT_LOG (&s->dev,"Read opregion val=%x\n" , val); +return val; +} + +void igd_write_opregion (XenPCIPassthroughState *s,uint32_t val) +{ +int ret; + +if (igd_guest_opregion) { +XEN_PT_LOG (&s->dev,"opregion register already been set, ignoring %x\n" , + val); +return ; + }
hw/xen/xen_pt_graphics.c err_out: · line 503
Quoted 10 lines
hw/xen/xen_pt_graphics.c +10
-0+ +xen_host_pci_get_block (&s->real_device,PCI_INTEL_OPREGION , + (uint8_t *)&igd_host_opregion,4 ); + igd_guest_opregion = (unsigned long )(val & ~0xfff ) + | (igd_host_opregion &0xfff ); + + ret = xc_domain_memory_mapping(xen_xc, xen_domid, + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT), + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT), + 3,
Why 3 pages instead of 2?
Quoted 18 lines
hw/xen/xen_pt_graphics.c +15
-0+ DPCI_ADD_MAPPING); + +if (ret) { +XEN_PT_ERR (&s->dev,"[%d]:Can't map IGD host opregion:0x%lx to" +" guest opregion:0x%lx.\n" , ret, + (unsigned long )(igd_host_opregion >>XC_PAGE_SHIFT ), + (unsigned long )(igd_guest_opregion >>XC_PAGE_SHIFT )); + igd_guest_opregion =0 ; +return ; + } + +XEN_PT_LOG (&s->dev,"Map OpRegion: 0x%lx -> 0x%lx\n" , + (unsigned long )(igd_host_opregion >>XC_PAGE_SHIFT ), + (unsigned long )(igd_guest_opregion >>XC_PAGE_SHIFT )); +}Signature · 1 line
1.9.1
Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mapping
Quoted 38 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 1:36 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mappingQuoted 27 lines · Tiejun Chen
The OpRegion shouldn't be mapped 1:1 because the address in the host can't be used in the guest directly.
This patch traps read and write access to the opregion of the Intel GPU config space (offset
0xfc).The original patch is from Jean Guyader <[email protected]>
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Jean Guyader <[email protected]>---
v3:* Fix some typos.
* Add more comments to make that readable.
* To unmapigd_opregionwhen callxen_pt_unregister_vga_regions().
* Improve some return paths.
* We need to map 3 pages for opregion as hvmloader set.
* Force to convert igd_guest/host_opoegion as an unsigned long type while callingxc_domain_memory_mapping().v2:
* We should return zero as an invalid address value while calling
igd_read_opregion().
[snip]
Quoted 9 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ +uint32_t igd_read_opregion(XenPCIPassthroughState *s) { + uint32_t val = 0; + + if (igd_guest_opregion == 0) { + return val;Sorry for not having spotted it before, but isn't this supposed to return an error? The old code returns -1 in this case.
I already commented this in v2 log above.
We shouldn't return "-1" to indicate an invalid address since we often think "!0" is a valid address value.
In Linux instance,
drivers/gpu/drm/i915/intel_opregion.c:
int intel_opregion_setup(struct drm_device *dev)
{
...
pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
if (asls == 0) {
DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
return -ENOTSUPP;
}
...Quoted 16 lines
Quoted 5 lines
(quoted diff) +3
-0+ } + + val = igd_guest_opregion;Review
Quoted 10 lines
(quoted diff) +10
-0+ + XEN_PT_LOG(&s->dev, "Read opregion val=%x\n", val); + return val; +} + +void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val) { + int ret; + + if (igd_guest_opregion) { + XEN_PT_LOG(&s->dev, "opregion register already been set,ignoring %x\n",
Quoted 15 lines
Review
Quoted 13 lines
(quoted diff) +13
-0+ val); + return; + } + + xen_host_pci_get_block(&s->real_device, PCI_INTEL_OPREGION, + (uint8_t *)&igd_host_opregion, 4); + igd_guest_opregion = (unsigned long)(val & ~0xfff) + | (igd_host_opregion & 0xfff); + + ret = xc_domain_memory_mapping(xen_xc, xen_domid, + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT), + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT), + 3,Why 3 pages instead of 2?
commit 408a9e56343b006c9e58a334f0b97dd2deedf9ac
Author: Keir Fraser <[email protected]> Date: Thu Jan 10 17:26:24 2013 +0000
hvmloader: Allocate 3 pages for Intel GPU OpRegion passthrough.
The 8kB region may not be page aligned, hence requiring 3 pages to be mapped through.
tools/firmware/hvmloader/config.h +2 -0
@@ -5,7 +5,9 @@enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt };extern enum virtual_vga virtual_vga; +extern unsigned long igd_opregion_pgbase; +#define IGD_OPREGION_PAGES 3
...
Thanks
Tiejun
Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mapping
Quoted 60 lines · Tiejun
Quoted 38 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 1:36 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mappingQuoted 27 lines · Tiejun Chen
The OpRegion shouldn't be mapped 1:1 because the address in the host can't be used in the guest directly.
This patch traps read and write access to the opregion of the Intel GPU config space (offset
0xfc).The original patch is from Jean Guyader <[email protected]>
Signed-off-by Yang Zhang <[email protected]>Signed-off-by Tiejun Chen <[email protected]>Cc Jean Guyader <[email protected]>---
v3:* Fix some typos.
* Add more comments to make that readable.
* To unmapigd_opregionwhen callxen_pt_unregister_vga_regions().
* Improve some return paths.
* We need to map 3 pages for opregion as hvmloader set.
* Force to convert igd_guest/host_opoegion as an unsigned long type while callingxc_domain_memory_mapping().v2:
* We should return zero as an invalid address value while calling
igd_read_opregion().[snip]
Quoted 9 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ +uint32_t igd_read_opregion(XenPCIPassthroughState *s) { + uint32_t val = 0; + + if (igd_guest_opregion == 0) { + return val;Sorry for not having spotted it before, but isn't this supposed to return an error? The old code returns -1 in this case.
I already commented this in v2 log above.
We shouldn't return "-1" to indicate an invalid address since we often think "!0" is a valid address value.
In Linux instance,
drivers/gpu/drm/i915/intel_opregion.c:int
intel_opregion_setup(struct drm_device *dev)
Quoted 9 lines
{
...
pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
if (asls == 0) {
DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
return -ENOTSUPP;
}
...Ops, you are right! igd_read_opregion returns an address not an error code.
In that case, given that xen_pt_intel_opregion_read can return an error code as well as an address, maybe it makes sense to do the same in igd_read_opregion and allow the function to return an error code and set the value by pointer.
Quoted 16 lines
Quoted 16 lines
Quoted 5 lines
(quoted diff) +3
-0+ } + + val = igd_guest_opregion;Review
Quoted 10 lines
(quoted diff) +10
-0+ + XEN_PT_LOG(&s->dev, "Read opregion val=%x\n", val); + return val; +} + +void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val) { + int ret; + + if (igd_guest_opregion) { + XEN_PT_LOG(&s->dev, "opregion register already been set,ignoring %x\n",
Quoted 15 lines
Quoted 7 lines
Quoted 7 lines
(quoted diff) +7
-0+ val); + return; + } + + xen_host_pci_get_block(&s->real_device, PCI_INTEL_OPREGION, + (uint8_t *)&igd_host_opregion, 4); + igd_guest_opregion = (unsigned long)(val & ~0xfff)Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ | (igd_host_opregion & 0xfff); + + ret = xc_domain_memory_mapping(xen_xc, xen_domid, + (unsigned long)(igd_guest_opregion >> XC_PAGE_SHIFT), + (unsigned long)(igd_host_opregion >> XC_PAGE_SHIFT), + 3,Why 3 pages instead of 2?
Thanks.
Quoted 23 lines
commit
408a9e56343b006c9e58a334f0b97dd2deedf9acAuthor: Keir Fraser <[email protected]> Date: Thu Jan 10 17:26:24 2013 +0000hvmloader: Allocate 3 pages for Intel GPU OpRegion passthrough.
The 8kB region may not be page aligned, hence requiring 3 pages to be mapped through.
Signed-off-by Keir Fraser <[email protected]>tools/firmware/hvmloader/config.h +2
-0@@ -5,7 +5,9 @@enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt };extern enum virtual_vga virtual_vga; +extern unsigned long igd_opregion_pgbase; +#define IGD_OPREGION_PAGES 3
Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mapping
Quoted 22 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 8:24 PM
To: Chen, Tiejun
Cc: Stefano Stabellini; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: RE: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mappingQuoted 11 lines · Tiejun
Quoted 11 lines
-----Original Message-----
From: Stefano Stabellini [mailto:[email protected]]
Sent: Wednesday, May 28, 2014 1:36 AM
To: Chen, Tiejun
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Kay, Allen M; Zhang, Yang Z
Subject: Re: [v3][PATCH 5/5] xen, gfx passthrough: add opregion mapping
[snip]
Quoted 30 lines
Quoted 8 lines
Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +6
-0+ +uint32_t igd_read_opregion(XenPCIPassthroughState *s) { + uint32_t val = 0; + + if (igd_guest_opregion == 0) { + return val;Sorry for not having spotted it before, but isn't this supposed to return an
error?
Quoted 5 lines
Quoted 1 line
The old code returns -1 in this case.
I already commented this in v2 log above.
We shouldn't return "-1" to indicate an invalid address since we often think
"!0" is a valid address value.
Quoted 5 lines
In Linux instance,
drivers/gpu/drm/i915/intel_opregion.c:Quoted 9 lines
int intel_opregion_setup(struct drm_device *dev) { ... pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls); if (asls == 0) { DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n"); return -ENOTSUPP; } ...
Quoted 6 lines
Ops, you are right!
igd_read_opregionreturns an address not an error code. In that case, given thatxen_pt_intel_opregion_readcan return an error code as well as an address, maybe it makes sense to do the same inigd_read_opregionand allow the function to return an error code and set the value by pointer.
I don't think so.
As I understand, we does check if that return value is valid, but not check if this read behavior is good. This pci read transmit should be guaranteed by the hardware, and this should be transparent to driver.
In qemu emulator, qemu should do this check on behavior of the hardware so we need an error code when use xen_pt_intel_oprerion() as a wrapper of igd_read_opregion(). But that return value we're talking about should be delivered directly if this pci read behavior is fine.
But even if this read is failed, we should do something in pci host controller of qemu to further emulate this issue. But as emulator, I think qemu often never do this thing just specific to a normal pci read if you have no any obvious reason.
Thanks
Tiejun
Any further comments?
Thanks
Tiejun
Quoted 80 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Tiejun Chen
Sent: Monday, May 26, 2014 5:43 PM
To: [email protected]; [email protected]; [email protected]; [email protected]
Cc: [email protected]; [email protected]; Kay, Allen M; [email protected]; [email protected]; Zhang, Yang Z
Subject: [Qemu-devel] [v3][PATCH 0/5] xen: add Intel IGD passthrough supportv3:
* In this case, as we discussed we will give priority to devices to reserve a specific devfn by passing "
device_model_args_hvm= ['-device', 'xen-platform,addr=0x3']" and "vga=none", so withdraw patch #1, #2 and #4.
* Fix some typos.
* Add more comments to make that readable.
* To unmapigd_opregionwhen callxen_pt_unregister_vga_regions().
* Improve some return paths.
* Force to convert igd_guest/host_opoegion as an unsigned long type while callingxc_domain_memory_mapping().
* We need to map 3 pages for opregion as hvmloader set.v2:
* rebase on current qemu tree.
* retrieve VGA bios from sysfs properly.
* redefine some function name.
* introduce bitmap to manage registe/runregister pci dev, and provide a common way to reserve some specific devfn.
* introduceis_igd_passthrough()to make sure we touch physical host bridge only in IGD case.
* We should return zero as an invalid address value while callingigd_read_opregion().Additionally, now its also not necessary to recompile seabios with some extra steps like v1.
The following patches are ported partially from Xen Qemu-traditional branch which are adding Intel IGD passthrough supporting to Qemu upstream.
To pass through IGD to guest, user need to add following lines in Xen config file:
gfx_passthru=1
pci=['00:02.0 <at> 2']Now successfully boot Ubuntu 14.04 guests with IGD assigned in Haswell desktop with Latest Xen + Qemu upstream.
----------------------------------------------------------------
Tiejun Chen (2):
xen, gfx passthrough: create intel isa bridge xen, gfx passthrough: create host bridge to passthroughYang Zhang (3):
xen, gfx passthrough: basic graphics passthrough support xen, gfx passthrough: support Intel IGD passthrough with VT-D xen, gfx passthrough: add opregion mappinghw/pci-host/piix.c | 56 +++++++++++++- hw/xen/Makefile.objs | 2 +- hw/xen/xen-host-pci-device.c | 5 ++ hw/xen/xen-host-pci-device.h | 1 + hw/xen/xen_pt.c | 10 +++ hw/xen/xen_pt.h | 12 ++- hw/xen/xen_pt_config_init.c | 50 ++++++++++++- hw/xen/xen_pt_graphics.c | 518 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++ qemu-options.hx | 9 +++ vl.c | 11 ++- 10 files changed, 668 insertions(+), 6 deletions(-) create mode 100644
hw/xen/xen_pt_graphics.cThanks
Tiejun