From patchwork Thu Aug 16 13:54:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 1332131 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 1DBA840211 for ; Thu, 16 Aug 2012 13:54:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932163Ab2HPNyo (ORCPT ); Thu, 16 Aug 2012 09:54:44 -0400 Received: from goliath.siemens.de ([192.35.17.28]:22689 "EHLO goliath.siemens.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757061Ab2HPNyl (ORCPT ); Thu, 16 Aug 2012 09:54:41 -0400 Received: from mail1.siemens.de (localhost [127.0.0.1]) by goliath.siemens.de (8.13.6/8.13.6) with ESMTP id q7GDsY2H030756; Thu, 16 Aug 2012 15:54:35 +0200 Received: from mchn199C.mchp.siemens.de ([139.25.109.49]) by mail1.siemens.de (8.13.6/8.13.6) with ESMTP id q7GDsYJC012893; Thu, 16 Aug 2012 15:54:34 +0200 From: Jan Kiszka To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, Alex Williamson Subject: [PATCH 02/19] pci-assign: Factor out kvm_device_pci_assign/deassign Date: Thu, 16 Aug 2012 15:54:16 +0200 Message-Id: <058bc548d7413a1e912e3c5e9f703440db58a8ca.1345125266.git.jan.kiszka@siemens.com> 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 In contrast to the old wrappers, the new ones only take the required parameters instead of a preinitialized kvm_assigned_pci_dev structure. We also move the dev_id generation into kvm_device_pci_assign and store the result in the AssignedDevice structure. It will serve as handle for all upcoming kvm_device_* functions. While refactoring these services, start moving KVM services where they should finally end up in upstream QEMU: in the i386-specific KVM layer. Signed-off-by: Jan Kiszka --- hw/device-assignment.c | 46 ++++++++++++---------------------------------- qemu-kvm.c | 14 -------------- qemu-kvm.h | 24 ------------------------ target-i386/kvm.c | 36 ++++++++++++++++++++++++++++++++++++ target-i386/kvm_i386.h | 6 ++++++ 5 files changed, 54 insertions(+), 72 deletions(-) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index 529e229..3f6196a 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 "kvm_i386.h" #define MSIX_PAGE_SIZE 0x1000 @@ -108,6 +109,7 @@ typedef struct { typedef struct AssignedDevice { PCIDevice dev; PCIHostDeviceAddress host; + uint32_t dev_id; uint32_t features; int intpin; uint8_t debug_flags; @@ -115,9 +117,6 @@ typedef struct AssignedDevice { PCIDevRegions real_device; int run; PCIINTxRoute intx_route; - uint16_t h_segnr; - uint8_t h_busnr; - uint8_t h_devfn; int irq_requested_type; int bound; struct { @@ -761,12 +760,6 @@ static void free_assigned_device(AssignedDevice *dev) free_dev_irq_entries(dev); } -static uint32_t calc_assigned_dev_id(AssignedDevice *dev) -{ - return (uint32_t)dev->h_segnr << 16 | (uint32_t)dev->h_busnr << 8 | - (uint32_t)dev->h_devfn; -} - static void assign_failed_examine(AssignedDevice *dev) { char name[PATH_MAX], dir[PATH_MAX], driver[PATH_MAX] = {}, *ns; @@ -820,24 +813,17 @@ fail: static int assign_device(AssignedDevice *dev) { - struct kvm_assigned_pci_dev assigned_dev_data; + uint32_t flags = KVM_DEV_ASSIGN_ENABLE_IOMMU; int r; /* Only pass non-zero PCI segment to capable module */ if (!kvm_check_extension(kvm_state, KVM_CAP_PCI_SEGMENT) && - dev->h_segnr) { + dev->host.domain) { fprintf(stderr, "Can't assign device inside non-zero PCI segment " "as this KVM module doesn't support it.\n"); return -ENODEV; } - memset(&assigned_dev_data, 0, sizeof(assigned_dev_data)); - assigned_dev_data.assigned_dev_id = calc_assigned_dev_id(dev); - assigned_dev_data.segnr = dev->h_segnr; - assigned_dev_data.busnr = dev->h_busnr; - assigned_dev_data.devfn = dev->h_devfn; - - assigned_dev_data.flags = KVM_DEV_ASSIGN_ENABLE_IOMMU; if (!kvm_check_extension(kvm_state, KVM_CAP_IOMMU)) { fprintf(stderr, "No IOMMU found. Unable to assign device \"%s\"\n", dev->dev.qdev.id); @@ -846,10 +832,10 @@ static int assign_device(AssignedDevice *dev) if (dev->features & ASSIGNED_DEVICE_SHARE_INTX_MASK && kvm_has_intx_set_mask()) { - assigned_dev_data.flags |= KVM_DEV_ASSIGN_PCI_2_3; + flags |= KVM_DEV_ASSIGN_PCI_2_3; } - r = kvm_assign_pci_device(kvm_state, &assigned_dev_data); + r = kvm_device_pci_assign(kvm_state, &dev->host, flags, &dev->dev_id); if (r < 0) { fprintf(stderr, "Failed to assign device \"%s\" : %s\n", dev->dev.qdev.id, strerror(-r)); @@ -889,7 +875,7 @@ static int assign_irq(AssignedDevice *dev) } memset(&assigned_irq_data, 0, sizeof(assigned_irq_data)); - assigned_irq_data.assigned_dev_id = calc_assigned_dev_id(dev); + assigned_irq_data.assigned_dev_id = dev->dev_id; assigned_irq_data.guest_irq = intx_route.irq; if (dev->irq_requested_type) { assigned_irq_data.flags = dev->irq_requested_type; @@ -940,13 +926,9 @@ retry: static void deassign_device(AssignedDevice *dev) { - struct kvm_assigned_pci_dev assigned_dev_data; int r; - memset(&assigned_dev_data, 0, sizeof(assigned_dev_data)); - assigned_dev_data.assigned_dev_id = calc_assigned_dev_id(dev); - - r = kvm_deassign_pci_device(kvm_state, &assigned_dev_data); + r = kvm_device_pci_deassign(kvm_state, dev->dev_id); if (r < 0) fprintf(stderr, "Failed to deassign device \"%s\" : %s\n", dev->dev.qdev.id, strerror(-r)); @@ -977,7 +959,7 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev) int r; memset(&assigned_irq_data, 0, sizeof assigned_irq_data); - assigned_irq_data.assigned_dev_id = calc_assigned_dev_id(assigned_dev); + assigned_irq_data.assigned_dev_id = assigned_dev->dev_id; /* Some guests gratuitously disable MSI even if they're not using it, * try to catch this by only deassigning irqs if the guest is using @@ -1059,7 +1041,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) return 0; } - msix_nr.assigned_dev_id = calc_assigned_dev_id(adev); + msix_nr.assigned_dev_id = adev->dev_id; msix_nr.entry_nr = entries_nr; r = kvm_assign_set_msix_nr(kvm_state, &msix_nr); if (r != 0) { @@ -1121,7 +1103,7 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev) int r; memset(&assigned_irq_data, 0, sizeof assigned_irq_data); - assigned_irq_data.assigned_dev_id = calc_assigned_dev_id(assigned_dev); + assigned_irq_data.assigned_dev_id = assigned_dev->dev_id; /* Some guests gratuitously disable MSIX even if they're not using it, * try to catch this by only deassigning irqs if the guest is using @@ -1200,8 +1182,7 @@ static void assigned_dev_pci_write_config(PCIDevice *pci_dev, uint32_t address, PCI_COMMAND_INTX_DISABLE); if (intx_masked != !!(old_cmd & PCI_COMMAND_INTX_DISABLE)) { - ret = kvm_device_intx_set_mask(kvm_state, - calc_assigned_dev_id(assigned_dev), + ret = kvm_device_intx_set_mask(kvm_state, assigned_dev->dev_id, intx_masked); if (ret) { perror("assigned_dev_pci_write_config: set intx mask"); @@ -1782,9 +1763,6 @@ static int assigned_initfn(struct PCIDevice *pci_dev) dev->run = 0; dev->intx_route.mode = PCI_INTX_DISABLED; dev->intx_route.irq = -1; - dev->h_segnr = dev->host.domain; - dev->h_busnr = dev->host.bus; - dev->h_devfn = PCI_DEVFN(dev->host.slot, dev->host.function); /* assign device to guest */ r = assign_device(dev); diff --git a/qemu-kvm.c b/qemu-kvm.c index efdeff1..7bf20d1 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -31,12 +31,6 @@ #define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1)) #ifdef KVM_CAP_DEVICE_ASSIGNMENT -int kvm_assign_pci_device(KVMState *s, - struct kvm_assigned_pci_dev *assigned_dev) -{ - return kvm_vm_ioctl(s, KVM_ASSIGN_PCI_DEVICE, assigned_dev); -} - static int kvm_old_assign_irq(KVMState *s, struct kvm_assigned_irq *assigned_irq) { @@ -77,14 +71,6 @@ int kvm_assign_irq(KVMState *s, struct kvm_assigned_irq *assigned_irq) #endif #endif -#ifdef KVM_CAP_DEVICE_DEASSIGNMENT -int kvm_deassign_pci_device(KVMState *s, - struct kvm_assigned_pci_dev *assigned_dev) -{ - return kvm_vm_ioctl(s, KVM_DEASSIGN_PCI_DEVICE, assigned_dev); -} -#endif - int kvm_del_routing_entry(struct kvm_irq_routing_entry *entry) { #ifdef KVM_CAP_IRQ_ROUTING diff --git a/qemu-kvm.h b/qemu-kvm.h index 3ebbbb6..54e615a 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -33,18 +33,6 @@ #include "kvm.h" /*! - * \brief Notifies host kernel about a PCI device to be assigned to a guest - * - * Used for PCI device assignment, this function notifies the host - * kernel about the assigning of the physical PCI device to a guest. - * - * \param kvm Pointer to the current kvm_context - * \param assigned_dev Parameters, like bus, devfn number, etc - */ -int kvm_assign_pci_device(KVMState *s, - struct kvm_assigned_pci_dev *assigned_dev); - -/*! * \brief Assign IRQ for an assigned device * * Used for PCI device assignment, this function assigns IRQ numbers for @@ -68,18 +56,6 @@ int kvm_deassign_irq(KVMState *s, struct kvm_assigned_irq *assigned_irq); int kvm_device_intx_set_mask(KVMState *s, uint32_t dev_id, bool masked); -/*! - * \brief Notifies host kernel about a PCI device to be deassigned from a guest - * - * Used for hot remove PCI device, this function notifies the host - * kernel about the deassigning of the physical PCI device from a guest. - * - * \param kvm Pointer to the current kvm_context - * \param assigned_dev Parameters, like bus, devfn number, etc - */ -int kvm_deassign_pci_device(KVMState *s, - struct kvm_assigned_pci_dev *assigned_dev); - struct kvm_irq_routing_entry; void kvm_add_routing_entry(KVMState *s, struct kvm_irq_routing_entry *entry); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 696b14a..f944f83 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -31,6 +31,7 @@ #include "hw/apic.h" #include "ioport.h" #include "hyperv.h" +#include "hw/pci.h" //#define DEBUG_KVM @@ -2055,3 +2056,38 @@ void kvm_arch_init_irq_routing(KVMState *s) kvm_msi_via_irqfd_allowed = true; kvm_gsi_routing_allowed = true; } + +/* Classic KVM device assignment interface. Will remain x86 only. */ +int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr, + uint32_t flags, uint32_t *dev_id) +{ + struct kvm_assigned_pci_dev dev_data; + int ret; + + memset(&dev_data, 0, sizeof(dev_data)); + dev_data.segnr = dev_addr->domain; + dev_data.busnr = dev_addr->bus; + dev_data.devfn = PCI_DEVFN(dev_addr->slot, dev_addr->function); + dev_data.assigned_dev_id = + (dev_addr->domain << 16) | (dev_addr->bus << 8) | dev_data.devfn; + dev_data.flags = flags; + + ret = kvm_vm_ioctl(s, KVM_ASSIGN_PCI_DEVICE, &dev_data); + if (ret < 0) { + return ret; + } + + *dev_id = dev_data.assigned_dev_id; + + return 0; +} + +int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id) +{ + struct kvm_assigned_pci_dev dev_data; + + memset(&dev_data, 0, sizeof(dev_data)); + dev_data.assigned_dev_id = dev_id; + + return kvm_vm_ioctl(s, KVM_DEASSIGN_PCI_DEVICE, &dev_data); +} diff --git a/target-i386/kvm_i386.h b/target-i386/kvm_i386.h index b82bbf4..5161f67 100644 --- a/target-i386/kvm_i386.h +++ b/target-i386/kvm_i386.h @@ -11,6 +11,12 @@ #ifndef QEMU_KVM_I386_H #define QEMU_KVM_I386_H +#include "kvm.h" + bool kvm_allows_irq0_override(void); +int kvm_device_pci_assign(KVMState *s, PCIHostDeviceAddress *dev_addr, + uint32_t flags, uint32_t *dev_id); +int kvm_device_pci_deassign(KVMState *s, uint32_t dev_id); + #endif