From: Claudio Fontana <claudio.fontana@huawei.com>
To: marcandre.lureau@redhat.com, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, drjones@redhat.com, cam@cs.ualberta.ca,
stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCH v4 46/47] ivshmem: use kvm irqfd for msi notifications
Date: Wed, 30 Sep 2015 13:47:51 +0200 [thread overview]
Message-ID: <560BCBE7.7050001@huawei.com> (raw)
In-Reply-To: <1443094669-4144-47-git-send-email-marcandre.lureau@redhat.com>
On 24.09.2015 13:37, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Use irqfd for improving context switch when notifying the guest.
> If the host doesn't support kvm irqfd, regular msi notifications are
> still supported.
>
> Note: the ivshmem implementation doesn't allow switching between MSI and
> IO interrupts, this patch doesn't either.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Paolo could you also take a look at this one?
Seems to work, but I am not familiar with the kvm msi irqfd primitives.
One comment below.
> ---
> hw/misc/ivshmem.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 169 insertions(+), 6 deletions(-)
>
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index 73644cc..39c0791 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -19,6 +19,7 @@
> #include "hw/hw.h"
> #include "hw/i386/pc.h"
> #include "hw/pci/pci.h"
> +#include "hw/pci/msi.h"
> #include "hw/pci/msix.h"
> #include "sysemu/kvm.h"
> #include "migration/migration.h"
> @@ -68,6 +69,7 @@ typedef struct Peer {
>
> typedef struct MSIVector {
> PCIDevice *pdev;
> + int virq;
> } MSIVector;
>
> typedef struct IVShmemState {
> @@ -293,13 +295,73 @@ static void fake_irqfd(void *opaque, const uint8_t *buf, int size) {
> msix_notify(pdev, vector);
> }
>
> +static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector,
> + MSIMessage msg)
> +{
> + IVShmemState *s = IVSHMEM(dev);
> + EventNotifier *n = &s->peers[s->vm_id].eventfds[vector];
> + MSIVector *v = &s->msi_vectors[vector];
> + int ret;
> +
> + IVSHMEM_DPRINTF("vector unmask %p %d\n", dev, vector);
> +
> + ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg);
> + if (ret < 0) {
> + return ret;
> + }
> +
> + return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq);
> +}
> +
> +static void ivshmem_vector_mask(PCIDevice *dev, unsigned vector)
> +{
> + IVShmemState *s = IVSHMEM(dev);
> + EventNotifier *n = &s->peers[s->vm_id].eventfds[vector];
> + int ret;
> +
> + IVSHMEM_DPRINTF("vector mask %p %d\n", dev, vector);
> +
> + ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n,
> + s->msi_vectors[vector].virq);
> + if (ret != 0) {
> + error_report("remove_irqfd_notifier_gsi failed");
> + }
> +}
> +
> +static void ivshmem_vector_poll(PCIDevice *dev,
> + unsigned int vector_start,
> + unsigned int vector_end)
> +{
> + IVShmemState *s = IVSHMEM(dev);
> + unsigned int vector;
> +
> + IVSHMEM_DPRINTF("vector poll %p %d-%d\n", dev, vector_start, vector_end);
> +
> + vector_end = MIN(vector_end, s->vectors);
> +
> + for (vector = vector_start; vector < vector_end; vector++) {
> + EventNotifier *notifier = &s->peers[s->vm_id].eventfds[vector];
> +
> + if (!msix_is_masked(dev, vector)) {
> + continue;
> + }
> +
> + if (event_notifier_test_and_clear(notifier)) {
> + msix_set_pending(dev, vector);
> + }
> + }
> +}
> +
> static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *n,
> int vector)
> {
> /* create a event character device based on the passed eventfd */
> IVShmemState *s = opaque;
> - CharDriverState * chr;
> + PCIDevice *pdev = PCI_DEVICE(s);
> int eventfd = event_notifier_get_fd(n);
> + CharDriverState *chr;
> +
> + s->msi_vectors[vector].pdev = pdev;
>
> chr = qemu_chr_open_eventfd(eventfd);
>
> @@ -484,6 +546,53 @@ static bool fifo_update_and_get(IVShmemState *s, const uint8_t *buf, int size,
> return true;
> }
>
> +static int ivshmem_add_kvm_msi_virq(IVShmemState *s, int vector)
> +{
> + PCIDevice *pdev = PCI_DEVICE(s);
> + MSIMessage msg = msix_get_message(pdev, vector);
> + int ret;
> +
> + IVSHMEM_DPRINTF("ivshmem_add_kvm_msi_virq vector:%d\n", vector);
> +
> + if (s->msi_vectors[vector].pdev != NULL) {
> + return 0;
> + }
> +
> + ret = kvm_irqchip_add_msi_route(kvm_state, msg); /* */
> + if (ret < 0) {
> + error_report("ivshmem: kvm_irqchip_add_msi_route failed");
> + return -1;
> + }
> +
> + s->msi_vectors[vector].virq = ret;
> + s->msi_vectors[vector].pdev = pdev;
> +
> + return 0;
> +}
> +
> +static void setup_interrupt(IVShmemState *s, int vector)
> +{
> + EventNotifier *n = &s->peers[s->vm_id].eventfds[vector];
> + bool with_irqfd = kvm_msi_via_irqfd_enabled() &&
> + ivshmem_has_feature(s, IVSHMEM_MSI);
> + PCIDevice *pdev = PCI_DEVICE(s);
> +
> + IVSHMEM_DPRINTF("setting up interrupt for vector: %d\n", vector);
> +
> + if (!with_irqfd) {
> + s->eventfd_chr[vector] = create_eventfd_chr_device(s, n, vector);
> + } else if (msix_enabled(pdev)) {
> + if (ivshmem_add_kvm_msi_virq(s, vector) < 0) {
> + return;
> + }
> +
> + if (!msix_is_masked(pdev, vector)) {
> + kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL,
> + s->msi_vectors[vector].virq);
> + }
> + }
Is an } else { here missing?
Should we add IVSHMEM_DPRINTFs to help the developer understand which of these paths have been taken?
> +}
> +
> static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
> {
> IVShmemState *s = opaque;
> @@ -587,11 +696,10 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
> IVSHMEM_DPRINTF("eventfds[%ld][%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) {
> - s->eventfd_chr[new_eventfd] = create_eventfd_chr_device(s,
> - &s->peers[s->vm_id].eventfds[new_eventfd],
> - new_eventfd);
> + setup_interrupt(s, new_eventfd);
> }
>
> if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
> @@ -666,10 +774,65 @@ static int ivshmem_setup_msi(IVShmemState * s)
> return 0;
> }
>
> -static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address,
> +static void ivshmem_enable_irqfd(IVShmemState *s)
> +{
> + PCIDevice *pdev = PCI_DEVICE(s);
> + int i;
> +
> + for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
> + ivshmem_add_kvm_msi_virq(s, i);
> + }
> +
> + if (msix_set_vector_notifiers(pdev,
> + ivshmem_vector_unmask,
> + ivshmem_vector_mask,
> + ivshmem_vector_poll)) {
> + error_report("ivshmem: msix_set_vector_notifiers failed");
> + }
> +}
> +
> +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_disable_irqfd(IVShmemState *s)
> +{
> + PCIDevice *pdev = PCI_DEVICE(s);
> + int i;
> +
> + for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
> + ivshmem_remove_kvm_msi_virq(s, i);
> + }
> +
> + msix_unset_vector_notifiers(pdev);
> +}
> +
> +static void ivshmem_write_config(PCIDevice *pdev, uint32_t address,
> uint32_t val, int len)
> {
> - pci_default_write_config(pci_dev, address, val, len);
> + IVShmemState *s = IVSHMEM(pdev);
> + int is_enabled, was_enabled = msix_enabled(pdev);
> +
> + pci_default_write_config(pdev, address, val, len);
> + is_enabled = msix_enabled(pdev);
> +
> + if (kvm_msi_via_irqfd_enabled() && s->vm_id != -1) {
> + if (!was_enabled && is_enabled) {
> + ivshmem_enable_irqfd(s);
> + } else if (was_enabled && !is_enabled) {
> + ivshmem_disable_irqfd(s);
> + }
> + }
> }
>
> static void pci_ivshmem_realize(PCIDevice *dev, Error **errp)
>
next prev parent reply other threads:[~2015-09-30 11:48 UTC|newest]
Thread overview: 94+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-24 11:37 [Qemu-devel] [PATCH v4 00/47] ivshmem improvements marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 01/47] char: add qemu_chr_free() marcandre.lureau
2015-09-29 13:13 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 02/47] msix: add VMSTATE_MSIX_TEST marcandre.lureau
2015-09-29 13:14 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 03/47] ivhsmem: read do not accept more than sizeof(long) marcandre.lureau
2015-09-29 13:15 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 04/47] ivshmem: fix number of bytes to push to fifo marcandre.lureau
2015-09-29 12:40 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 05/47] ivshmem: factor out the incoming fifo handling marcandre.lureau
2015-09-29 12:41 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 06/47] ivshmem: remove unnecessary dup() marcandre.lureau
2015-09-29 12:41 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 07/47] ivshmem: remove superflous ivshmem_attr field marcandre.lureau
2015-09-29 12:42 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 08/47] ivshmem: remove useless doorbell field marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 09/47] ivshmem: more qdev conversion marcandre.lureau
2015-09-29 12:42 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 10/47] ivshmem: remove last exit(1) marcandre.lureau
2015-09-29 12:43 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 11/47] ivshmem: limit maximum number of peers to G_MAXUINT16 marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 12/47] ivshmem: simplify around increase_dynamic_storage() marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 13/47] ivshmem: allocate eventfds in resize_peers() marcandre.lureau
2015-09-29 12:44 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 14/47] ivshmem: remove useless ivshmem_update_irq() val argument marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 15/47] ivshmem: initialize max_peer to -1 marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 16/47] ivshmem: remove max_peer field marcandre.lureau
2015-09-29 12:44 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 17/47] ivshmem: improve debug messages marcandre.lureau
2015-09-29 13:00 ` Claudio Fontana
2015-09-29 13:12 ` Marc-André Lureau
2015-09-29 13:21 ` Claudio Fontana
2015-09-29 13:24 ` Marc-André Lureau
2015-09-29 13:36 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 18/47] ivshmem: improve error handling marcandre.lureau
2015-09-29 13:01 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 19/47] ivshmem: print error on invalid peer id marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 20/47] ivshmem: simplify a bit the code marcandre.lureau
2015-09-29 13:04 ` Claudio Fontana
2015-09-29 13:06 ` Marc-André Lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 21/47] ivshmem: use common return marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 22/47] ivshmem: use common is_power_of_2() marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 23/47] ivshmem: migrate with VMStateDescription marcandre.lureau
2015-09-29 13:28 ` Claudio Fontana
2015-09-29 13:39 ` Marc-André Lureau
2015-09-29 14:15 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 24/47] ivshmem: shmfd can be 0 marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 25/47] ivshmem: check shm isn't already initialized marcandre.lureau
2015-09-29 13:32 ` Claudio Fontana
2015-09-29 13:34 ` Marc-André Lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 26/47] ivshmem: add device description marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 27/47] ivshmem: fix pci_ivshmem_exit() marcandre.lureau
2015-09-29 13:38 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 28/47] ivshmem: replace 'guest' for 'peer' appropriately marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 29/47] ivshmem: error on too many eventfd received marcandre.lureau
2015-09-29 13:39 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 30/47] ivshmem: reset mask on device reset marcandre.lureau
2015-09-29 13:40 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 31/47] contrib: add ivshmem client and server marcandre.lureau
2015-09-30 8:37 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 32/47] ivshmem-client: check the number of vectors marcandre.lureau
2015-09-29 13:47 ` Claudio Fontana
2015-09-29 14:01 ` Marc-André Lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 33/47] ivshmem-server: use a uint16 for client ID marcandre.lureau
2015-09-29 13:51 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 34/47] ivshmem-server: fix hugetlbfs support marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 35/47] docs: update ivshmem device spec marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 36/47] ivshmem: add check on protocol version in QEMU marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 37/47] contrib: remove unnecessary strdup() marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 38/47] msix: implement pba write (but read-only) marcandre.lureau
2015-10-02 13:47 ` Paolo Bonzini
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 39/47] qtest: add qtest_add_abrt_handler() marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 40/47] tests: add ivshmem qtest marcandre.lureau
2015-09-29 15:05 ` Claudio Fontana
2015-09-29 15:30 ` Marc-André Lureau
2015-09-30 11:38 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 41/47] ivshmem: do not keep shm_fd open marcandre.lureau
2015-09-29 15:10 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 42/47] ivshmem: use strtosz() marcandre.lureau
2015-09-24 12:13 ` Marc-André Lureau
2015-09-24 12:33 ` Marc-André Lureau
2015-09-29 14:34 ` Claudio Fontana
2015-09-29 14:51 ` Marc-André Lureau
2015-09-30 8:39 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 43/47] ivshmem: add hostmem backend marcandre.lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 44/47] ivshmem: remove EventfdEntry.vector marcandre.lureau
2015-09-29 14:32 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 45/47] ivshmem: rename MSI eventfd_table marcandre.lureau
2015-09-29 15:11 ` Claudio Fontana
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 46/47] ivshmem: use kvm irqfd for msi notifications marcandre.lureau
2015-09-30 11:47 ` Claudio Fontana [this message]
2015-10-02 13:29 ` Marc-André Lureau
2015-09-24 11:37 ` [Qemu-devel] [PATCH v4 47/47] ivshmem: use little-endian int64_t for the protocol marcandre.lureau
2015-09-29 14:28 ` Claudio Fontana
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=560BCBE7.7050001@huawei.com \
--to=claudio.fontana@huawei.com \
--cc=cam@cs.ualberta.ca \
--cc=drjones@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.