1 diff --git a/hw/pass-through.c b/hw/pass-through.c
2 index 6a53137..3420e95 100644
3 --- a/hw/pass-through.c
4 +++ b/hw/pass-through.c
9 +extern int vga_passthrough;
12 struct pt_dev *pt_dev;
14 @@ -1573,10 +1575,11 @@ static int pt_dev_is_virtfn(struct pci_dev *dev)
16 static int pt_register_regions(struct pt_dev *assigned_device)
20 uint32_t bar_data = 0;
21 struct pci_dev *pci_dev = assigned_device->pci_dev;
22 PCIDevice *d = &assigned_device->dev;
23 + uint16_t vendor_id, class;
25 /* Register PIO/MMIO BARs */
26 for ( i = 0; i < PCI_BAR_ENTRIES; i++ )
27 @@ -1632,6 +1635,28 @@ static int pt_register_regions(struct pt_dev *assigned_device)
28 (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr));
31 + /* Map legacy ioport and iomem, for specific devices */
32 + vendor_id = pci_read_word(pci_dev, 0x00);
33 + class = pci_read_word(pci_dev, 0x0a);
35 + PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class);
36 + if ( vga_passthrough && class == 0x0300 )
38 + PT_LOG("add an intel graphic card\n");
40 + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb,
42 + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32,
44 + ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32,
48 + PT_LOG("legacy mapping failed !\n");
56 @@ -1640,6 +1665,7 @@ static void pt_unregister_regions(struct pt_dev *assigned_device)
59 PCIDevice *d = (PCIDevice*)assigned_device;
60 + uint16_t class, vendor_id;
62 for ( i = 0; i < PCI_NUM_REGIONS; i++ )
64 @@ -1681,6 +1707,26 @@ static void pt_unregister_regions(struct pt_dev *assigned_device)
68 + /* unmap legacy ioport and iomem, for specific devices */
69 + vendor_id = pci_read_word(assigned_device->pci_dev, 0x00);
70 + class = pci_read_word(assigned_device->pci_dev, 0x0a);
72 + PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class);
73 + if ( vga_passthrough && class == 0x0300 )
75 + PT_LOG("remove an intel graphic card\n");
77 + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb,
78 + DPCI_REMOVE_MAPPING);
79 + ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32,
80 + DPCI_REMOVE_MAPPING);
81 + ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32,
82 + DPCI_REMOVE_MAPPING);
85 + PT_LOG("legacy unmapping failed !\n");
90 static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
91 @@ -4084,3 +4130,41 @@ err:
95 +u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr)
97 + struct pci_dev* pci_dev;
100 + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
103 + val = pci_read_byte(pci_dev, addr);
104 + pci_free_dev(pci_dev);
108 +u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr)
110 + struct pci_dev* pci_dev;
113 + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
116 + val = pci_read_word(pci_dev, addr);
117 + pci_free_dev(pci_dev);
121 +u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr)
123 + struct pci_dev* pci_dev;
126 + pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
129 + val = pci_read_long(pci_dev, addr);
130 + pci_free_dev(pci_dev);
133 diff --git a/hw/pass-through.h b/hw/pass-through.h
134 index a503e80..1752e8d 100644
135 --- a/hw/pass-through.h
136 +++ b/hw/pass-through.h
137 @@ -392,5 +392,9 @@ static inline pciaddr_t pt_pci_base_addr(pciaddr_t base)
138 return base & PCI_ADDR_MEM_MASK;
141 +u8 pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr);
142 +u16 pt_pci_host_read_word(int bus, int dev, int fn, u32 addr);
143 +u32 pt_pci_host_read_long(int bus, int dev, int fn, u32 addr);
145 #endif /* __PASSTHROUGH_H__ */
147 diff --git a/hw/pci.c b/hw/pci.c
148 index d7c516e..b2f4d43 100644
152 #include "virtio-net.h"
155 +#include "pass-through.h"
156 #include "exec-all.h"
157 #include "qemu-xen.h"
161 +extern int vga_passthrough;
166 @@ -611,7 +614,30 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
169 config_addr = addr & 0xff;
170 - val = pci_dev->config_read(pci_dev, config_addr, len);
171 + if (vga_passthrough && pci_dev->devfn == 0x00) //Host Bridge
173 + val = pci_dev->config_read(pci_dev, config_addr, len);
175 + if (config_addr == 0x52) // GMCH
176 + val = pt_pci_host_read_word(0, 0, 0, 0x52);
177 + if (config_addr == 0x02) // Device ID
180 + val = pt_pci_host_read_word(0, 0, 0, 0x02);
182 + if (config_addr == 0x0)
185 + val = pt_pci_host_read_word(0, 0, 0, 0x00);
187 + val = pt_pci_host_read_long(0, 0, 0, 0x00);
190 + else if (vga_passthrough && pci_dev->devfn == 0x10 && // intel graphic card
191 + config_addr == 0xfc) // OpRegion address
192 + val = 0; // force to fall back to SMI mode
194 + val = pci_dev->config_read(pci_dev, config_addr, len);
195 #if defined(DEBUG_PCI)
196 printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
197 pci_dev->name, config_addr, val, len);
198 diff --git a/vl.c b/vl.c
199 index b273c75..e519705 100644
202 @@ -233,6 +233,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
204 int win2k_install_hack = 0;
206 +int vga_passthrough = 0;
210 @@ -4275,6 +4276,7 @@ enum {
211 QEMU_OPTION_domainname,
214 + QEMU_OPTION_vga_passthrough,
216 /* Debug/Expert options: */
218 @@ -4448,6 +4450,7 @@ static const QEMUOption qemu_options[] = {
219 { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
220 { "vncunused", 0, QEMU_OPTION_vncunused },
221 { "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
222 + { "vga-passthrough", 0, QEMU_OPTION_vga_passthrough },
223 #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
224 { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
225 { "xen-create", 0, QEMU_OPTION_xen_create },
226 @@ -5281,6 +5284,9 @@ int main(int argc, char **argv, char **envp)
227 case QEMU_OPTION_disable_opengl:
230 + case QEMU_OPTION_vga_passthrough:
231 + vga_passthrough = 1;
233 case QEMU_OPTION_direct_pci: