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 "qemu/osdep.h" 27 #include "qapi/error.h" 28 #include "hw/hw.h" 29 #include "hw/i386/pc.h" 30 #include "hw/ide.h" 31 #include "hw/pci/pci.h" 32 #include "hw/irq.h" 33 #include "hw/xen/xen_common.h" 34 #include "hw/xen/xen_backend.h" 35 #include "trace.h" 36 #include "exec/address-spaces.h" 37 #include "sysemu/block-backend.h" 38 #include "qemu/error-report.h" 39 40 #include <xenguest.h> 41 42 //#define DEBUG_PLATFORM 43 44 #ifdef DEBUG_PLATFORM 45 #define DPRINTF(fmt, ...) do { \ 46 fprintf(stderr, "xen_platform: " fmt, ## __VA_ARGS__); \ 47 } while (0) 48 #else 49 #define DPRINTF(fmt, ...) do { } while (0) 50 #endif 51 52 #define PFFLAG_ROM_LOCK 1 /* Sets whether ROM memory area is RW or RO */ 53 54 typedef struct PCIXenPlatformState { 55 /*< private >*/ 56 PCIDevice parent_obj; 57 /*< public >*/ 58 59 MemoryRegion fixed_io; 60 MemoryRegion bar; 61 MemoryRegion mmio_bar; 62 uint8_t flags; /* used only for version_id == 2 */ 63 int drivers_blacklisted; 64 uint16_t driver_product_version; 65 66 /* Log from guest drivers */ 67 char log_buffer[4096]; 68 int log_buffer_off; 69 } PCIXenPlatformState; 70 71 #define TYPE_XEN_PLATFORM "xen-platform" 72 #define XEN_PLATFORM(obj) \ 73 OBJECT_CHECK(PCIXenPlatformState, (obj), TYPE_XEN_PLATFORM) 74 75 #define XEN_PLATFORM_IOPORT 0x10 76 77 /* Send bytes to syslog */ 78 static void log_writeb(PCIXenPlatformState *s, char val) 79 { 80 if (val == '\n' || s->log_buffer_off == sizeof(s->log_buffer) - 1) { 81 /* Flush buffer */ 82 s->log_buffer[s->log_buffer_off] = 0; 83 trace_xen_platform_log(s->log_buffer); 84 s->log_buffer_off = 0; 85 } else { 86 s->log_buffer[s->log_buffer_off++] = val; 87 } 88 } 89 90 /* Xen Platform, Fixed IOPort */ 91 #define UNPLUG_ALL_DISKS 1 92 #define UNPLUG_ALL_NICS 2 93 #define UNPLUG_AUX_IDE_DISKS 4 94 95 static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) 96 { 97 /* We have to ignore passthrough devices */ 98 if (pci_get_word(d->config + PCI_CLASS_DEVICE) == 99 PCI_CLASS_NETWORK_ETHERNET 100 && strcmp(d->name, "xen-pci-passthrough") != 0) { 101 object_unparent(OBJECT(d)); 102 } 103 } 104 105 static void pci_unplug_nics(PCIBus *bus) 106 { 107 pci_for_each_device(bus, 0, unplug_nic, NULL); 108 } 109 110 static void unplug_disks(PCIBus *b, PCIDevice *d, void *opaque) 111 { 112 uint32_t flags = *(uint32_t *)opaque; 113 bool aux = (flags & UNPLUG_AUX_IDE_DISKS) && 114 !(flags & UNPLUG_ALL_DISKS); 115 116 /* We have to ignore passthrough devices */ 117 if (!strcmp(d->name, "xen-pci-passthrough")) { 118 return; 119 } 120 121 switch (pci_get_word(d->config + PCI_CLASS_DEVICE)) { 122 case PCI_CLASS_STORAGE_IDE: 123 pci_piix3_xen_ide_unplug(DEVICE(d), aux); 124 break; 125 126 case PCI_CLASS_STORAGE_SCSI: 127 case PCI_CLASS_STORAGE_EXPRESS: 128 if (!aux) { 129 object_unparent(OBJECT(d)); 130 } 131 break; 132 133 default: 134 break; 135 } 136 } 137 138 static void pci_unplug_disks(PCIBus *bus, uint32_t flags) 139 { 140 pci_for_each_device(bus, 0, unplug_disks, &flags); 141 } 142 143 static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t val) 144 { 145 PCIXenPlatformState *s = opaque; 146 147 switch (addr) { 148 case 0: { 149 PCIDevice *pci_dev = PCI_DEVICE(s); 150 /* Unplug devices. Value is a bitmask of which devices to 151 unplug, with bit 0 the disk devices, bit 1 the network 152 devices, and bit 2 the non-primary-master IDE devices. */ 153 if (val & (UNPLUG_ALL_DISKS | UNPLUG_AUX_IDE_DISKS)) { 154 DPRINTF("unplug disks\n"); 155 pci_unplug_disks(pci_dev->bus, val); 156 } 157 if (val & UNPLUG_ALL_NICS) { 158 DPRINTF("unplug nics\n"); 159 pci_unplug_nics(pci_dev->bus); 160 } 161 break; 162 } 163 case 2: 164 switch (val) { 165 case 1: 166 DPRINTF("Citrix Windows PV drivers loaded in guest\n"); 167 break; 168 case 0: 169 DPRINTF("Guest claimed to be running PV product 0?\n"); 170 break; 171 default: 172 DPRINTF("Unknown PV product %d loaded in guest\n", val); 173 break; 174 } 175 s->driver_product_version = val; 176 break; 177 } 178 } 179 180 static void platform_fixed_ioport_writel(void *opaque, uint32_t addr, 181 uint32_t val) 182 { 183 switch (addr) { 184 case 0: 185 /* PV driver version */ 186 break; 187 } 188 } 189 190 static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t val) 191 { 192 PCIXenPlatformState *s = opaque; 193 194 switch (addr) { 195 case 0: /* Platform flags */ { 196 hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ? 197 HVMMEM_ram_ro : HVMMEM_ram_rw; 198 if (xc_hvm_set_mem_type(xen_xc, xen_domid, mem_type, 0xc0, 0x40)) { 199 DPRINTF("unable to change ro/rw state of ROM memory area!\n"); 200 } else { 201 s->flags = val & PFFLAG_ROM_LOCK; 202 DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n", 203 (mem_type == HVMMEM_ram_ro ? "ro":"rw")); 204 } 205 break; 206 } 207 case 2: 208 log_writeb(s, val); 209 break; 210 } 211 } 212 213 static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr) 214 { 215 PCIXenPlatformState *s = opaque; 216 217 switch (addr) { 218 case 0: 219 if (s->drivers_blacklisted) { 220 /* The drivers will recognise this magic number and refuse 221 * to do anything. */ 222 return 0xd249; 223 } else { 224 /* Magic value so that you can identify the interface. */ 225 return 0x49d2; 226 } 227 default: 228 return 0xffff; 229 } 230 } 231 232 static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr) 233 { 234 PCIXenPlatformState *s = opaque; 235 236 switch (addr) { 237 case 0: 238 /* Platform flags */ 239 return s->flags; 240 case 2: 241 /* Version number */ 242 return 1; 243 default: 244 return 0xff; 245 } 246 } 247 248 static void platform_fixed_ioport_reset(void *opaque) 249 { 250 PCIXenPlatformState *s = opaque; 251 252 platform_fixed_ioport_writeb(s, 0, 0); 253 } 254 255 static uint64_t platform_fixed_ioport_read(void *opaque, 256 hwaddr addr, 257 unsigned size) 258 { 259 switch (size) { 260 case 1: 261 return platform_fixed_ioport_readb(opaque, addr); 262 case 2: 263 return platform_fixed_ioport_readw(opaque, addr); 264 default: 265 return -1; 266 } 267 } 268 269 static void platform_fixed_ioport_write(void *opaque, hwaddr addr, 270 271 uint64_t val, unsigned size) 272 { 273 switch (size) { 274 case 1: 275 platform_fixed_ioport_writeb(opaque, addr, val); 276 break; 277 case 2: 278 platform_fixed_ioport_writew(opaque, addr, val); 279 break; 280 case 4: 281 platform_fixed_ioport_writel(opaque, addr, val); 282 break; 283 } 284 } 285 286 287 static const MemoryRegionOps platform_fixed_io_ops = { 288 .read = platform_fixed_ioport_read, 289 .write = platform_fixed_ioport_write, 290 .valid = { 291 .unaligned = true, 292 }, 293 .impl = { 294 .min_access_size = 1, 295 .max_access_size = 4, 296 .unaligned = true, 297 }, 298 .endianness = DEVICE_LITTLE_ENDIAN, 299 }; 300 301 static void platform_fixed_ioport_init(PCIXenPlatformState* s) 302 { 303 memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s, 304 "xen-fixed", 16); 305 memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT, 306 &s->fixed_io); 307 } 308 309 /* Xen Platform PCI Device */ 310 311 static uint64_t xen_platform_ioport_readb(void *opaque, hwaddr addr, 312 unsigned int size) 313 { 314 if (addr == 0) { 315 return platform_fixed_ioport_readb(opaque, 0); 316 } else { 317 return ~0u; 318 } 319 } 320 321 static void xen_platform_ioport_writeb(void *opaque, hwaddr addr, 322 uint64_t val, unsigned int size) 323 { 324 PCIXenPlatformState *s = opaque; 325 PCIDevice *pci_dev = PCI_DEVICE(s); 326 327 switch (addr) { 328 case 0: /* Platform flags */ 329 platform_fixed_ioport_writeb(opaque, 0, (uint32_t)val); 330 break; 331 case 4: 332 if (val == 1) { 333 /* 334 * SUSE unplug for Xenlinux 335 * xen-kmp used this since xen-3.0.4, instead the official protocol 336 * from xen-3.3+ It did an unconditional "outl(1, (ioaddr + 4));" 337 * Pre VMDP 1.7 used 4 and 8 depending on how VMDP was configured. 338 * If VMDP was to control both disk and LAN it would use 4. 339 * If it controlled just disk or just LAN, it would use 8 below. 340 */ 341 pci_unplug_disks(pci_dev->bus, UNPLUG_ALL_DISKS); 342 pci_unplug_nics(pci_dev->bus); 343 } 344 break; 345 case 8: 346 switch (val) { 347 case 1: 348 pci_unplug_disks(pci_dev->bus, UNPLUG_ALL_DISKS); 349 break; 350 case 2: 351 pci_unplug_nics(pci_dev->bus); 352 break; 353 default: 354 log_writeb(s, (uint32_t)val); 355 break; 356 } 357 break; 358 default: 359 break; 360 } 361 } 362 363 static const MemoryRegionOps xen_pci_io_ops = { 364 .read = xen_platform_ioport_readb, 365 .write = xen_platform_ioport_writeb, 366 .impl.min_access_size = 1, 367 .impl.max_access_size = 1, 368 }; 369 370 static void platform_ioport_bar_setup(PCIXenPlatformState *d) 371 { 372 memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d, 373 "xen-pci", 0x100); 374 } 375 376 static uint64_t platform_mmio_read(void *opaque, hwaddr addr, 377 unsigned size) 378 { 379 DPRINTF("Warning: attempted read from physical address " 380 "0x" TARGET_FMT_plx " in xen platform mmio space\n", addr); 381 382 return 0; 383 } 384 385 static void platform_mmio_write(void *opaque, hwaddr addr, 386 uint64_t val, unsigned size) 387 { 388 DPRINTF("Warning: attempted write of 0x%"PRIx64" to physical " 389 "address 0x" TARGET_FMT_plx " in xen platform mmio space\n", 390 val, addr); 391 } 392 393 static const MemoryRegionOps platform_mmio_handler = { 394 .read = &platform_mmio_read, 395 .write = &platform_mmio_write, 396 .endianness = DEVICE_NATIVE_ENDIAN, 397 }; 398 399 static void platform_mmio_setup(PCIXenPlatformState *d) 400 { 401 memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d, 402 "xen-mmio", 0x1000000); 403 } 404 405 static int xen_platform_post_load(void *opaque, int version_id) 406 { 407 PCIXenPlatformState *s = opaque; 408 409 platform_fixed_ioport_writeb(s, 0, s->flags); 410 411 return 0; 412 } 413 414 static const VMStateDescription vmstate_xen_platform = { 415 .name = "platform", 416 .version_id = 4, 417 .minimum_version_id = 4, 418 .post_load = xen_platform_post_load, 419 .fields = (VMStateField[]) { 420 VMSTATE_PCI_DEVICE(parent_obj, PCIXenPlatformState), 421 VMSTATE_UINT8(flags, PCIXenPlatformState), 422 VMSTATE_END_OF_LIST() 423 } 424 }; 425 426 static void xen_platform_realize(PCIDevice *dev, Error **errp) 427 { 428 PCIXenPlatformState *d = XEN_PLATFORM(dev); 429 uint8_t *pci_conf; 430 431 /* Device will crash on reset if xen is not initialized */ 432 if (!xen_enabled()) { 433 error_setg(errp, "xen-platform device requires the Xen accelerator"); 434 return; 435 } 436 437 pci_conf = dev->config; 438 439 pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); 440 441 pci_config_set_prog_interface(pci_conf, 0); 442 443 pci_conf[PCI_INTERRUPT_PIN] = 1; 444 445 platform_ioport_bar_setup(d); 446 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->bar); 447 448 /* reserve 16MB mmio address for share memory*/ 449 platform_mmio_setup(d); 450 pci_register_bar(dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, 451 &d->mmio_bar); 452 453 platform_fixed_ioport_init(d); 454 } 455 456 static void platform_reset(DeviceState *dev) 457 { 458 PCIXenPlatformState *s = XEN_PLATFORM(dev); 459 460 platform_fixed_ioport_reset(s); 461 } 462 463 static void xen_platform_class_init(ObjectClass *klass, void *data) 464 { 465 DeviceClass *dc = DEVICE_CLASS(klass); 466 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 467 468 k->realize = xen_platform_realize; 469 k->vendor_id = PCI_VENDOR_ID_XEN; 470 k->device_id = PCI_DEVICE_ID_XEN_PLATFORM; 471 k->class_id = PCI_CLASS_OTHERS << 8 | 0x80; 472 k->subsystem_vendor_id = PCI_VENDOR_ID_XEN; 473 k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM; 474 k->revision = 1; 475 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 476 dc->desc = "XEN platform pci device"; 477 dc->reset = platform_reset; 478 dc->vmsd = &vmstate_xen_platform; 479 } 480 481 static const TypeInfo xen_platform_info = { 482 .name = TYPE_XEN_PLATFORM, 483 .parent = TYPE_PCI_DEVICE, 484 .instance_size = sizeof(PCIXenPlatformState), 485 .class_init = xen_platform_class_init, 486 }; 487 488 static void xen_platform_register_types(void) 489 { 490 type_register_static(&xen_platform_info); 491 } 492 493 type_init(xen_platform_register_types) 494