From patchwork Fri Aug 17 06:58:56 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 1337531 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 5D0EDDF266 for ; Fri, 17 Aug 2012 07:00:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030187Ab2HQG72 (ORCPT ); Fri, 17 Aug 2012 02:59:28 -0400 Received: from thoth.sbs.de ([192.35.17.2]:30485 "EHLO thoth.sbs.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S964887Ab2HQG7Y (ORCPT ); Fri, 17 Aug 2012 02:59:24 -0400 Received: from mail1.siemens.de (localhost [127.0.0.1]) by thoth.sbs.de (8.13.6/8.13.6) with ESMTP id q7H6xKK6020994; Fri, 17 Aug 2012 08:59:20 +0200 Received: from mchn199C.mchp.siemens.de.com ([146.254.78.141]) by mail1.siemens.de (8.13.6/8.13.6) with SMTP id q7H6xF6x015872; Fri, 17 Aug 2012 08:59:20 +0200 From: Jan Kiszka To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, Alex Williamson , "Michael S. Tsirkin" Subject: [PATCH v2 08/20] pci-assign: Rework MSI assignment Date: Fri, 17 Aug 2012 08:58:56 +0200 Message-Id: X-Mailer: git-send-email 1.7.3.4 In-Reply-To: References: In-Reply-To: References: Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Introduce kvm_device_msi_assign and use upstream's kvm_irqchip_add_msi_route/kvm_irqchip_release_virq to provide MSI support for assigned devices. Signed-off-by: Jan Kiszka --- hw/device-assignment.c | 54 +++++++++++++++++++++++++---------------------- target-i386/kvm.c | 6 +++++ target-i386/kvm_i386.h | 1 + 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index d448fdc..1d0af34 100644 --- a/hw/device-assignment.c +++ b/hw/device-assignment.c @@ -41,6 +41,7 @@ #include "range.h" #include "sysemu.h" #include "pci.h" +#include "msi.h" #include "kvm_i386.h" #define MSIX_PAGE_SIZE 0x1000 @@ -138,6 +139,8 @@ typedef struct AssignedDevice { } cap; uint8_t emulate_config_read[PCI_CONFIG_SPACE_SIZE]; uint8_t emulate_config_write[PCI_CONFIG_SPACE_SIZE]; + int msi_virq_nr; + int *msi_virq; int irq_entries_nr; struct kvm_irq_routing_entry *entry; MSIXTableEntry *msix_table; @@ -702,6 +705,16 @@ static void free_dev_irq_entries(AssignedDevice *dev) { int i; + for (i = 0; i < dev->msi_virq_nr; i++) { + if (dev->msi_virq[i] >= 0) { + kvm_irqchip_release_virq(kvm_state, dev->msi_virq[i]); + dev->msi_virq[i] = -1; + } + } + g_free(dev->msi_virq); + dev->msi_virq = NULL; + dev->msi_virq_nr = 0; + for (i = 0; i < dev->irq_entries_nr; i++) { if (dev->entry[i].type) { kvm_del_routing_entry(&dev->entry[i]); @@ -973,7 +986,6 @@ static void assigned_dev_update_irq_routing(PCIDevice *dev) static void assigned_dev_update_msi(PCIDevice *pci_dev) { - struct kvm_assigned_irq assigned_irq_data; AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); uint8_t ctrl_byte = pci_get_byte(pci_dev->config + pci_dev->msi_cap + PCI_MSI_FLAGS); @@ -984,43 +996,35 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev) * MSI or intends to start. */ if (assigned_dev->assigned_irq_type == ASSIGNED_IRQ_MSI || (ctrl_byte & PCI_MSI_FLAGS_ENABLE)) { - - free_dev_irq_entries(assigned_dev); r = kvm_device_msi_deassign(kvm_state, assigned_dev->dev_id); /* -ENXIO means no assigned irq */ if (r && r != -ENXIO) perror("assigned_dev_update_msi: deassign irq"); + free_dev_irq_entries(assigned_dev); + assigned_dev->assigned_irq_type = ASSIGNED_IRQ_NONE; pci_device_set_intx_routing_notifier(pci_dev, NULL); } if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) { uint8_t *pos = pci_dev->config + pci_dev->msi_cap; - - assigned_dev->entry = g_malloc0(sizeof(*(assigned_dev->entry))); - assigned_dev->entry->u.msi.address_lo = - pci_get_long(pos + PCI_MSI_ADDRESS_LO); - assigned_dev->entry->u.msi.address_hi = 0; - assigned_dev->entry->u.msi.data = pci_get_word(pos + PCI_MSI_DATA_32); - assigned_dev->entry->type = KVM_IRQ_ROUTING_MSI; - r = kvm_get_irq_route_gsi(); - if (r < 0) { - perror("assigned_dev_update_msi: kvm_get_irq_route_gsi"); + MSIMessage msg; + int virq; + + msg.address = pci_get_long(pos + PCI_MSI_ADDRESS_LO); + msg.data = pci_get_word(pos + PCI_MSI_DATA_32); + virq = kvm_irqchip_add_msi_route(kvm_state, msg); + if (virq < 0) { + perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route"); return; } - assigned_dev->entry->gsi = r; - kvm_add_routing_entry(kvm_state, assigned_dev->entry); - kvm_irqchip_commit_routes(kvm_state); - assigned_dev->irq_entries_nr = 1; - - memset(&assigned_irq_data, 0, sizeof assigned_irq_data); - assigned_irq_data.assigned_dev_id = assigned_dev->dev_id; - assigned_irq_data.guest_irq = assigned_dev->entry->gsi; - assigned_irq_data.flags = KVM_DEV_IRQ_HOST_MSI | KVM_DEV_IRQ_GUEST_MSI; - if (kvm_assign_irq(kvm_state, &assigned_irq_data) < 0) { - perror("assigned_dev_enable_msi: assign irq"); + assigned_dev->msi_virq = g_malloc(sizeof(*assigned_dev->msi_virq)); + assigned_dev->msi_virq_nr = 1; + assigned_dev->msi_virq[0] = virq; + if (kvm_device_msi_assign(kvm_state, assigned_dev->dev_id, virq) < 0) { + perror("assigned_dev_update_msi: kvm_device_msi_assign"); } assigned_dev->intx_route.mode = PCI_INTX_DISABLED; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index c92b813..51be7b5 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2143,6 +2143,12 @@ int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi) (use_host_msi ? KVM_DEV_IRQ_HOST_MSI : KVM_DEV_IRQ_HOST_INTX)); } +int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq) +{ + return kvm_assign_irq_internal(s, dev_id, KVM_DEV_IRQ_HOST_MSI | + KVM_DEV_IRQ_GUEST_MSI, virq); +} + int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id) { return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSI | diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h index 28f26bb..e827f5b 100644 --- a/target-i386/kvm_i386.h +++ b/target-i386/kvm_i386.h @@ -24,6 +24,7 @@ int kvm_device_intx_assign(KVMState *s, uint32_t dev_id, int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked); int kvm_device_intx_deassign(KVMState *s, uint32_t dev_id, bool use_host_msi); +int kvm_device_msi_assign(KVMState *s, uint32_t dev_id, int virq); int kvm_device_msi_deassign(KVMState *s, uint32_t dev_id); int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id);