[PATCH v2 02/20] pci-assign: Factor out kvm_device_pci_assign/deassign

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <jan.kiszka@xxxxxxxxxxx>
---
 hw/device-assignment.c |   46 ++++++++++++----------------------------------
 qemu-kvm.c             |   14 --------------
 qemu-kvm.h             |   24 ------------------------
 target-i386/kvm.c      |   35 +++++++++++++++++++++++++++++++++++
 target-i386/kvm_i386.h |    6 ++++++
 5 files changed, 53 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..77c39e3 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,37 @@ 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 = {
+        .segnr = dev_addr->domain,
+        .busnr = dev_addr->bus,
+        .devfn = PCI_DEVFN(dev_addr->slot, dev_addr->function),
+        .flags = flags,
+    };
+    int ret;
+
+    dev_data.assigned_dev_id =
+        (dev_addr->domain << 16) | (dev_addr->bus << 8) | dev_data.devfn;
+
+    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 = {
+        .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
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux