[libvirt] [PATCH 03/12] libxl: nodeDevice* support for PCI devices

Marek Marczykowski marmarek at invisiblethingslab.com
Wed Apr 10 01:53:55 UTC 2013


For now only for PCI devices. Mostly copy-paste from old xen driver.
---
 src/libxl/libxl_driver.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 193 insertions(+)

diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 40a7a6b..011edf8 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -42,6 +42,7 @@
 #include "libxl.h"
 #include "libxl_driver.h"
 #include "libxl_conf.h"
+#include "node_device_conf.h"
 #include "xen_xm.h"
 #include "virtypedparam.h"
 #include "viruri.h"
@@ -3666,6 +3667,195 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
     return libxlDomainModifyDeviceFlags(dom, xml, flags, LIBXL_DEVICE_UPDATE);
 }
 
+static int
+libxlNodeDeviceGetPciInfo(virNodeDevicePtr dev,
+                               unsigned *domain,
+                               unsigned *bus,
+                               unsigned *slot,
+                               unsigned *function)
+{
+    virNodeDeviceDefPtr def = NULL;
+    virNodeDevCapsDefPtr cap;
+    char *xml = NULL;
+    int ret = -1;
+
+    xml = virNodeDeviceGetXMLDesc(dev, 0);
+    if (!xml)
+        goto out;
+
+    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
+    if (!def)
+        goto out;
+
+    cap = def->caps;
+    while (cap) {
+        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
+            *domain   = cap->data.pci_dev.domain;
+            *bus      = cap->data.pci_dev.bus;
+            *slot     = cap->data.pci_dev.slot;
+            *function = cap->data.pci_dev.function;
+            break;
+        }
+
+        cap = cap->next;
+    }
+
+    if (!cap) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("device %s is not a PCI device"), dev->name);
+        goto out;
+    }
+
+    ret = 0;
+out:
+    virNodeDeviceDefFree(def);
+    VIR_FREE(xml);
+    return ret;
+}
+
+static int
+libxlNodeDeviceDettach(virNodeDevicePtr dev)
+{
+    virPCIDevicePtr pci;
+    unsigned domain, bus, slot, function;
+    int ret = -1;
+
+    if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        return -1;
+
+    pci = virPCIDeviceNew(domain, bus, slot, function);
+    if (!pci)
+        return -1;
+
+    if (virPCIDeviceDetach(pci, NULL, NULL, "pciback") < 0)
+        goto out;
+
+    ret = 0;
+out:
+    virPCIDeviceFree(pci);
+    return ret;
+}
+
+static int
+libxlNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
+{
+    int numdomains;
+    int numpcidevs;
+    int ret = -1, i, j;
+    int *ids = NULL;
+    char *bdf = NULL;
+    char *xref = NULL;
+    unsigned int domain, bus, slot, function;
+    libxl_device_pci *pcidevs = NULL;
+    virConnectPtr conn = dev->conn;
+    libxlDriverPrivatePtr driver = conn->privateData;
+
+    /* Get active domains */
+    numdomains = libxlNumDomains(conn);
+    if (numdomains < 0) {
+        return ret;
+    }
+    if (numdomains > 0){
+        if (VIR_ALLOC_N(ids, numdomains) < 0) {
+            virReportOOMError();
+            goto out;
+        }
+        if ((numdomains = libxlListDomains(conn, &ids[0], numdomains)) < 0) {
+            goto out;
+        }
+    }
+
+    /* Get pci bdf */
+    if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        goto out;
+
+    if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
+                    domain, bus, slot, function) < 0) {
+        virReportOOMError();
+        goto out;
+    }
+
+    libxlDriverLock(driver);
+    /* Check if bdf is assigned to one of active domains */
+    for (i = 0; i < numdomains; i++) {
+        pcidevs = libxl_device_pci_list(driver->ctx, ids[i], &numpcidevs);
+        if (pcidevs == NULL) {
+            continue;
+        } else {
+            for (j = 0; j < numpcidevs; j++) {
+                if (pcidevs[j].bus == bus && pcidevs[j].dev == slot && pcidevs[j].func == function) {
+                    ret = ids[i];
+                    break;
+                }
+            }
+            VIR_FREE(pcidevs);
+        }
+    }
+    libxlDriverUnlock(driver);
+
+    VIR_FREE(xref);
+    VIR_FREE(bdf);
+out:
+    VIR_FREE(ids);
+
+    return ret;
+}
+
+static int
+libxlNodeDeviceReAttach(virNodeDevicePtr dev)
+{
+    virPCIDevicePtr pci;
+    unsigned domain, bus, slot, function;
+    int ret = -1;
+    int domid;
+
+    if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        return -1;
+
+    pci = virPCIDeviceNew(domain, bus, slot, function);
+    if (!pci)
+        return -1;
+
+    /* Check if device is assigned to an active guest */
+    if ((domid = libxlNodeDeviceAssignedDomainId(dev)) >= 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Device %s has been assigned to guest %d"),
+                       dev->name, domid);
+        goto out;
+    }
+
+    if (virPCIDeviceReattach(pci, NULL, NULL, "pciback") < 0)
+        goto out;
+
+    ret = 0;
+out:
+    virPCIDeviceFree(pci);
+    return ret;
+}
+
+static int
+libxlNodeDeviceReset(virNodeDevicePtr dev)
+{
+    virPCIDevicePtr pci;
+    unsigned domain, bus, slot, function;
+    int ret = -1;
+
+    if (libxlNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+        return -1;
+
+    pci = virPCIDeviceNew(domain, bus, slot, function);
+    if (!pci)
+        return -1;
+
+    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
+        goto out;
+
+    ret = 0;
+out:
+    virPCIDeviceFree(pci);
+    return ret;
+}
+
 static unsigned long long
 libxlNodeGetFreeMemory(virConnectPtr conn)
 {
@@ -4233,6 +4423,9 @@ static virDriver libxlDriver = {
     .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
     .domainEventRegister = libxlDomainEventRegister, /* 0.9.0 */
     .domainEventDeregister = libxlDomainEventDeregister, /* 0.9.0 */
+    .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.0.4 */
+    .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.0.4 */
+    .nodeDeviceReset = libxlNodeDeviceReset, /* 1.0.4 */
     .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
     .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
     .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
-- 
1.8.1.4





More information about the libvir-list mailing list