Mailing List Archive

[PATCH 23 of 23] libxl: convert PCI device handling to device API
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1317389278 -3600
# Node ID f0ab7f2102b37968da2181825ac492b14bc4b449
# Parent dc967a4691d5a7e05eac3522ab78c573a084b63c
libxl: convert PCI device handling to device API

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

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@lists.xensource.com
http://lists.xensource.com/xen-devel