]> Git Repo - qemu.git/blob - hw/xen_platform.c
vga: rename isa_vga_init() to isa_std_vga_init()
[qemu.git] / hw / xen_platform.c
1 /*
2  * XEN platform pci device, formerly known as the event channel device
3  *
4  * Copyright (c) 2003-2004 Intel Corp.
5  * Copyright (c) 2006 XenSource
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25
26 #include <assert.h>
27
28 #include "hw.h"
29 #include "pc.h"
30 #include "pci.h"
31 #include "irq.h"
32 #include "xen_common.h"
33 #include "net.h"
34 #include "xen_backend.h"
35 #include "trace.h"
36 #include "exec-memory.h"
37
38 #include <xenguest.h>
39
40 //#define DEBUG_PLATFORM
41
42 #ifdef DEBUG_PLATFORM
43 #define DPRINTF(fmt, ...) do { \
44     fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \
45 } while (0)
46 #else
47 #define DPRINTF(fmt, ...) do { } while (0)
48 #endif
49
50 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */
51
52 typedef struct PCIXenPlatformState {
53     PCIDevice  pci_dev;
54     MemoryRegion fixed_io;
55     MemoryRegion bar;
56     MemoryRegion mmio_bar;
57     uint8_t flags; /* used only for version_id == 2 */
58     int drivers_blacklisted;
59     uint16_t driver_product_version;
60
61     /* Log from guest drivers */
62     char log_buffer[4096];
63     int log_buffer_off;
64 } PCIXenPlatformState;
65
66 #define XEN_PLATFORM_IOPORT 0x10
67
68 /* Send bytes to syslog */
69 static void log_writeb(PCIXenPlatformState *s, char val)
70 {
71     if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) {
72         /* Flush buffer */
73         s->log_buffer[s->log_buffer_off] = 0;
74         trace_xen_platform_log(s->log_buffer);
75         s->log_buffer_off = 0;
76     } else {
77         s->log_buffer[s->log_buffer_off++] = val;
78     }
79 }
80
81 /* Xen Platform, Fixed IOPort */
82 #define UNPLUG_ALL_IDE_DISKS 1
83 #define UNPLUG_ALL_NICS 2
84 #define UNPLUG_AUX_IDE_DISKS 4
85
86 static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
87 {
88     /* We have to ignore passthrough devices */
89     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
90             PCI_CLASS_NETWORK_ETHERNET
91             && strcmp(d->name, "xen-pci-passthrough") != 0) {
92         qdev_free(&d->qdev);
93     }
94 }
95
96 static void pci_unplug_nics(PCIBus *bus)
97 {
98     pci_for_each_device(bus, 0, unplug_nic, NULL);
99 }
100
101 static void unplug_disks(PCIBus *b, PCIDevice *d, void *o)
102 {
103     /* We have to ignore passthrough devices */
104     if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
105             PCI_CLASS_STORAGE_IDE
106             && strcmp(d->name, "xen-pci-passthrough") != 0) {
107         qdev_unplug(&(d->qdev), NULL);
108     }
109 }
110
111 static void pci_unplug_disks(PCIBus *bus)
112 {
113     pci_for_each_device(bus, 0, unplug_disks, NULL);
114 }
115
116 static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
117 {
118     PCIXenPlatformState *s = opaque;
119
120     switch (addr) {
121     case 0:
122         /* Unplug devices.  Value is a bitmask of which devices to
123            unplug, with bit 0 the IDE devices, bit 1 the network
124            devices, and bit 2 the non-primary-master IDE devices. */
125         if (val & UNPLUG_ALL_IDE_DISKS) {
126             DPRINTF("unplug disks\n");
127             bdrv_drain_all();
128             bdrv_flush_all();
129             pci_unplug_disks(s->pci_dev.bus);
130         }
131         if (val & UNPLUG_ALL_NICS) {
132             DPRINTF("unplug nics\n");
133             pci_unplug_nics(s->pci_dev.bus);
134         }
135         if (val & UNPLUG_AUX_IDE_DISKS) {
136             DPRINTF("unplug auxiliary disks not supported\n");
137         }
138         break;
139     case 2:
140         switch (val) {
141         case 1:
142             DPRINTF("Citrix Windows PV drivers loaded in guest\n");
143             break;
144         case 0:
145             DPRINTF("Guest claimed to be running PV product 0?\n");
146             break;
147         default:
148             DPRINTF("Unknown PV product %d loaded in guest\n", val);
149             break;
150         }
151         s->driver_product_version = val;
152         break;
153     }
154 }
155
156 static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
157                                          uint32_t val)
158 {
159     switch (addr) {
160     case 0:
161         /* PV driver version */
162         break;
163     }
164 }
165
166 static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
167 {
168     PCIXenPlatformState *s = opaque;
169
170     switch (addr) {
171     case 0: /* Platform flags */ {
172         hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
173             HVMMEM_ram_ro : HVMMEM_ram_rw;
174         if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) {
175             DPRINTF("unable to change ro/rw state of ROM memory area!\n");
176         } else {
177             s->flags = val & PFFLAG_ROM_LOCK;
178             DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
179                     (mem_type == HVMMEM_ram_ro ? "ro":"rw"));
180         }
181         break;
182     }
183     case 2:
184         log_writeb(s, val);
185         break;
186     }
187 }
188
189 static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
190 {
191     PCIXenPlatformState *s = opaque;
192
193     switch (addr) {
194     case 0:
195         if (s->drivers_blacklisted) {
196             /* The drivers will recognise this magic number and refuse
197              * to do anything. */
198             return 0xd249;
199         } else {
200             /* Magic value so that you can identify the interface. */
201             return 0x49d2;
202         }
203     default:
204         return 0xffff;
205     }
206 }
207
208 static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
209 {
210     PCIXenPlatformState *s = opaque;
211
212     switch (addr) {
213     case 0:
214         /* Platform flags */
215         return s->flags;
216     case 2:
217         /* Version number */
218         return 1;
219     default:
220         return 0xff;
221     }
222 }
223
224 static void platform_fixed_ioport_reset(void *opaque)
225 {
226     PCIXenPlatformState *s = opaque;
227
228     platform_fixed_ioport_writeb(s, 0, 0);
229 }
230
231 const MemoryRegionPortio xen_platform_ioport[] = {
232     { 0, 16, 4, .write = platform_fixed_ioport_writel, },
233     { 0, 16, 2, .write = platform_fixed_ioport_writew, },
234     { 0, 16, 1, .write = platform_fixed_ioport_writeb, },
235     { 0, 16, 2, .read = platform_fixed_ioport_readw, },
236     { 0, 16, 1, .read = platform_fixed_ioport_readb, },
237     PORTIO_END_OF_LIST()
238 };
239
240 static const MemoryRegionOps platform_fixed_io_ops = {
241     .old_portio = xen_platform_ioport,
242     .endianness = DEVICE_NATIVE_ENDIAN,
243 };
244
245 static void platform_fixed_ioport_init(PCIXenPlatformState* s)
246 {
247     memory_region_init_io(&s->fixed_io, &platform_fixed_io_ops, s,
248                           "xen-fixed", 16);
249     memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT,
250                                 &s->fixed_io);
251 }
252
253 /* Xen Platform PCI Device */
254
255 static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
256 {
257     if (addr == 0) {
258         return platform_fixed_ioport_readb(opaque, 0);
259     } else {
260         return ~0u;
261     }
262 }
263
264 static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
265 {
266     PCIXenPlatformState *s = opaque;
267
268     switch (addr) {
269     case 0: /* Platform flags */
270         platform_fixed_ioport_writeb(opaque, 0, val);
271         break;
272     case 8:
273         log_writeb(s, val);
274         break;
275     default:
276         break;
277     }
278 }
279
280 static MemoryRegionPortio xen_pci_portio[] = {
281     { 0, 0x100, 1, .read = xen_platform_ioport_readb, },
282     { 0, 0x100, 1, .write = xen_platform_ioport_writeb, },
283     PORTIO_END_OF_LIST()
284 };
285
286 static const MemoryRegionOps xen_pci_io_ops = {
287     .old_portio = xen_pci_portio,
288 };
289
290 static void platform_ioport_bar_setup(PCIXenPlatformState *d)
291 {
292     memory_region_init_io(&d->bar, &xen_pci_io_ops, d, "xen-pci", 0x100);
293 }
294
295 static uint64_t platform_mmio_read(void *opaque, target_phys_addr_t addr,
296                                    unsigned size)
297 {
298     DPRINTF("Warning: attempted read from physical address "
299             "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr);
300
301     return 0;
302 }
303
304 static void platform_mmio_write(void *opaque, target_phys_addr_t addr,
305                                 uint64_t val, unsigned size)
306 {
307     DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical "
308             "address 0x" TARGET_FMT_plx " in xen platform mmio space\n",
309             val, addr);
310 }
311
312 static const MemoryRegionOps platform_mmio_handler = {
313     .read = &platform_mmio_read,
314     .write = &platform_mmio_write,
315     .endianness = DEVICE_NATIVE_ENDIAN,
316 };
317
318 static void platform_mmio_setup(PCIXenPlatformState *d)
319 {
320     memory_region_init_io(&d->mmio_bar, &platform_mmio_handler, d,
321                           "xen-mmio", 0x1000000);
322 }
323
324 static int xen_platform_post_load(void *opaque, int version_id)
325 {
326     PCIXenPlatformState *s = opaque;
327
328     platform_fixed_ioport_writeb(s, 0, s->flags);
329
330     return 0;
331 }
332
333 static const VMStateDescription vmstate_xen_platform = {
334     .name = "platform",
335     .version_id = 4,
336     .minimum_version_id = 4,
337     .minimum_version_id_old = 4,
338     .post_load = xen_platform_post_load,
339     .fields = (VMStateField []) {
340         VMSTATE_PCI_DEVICE(pci_dev, PCIXenPlatformState),
341         VMSTATE_UINT8(flags, PCIXenPlatformState),
342         VMSTATE_END_OF_LIST()
343     }
344 };
345
346 static int xen_platform_initfn(PCIDevice *dev)
347 {
348     PCIXenPlatformState *d = DO_UPCAST(PCIXenPlatformState, pci_dev, dev);
349     uint8_t *pci_conf;
350
351     pci_conf = d->pci_dev.config;
352
353     pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
354
355     pci_config_set_prog_interface(pci_conf, 0);
356
357     pci_conf[PCI_INTERRUPT_PIN] = 1;
358
359     platform_ioport_bar_setup(d);
360     pci_register_bar(&d->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar);
361
362     /* reserve 16MB mmio address for share memory*/
363     platform_mmio_setup(d);
364     pci_register_bar(&d->pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
365                      &d->mmio_bar);
366
367     platform_fixed_ioport_init(d);
368
369     return 0;
370 }
371
372 static void platform_reset(DeviceState *dev)
373 {
374     PCIXenPlatformState *s = DO_UPCAST(PCIXenPlatformState, pci_dev.qdev, dev);
375
376     platform_fixed_ioport_reset(s);
377 }
378
379 static void xen_platform_class_init(ObjectClass *klass, void *data)
380 {
381     DeviceClass *dc = DEVICE_CLASS(klass);
382     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
383
384     k->init = xen_platform_initfn;
385     k->vendor_id = PCI_VENDOR_ID_XEN;
386     k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
387     k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;
388     k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
389     k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
390     k->revision = 1;
391     dc->desc = "XEN platform pci device";
392     dc->reset = platform_reset;
393     dc->vmsd = &vmstate_xen_platform;
394 }
395
396 static TypeInfo xen_platform_info = {
397     .name          = "xen-platform",
398     .parent        = TYPE_PCI_DEVICE,
399     .instance_size = sizeof(PCIXenPlatformState),
400     .class_init    = xen_platform_class_init,
401 };
402
403 static void xen_platform_register_types(void)
404 {
405     type_register_static(&xen_platform_info);
406 }
407
408 type_init(xen_platform_register_types)
This page took 0.046403 seconds and 4 git commands to generate.