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