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

[Xen-devel] [PATCH 1 of 3] Move PCI specific function definitions in to libxl_pci.c



 tools/libxl/Makefile    |    2 +-
 tools/libxl/libxl.c     |  501 --------------------------------------------
 tools/libxl/libxl_pci.c |  538 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 539 insertions(+), 502 deletions(-)


diff -r ac7e4c6ec6c7 -r 20b2e15131c7 tools/libxl/Makefile
--- a/tools/libxl/Makefile      Fri Jul 23 19:23:49 2010 +0100
+++ b/tools/libxl/Makefile      Tue Jul 27 17:13:35 2010 +0100
@@ -18,7 +18,7 @@ CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_
 LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore) 
$(LDFLAGS_libblktapctl) -lutil
 
 LIBXL_OBJS-y = osdeps.o libxl_paths.o libxl_bootloader.o
-LIBXL_OBJS = flexarray.o libxl.o libxl_dom.o libxl_exec.o libxl_xshelp.o 
libxl_device.o libxl_internal.o xenguest.o libxl_utils.o $(LIBXL_OBJS-y)
+LIBXL_OBJS = flexarray.o libxl.o libxl_pci.o libxl_dom.o libxl_exec.o 
libxl_xshelp.o libxl_device.o libxl_internal.o xenguest.o libxl_utils.o 
$(LIBXL_OBJS-y)
 
 AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
 AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
diff -r ac7e4c6ec6c7 -r 20b2e15131c7 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Fri Jul 23 19:23:49 2010 +0100
+++ b/tools/libxl/libxl.c       Tue Jul 27 17:13:35 2010 +0100
@@ -2327,507 +2327,6 @@ int libxl_device_vfb_hard_shutdown(struc
 
 
/******************************************************************************/
 
-int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
-                          unsigned int bus, unsigned int dev,
-                          unsigned int func, unsigned int vdevfn)
-{
-    pcidev->domain = domain;
-    pcidev->bus = bus;
-    pcidev->dev = dev;
-    pcidev->func = func;
-    pcidev->vdevfn = vdevfn;
-    return 0;
-}
-
-static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev, int num)
-{
-    flexarray_t *front;
-    flexarray_t *back;
-    unsigned int boffset = 0;
-    unsigned int foffset = 0;
-    libxl_device device;
-    int i;
-
-    front = flexarray_make(16, 1);
-    if (!front)
-        return ERROR_NOMEM;
-    back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
-
-    XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend");
-
-    /* add pci device */
-    device.backend_devid = 0;
-    device.backend_domid = 0;
-    device.backend_kind = DEVICE_PCI;
-    device.devid = 0;
-    device.domid = domid;
-    device.kind = DEVICE_PCI;
-
-    flexarray_set(back, boffset++, "frontend-id");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
-    flexarray_set(back, boffset++, "online");
-    flexarray_set(back, boffset++, "1");
-    flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
-    flexarray_set(back, boffset++, "domain");
-    flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
-    for (i = 0; i < num; i++) {
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
-        if (pcidev->vdevfn) {
-            flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
-            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", 
pcidev->vdevfn));
-        }
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
-    }
-    flexarray_set(back, boffset++, "num_devs");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
-
-    flexarray_set(front, foffset++, "backend-id");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
-    flexarray_set(front, foffset++, "state");
-    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
-
-    libxl_device_generic_add(ctx, &device,
-                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
-                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
-
-    flexarray_free(back);
-    flexarray_free(front);
-    return 0;
-}
-
-static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t 
domid, libxl_device_pci *pcidev)
-{
-    flexarray_t *back;
-    char *num_devs, *be_path;
-    int num = 0;
-    unsigned int boffset = 0;
-    xs_transaction_t t;
-
-    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
-    num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", 
be_path));
-    if (!num_devs)
-        return libxl_create_pci_backend(ctx, domid, pcidev, 1);
-
-    if (!is_hvm(ctx, domid)) {
-        if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
-            return ERROR_FAIL;
-    }
-
-    back = flexarray_make(16, 1);
-    if (!back)
-        return ERROR_NOMEM;
-
-    XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
-    num = atoi(num_devs);
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
-    if (pcidev->vdevfn) {
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
-        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", 
pcidev->vdevfn));
-    }
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
-    flexarray_set(back, boffset++, "num_devs");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
-    flexarray_set(back, boffset++, "state");
-    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
-
-retry_transaction:
-    t = xs_transaction_start(ctx->xsh);
-    libxl_xs_writev(ctx, t, be_path,
-                    libxl_xs_kvs_of_flexarray(ctx, back, boffset));
-    if (!xs_transaction_end(ctx->xsh, t, 0))
-        if (errno == EAGAIN)
-            goto retry_transaction;
-
-    flexarray_free(back);
-    return 0;
-}
-
-static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t 
domid, libxl_device_pci *pcidev)
-{
-    char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath;
-    int num, i, j;
-    xs_transaction_t t;
-    unsigned int domain = 0, bus = 0, dev = 0, func = 0;
-
-    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
-    num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
-    num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
-    if (!num_devs)
-        return ERROR_INVAL;
-    num = atoi(num_devs);
-
-    if (!is_hvm(ctx, domid)) {
-        if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
-            XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", 
be_path);
-            return ERROR_FAIL;
-        }
-    }
-
-    for (i = 0; i < num; i++) {
-        xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", 
be_path, i));
-        sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
-        if (domain == pcidev->domain && bus == pcidev->bus &&
-            pcidev->dev == dev && pcidev->func == func) {
-            break;
-        }
-    }
-    if (i == num) {
-        XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore");
-        return ERROR_INVAL;
-    }
-
-retry_transaction:
-    t = xs_transaction_start(ctx->xsh);
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", 
strlen("5"));
-    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", 
strlen("7"));
-    if (!xs_transaction_end(ctx->xsh, t, 0))
-        if (errno == EAGAIN)
-            goto retry_transaction;
-
-    if (!is_hvm(ctx, domid)) {
-        if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
-            XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", 
be_path);
-            return ERROR_FAIL;
-        }
-    }
-
-retry_transaction2:
-    t = xs_transaction_start(ctx->xsh);
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
-    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
-    libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
-    for (j = i + 1; j < num; j++) {
-        tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 
1), tmp, strlen(tmp));
-        xs_rm(ctx->xsh, t, tmppath);
-        tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), 
tmp, strlen(tmp));
-        xs_rm(ctx->xsh, t, tmppath);
-        tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), 
tmp, strlen(tmp));
-        xs_rm(ctx->xsh, t, tmppath);
-        tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        if (tmp) {
-            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j 
- 1), tmp, strlen(tmp));
-            xs_rm(ctx->xsh, t, tmppath);
-        }
-        tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        if (tmp) {
-            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j 
- 1), tmp, strlen(tmp));
-            xs_rm(ctx->xsh, t, tmppath);
-        }
-        tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j);
-        tmp = libxl_xs_read(ctx, t, tmppath);
-        if (tmp) {
-            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, 
j - 1), tmp, strlen(tmp));
-            xs_rm(ctx->xsh, t, tmppath);
-        }
-    }
-    if (!xs_transaction_end(ctx->xsh, t, 0))
-        if (errno == EAGAIN)
-            goto retry_transaction2;
-
-    if (num == 1) {
-        char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/frontend", be_path));
-        libxl_device_destroy(ctx, be_path, 1);
-        xs_rm(ctx->xsh, XBT_NULL, be_path);
-        xs_rm(ctx->xsh, XBT_NULL, fe_path);
-        return 0;
-    }
-
-    return 0;
-}
-
-int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev)
-{
-    char *path;
-    char *state, *vdevfn;
-    int rc, hvm;
-    int stubdomid = 0;
-
-    /* TODO: check if the device can be assigned */
-
-    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
-
-    stubdomid = libxl_get_stubdom_id(ctx, domid);
-    if (stubdomid != 0) {
-        libxl_device_pci pcidev_s = *pcidev;
-        libxl_device_pci_add(ctx, stubdomid, &pcidev_s);
-    }
-
-    hvm = is_hvm(ctx, domid);
-    if (hvm) {
-        if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 
0) {
-            return ERROR_FAIL;
-        }
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        state = libxl_xs_read(ctx, XBT_NULL, path);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
-        if (pcidev->vdevfn)
-            libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
-                           pcidev->bus, pcidev->dev, pcidev->func, 
pcidev->vdevfn);
-        else
-            libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
-                           pcidev->bus, pcidev->dev, pcidev->func);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid);
-        xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
-        if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, 
NULL) < 0)
-            XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
-        vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
-        sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
-    } else {
-        char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
-                                         pcidev->bus, pcidev->dev, 
pcidev->func);
-        FILE *f = fopen(sysfs_path, "r");
-        unsigned long long start = 0, end = 0, flags = 0, size = 0;
-        int irq = 0;
-        int i;
-
-        if (f == NULL) {
-            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
-            return ERROR_FAIL;
-        }
-        for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-            if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
-                continue;
-            size = end - start + 1;
-            if (start) {
-                if (flags & PCI_BAR_IO) {
-                    rc = xc_domain_ioport_permission(ctx->xch, domid, start, 
size, 1);
-                    if (rc < 0) {
-                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
-                        fclose(f);
-                        return ERROR_FAIL;
-                    }
-                } else {
-                    rc = xc_domain_iomem_permission(ctx->xch, domid, 
start>>XC_PAGE_SHIFT,
-                                                    
(size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
-                    if (rc < 0) {
-                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
-                        fclose(f);
-                        return ERROR_FAIL;
-                    }
-                }
-            }
-        }
-        fclose(f);
-        sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
-                                   pcidev->bus, pcidev->dev, pcidev->func);
-        f = fopen(sysfs_path, "r");
-        if (f == NULL) {
-            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
-            goto out;
-        }
-        if ((fscanf(f, "%u", &irq) == 1) && irq) {
-            rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
-            if (rc < 0) {
-                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_physdev_map_pirq irq=%d", irq);
-                fclose(f);
-                return ERROR_FAIL;
-            }
-            rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
-            if (rc < 0) {
-                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_irq_permission irq=%d", irq);
-                fclose(f);
-                return ERROR_FAIL;
-            }
-        }
-        fclose(f);
-    }
-out:
-    if (!libxl_is_stubdom(ctx, domid, NULL)) {
-        rc = xc_assign_device(ctx->xch, domid, pcidev->value);
-        if (rc < 0) {
-            XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed");
-            return ERROR_FAIL;
-        }
-    }
-
-    libxl_device_pci_add_xenstore(ctx, domid, pcidev);
-    return 0;
-}
-
-int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev)
-{
-    char *path;
-    char *state;
-    int hvm, rc;
-    int stubdomid = 0;
-
-    /* TODO: check if the device can be detached */
-    libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
-
-    hvm = is_hvm(ctx, domid);
-    if (hvm) {
-        if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 
0) {
-            return ERROR_FAIL;
-        }
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        state = libxl_xs_read(ctx, XBT_NULL, path);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
-        libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
-                       pcidev->bus, pcidev->dev, pcidev->func);
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid);
-        xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
-        if (libxl_wait_for_device_model(ctx, domid, "pci-removed", NULL, NULL) 
< 0) {
-            XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
-            return ERROR_FAIL;
-        }
-        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
-        xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
-    } else {
-        char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
-                                         pcidev->bus, pcidev->dev, 
pcidev->func);
-        FILE *f = fopen(sysfs_path, "r");
-        unsigned int start = 0, end = 0, flags = 0, size = 0;
-        int irq = 0;
-        int i;
-
-        if (f == NULL) {
-            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
-            goto skip1;
-        }
-        for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-            if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
-                continue;
-            size = end - start + 1;
-            if (start) {
-                if (flags & PCI_BAR_IO) {
-                    rc = xc_domain_ioport_permission(ctx->xch, domid, start, 
size, 0);
-                    if (rc < 0)
-                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, 
"xc_domain_ioport_permission error 0x%x/0x%x", start, size);
-                } else {
-                    rc = xc_domain_iomem_permission(ctx->xch, domid, 
start>>XC_PAGE_SHIFT,
-                                                    
(size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
-                    if (rc < 0)
-                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, 
"xc_domain_iomem_permission error 0x%x/0x%x", start, size);
-                }
-            }
-        }
-        fclose(f);
-skip1:
-        sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
-                                   pcidev->bus, pcidev->dev, pcidev->func);
-        f = fopen(sysfs_path, "r");
-        if (f == NULL) {
-            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
-            goto out;
-        }
-        if ((fscanf(f, "%u", &irq) == 1) && irq) {
-            rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
-            if (rc < 0) {
-                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq 
irq=%d", irq);
-            }
-            rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
-            if (rc < 0) {
-                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, 
"xc_domain_irq_permission irq=%d", irq);
-            }
-        }
-        fclose(f);
-    }
-out:
-    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
-
-    if (!libxl_is_stubdom(ctx, domid, NULL)) {
-        rc = xc_deassign_device(ctx->xch, domid, pcidev->value);
-        if (rc < 0)
-            XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device 
failed");
-    }
-
-    stubdomid = libxl_get_stubdom_id(ctx, domid);
-    if (stubdomid != 0) {
-        libxl_device_pci pcidev_s = *pcidev;
-        libxl_device_pci_remove(ctx, stubdomid, &pcidev_s);
-    }
-
-    return 0;
-}
-
-libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, 
int *num)
-{
-    char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
-    int n, i;
-    unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
-    libxl_device_pci *pcidevs;
-
-    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
-    num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", 
be_path));
-    if (!num_devs) {
-        *num = 0;
-        return NULL;
-    }
-    n = atoi(num_devs);
-    pcidevs = calloc(n, sizeof(libxl_device_pci));
-    *num = n;
-
-    for (i = 0; i < n; i++) {
-        xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", 
be_path, i));
-        sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
-        xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/vdevfn-%d", be_path, i));
-        if (xsvdevfn)
-            vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
-        libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
-        xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%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);
-        }
-    }
-    return pcidevs;
-}
-
-int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid)
-{
-    libxl_device_pci *pcidevs;
-    int num, i;
-
-    pcidevs = libxl_device_pci_list(ctx, domid, &num);
-    for (i = 0; i < num; i++) {
-        if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0)
-            return ERROR_FAIL;
-    }
-    free(pcidevs);
-    return 0;
-}
-
 int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t 
max_memkb)
 {
     char *mem, *endptr;
diff -r ac7e4c6ec6c7 -r 20b2e15131c7 tools/libxl/libxl_pci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_pci.c   Tue Jul 27 17:13:35 2010 +0100
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 2009      Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@xxxxxxxxxxxxx>
+ * Author Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h> /* for write, unlink and close */
+#include <stdint.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "libxl.h"
+#include "libxl_utils.h"
+#include "libxl_internal.h"
+#include "flexarray.h"
+
+static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev, int num)
+{
+    flexarray_t *front;
+    flexarray_t *back;
+    unsigned int boffset = 0;
+    unsigned int foffset = 0;
+    libxl_device device;
+    int i;
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend");
+
+    /* add pci device */
+    device.backend_devid = 0;
+    device.backend_domid = 0;
+    device.backend_kind = DEVICE_PCI;
+    device.devid = 0;
+    device.domid = domid;
+    device.kind = DEVICE_PCI;
+
+    flexarray_set(back, boffset++, "frontend-id");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
+    flexarray_set(back, boffset++, "online");
+    flexarray_set(back, boffset++, "1");
+    flexarray_set(back, boffset++, "state");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, "domain");
+    flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
+    for (i = 0; i < num; i++) {
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, 
pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
+        if (pcidev->vdevfn) {
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
+            flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", 
pcidev->vdevfn));
+        }
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    }
+    flexarray_set(back, boffset++, "num_devs");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
+
+    flexarray_set(front, foffset++, "backend-id");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
+    flexarray_set(front, foffset++, "state");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+
+    flexarray_free(back);
+    flexarray_free(front);
+    return 0;
+}
+
+static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t 
domid, libxl_device_pci *pcidev)
+{
+    flexarray_t *back;
+    char *num_devs, *be_path;
+    int num = 0;
+    unsigned int boffset = 0;
+    xs_transaction_t t;
+
+    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
+    num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", 
be_path));
+    if (!num_devs)
+        return libxl_create_pci_backend(ctx, domid, pcidev, 1);
+
+    if (!is_hvm(ctx, domid)) {
+        if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
+            return ERROR_FAIL;
+    }
+
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
+    num = atoi(num_devs);
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, 
pcidev->bus, pcidev->dev, pcidev->func));
+    if (pcidev->vdevfn) {
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
+        flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", 
pcidev->vdevfn));
+    }
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, 
"msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
+    flexarray_set(back, boffset++, "num_devs");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
+    flexarray_set(back, boffset++, "state");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    libxl_xs_writev(ctx, t, be_path,
+                    libxl_xs_kvs_of_flexarray(ctx, back, boffset));
+    if (!xs_transaction_end(ctx->xsh, t, 0))
+        if (errno == EAGAIN)
+            goto retry_transaction;
+
+    flexarray_free(back);
+    return 0;
+}
+
+static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t 
domid, libxl_device_pci *pcidev)
+{
+    char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath;
+    int num, i, j;
+    xs_transaction_t t;
+    unsigned int domain = 0, bus = 0, dev = 0, func = 0;
+
+    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
+    num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
+    num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
+    if (!num_devs)
+        return ERROR_INVAL;
+    num = atoi(num_devs);
+
+    if (!is_hvm(ctx, domid)) {
+        if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
+            XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", 
be_path);
+            return ERROR_FAIL;
+        }
+    }
+
+    for (i = 0; i < num; i++) {
+        xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", 
be_path, i));
+        sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
+        if (domain == pcidev->domain && bus == pcidev->bus &&
+            pcidev->dev == dev && pcidev->func == func) {
+            break;
+        }
+    }
+    if (i == num) {
+        XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore");
+        return ERROR_INVAL;
+    }
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", 
strlen("5"));
+    xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", 
strlen("7"));
+    if (!xs_transaction_end(ctx->xsh, t, 0))
+        if (errno == EAGAIN)
+            goto retry_transaction;
+
+    if (!is_hvm(ctx, domid)) {
+        if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
+            XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", 
be_path);
+            return ERROR_FAIL;
+        }
+    }
+
+retry_transaction2:
+    t = xs_transaction_start(ctx->xsh);
+    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
+    xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
+    libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
+    for (j = i + 1; j < num; j++) {
+        tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j);
+        tmp = libxl_xs_read(ctx, t, tmppath);
+        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 
1), tmp, strlen(tmp));
+        xs_rm(ctx->xsh, t, tmppath);
+        tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j);
+        tmp = libxl_xs_read(ctx, t, tmppath);
+        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), 
tmp, strlen(tmp));
+        xs_rm(ctx->xsh, t, tmppath);
+        tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j);
+        tmp = libxl_xs_read(ctx, t, tmppath);
+        xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), 
tmp, strlen(tmp));
+        xs_rm(ctx->xsh, t, tmppath);
+        tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j);
+        tmp = libxl_xs_read(ctx, t, tmppath);
+        if (tmp) {
+            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j 
- 1), tmp, strlen(tmp));
+            xs_rm(ctx->xsh, t, tmppath);
+        }
+        tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j);
+        tmp = libxl_xs_read(ctx, t, tmppath);
+        if (tmp) {
+            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j 
- 1), tmp, strlen(tmp));
+            xs_rm(ctx->xsh, t, tmppath);
+        }
+        tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j);
+        tmp = libxl_xs_read(ctx, t, tmppath);
+        if (tmp) {
+            xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, 
j - 1), tmp, strlen(tmp));
+            xs_rm(ctx->xsh, t, tmppath);
+        }
+    }
+    if (!xs_transaction_end(ctx->xsh, t, 0))
+        if (errno == EAGAIN)
+            goto retry_transaction2;
+
+    if (num == 1) {
+        char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/frontend", be_path));
+        libxl_device_destroy(ctx, be_path, 1);
+        xs_rm(ctx->xsh, XBT_NULL, be_path);
+        xs_rm(ctx->xsh, XBT_NULL, fe_path);
+        return 0;
+    }
+
+    return 0;
+}
+
+int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev)
+{
+    char *path;
+    char *state, *vdevfn;
+    int rc, hvm;
+    int stubdomid = 0;
+
+    /* TODO: check if the device can be assigned */
+
+    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
+
+    stubdomid = libxl_get_stubdom_id(ctx, domid);
+    if (stubdomid != 0) {
+        libxl_device_pci pcidev_s = *pcidev;
+        libxl_device_pci_add(ctx, stubdomid, &pcidev_s);
+    }
+
+    hvm = is_hvm(ctx, domid);
+    if (hvm) {
+        if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 
0) {
+            return ERROR_FAIL;
+        }
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
+        state = libxl_xs_read(ctx, XBT_NULL, path);
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
+        if (pcidev->vdevfn)
+            libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
+                           pcidev->bus, pcidev->dev, pcidev->func, 
pcidev->vdevfn);
+        else
+            libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
+                           pcidev->bus, pcidev->dev, pcidev->func);
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid);
+        xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
+        if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, 
NULL) < 0)
+            XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
+        vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
+        sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
+        xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
+    } else {
+        char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
+                                         pcidev->bus, pcidev->dev, 
pcidev->func);
+        FILE *f = fopen(sysfs_path, "r");
+        unsigned long long start = 0, end = 0, flags = 0, size = 0;
+        int irq = 0;
+        int i;
+
+        if (f == NULL) {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
+            return ERROR_FAIL;
+        }
+        for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
+            if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
+                continue;
+            size = end - start + 1;
+            if (start) {
+                if (flags & PCI_BAR_IO) {
+                    rc = xc_domain_ioport_permission(ctx->xch, domid, start, 
size, 1);
+                    if (rc < 0) {
+                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
+                        fclose(f);
+                        return ERROR_FAIL;
+                    }
+                } else {
+                    rc = xc_domain_iomem_permission(ctx->xch, domid, 
start>>XC_PAGE_SHIFT,
+                                                    
(size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
+                    if (rc < 0) {
+                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
+                        fclose(f);
+                        return ERROR_FAIL;
+                    }
+                }
+            }
+        }
+        fclose(f);
+        sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
+                                   pcidev->bus, pcidev->dev, pcidev->func);
+        f = fopen(sysfs_path, "r");
+        if (f == NULL) {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
+            goto out;
+        }
+        if ((fscanf(f, "%u", &irq) == 1) && irq) {
+            rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
+            if (rc < 0) {
+                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_physdev_map_pirq irq=%d", irq);
+                fclose(f);
+                return ERROR_FAIL;
+            }
+            rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
+            if (rc < 0) {
+                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: 
xc_domain_irq_permission irq=%d", irq);
+                fclose(f);
+                return ERROR_FAIL;
+            }
+        }
+        fclose(f);
+    }
+out:
+    if (!libxl_is_stubdom(ctx, domid, NULL)) {
+        rc = xc_assign_device(ctx->xch, domid, pcidev->value);
+        if (rc < 0) {
+            XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed");
+            return ERROR_FAIL;
+        }
+    }
+
+    libxl_device_pci_add_xenstore(ctx, domid, pcidev);
+    return 0;
+}
+
+int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev)
+{
+    char *path;
+    char *state;
+    int hvm, rc;
+    int stubdomid = 0;
+
+    /* TODO: check if the device can be detached */
+    libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
+
+    hvm = is_hvm(ctx, domid);
+    if (hvm) {
+        if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 
0) {
+            return ERROR_FAIL;
+        }
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
+        state = libxl_xs_read(ctx, XBT_NULL, path);
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", 
domid);
+        libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
+                       pcidev->bus, pcidev->dev, pcidev->func);
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", 
domid);
+        xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
+        if (libxl_wait_for_device_model(ctx, domid, "pci-removed", NULL, NULL) 
< 0) {
+            XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
+            return ERROR_FAIL;
+        }
+        path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", 
domid);
+        xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
+    } else {
+        char *sysfs_path = libxl_sprintf(ctx, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
+                                         pcidev->bus, pcidev->dev, 
pcidev->func);
+        FILE *f = fopen(sysfs_path, "r");
+        unsigned int start = 0, end = 0, flags = 0, size = 0;
+        int irq = 0;
+        int i;
+
+        if (f == NULL) {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
+            goto skip1;
+        }
+        for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
+            if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
+                continue;
+            size = end - start + 1;
+            if (start) {
+                if (flags & PCI_BAR_IO) {
+                    rc = xc_domain_ioport_permission(ctx->xch, domid, start, 
size, 0);
+                    if (rc < 0)
+                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, 
"xc_domain_ioport_permission error 0x%x/0x%x", start, size);
+                } else {
+                    rc = xc_domain_iomem_permission(ctx->xch, domid, 
start>>XC_PAGE_SHIFT,
+                                                    
(size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
+                    if (rc < 0)
+                        XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, 
"xc_domain_iomem_permission error 0x%x/0x%x", start, size);
+                }
+            }
+        }
+        fclose(f);
+skip1:
+        sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", 
pcidev->domain,
+                                   pcidev->bus, pcidev->dev, pcidev->func);
+        f = fopen(sysfs_path, "r");
+        if (f == NULL) {
+            XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
+            goto out;
+        }
+        if ((fscanf(f, "%u", &irq) == 1) && irq) {
+            rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
+            if (rc < 0) {
+                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq 
irq=%d", irq);
+            }
+            rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
+            if (rc < 0) {
+                XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, 
"xc_domain_irq_permission irq=%d", irq);
+            }
+        }
+        fclose(f);
+    }
+out:
+    libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, 
pcidev->func);
+
+    if (!libxl_is_stubdom(ctx, domid, NULL)) {
+        rc = xc_deassign_device(ctx->xch, domid, pcidev->value);
+        if (rc < 0)
+            XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device 
failed");
+    }
+
+    stubdomid = libxl_get_stubdom_id(ctx, domid);
+    if (stubdomid != 0) {
+        libxl_device_pci pcidev_s = *pcidev;
+        libxl_device_pci_remove(ctx, stubdomid, &pcidev_s);
+    }
+
+    return 0;
+}
+
+libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, 
int *num)
+{
+    char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
+    int n, i;
+    unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
+    libxl_device_pci *pcidevs;
+
+    be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", 
libxl_xs_get_dompath(ctx, 0), domid);
+    num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", 
be_path));
+    if (!num_devs) {
+        *num = 0;
+        return NULL;
+    }
+    n = atoi(num_devs);
+    pcidevs = calloc(n, sizeof(libxl_device_pci));
+    *num = n;
+
+    for (i = 0; i < n; i++) {
+        xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", 
be_path, i));
+        sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
+        xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, 
"%s/vdevfn-%d", be_path, i));
+        if (xsvdevfn)
+            vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
+        libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
+        xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%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);
+        }
+    }
+    return pcidevs;
+}
+
+int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_list(ctx, domid, &num);
+    for (i = 0; i < num; i++) {
+        if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0)
+            return ERROR_FAIL;
+    }
+    free(pcidevs);
+    return 0;
+}
+
+int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
+                          unsigned int bus, unsigned int dev,
+                          unsigned int func, unsigned int vdevfn)
+{
+    pcidev->domain = domain;
+    pcidev->bus = bus;
+    pcidev->dev = dev;
+    pcidev->func = func;
+    pcidev->vdevfn = vdevfn;
+    return 0;
+}
+

_______________________________________________
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®.