diff options
Diffstat (limited to 'hw/virtio-pci.c')
| -rw-r--r-- | hw/virtio-pci.c | 131 |
1 files changed, 40 insertions, 91 deletions
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 9342eed070..125eded9ca 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -160,7 +160,7 @@ static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f) } static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, - int n, bool assign) + int n, bool assign, bool set_handler) { VirtQueue *vq = virtio_get_queue(proxy->vdev, n); EventNotifier *notifier = virtio_queue_get_host_notifier(vq); @@ -173,46 +173,18 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, __func__, r); return r; } + virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler); memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, - true, n, event_notifier_get_fd(notifier)); + true, n, notifier); } else { memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, - true, n, event_notifier_get_fd(notifier)); - /* Handle the race condition where the guest kicked and we deassigned - * before we got around to handling the kick. - */ - if (event_notifier_test_and_clear(notifier)) { - virtio_queue_notify_vq(vq); - } - + true, n, notifier); + virtio_queue_set_host_notifier_fd_handler(vq, false, false); event_notifier_cleanup(notifier); } return r; } -static void virtio_pci_host_notifier_read(void *opaque) -{ - VirtQueue *vq = opaque; - EventNotifier *n = virtio_queue_get_host_notifier(vq); - if (event_notifier_test_and_clear(n)) { - virtio_queue_notify_vq(vq); - } -} - -static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy, - int n, bool assign) -{ - VirtQueue *vq = virtio_get_queue(proxy->vdev, n); - EventNotifier *notifier = virtio_queue_get_host_notifier(vq); - if (assign) { - qemu_set_fd_handler(event_notifier_get_fd(notifier), - virtio_pci_host_notifier_read, NULL, vq); - } else { - qemu_set_fd_handler(event_notifier_get_fd(notifier), - NULL, NULL, NULL); - } -} - static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy) { int n, r; @@ -228,12 +200,10 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy) continue; } - r = virtio_pci_set_host_notifier_internal(proxy, n, true); + r = virtio_pci_set_host_notifier_internal(proxy, n, true, true); if (r < 0) { goto assign_error; } - - virtio_pci_set_host_notifier_fd_handler(proxy, n, true); } proxy->ioeventfd_started = true; return; @@ -244,8 +214,7 @@ assign_error: continue; } - virtio_pci_set_host_notifier_fd_handler(proxy, n, false); - r = virtio_pci_set_host_notifier_internal(proxy, n, false); + r = virtio_pci_set_host_notifier_internal(proxy, n, false, false); assert(r >= 0); } proxy->ioeventfd_started = false; @@ -266,8 +235,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) continue; } - virtio_pci_set_host_notifier_fd_handler(proxy, n, false); - r = virtio_pci_set_host_notifier_internal(proxy, n, false); + r = virtio_pci_set_host_notifier_internal(proxy, n, false, false); assert(r >= 0); } proxy->ioeventfd_started = false; @@ -528,25 +496,15 @@ static unsigned virtio_pci_get_features(void *opaque) return proxy->host_features; } -static void virtio_pci_guest_notifier_read(void *opaque) -{ - VirtQueue *vq = opaque; - EventNotifier *n = virtio_queue_get_guest_notifier(vq); - if (event_notifier_test_and_clear(n)) { - virtio_irq(vq); - } -} - static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, unsigned int queue_no, unsigned int vector, MSIMessage msg) { VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no); + EventNotifier *n = virtio_queue_get_guest_notifier(vq); VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; - int fd, ret; - - fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vq)); + int ret; if (irqfd->users == 0) { ret = kvm_irqchip_add_msi_route(kvm_state, msg); @@ -557,7 +515,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, } irqfd->users++; - ret = kvm_irqchip_add_irqfd(kvm_state, fd, irqfd->virq); + ret = kvm_irqchip_add_irq_notifier(kvm_state, n, irqfd->virq); if (ret < 0) { if (--irqfd->users == 0) { kvm_irqchip_release_virq(kvm_state, irqfd->virq); @@ -565,8 +523,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, return ret; } - qemu_set_fd_handler(fd, NULL, NULL, NULL); - + virtio_queue_set_guest_notifier_fd_handler(vq, true, true); return 0; } @@ -575,19 +532,18 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, unsigned int vector) { VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no); + EventNotifier *n = virtio_queue_get_guest_notifier(vq); VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; - int fd, ret; - - fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vq)); + int ret; - ret = kvm_irqchip_remove_irqfd(kvm_state, fd, irqfd->virq); + ret = kvm_irqchip_remove_irq_notifier(kvm_state, n, irqfd->virq); assert(ret == 0); if (--irqfd->users == 0) { kvm_irqchip_release_virq(kvm_state, irqfd->virq); } - qemu_set_fd_handler(fd, virtio_pci_guest_notifier_read, NULL, vq); + virtio_queue_set_guest_notifier_fd_handler(vq, true, false); } static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector, @@ -649,14 +605,9 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign) if (r < 0) { return r; } - qemu_set_fd_handler(event_notifier_get_fd(notifier), - virtio_pci_guest_notifier_read, NULL, vq); + virtio_queue_set_guest_notifier_fd_handler(vq, true, false); } else { - qemu_set_fd_handler(event_notifier_get_fd(notifier), - NULL, NULL, NULL); - /* Test and clear notifier before closing it, - * in case poll callback didn't have time to run. */ - virtio_pci_guest_notifier_read(vq); + virtio_queue_set_guest_notifier_fd_handler(vq, false, false); event_notifier_cleanup(notifier); } @@ -732,7 +683,7 @@ static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign) * currently only stops on status change away from ok, * reset, vmstop and such. If we do add code to start here, * need to check vmstate, device state etc. */ - return virtio_pci_set_host_notifier_internal(proxy, n, assign); + return virtio_pci_set_host_notifier_internal(proxy, n, assign, false); } static void virtio_pci_vmstate_change(void *opaque, bool running) @@ -782,13 +733,10 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev) pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id); config[PCI_INTERRUPT_PIN] = 1; - memory_region_init(&proxy->msix_bar, "virtio-msix", 4096); - if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, - &proxy->msix_bar, 1, 0)) { - pci_register_bar(&proxy->pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, - &proxy->msix_bar); - } else + if (vdev->nvectors && + msix_init_exclusive_bar(&proxy->pci_dev, vdev->nvectors, 1)) { vdev->nvectors = 0; + } proxy->pci_dev.config_write = virtio_write_config; @@ -831,24 +779,21 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev) return 0; } -static int virtio_exit_pci(PCIDevice *pci_dev) +static void virtio_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); - int r; memory_region_destroy(&proxy->bar); - r = msix_uninit(pci_dev, &proxy->msix_bar); - memory_region_destroy(&proxy->msix_bar); - return r; + msix_uninit_exclusive_bar(pci_dev); } -static int virtio_blk_exit_pci(PCIDevice *pci_dev) +static void virtio_blk_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); virtio_pci_stop_ioeventfd(proxy); virtio_blk_exit(proxy->vdev); - return virtio_exit_pci(pci_dev); + virtio_exit_pci(pci_dev); } static int virtio_serial_init_pci(PCIDevice *pci_dev) @@ -873,13 +818,13 @@ static int virtio_serial_init_pci(PCIDevice *pci_dev) return 0; } -static int virtio_serial_exit_pci(PCIDevice *pci_dev) +static void virtio_serial_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); virtio_pci_stop_ioeventfd(proxy); virtio_serial_exit(proxy->vdev); - return virtio_exit_pci(pci_dev); + virtio_exit_pci(pci_dev); } static int virtio_net_init_pci(PCIDevice *pci_dev) @@ -897,13 +842,13 @@ static int virtio_net_init_pci(PCIDevice *pci_dev) return 0; } -static int virtio_net_exit_pci(PCIDevice *pci_dev) +static void virtio_net_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); virtio_pci_stop_ioeventfd(proxy); virtio_net_exit(proxy->vdev); - return virtio_exit_pci(pci_dev); + virtio_exit_pci(pci_dev); } static int virtio_balloon_init_pci(PCIDevice *pci_dev) @@ -924,18 +869,19 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev) return 0; } -static int virtio_balloon_exit_pci(PCIDevice *pci_dev) +static void virtio_balloon_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); virtio_pci_stop_ioeventfd(proxy); virtio_balloon_exit(proxy->vdev); - return virtio_exit_pci(pci_dev); + virtio_exit_pci(pci_dev); } static Property virtio_blk_properties[] = { DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf), + DEFINE_BLOCK_CHS_PROPERTIES(VirtIOPCIProxy, blk.conf), DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial), #ifdef __linux__ DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true), @@ -1071,7 +1017,9 @@ static int virtio_scsi_init_pci(PCIDevice *pci_dev) return -EINVAL; } - vdev->nvectors = proxy->nvectors; + vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED + ? proxy->scsi.num_queues + 3 + : proxy->nvectors; virtio_init_pci(proxy, vdev); /* make the actual value visible */ @@ -1079,16 +1027,17 @@ static int virtio_scsi_init_pci(PCIDevice *pci_dev) return 0; } -static int virtio_scsi_exit_pci(PCIDevice *pci_dev) +static void virtio_scsi_exit_pci(PCIDevice *pci_dev) { VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); virtio_scsi_exit(proxy->vdev); - return virtio_exit_pci(pci_dev); + virtio_exit_pci(pci_dev); } static Property virtio_scsi_properties[] = { - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), + DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED), DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi), DEFINE_PROP_END_OF_LIST(), }; |