[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Re: [PATCH 2 of 3] Check whether a PCI device is assignable before assigning it do a domU
On Wed, 28 Jul 2010, Gianni Tedesco (3P) wrote: > tools/libxl/libxl.h | 3 +- > tools/libxl/libxl_internal.h | 3 + > tools/libxl/libxl_pci.c | 186 > +++++++++++++++++++++++++++++++++++++++--- > tools/libxl/xl.h | 1 + > tools/libxl/xl_cmdimpl.c | 36 +++++++- > tools/libxl/xl_cmdtable.c | 5 + > 6 files changed, 214 insertions(+), 20 deletions(-) > > > Implement a new libxl function libxl_device_pci_list_assignable. This is > used to implement the xl list-assignable-pci-devices command and part of > the implementation is used to make sure that PCI devices are not multiply > assigned to one or more domU's before doing the passthrough assignment. > > The function libxl_device_pci_list changes to libxl_device_pci_list_assigned > due to a parameter change for consistency with pci_list_assignable. > > Signed-off-by: Gianni Tedesco <gianni.tedesco@xxxxxxxxxx> > > diff -r e2520c8b96b7 -r 099e4eb3803a tools/libxl/libxl.h > --- a/tools/libxl/libxl.h Wed Jul 28 20:29:08 2010 +0100 > +++ b/tools/libxl/libxl.h Wed Jul 28 20:31:59 2010 +0100 > @@ -521,7 +521,8 @@ int libxl_device_vfb_hard_shutdown(struc > int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, > libxl_device_pci *pcidev); > int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, > libxl_device_pci *pcidev); > int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid); > -libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t > domid, int *num); > +int libxl_device_pci_list_assigned(struct libxl_ctx *ctx, libxl_device_pci > **list, uint32_t domid, int *num); > +int libxl_device_pci_list_assignable(struct libxl_ctx *ctx, libxl_device_pci > **list, int *num); > int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain, > unsigned int bus, unsigned int dev, > unsigned int func, unsigned int vdevfn); > diff -r e2520c8b96b7 -r 099e4eb3803a tools/libxl/libxl_internal.h > --- a/tools/libxl/libxl_internal.h Wed Jul 28 20:29:08 2010 +0100 > +++ b/tools/libxl/libxl_internal.h Wed Jul 28 20:31:59 2010 +0100 > @@ -91,6 +91,9 @@ typedef struct { > #define XC_PCI_BDF "0x%x, 0x%x, 0x%x, 0x%x" > #define AUTO_PHP_SLOT 0x100 > #define SYSFS_PCI_DEV "/sys/bus/pci/devices" > +#define SYSFS_PCIBACK_DRIVER "/sys/bus/pci/drivers/pciback" > +#define SYSFS_PCISTUB_DRIVER "/sys/bus/pci/drivers/pcistub" > + > #define PROC_PCI_NUM_RESOURCES 7 > #define PCI_BAR_IO 0x01 > > diff -r e2520c8b96b7 -r 099e4eb3803a tools/libxl/libxl_pci.c > --- a/tools/libxl/libxl_pci.c Wed Jul 28 20:29:08 2010 +0100 > +++ b/tools/libxl/libxl_pci.c Wed Jul 28 20:31:59 2010 +0100 > @@ -28,6 +28,7 @@ > #include <unistd.h> /* for write, unlink and close */ > #include <stdint.h> > #include <inttypes.h> > +#include <dirent.h> > #include <assert.h> > > #include "libxl.h" > @@ -258,22 +259,77 @@ retry_transaction2: > return 0; > } > > -int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, > libxl_device_pci *pcidev) > +int get_all_assigned_devices(struct libxl_ctx *ctx, libxl_device_pci **list, > int *num) shouldn't this be static? > +{ > + libxl_device_pci *pcidevs = NULL; > + char **domlist; > + unsigned int nd = 0, i; > + > + *list = NULL; > + *num = 0; > + > + domlist = libxl_xs_directory(ctx, XBT_NULL, "/local/domain", &nd); > + for(i = 0; i < nd; i++) { > + char *path, *num_devs; > + > + path = libxl_sprintf(ctx, > "/local/domain/0/backend/pci/%s/0/num_devs", domlist[i]); > + num_devs = libxl_xs_read(ctx, XBT_NULL, path); > + if ( num_devs ) { > + int ndev = atoi(num_devs), j; > + char *devpath, *bdf; > + > + pcidevs = calloc(sizeof(*pcidevs), ndev); > + for(j = (pcidevs) ? 0 : ndev; j < ndev; j++) { > + devpath = libxl_sprintf(ctx, > "/local/domain/0/backend/pci/%s/0/dev-%u", > + domlist[i], j); > + bdf = libxl_xs_read(ctx, XBT_NULL, devpath); > + if ( bdf ) { > + unsigned dom, bus, dev, func; > + if ( sscanf(bdf, PCI_BDF, &dom, &bus, &dev, &func) != 4 ) > + continue; > + > + libxl_device_pci_init(pcidevs + *num, dom, bus, dev, > func, 0); > + (*num)++; > + } > + } > + } > + } > + > + if ( 0 == *num ) { > + free(pcidevs); > + pcidevs = NULL; > + }else{ > + *list = pcidevs; > + } > + > + return 0; > +} > + > +static int is_assigned(libxl_device_pci *assigned, int num_assigned, > + int dom, int bus, int dev, int func) > +{ > + int i; > + > + for(i = 0; i < num_assigned; i++) { > + if ( assigned[i].domain != dom ) > + continue; > + if ( assigned[i].bus != bus ) > + continue; > + if ( assigned[i].dev != dev ) > + continue; > + if ( assigned[i].func != func ) > + continue; > + return 1; > + } > + > + return 0; > +} > + > +static int do_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) { > @@ -370,6 +426,38 @@ out: > return 0; > } > > +int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, > libxl_device_pci *pcidev) > +{ > + libxl_device_pci *assigned; > + int num_assigned, rc; > + int stubdomid = 0; > + > + rc = get_all_assigned_devices(ctx, &assigned, &num_assigned); > + if ( rc ) { > + XL_LOG(ctx, XL_LOG_ERROR, "cannot determine if device is assigned, > refusing to continue"); > + return ERROR_FAIL; > + } > + if ( is_assigned(assigned, num_assigned, pcidev->domain, > + pcidev->bus, pcidev->dev, pcidev->func) ) { > + XL_LOG(ctx, XL_LOG_ERROR, "PCI device already attached to a domain"); > + free(assigned); > + return ERROR_FAIL; > + } > + free(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; > + rc = do_pci_add(ctx, stubdomid, &pcidev_s); > + if ( rc ) > + return rc; > + } > + > + return do_pci_add(ctx, domid, pcidev); > +} > + > int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, > libxl_device_pci *pcidev) > { > char *path; > @@ -466,7 +554,66 @@ out: > return 0; > } > > -libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t > domid, int *num) > +static libxl_device_pci *scan_sys_pcidir(libxl_device_pci *pcidevs, > libxl_device_pci *assigned, > + int num_assigned, const char *path, > int *num) > +{ > + libxl_device_pci *new; > + struct dirent *de; > + DIR *dir; > + > + dir = opendir(path); > + if ( NULL == dir ) > + return pcidevs; > + > + while( (de = readdir(dir)) ) { > + unsigned dom, bus, dev, func; > + if ( sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4 ) > + continue; > + > + if ( is_assigned(assigned, num_assigned, dom, bus, dev, func) ) > + continue; > + > + new = realloc(pcidevs, ((*num) + 1) * sizeof(*new)); > + if ( NULL == new ) > + continue; > + > + pcidevs = new; > + new = pcidevs + *num; > + > + memset(new, 0, sizeof(*new)); > + libxl_device_pci_init(new, dom, bus, dev, func, 0); > + (*num)++; > + } > + > + closedir(dir); > + return pcidevs; > +} > + > +int libxl_device_pci_list_assignable(struct libxl_ctx *ctx, libxl_device_pci > **list, int *num) > +{ > + libxl_device_pci *pcidevs = NULL; > + libxl_device_pci *assigned; > + int num_assigned, rc; > + > + *num = 0; > + *list = NULL; > + > + rc = get_all_assigned_devices(ctx, &assigned, &num_assigned); > + if ( rc ) > + return rc; > + > + pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned, > + SYSFS_PCIBACK_DRIVER, num); > + pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned, > + SYSFS_PCISTUB_DRIVER, num); > + I still think we should remove pcistub scanning from here: when running on xen people should use pciback anyway. > + free(assigned); > + if ( *num ) > + *list = pcidevs; > + return 0; > +} > + > +int libxl_device_pci_list_assigned(struct libxl_ctx *ctx, libxl_device_pci > **list, uint32_t domid, int *num) > { > char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts; > int n, i; > @@ -477,7 +624,8 @@ libxl_device_pci *libxl_device_pci_list( > num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, > "%s/num_devs", be_path)); > if (!num_devs) { > *num = 0; > - return NULL; > + *list = NULL; > + return ERROR_FAIL; > } > n = atoi(num_devs); > pcidevs = calloc(n, sizeof(libxl_device_pci)); > @@ -507,15 +655,19 @@ libxl_device_pci *libxl_device_pci_list( > } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL); > } > } > - return pcidevs; > + if ( *num ) > + *list = pcidevs; > + return 0; > } > > int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid) > { > libxl_device_pci *pcidevs; > - int num, i; > + int num, i, rc; > > - pcidevs = libxl_device_pci_list(ctx, domid, &num); > + rc = libxl_device_pci_list_assigned(ctx, &pcidevs, domid, &num); > + if ( rc ) > + return rc; > for (i = 0; i < num; i++) { > if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0) > return ERROR_FAIL; > diff -r e2520c8b96b7 -r 099e4eb3803a tools/libxl/xl.h > --- a/tools/libxl/xl.h Wed Jul 28 20:29:08 2010 +0100 > +++ b/tools/libxl/xl.h Wed Jul 28 20:31:59 2010 +0100 > @@ -32,6 +32,7 @@ int main_cd_insert(int argc, char **argv > int main_console(int argc, char **argv); > int main_vncviewer(int argc, char **argv); > int main_pcilist(int argc, char **argv); > +int main_pcilist_assignable(int argc, char **argv); > int main_pcidetach(int argc, char **argv); > int main_pciattach(int argc, char **argv); > int main_restore(int argc, char **argv); > diff -r e2520c8b96b7 -r 099e4eb3803a tools/libxl/xl_cmdimpl.c > --- a/tools/libxl/xl_cmdimpl.c Wed Jul 28 20:29:08 2010 +0100 > +++ b/tools/libxl/xl_cmdimpl.c Wed Jul 28 20:31:59 2010 +0100 > @@ -1920,6 +1920,39 @@ int main_vncviewer(int argc, char **argv > exit(0); > } > > +void pcilist_assignable(void) > +{ > + libxl_device_pci *pcidevs; > + int num, i; > + > + if ( libxl_device_pci_list_assignable(&ctx, &pcidevs, &num) ) > + return; > + for (i = 0; i < num; i++) { > + printf("%04x:%02x:%02x:%01x\n", > + pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, > pcidevs[i].func); > + } > + free(pcidevs); > +} > + > +int main_pcilist_assignable(int argc, char **argv) > +{ > + int opt; > + > + while ((opt = getopt(argc, argv, "h")) != -1) { > + switch (opt) { > + case 'h': > + help("pci-list-assignable-devices"); > + exit(0); > + default: > + fprintf(stderr, "option not supported\n"); > + break; > + } > + } > + > + pcilist_assignable(); > + exit(0); > +} > + > void pcilist(char *dom) > { > libxl_device_pci *pcidevs; > @@ -1927,8 +1960,7 @@ void pcilist(char *dom) > > find_domain(dom); > > - pcidevs = libxl_device_pci_list(&ctx, domid, &num); > - if (!num) > + if (libxl_device_pci_list_assigned(&ctx, &pcidevs, domid, &num)) > return; > printf("VFn domain bus slot func\n"); > for (i = 0; i < num; i++) { > diff -r e2520c8b96b7 -r 099e4eb3803a tools/libxl/xl_cmdtable.c > --- a/tools/libxl/xl_cmdtable.c Wed Jul 28 20:29:08 2010 +0100 > +++ b/tools/libxl/xl_cmdtable.c Wed Jul 28 20:31:59 2010 +0100 > @@ -68,6 +68,11 @@ struct cmd_spec cmd_table[] = { > "List pass-through pci devices for a domain", > "<Domain>", > }, > + { "pci-list-assignable-devices", > + &main_pcilist_assignable, > + "List all the assignable pci devices", > + "", > + }, > { "pause", > &main_pause, > "Pause execution of a domain", > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |