diff options
author | Peter Maydell | 2018-02-07 21:40:36 +0100 |
---|---|---|
committer | Peter Maydell | 2018-02-07 21:40:36 +0100 |
commit | 7b213bb4755dc99e447c19c532768ef5105b9771 (patch) | |
tree | cc13202d4cc96c90b7ff3964a45343c6ab8f797e /hw/misc | |
parent | Merge remote-tracking branch 'remotes/armbru/tags/pull-error-2018-02-06' into... (diff) | |
parent | Add the WHPX acceleration enlightenments (diff) | |
download | qemu-7b213bb4755dc99e447c19c532768ef5105b9771.tar.gz qemu-7b213bb4755dc99e447c19c532768ef5105b9771.tar.xz qemu-7b213bb4755dc99e447c19c532768ef5105b9771.zip |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* socket option parsing fix (Daniel)
* SCSI fixes (Fam)
* Readline double-free fix (Greg)
* More HVF attribution fixes (Izik)
* WHPX (Windows Hypervisor Platform Extensions) support (Justin)
* POLLHUP handler (Klim)
* ivshmem fixes (Ladi)
* memfd memory backend (Marc-André)
* improved error message (Marcelo)
* Memory fixes (Peter Xu, Zhecheng)
* Remove obsolete code and comments (Peter M.)
* qdev API improvements (Philippe)
* Add CONFIG_I2C switch (Thomas)
# gpg: Signature made Wed 07 Feb 2018 15:24:08 GMT
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (47 commits)
Add the WHPX acceleration enlightenments
Introduce the WHPX impl
Add the WHPX vcpu API
Add the Windows Hypervisor Platform accelerator.
tests/test-filter-redirector: move close()
tests: use memfd in vhost-user-test
vhost-user-test: make read-guest-mem setup its own qemu
tests: keep compiling failing vhost-user tests
Add memfd based hostmem
memfd: add hugetlbsize argument
memfd: add hugetlb support
memfd: add error argument, instead of perror()
cpus: join thread when removing a vCPU
cpus: hvf: unregister thread with RCU
cpus: tcg: unregister thread with RCU, fix exiting of loop on unplug
cpus: dummy: unregister thread with RCU, exit loop on unplug
cpus: kvm: unregister thread with RCU
cpus: hax: register/unregister thread with RCU, exit loop on unplug
ivshmem: Disable irqfd on device reset
ivshmem: Improve MSI irqfd error handling
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
# Conflicts:
# cpus.c
Diffstat (limited to 'hw/misc')
-rw-r--r-- | hw/misc/ivshmem.c | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 4919011f38..16f03701b7 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -76,6 +76,7 @@ typedef struct Peer { typedef struct MSIVector { PCIDevice *pdev; int virq; + bool unmasked; } MSIVector; typedef struct IVShmemState { @@ -316,6 +317,11 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector, int ret; IVSHMEM_DPRINTF("vector unmask %p %d\n", dev, vector); + if (!v->pdev) { + error_report("ivshmem: vector %d route does not exist", vector); + return -EINVAL; + } + assert(!v->unmasked); ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg, dev); if (ret < 0) { @@ -323,22 +329,35 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector, } kvm_irqchip_commit_routes(kvm_state); - return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq); + ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq); + if (ret < 0) { + return ret; + } + v->unmasked = true; + + return 0; } static void ivshmem_vector_mask(PCIDevice *dev, unsigned vector) { IVShmemState *s = IVSHMEM_COMMON(dev); EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; + MSIVector *v = &s->msi_vectors[vector]; int ret; IVSHMEM_DPRINTF("vector mask %p %d\n", dev, vector); + if (!v->pdev) { + error_report("ivshmem: vector %d route does not exist", vector); + return; + } + assert(v->unmasked); - ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, - s->msi_vectors[vector].virq); - if (ret != 0) { + ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, v->virq); + if (ret < 0) { error_report("remove_irqfd_notifier_gsi failed"); + return; } + v->unmasked = false; } static void ivshmem_vector_poll(PCIDevice *dev, @@ -738,10 +757,14 @@ static void ivshmem_msix_vector_use(IVShmemState *s) } } +static void ivshmem_disable_irqfd(IVShmemState *s); + static void ivshmem_reset(DeviceState *d) { IVShmemState *s = IVSHMEM_COMMON(d); + ivshmem_disable_irqfd(s); + s->intrstatus = 0; s->intrmask = 0; if (ivshmem_has_feature(s, IVSHMEM_MSI)) { @@ -766,6 +789,20 @@ static int ivshmem_setup_interrupts(IVShmemState *s, Error **errp) return 0; } +static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector) +{ + IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector); + + if (s->msi_vectors[vector].pdev == NULL) { + return; + } + + /* it was cleaned when masked in the frontend. */ + kvm_irqchip_release_virq(kvm_state, s->msi_vectors[vector].virq); + + s->msi_vectors[vector].pdev = NULL; +} + static void ivshmem_enable_irqfd(IVShmemState *s) { PCIDevice *pdev = PCI_DEVICE(s); @@ -777,7 +814,7 @@ static void ivshmem_enable_irqfd(IVShmemState *s) ivshmem_add_kvm_msi_virq(s, i, &err); if (err) { error_report_err(err); - /* TODO do we need to handle the error? */ + goto undo; } } @@ -786,21 +823,14 @@ static void ivshmem_enable_irqfd(IVShmemState *s) ivshmem_vector_mask, ivshmem_vector_poll)) { error_report("ivshmem: msix_set_vector_notifiers failed"); + goto undo; } -} + return; -static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector) -{ - IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector); - - if (s->msi_vectors[vector].pdev == NULL) { - return; +undo: + while (--i >= 0) { + ivshmem_remove_kvm_msi_virq(s, i); } - - /* it was cleaned when masked in the frontend. */ - kvm_irqchip_release_virq(kvm_state, s->msi_vectors[vector].virq); - - s->msi_vectors[vector].pdev = NULL; } static void ivshmem_disable_irqfd(IVShmemState *s) @@ -808,11 +838,24 @@ static void ivshmem_disable_irqfd(IVShmemState *s) PCIDevice *pdev = PCI_DEVICE(s); int i; + if (!pdev->msix_vector_use_notifier) { + return; + } + + msix_unset_vector_notifiers(pdev); + for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) { + /* + * MSI-X is already disabled here so msix_unset_vector_notifiers() + * didn't call our release notifier. Do it now to keep our masks and + * unmasks balanced. + */ + if (s->msi_vectors[i].unmasked) { + ivshmem_vector_mask(pdev, i); + } ivshmem_remove_kvm_msi_virq(s, i); } - msix_unset_vector_notifiers(pdev); } static void ivshmem_write_config(PCIDevice *pdev, uint32_t address, |