kbd-led: Add missing include file.
[xenclient/ioemu-pq.git] / master / vga-passthrough
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
5 @@ -90,6 +90,8 @@
6  #include "qemu-xen.h"
7  #include <unistd.h>
8  
9 +extern int vga_passthrough;
10 +
11  struct php_dev {
12      struct pt_dev *pt_dev;
13      uint8_t valid;
14 @@ -1573,10 +1575,11 @@ static int pt_dev_is_virtfn(struct pci_dev *dev)
15  
16  static int pt_register_regions(struct pt_dev *assigned_device)
17  {
18 -    int i = 0;
19 +    int i = 0, ret = 0;
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;
24  
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));
29      }
30  
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);
34 +
35 +    PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class);
36 +    if ( vga_passthrough && class == 0x0300 )
37 +    {
38 +        PT_LOG("add an intel graphic card\n");
39 +
40 +        ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3B0, 0x3B0, 0xb,
41 +                                      DPCI_ADD_MAPPING);
42 +        ret = xc_domain_ioport_mapping(xc_handle, domid, 0x3C0, 0x3C0, 32,
43 +                                      DPCI_ADD_MAPPING);
44 +        ret |= xc_domain_memory_mapping(xc_handle, domid, 0xa0, 0xa0, 32,
45 +                                       DPCI_ADD_MAPPING);
46 +        if ( ret != 0 )
47 +        {
48 +            PT_LOG("legacy mapping failed !\n");
49 +            return ret;
50 +        }
51 +    }
52 +
53      return 0;
54  }
55  
56 @@ -1640,6 +1665,7 @@ static void pt_unregister_regions(struct pt_dev *assigned_device)
57      int i, type, ret;
58      uint32_t e_size;
59      PCIDevice *d = (PCIDevice*)assigned_device;
60 +    uint16_t class, vendor_id;
61  
62      for ( i = 0; i < PCI_NUM_REGIONS; i++ )
63      {
64 @@ -1681,6 +1707,26 @@ static void pt_unregister_regions(struct pt_dev *assigned_device)
65  
66      }
67  
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);
71 +
72 +    PT_LOG("Real device vendor_id=0x%x class=0x%x\n", vendor_id, class);
73 +    if ( vga_passthrough && class == 0x0300 )
74 +    {
75 +        PT_LOG("remove an intel graphic card\n");
76 +
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);
83 +        if ( ret != 0 )
84 +        {
85 +            PT_LOG("legacy unmapping failed !\n");
86 +        }
87 +    }
88  }
89  
90  static uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
91 @@ -4084,3 +4130,41 @@ err:
92      return status;
93  }
94  
95 +u8      pt_pci_host_read_byte(int bus, int dev, int fn, u32 addr)
96 +{
97 +    struct pci_dev*     pci_dev;
98 +    u8                  val;
99 +
100 +    pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
101 +    if (!pci_dev)
102 +        return 0;
103 +    val = pci_read_byte(pci_dev, addr);
104 +    pci_free_dev(pci_dev);
105 +    return val;
106 +}
107 +
108 +u16     pt_pci_host_read_word(int bus, int dev, int fn, u32 addr)
109 +{
110 +    struct pci_dev*     pci_dev;
111 +    u16                 val;
112 +
113 +    pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
114 +    if (!pci_dev)
115 +        return 0;
116 +    val = pci_read_word(pci_dev, addr);
117 +    pci_free_dev(pci_dev);
118 +    return val;
119 +}
120 +
121 +u32     pt_pci_host_read_long(int bus, int dev, int fn, u32 addr)
122 +{
123 +    struct pci_dev*     pci_dev;
124 +    u32                 val;
125 +
126 +    pci_dev = pci_get_dev(dpci_infos.pci_access, 0, bus, dev, fn);
127 +    if (!pci_dev)
128 +        return 0;
129 +    val = pci_read_long(pci_dev, addr);
130 +    pci_free_dev(pci_dev);
131 +    return val;
132 +}
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;
139  }
140  
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);
144 +
145  #endif /* __PASSTHROUGH_H__ */
146  
147 diff --git a/hw/pci.c b/hw/pci.c
148 index d7c516e..b2f4d43 100644
149 --- a/hw/pci.c
150 +++ b/hw/pci.c
151 @@ -28,11 +28,14 @@
152  #include "virtio-net.h"
153  #include "sysemu.h"
154  
155 +#include "pass-through.h"
156  #include "exec-all.h"
157  #include "qemu-xen.h"
158  
159  //#define DEBUG_PCI
160  
161 +extern int vga_passthrough;
162 +
163  struct PCIBus {
164      int bus_num;
165      int devfn_min;
166 @@ -611,7 +614,30 @@ uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
167          goto the_end;
168      }
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
172 +    {
173 +       val = pci_dev->config_read(pci_dev, config_addr, len);
174 +
175 +        if (config_addr == 0x52) // GMCH
176 +            val = pt_pci_host_read_word(0, 0, 0, 0x52);
177 +        if (config_addr == 0x02) // Device ID
178 +       {
179 +           if (len == 2)
180 +               val = pt_pci_host_read_word(0, 0, 0, 0x02);
181 +       }
182 +       if (config_addr == 0x0)
183 +       {
184 +           if (len == 2)
185 +               val = pt_pci_host_read_word(0, 0, 0, 0x00);
186 +           else if (len == 4)
187 +               val = pt_pci_host_read_long(0, 0, 0, 0x00);
188 +       }
189 +    }
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
193 +    else
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
200 --- a/vl.c
201 +++ b/vl.c
202 @@ -233,6 +233,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
203  #ifdef TARGET_I386
204  int win2k_install_hack = 0;
205  int rtc_td_hack = 0;
206 +int vga_passthrough = 0;
207  #endif
208  int usb_enabled = 0;
209  int smp_cpus = 1;
210 @@ -4275,6 +4276,7 @@ enum {
211      QEMU_OPTION_domainname,
212      QEMU_OPTION_acpi,
213      QEMU_OPTION_vcpus,
214 +    QEMU_OPTION_vga_passthrough,
215  
216      /* Debug/Expert options: */
217      QEMU_OPTION_serial,
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:
228                  opengl_enabled = 0;
229                  break;
230 +            case QEMU_OPTION_vga_passthrough:
231 +                vga_passthrough = 1;
232 +                break;
233              case QEMU_OPTION_direct_pci:
234                 direct_pci = optarg;
235                  break;