From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:45712) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tb3OR-0006S5-IA for qemu-devel@nongnu.org; Wed, 21 Nov 2012 01:02:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tb3OQ-0003PR-DY for qemu-devel@nongnu.org; Wed, 21 Nov 2012 01:02:39 -0500 Received: from mail-oa0-f45.google.com ([209.85.219.45]:58210) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tb3OQ-0003PH-7g for qemu-devel@nongnu.org; Wed, 21 Nov 2012 01:02:38 -0500 Received: by mail-oa0-f45.google.com with SMTP id i18so6295511oag.4 for ; Tue, 20 Nov 2012 22:02:37 -0800 (PST) From: Liu Ping Fan Date: Wed, 21 Nov 2012 14:02:31 +0800 Message-Id: <1353477751-9846-1-git-send-email-qemulist@gmail.com> Subject: [Qemu-devel] [PATCH] ivshmem: use irqfd to interrupt among VMs List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Jan Kiszka , Cam Macdonell From: Liu Ping Fan Using irqfd, so we can avoid switch between kernel and user when VMs interrupts each other. Signed-off-by: Liu Ping Fan --- hw/ivshmem.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 47 insertions(+), 1 deletions(-) diff --git a/hw/ivshmem.c b/hw/ivshmem.c index f6dbb21..81c7354 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -19,6 +19,7 @@ #include "hw.h" #include "pc.h" #include "pci.h" +#include "msi.h" #include "msix.h" #include "kvm.h" #include "migration.h" @@ -54,6 +55,11 @@ typedef struct EventfdEntry { int vector; } EventfdEntry; +typedef struct IrqfdEntry { + int virq; + bool used; +} IrqfdEntry; + typedef struct IVShmemState { PCIDevice dev; uint32_t intrmask; @@ -83,6 +89,8 @@ typedef struct IVShmemState { uint32_t vectors; uint32_t features; EventfdEntry *eventfd_table; + IrqfdEntry *vector_irqfd; + bool irqfd_enable; Error *migration_blocker; @@ -632,6 +640,38 @@ static void ivshmem_write_config(PCIDevice *pci_dev, uint32_t address, msix_write_config(pci_dev, address, val, len); } +static int ivshmem_vector_use(PCIDevice *dev, unsigned vector, + MSIMessage msg) +{ + IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); + int virq; + EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; + + virq = kvm_irqchip_add_msi_route(kvm_state, msg); + if (virq >= 0 && kvm_irqchip_add_irqfd_notifier(kvm_state, n, virq) >= 0) { + s->vector_irqfd[vector].virq = virq; + s->vector_irqfd[vector].used = true; + qemu_chr_add_handlers(s->eventfd_chr[vector], NULL, NULL, NULL, NULL); + } else if (virq >= 0) { + kvm_irqchip_release_virq(kvm_state, virq); + } + return 0; +} + +static void ivshmem_vector_release(PCIDevice *dev, unsigned vector) +{ + IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); + EventNotifier *n = &s->peers[s->vm_id].eventfds[vector]; + int virq = s->vector_irqfd[vector].virq; + + if (s->vector_irqfd[vector].used) { + kvm_irqchip_remove_irqfd_notifier(kvm_state, n, virq); + kvm_irqchip_release_virq(kvm_state, virq); + s->vector_irqfd[vector].virq = -1; + s->vector_irqfd[vector].used = false; + } +} + static int pci_ivshmem_init(PCIDevice *dev) { IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); @@ -759,7 +799,13 @@ static int pci_ivshmem_init(PCIDevice *dev) } s->dev.config_write = ivshmem_write_config; - + if (kvm_gsi_routing_enabled()) { + s->irqfd_enable = msix_set_vector_notifiers(dev, ivshmem_vector_use, + ivshmem_vector_release) >= 0 ? true : false; + if (s->irqfd_enable) { + s->vector_irqfd = g_new0(IrqfdEntry, s->vectors); + } + } return 0; } -- 1.7.4.4