debuggers.hg

changeset 21962:3eec4c068649

xl: centralize BDF parsing in to libxl

Introduce a new libxl call libxl_device_pci_parse_bdf() and use it
consistently.

This patch also fixes an infinite loop bug in xl create. If there is a
parse-error on any pci config file entry then xl will attempt to skip it, but
since num_pcidevs is used to index the config list and is not incremented when
skipping, this caused an infinite loop. Solve that problem by introducing a new
loop counter variable.

Note that virtual PCI slots are not parsed by the new code. However this is
a step towards support for virtual slots and multi-function device assignment
since only one location in the code will need to be changed now.

Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Gianni Tedesco <gianni.tedesco@citrix.com>
date Wed Aug 04 14:24:19 2010 +0100 (2010-08-04)
parents b8a651785471
children b92dfdc284dd
files tools/libxl/libxl.h tools/libxl/libxl_pci.c tools/libxl/xl_cmdimpl.c
line diff
     1.1 --- a/tools/libxl/libxl.h	Wed Aug 04 14:23:29 2010 +0100
     1.2 +++ b/tools/libxl/libxl.h	Wed Aug 04 14:24:19 2010 +0100
     1.3 @@ -516,16 +516,12 @@ int libxl_device_vfb_add(libxl_ctx *ctx,
     1.4  int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid);
     1.5  int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid);
     1.6  
     1.7 -#define PCI_BDF                "%04x:%02x:%02x.%01x"
     1.8 -#define PCI_BDF_VDEVFN         "%04x:%02x:%02x.%01x@%02x"
     1.9  int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev);
    1.10  int libxl_device_pci_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev);
    1.11  int libxl_device_pci_shutdown(libxl_ctx *ctx, uint32_t domid);
    1.12  int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, uint32_t domid, int *num);
    1.13  int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, int *num);
    1.14 -int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
    1.15 -                          unsigned int bus, unsigned int dev,
    1.16 -                          unsigned int func, unsigned int vdevfn);
    1.17 +int libxl_device_pci_parse_bdf(libxl_device_pci *pcidev, const char *str);
    1.18  
    1.19  /*
    1.20   * Functions for allowing users of libxl to store private data
     2.1 --- a/tools/libxl/libxl_pci.c	Wed Aug 04 14:23:29 2010 +0100
     2.2 +++ b/tools/libxl/libxl_pci.c	Wed Aug 04 14:24:19 2010 +0100
     2.3 @@ -36,6 +36,59 @@
     2.4  #include "libxl_internal.h"
     2.5  #include "flexarray.h"
     2.6  
     2.7 +#define PCI_BDF                "%04x:%02x:%02x.%01x"
     2.8 +#define PCI_BDF_SHORT          "%02x:%02x.%01x"
     2.9 +#define PCI_BDF_VDEVFN         "%04x:%02x:%02x.%01x@%02x"
    2.10 +
    2.11 +static int pcidev_init(libxl_device_pci *pcidev, unsigned int domain,
    2.12 +                          unsigned int bus, unsigned int dev,
    2.13 +                          unsigned int func, unsigned int vdevfn)
    2.14 +{
    2.15 +    pcidev->domain = domain;
    2.16 +    pcidev->bus = bus;
    2.17 +    pcidev->dev = dev;
    2.18 +    pcidev->func = func;
    2.19 +    pcidev->vdevfn = vdevfn;
    2.20 +    return 0;
    2.21 +}
    2.22 +
    2.23 +int libxl_device_pci_parse_bdf(libxl_device_pci *pcidev, const char *str)
    2.24 +{
    2.25 +    unsigned dom, bus, dev, func;
    2.26 +    char *p, *buf2;
    2.27 +    int rc;
    2.28 +
    2.29 +    if ( NULL == (buf2 = strdup(str)) )
    2.30 +        return ERROR_NOMEM;
    2.31 +
    2.32 +    p = strtok(buf2, ",");
    2.33 +
    2.34 +    if ( sscanf(str, PCI_BDF, &dom, &bus, &dev, &func) != 4 ) {
    2.35 +        dom = 0;
    2.36 +        if ( sscanf(str, PCI_BDF_SHORT, &bus, &dev, &func) != 3 ) {
    2.37 +            rc = ERROR_FAIL;
    2.38 +            goto out;
    2.39 +        }
    2.40 +    }
    2.41 +
    2.42 +    rc = pcidev_init(pcidev, dom, bus, dev, func, 0);
    2.43 +
    2.44 +    while ((p = strtok(NULL, ",=")) != NULL) {
    2.45 +        while (*p == ' ')
    2.46 +            p++;
    2.47 +        if (!strcmp(p, "msitranslate")) {
    2.48 +            p = strtok(NULL, ",=");
    2.49 +            pcidev->msitranslate = atoi(p);
    2.50 +        } else if (!strcmp(p, "power_mgmt")) {
    2.51 +            p = strtok(NULL, ",=");
    2.52 +            pcidev->power_mgmt = atoi(p);
    2.53 +        }
    2.54 +    }
    2.55 +out:
    2.56 +    free(buf2);
    2.57 +    return rc;
    2.58 +}
    2.59 +
    2.60  static int libxl_create_pci_backend(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num)
    2.61  {
    2.62      flexarray_t *front;
    2.63 @@ -288,7 +341,7 @@ static int get_all_assigned_devices(libx
    2.64                      if ( sscanf(bdf, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
    2.65                          continue;
    2.66  
    2.67 -                    libxl_device_pci_init(pcidevs + *num, dom, bus, dev, func, 0);
    2.68 +                    pcidev_init(pcidevs + *num, dom, bus, dev, func, 0);
    2.69                      (*num)++;
    2.70                  }
    2.71              }
    2.72 @@ -366,7 +419,7 @@ int libxl_device_pci_list_assignable(lib
    2.73          new = pcidevs + *num;
    2.74  
    2.75          memset(new, 0, sizeof(*new));
    2.76 -        libxl_device_pci_init(new, dom, bus, dev, func, 0);
    2.77 +        pcidev_init(new, dom, bus, dev, func, 0);
    2.78          (*num)++;
    2.79      }
    2.80  
    2.81 @@ -629,7 +682,7 @@ int libxl_device_pci_list_assigned(libxl
    2.82          xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
    2.83          if (xsvdevfn)
    2.84              vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
    2.85 -        libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
    2.86 +        pcidev_init(pcidevs + i, domain, bus, dev, func, vdevfn);
    2.87          xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
    2.88          if (xsopts) {
    2.89              char *saveptr;
    2.90 @@ -668,18 +721,6 @@ int libxl_device_pci_shutdown(libxl_ctx 
    2.91      return 0;
    2.92  }
    2.93  
    2.94 -int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
    2.95 -                          unsigned int bus, unsigned int dev,
    2.96 -                          unsigned int func, unsigned int vdevfn)
    2.97 -{
    2.98 -    pcidev->domain = domain;
    2.99 -    pcidev->bus = bus;
   2.100 -    pcidev->dev = dev;
   2.101 -    pcidev->func = func;
   2.102 -    pcidev->vdevfn = vdevfn;
   2.103 -    return 0;
   2.104 -}
   2.105 -
   2.106  int libxl_device_pci_reset(libxl_ctx *ctx, unsigned int domain, unsigned int bus,
   2.107                           unsigned int dev, unsigned int func)
   2.108  {
     3.1 --- a/tools/libxl/xl_cmdimpl.c	Wed Aug 04 14:23:29 2010 +0100
     3.2 +++ b/tools/libxl/xl_cmdimpl.c	Wed Aug 04 14:24:19 2010 +0100
     3.3 @@ -495,7 +495,7 @@ static void printf_info(int domid,
     3.4      for (i = 0; i < d_config->num_pcidevs; i++) {
     3.5          printf("\t(device\n");
     3.6          printf("\t\t(pci\n");
     3.7 -        printf("\t\t\t(pci dev "PCI_BDF_VDEVFN")\n",
     3.8 +        printf("\t\t\t(pci dev %04x:%02x:%02x.%01x@%02x)\n",
     3.9                 d_config->pcidevs[i].domain, d_config->pcidevs[i].bus,
    3.10                 d_config->pcidevs[i].dev, d_config->pcidevs[i].func,
    3.11                 d_config->pcidevs[i].vdevfn);
    3.12 @@ -953,46 +953,20 @@ skip_vfb:
    3.13          pci_power_mgmt = l;
    3.14  
    3.15      if (!xlu_cfg_get_list (config, "pci", &pcis, 0)) {
    3.16 +        int i;
    3.17          d_config->num_pcidevs = 0;
    3.18          d_config->pcidevs = NULL;
    3.19 -        while ((buf = xlu_cfg_get_listitem (pcis, d_config->num_pcidevs)) != NULL) {
    3.20 +        for(i = 0; (buf = xlu_cfg_get_listitem (pcis, i)) != NULL; i++) {
    3.21              libxl_device_pci *pcidev;
    3.22 -            unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
    3.23 -            char *buf2 = strdup(buf);
    3.24 -            char *p;
    3.25  
    3.26              d_config->pcidevs = (libxl_device_pci *) realloc(d_config->pcidevs, sizeof (libxl_device_pci) * (d_config->num_pcidevs + 1));
    3.27              pcidev = d_config->pcidevs + d_config->num_pcidevs;
    3.28              memset(pcidev, 0x00, sizeof(libxl_device_pci));
    3.29  
    3.30 -            p = strtok(buf2, ",");
    3.31 -            if (!p)
    3.32 -                goto skip_pci;
    3.33 -            if (sscanf(p, PCI_BDF_VDEVFN, &domain, &bus, &dev, &func, &vdevfn) < 4) {
    3.34 -                domain = 0;
    3.35 -                if (sscanf(p, "%02x:%02x.%01x@%02x", &bus, &dev, &func, &vdevfn) < 3) {
    3.36 -                    fprintf(stderr,"xl: Unable to parse pci bdf (%s)\n", p);
    3.37 -                    goto skip_pci;
    3.38 -                }
    3.39 -            }
    3.40 -
    3.41 -            libxl_device_pci_init(pcidev, domain, bus, dev, func, vdevfn);
    3.42              pcidev->msitranslate = pci_msitranslate;
    3.43              pcidev->power_mgmt = pci_power_mgmt;
    3.44 -            while ((p = strtok(NULL, ",=")) != NULL) {
    3.45 -                while (*p == ' ')
    3.46 -                    p++;
    3.47 -                if (!strcmp(p, "msitranslate")) {
    3.48 -                    p = strtok(NULL, ",=");
    3.49 -                    pcidev->msitranslate = atoi(p);
    3.50 -                } else if (!strcmp(p, "power_mgmt")) {
    3.51 -                    p = strtok(NULL, ",=");
    3.52 -                    pcidev->power_mgmt = atoi(p);
    3.53 -                }
    3.54 -            }
    3.55 -            d_config->num_pcidevs++;
    3.56 -skip_pci:
    3.57 -            free(buf2);
    3.58 +            if (!libxl_device_pci_parse_bdf(pcidev, buf))
    3.59 +                d_config->num_pcidevs++;
    3.60          }
    3.61      }
    3.62  
    3.63 @@ -2019,16 +1993,14 @@ int main_pcilist(int argc, char **argv)
    3.64  void pcidetach(char *dom, char *bdf)
    3.65  {
    3.66      libxl_device_pci pcidev;
    3.67 -    unsigned int domain, bus, dev, func;
    3.68  
    3.69      find_domain(dom);
    3.70  
    3.71      memset(&pcidev, 0x00, sizeof(pcidev));
    3.72 -    if (sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func) != 4) {
    3.73 +    if (libxl_device_pci_parse_bdf(&pcidev, bdf)) {
    3.74          fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
    3.75          exit(2);
    3.76      }
    3.77 -    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
    3.78      libxl_device_pci_remove(&ctx, domid, &pcidev);
    3.79  }
    3.80  
    3.81 @@ -2061,16 +2033,14 @@ int main_pcidetach(int argc, char **argv
    3.82  void pciattach(char *dom, char *bdf, char *vs)
    3.83  {
    3.84      libxl_device_pci pcidev;
    3.85 -    unsigned int domain, bus, dev, func;
    3.86  
    3.87      find_domain(dom);
    3.88  
    3.89      memset(&pcidev, 0x00, sizeof(pcidev));
    3.90 -    if (sscanf(bdf, PCI_BDF, &domain, &bus, &dev, &func) != 4) {
    3.91 +    if (libxl_device_pci_parse_bdf(&pcidev, bdf)) {
    3.92          fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
    3.93          exit(2);
    3.94      }
    3.95 -    libxl_device_pci_init(&pcidev, domain, bus, dev, func, 0);
    3.96      libxl_device_pci_add(&ctx, domid, &pcidev);
    3.97  }
    3.98