[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |