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

[Xen-devel] [PATCH 23 of 23] libxl: convert PCI device handling to device API



# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1317389278 -3600
# Node ID f0ab7f2102b37968da2181825ac492b14bc4b449
# Parent  dc967a4691d5a7e05eac3522ab78c573a084b63c
libxl: convert PCI device handling to device API

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>

diff -r dc967a4691d5 -r f0ab7f2102b3 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Fri Sep 30 14:27:28 2011 +0100
+++ b/tools/libxl/libxl.c       Fri Sep 30 14:27:58 2011 +0100
@@ -754,7 +754,7 @@ int libxl_domain_destroy(libxl_ctx *ctx,
         goto out;
     }
 
-    if (libxl_device_pci_shutdown(ctx, domid) < 0)
+    if (libxl__device_pci_force_remove_all(&gc, domid) < 0)
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "pci shutdown failed for domid %d", 
domid);
     rc = xc_domain_pause(ctx->xch, domid);
     if (rc < 0) {
diff -r dc967a4691d5 -r f0ab7f2102b3 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Fri Sep 30 14:27:28 2011 +0100
+++ b/tools/libxl/libxl.h       Fri Sep 30 14:27:58 2011 +0100
@@ -498,12 +498,28 @@ int libxl_device_vfb_add(libxl_ctx *ctx,
 int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb 
*vfb);
 int libxl_device_vfb_force_remove(libxl_ctx *ctx, uint32_t domid, 
libxl_device_vfb *vfb);
 
+/* PCI Passthrough */
+int libxl_device_pci_init(libxl_ctx *ctx, libxl_device_pci *pci);
 int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev);
-int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev, int force);
-int libxl_device_pci_shutdown(libxl_ctx *ctx, uint32_t domid);
-int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, 
uint32_t domid, int *num);
-int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, 
int *num);
-int libxl_device_pci_parse_bdf(libxl_ctx *ctx, libxl_device_pci *pcidev, const 
char *str);
+int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev);
+int libxl_device_pci_force_remove(libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev);
+libxl_device_pci *libxl_device_pci_list(libxl_ctx *ctx, uint32_t domid, int 
*num);
+
+/*
+ * Parse a PCI BDF into a PCI device structure.
+ */
+int libxl_device_pci_parse_bdf(libxl_ctx *ctx,
+                               libxl_device_pci *pcidev,
+                               const char *str);
+
+/*
+ * Similar to libxl_device_pci_list but returns all devices which
+ * could be assigned to a domain (i.e. are bound to the backend
+ * driver) but are not currently.
+ */
+libxl_device_pci *libxl_device_pci_list_assignable(libxl_ctx *ctx, int *num);
+
+/* CPUID handling */
 int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str);
 int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
                                   const char* str);
diff -r dc967a4691d5 -r f0ab7f2102b3 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Fri Sep 30 14:27:28 2011 +0100
+++ b/tools/libxl/libxl_internal.h      Fri Sep 30 14:27:58 2011 +0100
@@ -252,6 +252,7 @@ _hidden int libxl__wait_for_backend(libx
 _hidden int libxl__device_pci_add(libxl__gc *gc, uint32_t domid, 
libxl_device_pci *pcidev, int starting);
 _hidden int libxl__create_pci_backend(libxl__gc *gc, uint32_t domid,
                                       libxl_device_pci *pcidev, int num);
+_hidden int libxl__device_pci_force_remove_all(libxl__gc *gc, uint32_t domid);
 
 /* xl_exec */
 
diff -r dc967a4691d5 -r f0ab7f2102b3 tools/libxl/libxl_pci.c
--- a/tools/libxl/libxl_pci.c   Fri Sep 30 14:27:28 2011 +0100
+++ b/tools/libxl/libxl_pci.c   Fri Sep 30 14:27:58 2011 +0100
@@ -486,7 +486,7 @@ static int is_assigned(libxl_device_pci 
     return 0;
 }
 
-int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, 
int *num)
+libxl_device_pci *libxl_device_pci_list_assignable(libxl_ctx *ctx, int *num)
 {
     libxl__gc gc = LIBXL_INIT_GC(ctx);
     libxl_device_pci *pcidevs = NULL, *new, *assigned;
@@ -495,13 +495,10 @@ int libxl_device_pci_list_assignable(lib
     int rc, num_assigned;
 
     *num = 0;
-    *list = NULL;
 
     rc = get_all_assigned_devices(&gc, &assigned, &num_assigned);
-    if ( rc ) {
-        libxl__free_all(&gc);
-        return rc;
-    }
+    if ( rc )
+        goto out;
 
     dir = opendir(SYSFS_PCIBACK_DRIVER);
     if ( NULL == dir ) {
@@ -510,8 +507,7 @@ int libxl_device_pci_list_assignable(lib
         }else{
             LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't open %s", 
SYSFS_PCIBACK_DRIVER);
         }
-        libxl__free_all(&gc);
-        return ERROR_FAIL;
+        goto out_closedir;
     }
 
     while( (de = readdir(dir)) ) {
@@ -534,10 +530,11 @@ int libxl_device_pci_list_assignable(lib
         (*num)++;
     }
 
+out_closedir:
     closedir(dir);
-    *list = pcidevs;
+out:
     libxl__free_all(&gc);
-    return 0;
+    return pcidevs;
 }
 
 /*
@@ -846,21 +843,25 @@ static int do_pci_remove(libxl__gc *gc, 
     int hvm = 0, rc, num;
     int stubdomid = 0;
 
-    if ( !libxl_device_pci_list_assigned(ctx, &assigned, domid, &num) ) {
-        if ( !is_assigned(assigned, num, pcidev->domain,
-                         pcidev->bus, pcidev->dev, pcidev->func) ) {
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "PCI device not attached to this 
domain");
-            return ERROR_INVAL;
-        }
+    assigned = libxl_device_pci_list(ctx, domid, &num);
+    if ( assigned == NULL )
+        return ERROR_FAIL;
+
+    rc = ERROR_INVAL;
+    if ( !is_assigned(assigned, num, pcidev->domain,
+                      pcidev->bus, pcidev->dev, pcidev->func) ) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "PCI device not attached to this 
domain");
+        goto out_fail;
     }
 
+    rc = ERROR_FAIL;
     switch (libxl__domain_type(gc, domid)) {
     case LIBXL_DOMAIN_TYPE_HVM:
         hvm = 1;
         if (libxl__wait_for_device_model(gc, domid, "running",
-                                         NULL, NULL, NULL) < 0) {
-            return ERROR_FAIL;
-        }
+                                         NULL, NULL, NULL) < 0)
+            goto out_fail;
+
         path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", 
domid);
         state = libxl__xs_read(gc, XBT_NULL, path);
         path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", 
domid);
@@ -879,7 +880,7 @@ static int do_pci_remove(libxl__gc *gc, 
                  * SCI, if it doesn't respond in time then we may wish to
                  * force the removal.
                  */
-                return ERROR_FAIL;
+                goto out_fail;
             }
         }
         path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", 
domid);
@@ -955,25 +956,31 @@ out:
     stubdomid = libxl_get_stubdom_id(ctx, domid);
     if (stubdomid != 0) {
         libxl_device_pci pcidev_s = *pcidev;
-        libxl_device_pci_remove(ctx, stubdomid, &pcidev_s, force);
+        if (force)
+                libxl_device_pci_force_remove(ctx, stubdomid, &pcidev_s);
+        else
+                libxl_device_pci_remove(ctx, stubdomid, &pcidev_s);
     }
 
     libxl__device_pci_remove_xenstore(gc, domid, pcidev);
 
-    return 0;
+    rc = 0;
+out_fail:
+    free(assigned);
+    return rc;
+
 }
 
-int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid,
-                            libxl_device_pci *pcidev, int force)
+static int libxl__device_pci_remove_common(libxl__gc *gc, uint32_t domid,
+                                           libxl_device_pci *pcidev, int force)
 {
-    libxl__gc gc = LIBXL_INIT_GC(ctx);
     unsigned int orig_vdev, pfunc_mask;
     int i, rc;
 
     orig_vdev = pcidev->vdevfn & ~7U;
 
     if ( pcidev->vfunc_mask == LIBXL_PCI_FUNC_ALL ) {
-        if ( pci_multifunction_check(&gc, pcidev, &pfunc_mask) ) {
+        if ( pci_multifunction_check(gc, pcidev, &pfunc_mask) ) {
             rc = ERROR_FAIL;
             goto out;
         }
@@ -990,81 +997,118 @@ int libxl_device_pci_remove(libxl_ctx *c
             }else{
                 pcidev->vdevfn = orig_vdev;
             }
-            if ( do_pci_remove(&gc, domid, pcidev, force) )
+            if ( do_pci_remove(gc, domid, pcidev, force) )
                 rc = ERROR_FAIL;
         }
     }
 
 out:
+    return rc;
+}
+
+int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci 
*pcidev)
+{
+    libxl__gc gc = LIBXL_INIT_GC(ctx);
+    int rc;
+
+    rc = libxl__device_pci_remove_common(&gc, domid, pcidev, 0);
+
     libxl__free_all(&gc);
     return rc;
 }
 
-int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, 
uint32_t domid, int *num)
+int libxl_device_pci_force_remove(libxl_ctx *ctx, uint32_t domid,
+                                  libxl_device_pci *pcidev)
 {
     libxl__gc gc = LIBXL_INIT_GC(ctx);
-    char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
+    int rc;
+
+    rc = libxl__device_pci_remove_common(&gc, domid, pcidev, 1);
+
+    libxl__free_all(&gc);
+    return rc;
+}
+
+static void libxl__device_pci_from_xs_be(libxl__gc *gc,
+                                         const char *be_path,
+                                         libxl_device_pci *pci,
+                                         int nr)
+{
+    char *s;
+    unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
+
+    s = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/dev-%d", be_path, 
nr));
+    sscanf(s, PCI_BDF, &domain, &bus, &dev, &func);
+
+    s = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/vdevfn-%d", 
be_path, nr));
+    if (s)
+        vdevfn = strtol(s, (char **) NULL, 16);
+
+    pcidev_init(pci, domain, bus, dev, func, vdevfn);
+
+    s = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/opts-%d", be_path, 
nr));
+    if (s) {
+        char *saveptr;
+        char *p = strtok_r(s, ",=", &saveptr);
+        do {
+            while (*p == ' ')
+                p++;
+            if (!strcmp(p, "msitranslate")) {
+                p = strtok_r(NULL, ",=", &saveptr);
+                pci->msitranslate = atoi(p);
+            } else if (!strcmp(p, "power_mgmt")) {
+                p = strtok_r(NULL, ",=", &saveptr);
+                pci->power_mgmt = atoi(p);
+            }
+        } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
+    }
+}
+
+libxl_device_pci *libxl_device_pci_list(libxl_ctx *ctx, uint32_t domid, int 
*num)
+{
+    libxl__gc gc = LIBXL_INIT_GC(ctx);
+    char *be_path, *num_devs;
     int n, i;
-    unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
-    libxl_device_pci *pcidevs;
+    libxl_device_pci *pcidevs = NULL;
+
+    *num = 0;
 
     be_path = libxl__sprintf(&gc, "%s/backend/pci/%d/0", 
libxl__xs_get_dompath(&gc, 0), domid);
     num_devs = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, 
"%s/num_devs", be_path));
-    if (!num_devs) {
-        *num = 0;
-        *list = NULL;
-        libxl__free_all(&gc);
-        return 0;
-    }
+    if (!num_devs)
+        goto out;
+
     n = atoi(num_devs);
     pcidevs = calloc(n, sizeof(libxl_device_pci));
+
+    for (i = 0; i < n; i++)
+        libxl__device_pci_from_xs_be(&gc, be_path, pcidevs + i, i);
+
     *num = n;
-
-    for (i = 0; i < n; i++) {
-        xsdev = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/dev-%d", 
be_path, i));
-        sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
-        xsvdevfn = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, 
"%s/vdevfn-%d", be_path, i));
-        if (xsvdevfn)
-            vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
-        pcidev_init(pcidevs + i, domain, bus, dev, func, vdevfn);
-        xsopts = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, 
"%s/opts-%d", be_path, i));
-        if (xsopts) {
-            char *saveptr;
-            char *p = strtok_r(xsopts, ",=", &saveptr);
-            do {
-                while (*p == ' ')
-                    p++;
-                if (!strcmp(p, "msitranslate")) {
-                    p = strtok_r(NULL, ",=", &saveptr);
-                    pcidevs[i].msitranslate = atoi(p);
-                } else if (!strcmp(p, "power_mgmt")) {
-                    p = strtok_r(NULL, ",=", &saveptr);
-                    pcidevs[i].power_mgmt = atoi(p);
-                }
-            } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
-        }
-    }
-    *list = pcidevs;
+out:
     libxl__free_all(&gc);
-    return 0;
+    return pcidevs;
 }
 
-int libxl_device_pci_shutdown(libxl_ctx *ctx, uint32_t domid)
+int libxl__device_pci_force_remove_all(libxl__gc *gc, uint32_t domid)
 {
+    libxl_ctx *ctx = libxl__gc_owner(gc);
     libxl_device_pci *pcidevs;
-    int num, i, rc;
+    int num, i, rc = 0;
 
-    rc = libxl_device_pci_list_assigned(ctx, &pcidevs, domid, &num);
-    if ( rc )
-        return rc;
+    pcidevs = libxl_device_pci_list(ctx, domid, &num);
+    if ( pcidevs == NULL )
+        return ERROR_FAIL;
+
     for (i = 0; i < num; i++) {
         /* Force remove on shutdown since, on HVM, qemu will not always
          * respond to SCI interrupt because the guest kernel has shut down the
          * devices by the time we even get here!
          */
-        if (libxl_device_pci_remove(ctx, domid, pcidevs + i, 1) < 0)
-            return ERROR_FAIL;
+        if (libxl_device_pci_force_remove(ctx, domid, pcidevs + i) < 0)
+            rc = ERROR_FAIL;
     }
+
     free(pcidevs);
     return 0;
 }
diff -r dc967a4691d5 -r f0ab7f2102b3 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c  Fri Sep 30 14:27:28 2011 +0100
+++ b/tools/libxl/xl_cmdimpl.c  Fri Sep 30 14:27:58 2011 +0100
@@ -2078,11 +2078,14 @@ static void pcilist_assignable(void)
     libxl_device_pci *pcidevs;
     int num, i;
 
-    if ( libxl_device_pci_list_assignable(ctx, &pcidevs, &num) )
+    pcidevs = libxl_device_pci_list_assignable(ctx, &num);
+
+    if ( pcidevs == NULL )
         return;
     for (i = 0; i < num; i++) {
         printf("%04x:%02x:%02x.%01x\n",
-                pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, 
pcidevs[i].func);
+               pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, 
pcidevs[i].func);
+        libxl_device_pci_destroy(&pcidevs[i]);
     }
     free(pcidevs);
 }
@@ -2105,7 +2108,8 @@ static void pcilist(const char *dom)
 
     find_domain(dom);
 
-    if (libxl_device_pci_list_assigned(ctx, &pcidevs, domid, &num))
+    pcidevs = libxl_device_pci_list(ctx, domid, &num);
+    if (pcidevs == NULL)
         return;
     printf("Vdev Device\n");
     for (i = 0; i < num; i++) {
@@ -2142,7 +2146,10 @@ static void pcidetach(const char *dom, c
         fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", 
bdf);
         exit(2);
     }
-    libxl_device_pci_remove(ctx, domid, &pcidev, force);
+    if (force)
+        libxl_device_pci_force_remove(ctx, domid, &pcidev);
+    else
+        libxl_device_pci_remove(ctx, domid, &pcidev);
     libxl_device_pci_destroy(&pcidev);
 }
 
diff -r dc967a4691d5 -r f0ab7f2102b3 tools/python/xen/lowlevel/xl/xl.c
--- a/tools/python/xen/lowlevel/xl/xl.c Fri Sep 30 14:27:28 2011 +0100
+++ b/tools/python/xen/lowlevel/xl/xl.c Fri Sep 30 14:27:58 2011 +0100
@@ -521,9 +521,16 @@ static PyObject *pyxl_pci_del(XlObject *
         return NULL;
     }
     pci = (Py_device_pci *)obj;
-    if ( libxl_device_pci_remove(self->ctx, domid, &pci->obj, force) ) {
-        PyErr_SetString(xl_error_obj, "cannot remove pci device");
-        return NULL;
+    if ( force ) {
+        if ( libxl_device_pci_force_remove(self->ctx, domid, &pci->obj) ) {
+            PyErr_SetString(xl_error_obj, "cannot remove pci device");
+            return NULL;
+        }
+    } else {
+        if ( libxl_device_pci_remove(self->ctx, domid, &pci->obj) ) {
+            PyErr_SetString(xl_error_obj, "cannot remove pci device");
+            return NULL;
+        }
     }
     Py_INCREF(Py_None);
     return Py_None;
@@ -558,7 +565,8 @@ static PyObject *pyxl_pci_list_assignabl
     PyObject *list;
     int nr_dev, i;
 
-    if ( libxl_device_pci_list_assignable(self->ctx, &dev, &nr_dev) ) {
+    dev = libxl_device_pci_list_assignable(self->ctx, &nr_dev);
+    if ( dev == NULL ) {
         PyErr_SetString(xl_error_obj, "Cannot list assignable devices");
         return NULL;
     }
@@ -594,7 +602,8 @@ static PyObject *pyxl_pci_list(XlObject 
     if ( !PyArg_ParseTuple(args, "i", &domid) )
         return NULL;
 
-    if ( libxl_device_pci_list_assigned(self->ctx, &dev, domid, &nr_dev) ) {
+    dev = libxl_device_pci_list(self->ctx, domid, &nr_dev);
+    if ( dev == NULL ) {
         PyErr_SetString(xl_error_obj, "Cannot list assignable devices");
         return NULL;
     }

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.