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
|