WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] libxl: Move PCI specific functions to lib

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] libxl: Move PCI specific functions to libxl_pci.c
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 28 Jul 2010 04:55:29 -0700
Delivery-date: Wed, 28 Jul 2010 04:58:48 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
# Date 1280250562 -3600
# Node ID ebede381efe85555412ff541666a4a712d1467a4
# Parent  05d5048a7895b8f037ec1abf67d913ea8d690993
libxl: Move PCI specific functions to libxl_pci.c

Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
Committed-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
---
 tools/libxl/Makefile    |    2 
 tools/libxl/libxl.c     |  501 --------------------------------------------
 tools/libxl/libxl_pci.c |  538 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 539 insertions(+), 502 deletions(-)

diff -r 05d5048a7895 -r ebede381efe8 tools/libxl/Makefile
--- a/tools/libxl/Makefile      Tue Jul 27 17:55:20 2010 +0100
+++ b/tools/libxl/Makefile      Tue Jul 27 18:09:22 2010 +0100
@@ -18,7 +18,7 @@ LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_l
 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 05d5048a7895 -r ebede381efe8 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Tue Jul 27 17:55:20 2010 +0100
+++ b/tools/libxl/libxl.c       Tue Jul 27 18:09:22 2010 +0100
@@ -2366,507 +2366,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 05d5048a7895 -r ebede381efe8 tools/libxl/libxl_pci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_pci.c   Tue Jul 27 18:09:22 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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] libxl: Move PCI specific functions to libxl_pci.c, Xen patchbot-unstable <=