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

[Xen-devel] Re: [PATCH 2 of 3] Check whether a PCI device is assignable

To: "Gianni Tedesco (3P)" <gianni.tedesco@xxxxxxxxxx>
Subject: [Xen-devel] Re: [PATCH 2 of 3] Check whether a PCI device is assignable before assigning it do a domU
From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Date: Thu, 29 Jul 2010 15:36:25 +0100
Cc: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>, Stabellini <Stefano.Stabellini@xxxxxxxxxxxxx>, Stefano
Delivery-date: Thu, 29 Jul 2010 07:36:25 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <099e4eb3803a528eb5d1.1280346050@xxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1280346048@xxxxxxxxxxxxxxxxxxxxxx> <099e4eb3803a528eb5d1.1280346050@xxxxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Alpine 2.00 (DEB 1167 2008-08-23)
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

<Prev in Thread] Current Thread [Next in Thread>