# 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
|