qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC][PATCH 39/45] pci-assign: Use generic MSI support


From: Jan Kiszka
Subject: [Qemu-devel] [RFC][PATCH 39/45] pci-assign: Use generic MSI support
Date: Mon, 17 Oct 2011 11:28:13 +0200

Implement MSI support of a assigned devices via the generic MSI layer of
QEMU. Use config notifiers to update the vector route or switch back to
INTx when MSI gets disabled again.

Using the generic layer not only saves a bit code, it also fixes reset
while legacy MSI is in use and adds 64 bit support.

Signed-off-by: Jan Kiszka <address@hidden>
---
 hw/device-assignment.c |   77 +++++++++++++++++++----------------------------
 1 files changed, 31 insertions(+), 46 deletions(-)

diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index 2484afd..10b30a3 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -699,10 +699,6 @@ static void free_assigned_device(AssignedDevice *dev)
         close(dev->real_device.config_fd);
     }
 
-    if (dev->dev.msi_cache) {
-        kvm_msi_cache_invalidate(&dev->dev.msi_cache[0]);
-        g_free(dev->dev.msi_cache);
-    }
     invalidate_msix_vectors(dev);
     g_free(dev->dev.msix_cache);
 }
@@ -847,7 +843,7 @@ static int assign_intx(AssignedDevice *dev)
 
     irq_type = KVM_DEV_IRQ_GUEST_INTX;
     if (dev->features & ASSIGNED_DEVICE_PREFER_MSI_MASK &&
-        dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
+        msi_present(&dev->dev)) {
         irq_type |= KVM_DEV_IRQ_HOST_MSI;
     } else {
         irq_type |= KVM_DEV_IRQ_HOST_INTX;
@@ -920,31 +916,33 @@ void assigned_dev_update_irqs(void)
     }
 }
 
-static void assigned_dev_update_msi(PCIDevice *pci_dev)
+static void assigned_dev_update_msi(PCIDevice *pci_dev, bool enabled)
 {
     AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
-    uint8_t ctrl_byte = pci_get_byte(pci_dev->config + pci_dev->msi_cap +
-                                     PCI_MSI_FLAGS);
-
-    if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) {
-        uint8_t *pos = pci_dev->config + pci_dev->msi_cap;
-        MSIMessage msg;
 
-        deassign_irq(dev);
+    if (!enabled) {
+        assign_intx(dev);
+    }
+}
 
-        msg.address = pci_get_long(pos + PCI_MSI_ADDRESS_LO);
-        msg.data = pci_get_word(pos + PCI_MSI_DATA_32);
+static int assigned_dev_update_msi_vector(PCIDevice *pci_dev,
+                                          unsigned int vector,
+                                          MSIMessage *msg, bool masked)
+{
+    AssignedDevice *dev = DO_UPCAST(AssignedDevice, dev, pci_dev);
+    int ret;
 
-        if (kvm_device_msi_assign(kvm_state, calc_assigned_dev_id(dev), &msg,
-                                  &dev->dev.msi_cache[0]) < 0) {
-            perror("assigned_dev_update_msi: assign msi");
-            return;
+    if (!masked) {
+        deassign_irq(dev);
+        ret = kvm_device_msi_assign(kvm_state, calc_assigned_dev_id(dev), msg,
+                                    &dev->dev.msi_cache[0]);
+        if (ret < 0) {
+            perror("assigned_dev_update_msi_vector: assign msi");
+            return ret;
         }
         dev->irq_requested_type = KVM_DEV_IRQ_HOST_MSI | KVM_DEV_IRQ_GUEST_MSI;
-    } else {
-        kvm_msi_cache_invalidate(&dev->dev.msi_cache[0]);
-        assign_intx(dev);
     }
+    return 0;
 }
 
 static int assigned_dev_set_msix_vectors(PCIDevice *pci_dev)
@@ -1085,12 +1083,6 @@ static void assigned_dev_pci_write_config(PCIDevice 
*pci_dev, uint32_t address,
 
     pci_default_write_config(pci_dev, address, val, len);
 
-    if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
-        if (range_covers_byte(address, len,
-                              pci_dev->msi_cap + PCI_MSI_FLAGS)) {
-            assigned_dev_update_msi(pci_dev);
-        }
-    }
     if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
         if (range_covers_byte(address, len,
                               pci_dev->msix_cap + PCI_MSIX_FLAGS + 1)) {
@@ -1136,26 +1128,19 @@ static int assigned_device_pci_cap_init(PCIDevice 
*pci_dev)
      * MSI capability is the 1st capability in capability config */
     pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSI, 0);
     if (pos != 0 && kvm_check_extension(kvm_state, KVM_CAP_ASSIGN_DEV_IRQ)) {
-        dev->cap.available |= ASSIGNED_DEVICE_CAP_MSI;
-        /* Only 32-bit/no-mask currently supported */
-        if ((ret = pci_add_capability(pci_dev, PCI_CAP_ID_MSI, pos, 10)) < 0) {
+        uint16_t flags = pci_get_word(pci_dev->config + pos + PCI_MSI_FLAGS);
+
+        /* Note: KVM does not support multiple messages */
+        ret = msi_init(pci_dev, pos, 1, flags & PCI_MSI_FLAGS_64BIT,
+                       flags & PCI_MSI_FLAGS_MASKBIT);
+        if (ret < 0) {
+            return ret;
+        }
+        ret = msi_set_config_notifiers(pci_dev, assigned_dev_update_msi,
+                                       assigned_dev_update_msi_vector);
+        if (ret < 0) {
             return ret;
         }
-        pci_dev->msi_cap = pos;
-
-        pci_set_word(pci_dev->config + pos + PCI_MSI_FLAGS,
-                     pci_get_word(pci_dev->config + pos + PCI_MSI_FLAGS) &
-                     PCI_MSI_FLAGS_QMASK);
-        pci_set_long(pci_dev->config + pos + PCI_MSI_ADDRESS_LO, 0);
-        pci_set_word(pci_dev->config + pos + PCI_MSI_DATA_32, 0);
-
-        /* Set writable fields */
-        pci_set_word(pci_dev->wmask + pos + PCI_MSI_FLAGS,
-                     PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
-        pci_set_long(pci_dev->wmask + pos + PCI_MSI_ADDRESS_LO, 0xfffffffc);
-        pci_set_word(pci_dev->wmask + pos + PCI_MSI_DATA_32, 0xffff);
-
-        dev->dev.msi_cache = g_malloc0(sizeof(MSIRoutingCache));
     }
     /* Expose MSI-X capability */
     pos = pci_find_cap_offset(pci_dev, PCI_CAP_ID_MSIX, 0);
-- 
1.7.3.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]