static void process_msg_disconnect(IVShmemState *s, uint16_t posn, Error **errp) { IVSHMEM_DPRINTF("posn %d has gone away\n", posn); if (posn >= s->nb_peers || posn == s->vm_id) { error_setg(errp, "invalid peer %d", posn); return; } close_peer_eventfds(s, posn); }
static void pci_ivshmem_exit(PCIDevice *dev) { IVShmemState *s = IVSHMEM(dev); int i; fifo8_destroy(&s->incoming_fifo); if (s->migration_blocker) { migrate_del_blocker(s->migration_blocker); error_free(s->migration_blocker); } if (memory_region_is_mapped(&s->ivshmem)) { if (!s->hostmem) { void *addr = memory_region_get_ram_ptr(&s->ivshmem); int fd; if (munmap(addr, s->ivshmem_size) == -1) { error_report("Failed to munmap shared memory %s", strerror(errno)); } fd = qemu_get_ram_fd(memory_region_get_ram_addr(&s->ivshmem)); if (fd != -1) { close(fd); } } vmstate_unregister_ram(&s->ivshmem, DEVICE(dev)); memory_region_del_subregion(&s->bar, &s->ivshmem); } if (s->eventfd_chr) { for (i = 0; i < s->vectors; i++) { if (s->eventfd_chr[i]) { qemu_chr_free(s->eventfd_chr[i]); } } g_free(s->eventfd_chr); } if (s->peers) { for (i = 0; i < s->nb_peers; i++) { close_peer_eventfds(s, i); } g_free(s->peers); } if (ivshmem_has_feature(s, IVSHMEM_MSI)) { msix_uninit_exclusive_bar(dev); } g_free(s->msi_vectors); }
static void ivshmem_exit(PCIDevice *dev) { IVShmemState *s = IVSHMEM_COMMON(dev); int i; if (s->migration_blocker) { migrate_del_blocker(s->migration_blocker); error_free(s->migration_blocker); } if (memory_region_is_mapped(s->ivshmem_bar2)) { if (!s->hostmem) { void *addr = memory_region_get_ram_ptr(s->ivshmem_bar2); int fd; if (munmap(addr, memory_region_size(s->ivshmem_bar2) == -1)) { error_report("Failed to munmap shared memory %s", strerror(errno)); } fd = memory_region_get_fd(s->ivshmem_bar2); close(fd); } vmstate_unregister_ram(s->ivshmem_bar2, DEVICE(dev)); } if (s->peers) { for (i = 0; i < s->nb_peers; i++) { close_peer_eventfds(s, i); } g_free(s->peers); } if (ivshmem_has_feature(s, IVSHMEM_MSI)) { msix_uninit_exclusive_bar(dev); } g_free(s->msi_vectors); }
static void ivshmem_read(void *opaque, const uint8_t *buf, int size) { IVShmemState *s = opaque; int incoming_fd; int new_eventfd; int64_t incoming_posn; Error *err = NULL; Peer *peer; if (!fifo_update_and_get_i64(s, buf, size, &incoming_posn)) { return; } if (incoming_posn < -1) { IVSHMEM_DPRINTF("invalid incoming_posn %" PRId64 "\n", incoming_posn); return; } /* pick off s->server_chr->msgfd and store it, posn should accompany msg */ incoming_fd = qemu_chr_fe_get_msgfd(s->server_chr); IVSHMEM_DPRINTF("posn is %" PRId64 ", fd is %d\n", incoming_posn, incoming_fd); /* make sure we have enough space for this peer */ if (incoming_posn >= s->nb_peers) { if (resize_peers(s, incoming_posn + 1) < 0) { error_report("failed to resize peers array"); if (incoming_fd != -1) { close(incoming_fd); } return; } } peer = &s->peers[incoming_posn]; if (incoming_fd == -1) { /* if posn is positive and unseen before then this is our posn*/ if (incoming_posn >= 0 && s->vm_id == -1) { /* receive our posn */ s->vm_id = incoming_posn; } else { /* otherwise an fd == -1 means an existing peer has gone away */ IVSHMEM_DPRINTF("posn %" PRId64 " has gone away\n", incoming_posn); close_peer_eventfds(s, incoming_posn); } return; } /* if the position is -1, then it's shared memory region fd */ if (incoming_posn == -1) { void * map_ptr; if (memory_region_is_mapped(&s->ivshmem)) { error_report("shm already initialized"); close(incoming_fd); return; } if (check_shm_size(s, incoming_fd, &err) == -1) { error_report_err(err); close(incoming_fd); return; } /* mmap the region and map into the BAR2 */ map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, incoming_fd, 0); if (map_ptr == MAP_FAILED) { error_report("Failed to mmap shared memory %s", strerror(errno)); close(incoming_fd); return; } memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2", s->ivshmem_size, map_ptr); qemu_set_ram_fd(s->ivshmem.ram_addr, incoming_fd); vmstate_register_ram(&s->ivshmem, DEVICE(s)); IVSHMEM_DPRINTF("guest h/w addr = %p, size = %" PRIu64 "\n", map_ptr, s->ivshmem_size); memory_region_add_subregion(&s->bar, 0, &s->ivshmem); return; } /* each peer has an associated array of eventfds, and we keep * track of how many eventfds received so far */ /* get a new eventfd: */ if (peer->nb_eventfds >= s->vectors) { error_report("Too many eventfd received, device has %d vectors", s->vectors); close(incoming_fd); return; } new_eventfd = peer->nb_eventfds++; /* this is an eventfd for a particular peer VM */ IVSHMEM_DPRINTF("eventfds[%" PRId64 "][%d] = %d\n", incoming_posn, new_eventfd, incoming_fd); event_notifier_init_fd(&peer->eventfds[new_eventfd], incoming_fd); fcntl_setfl(incoming_fd, O_NONBLOCK); /* msix/irqfd poll non block */ if (incoming_posn == s->vm_id) { setup_interrupt(s, new_eventfd); } if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { ivshmem_add_eventfd(s, incoming_posn, new_eventfd); } }