1 /* 2 * Inter-VM Shared Memory PCI device. 3 * 4 * Author: 5 * Cam Macdonell <cam@cs.ualberta.ca> 6 * 7 * Based On: cirrus_vga.c 8 * Copyright (c) 2004 Fabrice Bellard 9 * Copyright (c) 2004 Makoto Suzuki (suzu) 10 * 11 * and rtl8139.c 12 * Copyright (c) 2006 Igor Kovalenko 13 * 14 * This code is licensed under the GNU GPL v2. 15 * 16 * Contributions after 2012-01-13 are licensed under the terms of the 17 * GNU GPL, version 2 or (at your option) any later version. 18 */ 19 #include "hw/hw.h" 20 #include "hw/i386/pc.h" 21 #include "hw/pci/pci.h" 22 #include "hw/pci/msix.h" 23 #include "sysemu/kvm.h" 24 #include "migration/migration.h" 25 #include "qapi/qmp/qerror.h" 26 #include "qemu/event_notifier.h" 27 #include "sysemu/char.h" 28 29 #include <sys/mman.h> 30 #include <sys/types.h> 31 32 #define PCI_VENDOR_ID_IVSHMEM PCI_VENDOR_ID_REDHAT_QUMRANET 33 #define PCI_DEVICE_ID_IVSHMEM 0x1110 34 35 #define IVSHMEM_IOEVENTFD 0 36 #define IVSHMEM_MSI 1 37 38 #define IVSHMEM_PEER 0 39 #define IVSHMEM_MASTER 1 40 41 #define IVSHMEM_REG_BAR_SIZE 0x100 42 43 //#define DEBUG_IVSHMEM 44 #ifdef DEBUG_IVSHMEM 45 #define IVSHMEM_DPRINTF(fmt, ...) \ 46 do {printf("IVSHMEM: " fmt, ## __VA_ARGS__); } while (0) 47 #else 48 #define IVSHMEM_DPRINTF(fmt, ...) 49 #endif 50 51 typedef struct Peer { 52 int nb_eventfds; 53 EventNotifier *eventfds; 54 } Peer; 55 56 typedef struct EventfdEntry { 57 PCIDevice *pdev; 58 int vector; 59 } EventfdEntry; 60 61 typedef struct IVShmemState { 62 PCIDevice dev; 63 uint32_t intrmask; 64 uint32_t intrstatus; 65 uint32_t doorbell; 66 67 CharDriverState **eventfd_chr; 68 CharDriverState *server_chr; 69 MemoryRegion ivshmem_mmio; 70 71 /* We might need to register the BAR before we actually have the memory. 72 * So prepare a container MemoryRegion for the BAR immediately and 73 * add a subregion when we have the memory. 74 */ 75 MemoryRegion bar; 76 MemoryRegion ivshmem; 77 uint64_t ivshmem_size; /* size of shared memory region */ 78 uint32_t ivshmem_attr; 79 uint32_t ivshmem_64bit; 80 int shm_fd; /* shared memory file descriptor */ 81 82 Peer *peers; 83 int nb_peers; /* how many guests we have space for */ 84 int max_peer; /* maximum numbered peer */ 85 86 int vm_id; 87 uint32_t vectors; 88 uint32_t features; 89 EventfdEntry *eventfd_table; 90 91 Error *migration_blocker; 92 93 char * shmobj; 94 char * sizearg; 95 char * role; 96 int role_val; /* scalar to avoid multiple string comparisons */ 97 } IVShmemState; 98 99 /* registers for the Inter-VM shared memory device */ 100 enum ivshmem_registers { 101 INTRMASK = 0, 102 INTRSTATUS = 4, 103 IVPOSITION = 8, 104 DOORBELL = 12, 105 }; 106 107 static inline uint32_t ivshmem_has_feature(IVShmemState *ivs, 108 unsigned int feature) { 109 return (ivs->features & (1 << feature)); 110 } 111 112 static inline bool is_power_of_two(uint64_t x) { 113 return (x & (x - 1)) == 0; 114 } 115 116 /* accessing registers - based on rtl8139 */ 117 static void ivshmem_update_irq(IVShmemState *s, int val) 118 { 119 int isr; 120 isr = (s->intrstatus & s->intrmask) & 0xffffffff; 121 122 /* don't print ISR resets */ 123 if (isr) { 124 IVSHMEM_DPRINTF("Set IRQ to %d (%04x %04x)\n", 125 isr ? 1 : 0, s->intrstatus, s->intrmask); 126 } 127 128 qemu_set_irq(s->dev.irq[0], (isr != 0)); 129 } 130 131 static void ivshmem_IntrMask_write(IVShmemState *s, uint32_t val) 132 { 133 IVSHMEM_DPRINTF("IntrMask write(w) val = 0x%04x\n", val); 134 135 s->intrmask = val; 136 137 ivshmem_update_irq(s, val); 138 } 139 140 static uint32_t ivshmem_IntrMask_read(IVShmemState *s) 141 { 142 uint32_t ret = s->intrmask; 143 144 IVSHMEM_DPRINTF("intrmask read(w) val = 0x%04x\n", ret); 145 146 return ret; 147 } 148 149 static void ivshmem_IntrStatus_write(IVShmemState *s, uint32_t val) 150 { 151 IVSHMEM_DPRINTF("IntrStatus write(w) val = 0x%04x\n", val); 152 153 s->intrstatus = val; 154 155 ivshmem_update_irq(s, val); 156 } 157 158 static uint32_t ivshmem_IntrStatus_read(IVShmemState *s) 159 { 160 uint32_t ret = s->intrstatus; 161 162 /* reading ISR clears all interrupts */ 163 s->intrstatus = 0; 164 165 ivshmem_update_irq(s, 0); 166 167 return ret; 168 } 169 170 static void ivshmem_io_write(void *opaque, hwaddr addr, 171 uint64_t val, unsigned size) 172 { 173 IVShmemState *s = opaque; 174 175 uint16_t dest = val >> 16; 176 uint16_t vector = val & 0xff; 177 178 addr &= 0xfc; 179 180 IVSHMEM_DPRINTF("writing to addr " TARGET_FMT_plx "\n", addr); 181 switch (addr) 182 { 183 case INTRMASK: 184 ivshmem_IntrMask_write(s, val); 185 break; 186 187 case INTRSTATUS: 188 ivshmem_IntrStatus_write(s, val); 189 break; 190 191 case DOORBELL: 192 /* check that dest VM ID is reasonable */ 193 if (dest > s->max_peer) { 194 IVSHMEM_DPRINTF("Invalid destination VM ID (%d)\n", dest); 195 break; 196 } 197 198 /* check doorbell range */ 199 if (vector < s->peers[dest].nb_eventfds) { 200 IVSHMEM_DPRINTF("Notifying VM %d on vector %d\n", dest, vector); 201 event_notifier_set(&s->peers[dest].eventfds[vector]); 202 } 203 break; 204 default: 205 IVSHMEM_DPRINTF("Invalid VM Doorbell VM %d\n", dest); 206 } 207 } 208 209 static uint64_t ivshmem_io_read(void *opaque, hwaddr addr, 210 unsigned size) 211 { 212 213 IVShmemState *s = opaque; 214 uint32_t ret; 215 216 switch (addr) 217 { 218 case INTRMASK: 219 ret = ivshmem_IntrMask_read(s); 220 break; 221 222 case INTRSTATUS: 223 ret = ivshmem_IntrStatus_read(s); 224 break; 225 226 case IVPOSITION: 227 /* return my VM ID if the memory is mapped */ 228 if (s->shm_fd > 0) { 229 ret = s->vm_id; 230 } else { 231 ret = -1; 232 } 233 break; 234 235 default: 236 IVSHMEM_DPRINTF("why are we reading " TARGET_FMT_plx "\n", addr); 237 ret = 0; 238 } 239 240 return ret; 241 } 242 243 static const MemoryRegionOps ivshmem_mmio_ops = { 244 .read = ivshmem_io_read, 245 .write = ivshmem_io_write, 246 .endianness = DEVICE_NATIVE_ENDIAN, 247 .impl = { 248 .min_access_size = 4, 249 .max_access_size = 4, 250 }, 251 }; 252 253 static void ivshmem_receive(void *opaque, const uint8_t *buf, int size) 254 { 255 IVShmemState *s = opaque; 256 257 ivshmem_IntrStatus_write(s, *buf); 258 259 IVSHMEM_DPRINTF("ivshmem_receive 0x%02x\n", *buf); 260 } 261 262 static int ivshmem_can_receive(void * opaque) 263 { 264 return 8; 265 } 266 267 static void ivshmem_event(void *opaque, int event) 268 { 269 IVSHMEM_DPRINTF("ivshmem_event %d\n", event); 270 } 271 272 static void fake_irqfd(void *opaque, const uint8_t *buf, int size) { 273 274 EventfdEntry *entry = opaque; 275 PCIDevice *pdev = entry->pdev; 276 277 IVSHMEM_DPRINTF("interrupt on vector %p %d\n", pdev, entry->vector); 278 msix_notify(pdev, entry->vector); 279 } 280 281 static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n, 282 int vector) 283 { 284 /* create a event character device based on the passed eventfd */ 285 IVShmemState *s = opaque; 286 CharDriverState * chr; 287 int eventfd = event_notifier_get_fd(n); 288 289 chr = qemu_chr_open_eventfd(eventfd); 290 291 if (chr == NULL) { 292 fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd); 293 exit(-1); 294 } 295 qemu_chr_fe_claim_no_fail(chr); 296 297 /* if MSI is supported we need multiple interrupts */ 298 if (ivshmem_has_feature(s, IVSHMEM_MSI)) { 299 s->eventfd_table[vector].pdev = &s->dev; 300 s->eventfd_table[vector].vector = vector; 301 302 qemu_chr_add_handlers(chr, ivshmem_can_receive, fake_irqfd, 303 ivshmem_event, &s->eventfd_table[vector]); 304 } else { 305 qemu_chr_add_handlers(chr, ivshmem_can_receive, ivshmem_receive, 306 ivshmem_event, s); 307 } 308 309 return chr; 310 311 } 312 313 static int check_shm_size(IVShmemState *s, int fd) { 314 /* check that the guest isn't going to try and map more memory than the 315 * the object has allocated return -1 to indicate error */ 316 317 struct stat buf; 318 319 fstat(fd, &buf); 320 321 if (s->ivshmem_size > buf.st_size) { 322 fprintf(stderr, 323 "IVSHMEM ERROR: Requested memory size greater" 324 " than shared object size (%" PRIu64 " > %" PRIu64")\n", 325 s->ivshmem_size, (uint64_t)buf.st_size); 326 return -1; 327 } else { 328 return 0; 329 } 330 } 331 332 /* create the shared memory BAR when we are not using the server, so we can 333 * create the BAR and map the memory immediately */ 334 static void create_shared_memory_BAR(IVShmemState *s, int fd) { 335 336 void * ptr; 337 338 s->shm_fd = fd; 339 340 ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 341 342 memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2", 343 s->ivshmem_size, ptr); 344 vmstate_register_ram(&s->ivshmem, &s->dev.qdev); 345 memory_region_add_subregion(&s->bar, 0, &s->ivshmem); 346 347 /* region for shared memory */ 348 pci_register_bar(&s->dev, 2, s->ivshmem_attr, &s->bar); 349 } 350 351 static void ivshmem_add_eventfd(IVShmemState *s, int posn, int i) 352 { 353 memory_region_add_eventfd(&s->ivshmem_mmio, 354 DOORBELL, 355 4, 356 true, 357 (posn << 16) | i, 358 &s->peers[posn].eventfds[i]); 359 } 360 361 static void ivshmem_del_eventfd(IVShmemState *s, int posn, int i) 362 { 363 memory_region_del_eventfd(&s->ivshmem_mmio, 364 DOORBELL, 365 4, 366 true, 367 (posn << 16) | i, 368 &s->peers[posn].eventfds[i]); 369 } 370 371 static void close_guest_eventfds(IVShmemState *s, int posn) 372 { 373 int i, guest_curr_max; 374 375 if (!ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { 376 return; 377 } 378 379 guest_curr_max = s->peers[posn].nb_eventfds; 380 381 memory_region_transaction_begin(); 382 for (i = 0; i < guest_curr_max; i++) { 383 ivshmem_del_eventfd(s, posn, i); 384 } 385 memory_region_transaction_commit(); 386 for (i = 0; i < guest_curr_max; i++) { 387 event_notifier_cleanup(&s->peers[posn].eventfds[i]); 388 } 389 390 g_free(s->peers[posn].eventfds); 391 s->peers[posn].nb_eventfds = 0; 392 } 393 394 /* this function increase the dynamic storage need to store data about other 395 * guests */ 396 static void increase_dynamic_storage(IVShmemState *s, int new_min_size) { 397 398 int j, old_nb_alloc; 399 400 old_nb_alloc = s->nb_peers; 401 402 while (new_min_size >= s->nb_peers) 403 s->nb_peers = s->nb_peers * 2; 404 405 IVSHMEM_DPRINTF("bumping storage to %d guests\n", s->nb_peers); 406 s->peers = g_realloc(s->peers, s->nb_peers * sizeof(Peer)); 407 408 /* zero out new pointers */ 409 for (j = old_nb_alloc; j < s->nb_peers; j++) { 410 s->peers[j].eventfds = NULL; 411 s->peers[j].nb_eventfds = 0; 412 } 413 } 414 415 static void ivshmem_read(void *opaque, const uint8_t * buf, int flags) 416 { 417 IVShmemState *s = opaque; 418 int incoming_fd, tmp_fd; 419 int guest_max_eventfd; 420 long incoming_posn; 421 422 memcpy(&incoming_posn, buf, sizeof(long)); 423 /* pick off s->server_chr->msgfd and store it, posn should accompany msg */ 424 tmp_fd = qemu_chr_fe_get_msgfd(s->server_chr); 425 IVSHMEM_DPRINTF("posn is %ld, fd is %d\n", incoming_posn, tmp_fd); 426 427 /* make sure we have enough space for this guest */ 428 if (incoming_posn >= s->nb_peers) { 429 increase_dynamic_storage(s, incoming_posn); 430 } 431 432 if (tmp_fd == -1) { 433 /* if posn is positive and unseen before then this is our posn*/ 434 if ((incoming_posn >= 0) && 435 (s->peers[incoming_posn].eventfds == NULL)) { 436 /* receive our posn */ 437 s->vm_id = incoming_posn; 438 return; 439 } else { 440 /* otherwise an fd == -1 means an existing guest has gone away */ 441 IVSHMEM_DPRINTF("posn %ld has gone away\n", incoming_posn); 442 close_guest_eventfds(s, incoming_posn); 443 return; 444 } 445 } 446 447 /* because of the implementation of get_msgfd, we need a dup */ 448 incoming_fd = dup(tmp_fd); 449 450 if (incoming_fd == -1) { 451 fprintf(stderr, "could not allocate file descriptor %s\n", 452 strerror(errno)); 453 return; 454 } 455 456 /* if the position is -1, then it's shared memory region fd */ 457 if (incoming_posn == -1) { 458 459 void * map_ptr; 460 461 s->max_peer = 0; 462 463 if (check_shm_size(s, incoming_fd) == -1) { 464 exit(-1); 465 } 466 467 /* mmap the region and map into the BAR2 */ 468 map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, 469 incoming_fd, 0); 470 memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), 471 "ivshmem.bar2", s->ivshmem_size, map_ptr); 472 vmstate_register_ram(&s->ivshmem, &s->dev.qdev); 473 474 IVSHMEM_DPRINTF("guest h/w addr = %" PRIu64 ", size = %" PRIu64 "\n", 475 s->ivshmem_offset, s->ivshmem_size); 476 477 memory_region_add_subregion(&s->bar, 0, &s->ivshmem); 478 479 /* only store the fd if it is successfully mapped */ 480 s->shm_fd = incoming_fd; 481 482 return; 483 } 484 485 /* each guest has an array of eventfds, and we keep track of how many 486 * guests for each VM */ 487 guest_max_eventfd = s->peers[incoming_posn].nb_eventfds; 488 489 if (guest_max_eventfd == 0) { 490 /* one eventfd per MSI vector */ 491 s->peers[incoming_posn].eventfds = g_new(EventNotifier, s->vectors); 492 } 493 494 /* this is an eventfd for a particular guest VM */ 495 IVSHMEM_DPRINTF("eventfds[%ld][%d] = %d\n", incoming_posn, 496 guest_max_eventfd, incoming_fd); 497 event_notifier_init_fd(&s->peers[incoming_posn].eventfds[guest_max_eventfd], 498 incoming_fd); 499 500 /* increment count for particular guest */ 501 s->peers[incoming_posn].nb_eventfds++; 502 503 /* keep track of the maximum VM ID */ 504 if (incoming_posn > s->max_peer) { 505 s->max_peer = incoming_posn; 506 } 507 508 if (incoming_posn == s->vm_id) { 509 s->eventfd_chr[guest_max_eventfd] = create_eventfd_chr_device(s, 510 &s->peers[s->vm_id].eventfds[guest_max_eventfd], 511 guest_max_eventfd); 512 } 513 514 if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { 515 ivshmem_add_eventfd(s, incoming_posn, guest_max_eventfd); 516 } 517 } 518 519 /* Select the MSI-X vectors used by device. 520 * ivshmem maps events to vectors statically, so 521 * we just enable all vectors on init and after reset. */ 522 static void ivshmem_use_msix(IVShmemState * s) 523 { 524 int i; 525 526 if (!msix_present(&s->dev)) { 527 return; 528 } 529 530 for (i = 0; i < s->vectors; i++) { 531 msix_vector_use(&s->dev, i); 532 } 533 } 534 535 static void ivshmem_reset(DeviceState *d) 536 { 537 IVShmemState *s = DO_UPCAST(IVShmemState, dev.qdev, d); 538 539 s->intrstatus = 0; 540 ivshmem_use_msix(s); 541 } 542 543 static uint64_t ivshmem_get_size(IVShmemState * s) { 544 545 uint64_t value; 546 char *ptr; 547 548 value = strtoull(s->sizearg, &ptr, 10); 549 switch (*ptr) { 550 case 0: case 'M': case 'm': 551 value <<= 20; 552 break; 553 case 'G': case 'g': 554 value <<= 30; 555 break; 556 default: 557 fprintf(stderr, "qemu: invalid ram size: %s\n", s->sizearg); 558 exit(1); 559 } 560 561 /* BARs must be a power of 2 */ 562 if (!is_power_of_two(value)) { 563 fprintf(stderr, "ivshmem: size must be power of 2\n"); 564 exit(1); 565 } 566 567 return value; 568 } 569 570 static void ivshmem_setup_msi(IVShmemState * s) 571 { 572 if (msix_init_exclusive_bar(&s->dev, s->vectors, 1)) { 573 IVSHMEM_DPRINTF("msix initialization failed\n"); 574 exit(1); 575 } 576 577 IVSHMEM_DPRINTF("msix initialized (%d vectors)\n", s->vectors); 578 579 /* allocate QEMU char devices for receiving interrupts */ 580 s->eventfd_table = g_malloc0(s->vectors * sizeof(EventfdEntry)); 581 582 ivshmem_use_msix(s); 583 } 584 585 static void ivshmem_save(QEMUFile* f, void *opaque) 586 { 587 IVShmemState *proxy = opaque; 588 589 IVSHMEM_DPRINTF("ivshmem_save\n"); 590 pci_device_save(&proxy->dev, f); 591 592 if (ivshmem_has_feature(proxy, IVSHMEM_MSI)) { 593 msix_save(&proxy->dev, f); 594 } else { 595 qemu_put_be32(f, proxy->intrstatus); 596 qemu_put_be32(f, proxy->intrmask); 597 } 598 599 } 600 601 static int ivshmem_load(QEMUFile* f, void *opaque, int version_id) 602 { 603 IVSHMEM_DPRINTF("ivshmem_load\n"); 604 605 IVShmemState *proxy = opaque; 606 int ret; 607 608 if (version_id > 0) { 609 return -EINVAL; 610 } 611 612 if (proxy->role_val == IVSHMEM_PEER) { 613 fprintf(stderr, "ivshmem: 'peer' devices are not migratable\n"); 614 return -EINVAL; 615 } 616 617 ret = pci_device_load(&proxy->dev, f); 618 if (ret) { 619 return ret; 620 } 621 622 if (ivshmem_has_feature(proxy, IVSHMEM_MSI)) { 623 msix_load(&proxy->dev, f); 624 ivshmem_use_msix(proxy); 625 } else { 626 proxy->intrstatus = qemu_get_be32(f); 627 proxy->intrmask = qemu_get_be32(f); 628 } 629 630 return 0; 631 } 632 633 static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address, 634 uint32_t val, int len) 635 { 636 pci_default_write_config(pci_dev, address, val, len); 637 msix_write_config(pci_dev, address, val, len); 638 } 639 640 static int pci_ivshmem_init(PCIDevice *dev) 641 { 642 IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); 643 uint8_t *pci_conf; 644 645 if (s->sizearg == NULL) 646 s->ivshmem_size = 4 << 20; /* 4 MB default */ 647 else { 648 s->ivshmem_size = ivshmem_get_size(s); 649 } 650 651 register_savevm(&s->dev.qdev, "ivshmem", 0, 0, ivshmem_save, ivshmem_load, 652 dev); 653 654 /* IRQFD requires MSI */ 655 if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) && 656 !ivshmem_has_feature(s, IVSHMEM_MSI)) { 657 fprintf(stderr, "ivshmem: ioeventfd/irqfd requires MSI\n"); 658 exit(1); 659 } 660 661 /* check that role is reasonable */ 662 if (s->role) { 663 if (strncmp(s->role, "peer", 5) == 0) { 664 s->role_val = IVSHMEM_PEER; 665 } else if (strncmp(s->role, "master", 7) == 0) { 666 s->role_val = IVSHMEM_MASTER; 667 } else { 668 fprintf(stderr, "ivshmem: 'role' must be 'peer' or 'master'\n"); 669 exit(1); 670 } 671 } else { 672 s->role_val = IVSHMEM_MASTER; /* default */ 673 } 674 675 if (s->role_val == IVSHMEM_PEER) { 676 error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, 677 "peer mode", "ivshmem"); 678 migrate_add_blocker(s->migration_blocker); 679 } 680 681 pci_conf = s->dev.config; 682 pci_conf[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY; 683 684 pci_config_set_interrupt_pin(pci_conf, 1); 685 686 s->shm_fd = 0; 687 688 memory_region_init_io(&s->ivshmem_mmio, OBJECT(s), &ivshmem_mmio_ops, s, 689 "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE); 690 691 /* region for registers*/ 692 pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, 693 &s->ivshmem_mmio); 694 695 memory_region_init(&s->bar, OBJECT(s), "ivshmem-bar2-container", s->ivshmem_size); 696 s->ivshmem_attr = PCI_BASE_ADDRESS_SPACE_MEMORY | 697 PCI_BASE_ADDRESS_MEM_PREFETCH; 698 if (s->ivshmem_64bit) { 699 s->ivshmem_attr |= PCI_BASE_ADDRESS_MEM_TYPE_64; 700 } 701 702 if ((s->server_chr != NULL) && 703 (strncmp(s->server_chr->filename, "unix:", 5) == 0)) { 704 /* if we get a UNIX socket as the parameter we will talk 705 * to the ivshmem server to receive the memory region */ 706 707 if (s->shmobj != NULL) { 708 fprintf(stderr, "WARNING: do not specify both 'chardev' " 709 "and 'shm' with ivshmem\n"); 710 } 711 712 IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n", 713 s->server_chr->filename); 714 715 if (ivshmem_has_feature(s, IVSHMEM_MSI)) { 716 ivshmem_setup_msi(s); 717 } 718 719 /* we allocate enough space for 16 guests and grow as needed */ 720 s->nb_peers = 16; 721 s->vm_id = -1; 722 723 /* allocate/initialize space for interrupt handling */ 724 s->peers = g_malloc0(s->nb_peers * sizeof(Peer)); 725 726 pci_register_bar(&s->dev, 2, s->ivshmem_attr, &s->bar); 727 728 s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *)); 729 730 qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive, ivshmem_read, 731 ivshmem_event, s); 732 } else { 733 /* just map the file immediately, we're not using a server */ 734 int fd; 735 736 if (s->shmobj == NULL) { 737 fprintf(stderr, "Must specify 'chardev' or 'shm' to ivshmem\n"); 738 exit(1); 739 } 740 741 IVSHMEM_DPRINTF("using shm_open (shm object = %s)\n", s->shmobj); 742 743 /* try opening with O_EXCL and if it succeeds zero the memory 744 * by truncating to 0 */ 745 if ((fd = shm_open(s->shmobj, O_CREAT|O_RDWR|O_EXCL, 746 S_IRWXU|S_IRWXG|S_IRWXO)) > 0) { 747 /* truncate file to length PCI device's memory */ 748 if (ftruncate(fd, s->ivshmem_size) != 0) { 749 fprintf(stderr, "ivshmem: could not truncate shared file\n"); 750 } 751 752 } else if ((fd = shm_open(s->shmobj, O_CREAT|O_RDWR, 753 S_IRWXU|S_IRWXG|S_IRWXO)) < 0) { 754 fprintf(stderr, "ivshmem: could not open shared file\n"); 755 exit(-1); 756 757 } 758 759 if (check_shm_size(s, fd) == -1) { 760 exit(-1); 761 } 762 763 create_shared_memory_BAR(s, fd); 764 765 } 766 767 s->dev.config_write = ivshmem_write_config; 768 769 return 0; 770 } 771 772 static void pci_ivshmem_uninit(PCIDevice *dev) 773 { 774 IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); 775 776 if (s->migration_blocker) { 777 migrate_del_blocker(s->migration_blocker); 778 error_free(s->migration_blocker); 779 } 780 781 memory_region_destroy(&s->ivshmem_mmio); 782 memory_region_del_subregion(&s->bar, &s->ivshmem); 783 vmstate_unregister_ram(&s->ivshmem, &s->dev.qdev); 784 memory_region_destroy(&s->ivshmem); 785 memory_region_destroy(&s->bar); 786 unregister_savevm(&dev->qdev, "ivshmem", s); 787 } 788 789 static Property ivshmem_properties[] = { 790 DEFINE_PROP_CHR("chardev", IVShmemState, server_chr), 791 DEFINE_PROP_STRING("size", IVShmemState, sizearg), 792 DEFINE_PROP_UINT32("vectors", IVShmemState, vectors, 1), 793 DEFINE_PROP_BIT("ioeventfd", IVShmemState, features, IVSHMEM_IOEVENTFD, false), 794 DEFINE_PROP_BIT("msi", IVShmemState, features, IVSHMEM_MSI, true), 795 DEFINE_PROP_STRING("shm", IVShmemState, shmobj), 796 DEFINE_PROP_STRING("role", IVShmemState, role), 797 DEFINE_PROP_UINT32("use64", IVShmemState, ivshmem_64bit, 1), 798 DEFINE_PROP_END_OF_LIST(), 799 }; 800 801 static void ivshmem_class_init(ObjectClass *klass, void *data) 802 { 803 DeviceClass *dc = DEVICE_CLASS(klass); 804 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 805 806 k->init = pci_ivshmem_init; 807 k->exit = pci_ivshmem_uninit; 808 k->vendor_id = PCI_VENDOR_ID_IVSHMEM; 809 k->device_id = PCI_DEVICE_ID_IVSHMEM; 810 k->class_id = PCI_CLASS_MEMORY_RAM; 811 dc->reset = ivshmem_reset; 812 dc->props = ivshmem_properties; 813 } 814 815 static const TypeInfo ivshmem_info = { 816 .name = "ivshmem", 817 .parent = TYPE_PCI_DEVICE, 818 .instance_size = sizeof(IVShmemState), 819 .class_init = ivshmem_class_init, 820 }; 821 822 static void ivshmem_register_types(void) 823 { 824 type_register_static(&ivshmem_info); 825 } 826 827 type_init(ivshmem_register_types) 828