debuggers.hg

changeset 21964:9c720d64160b

xl: implement pci attach to explicitly defined virtual PCI slot

Move to state-machine parser for PCI BDF's now that the number of possible
sscanf expressions is sufficiently large to make it worth it. Also implement
parsing of virtual PCI slot numbers.

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:43:00 2010 +0100 (2010-08-04)
parents b92dfdc284dd
children 20540b8fe4b6
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:24:43 2010 +0100
     1.2 +++ b/tools/libxl/libxl.h	Wed Aug 04 14:43:00 2010 +0100
     1.3 @@ -521,7 +521,7 @@ int libxl_device_pci_remove(libxl_ctx *c
     1.4  int libxl_device_pci_shutdown(libxl_ctx *ctx, uint32_t domid);
     1.5  int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, uint32_t domid, int *num);
     1.6  int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, int *num);
     1.7 -int libxl_device_pci_parse_bdf(libxl_device_pci *pcidev, const char *str);
     1.8 +int libxl_device_pci_parse_bdf(libxl_ctx *ctx, libxl_device_pci *pcidev, const char *str);
     1.9  
    1.10  /*
    1.11   * Functions for allowing users of libxl to store private data
     2.1 --- a/tools/libxl/libxl_pci.c	Wed Aug 04 14:24:43 2010 +0100
     2.2 +++ b/tools/libxl/libxl_pci.c	Wed Aug 04 14:43:00 2010 +0100
     2.3 @@ -52,41 +52,143 @@ static int pcidev_init(libxl_device_pci 
     2.4      return 0;
     2.5  }
     2.6  
     2.7 -int libxl_device_pci_parse_bdf(libxl_device_pci *pcidev, const char *str)
     2.8 +static int hex_convert(const char *str, unsigned int *val, unsigned int mask)
     2.9  {
    2.10 -    unsigned dom, bus, dev, func;
    2.11 -    char *p, *buf2;
    2.12 -    int rc;
    2.13 +    unsigned long ret;
    2.14 +    char *end;
    2.15 +
    2.16 +    ret = strtoul(str, &end, 16);
    2.17 +    if ( end == str || *end != '\0' )
    2.18 +        return -1;
    2.19 +    if ( ret & ~mask )
    2.20 +        return -1;
    2.21 +    *val = (unsigned int)ret & mask;
    2.22 +    return 0;
    2.23 +}
    2.24  
    2.25 -    if ( NULL == (buf2 = strdup(str)) )
    2.26 +#define STATE_DOMAIN    0
    2.27 +#define STATE_BUS       1
    2.28 +#define STATE_DEV       2
    2.29 +#define STATE_FUNC      3
    2.30 +#define STATE_VSLOT     4
    2.31 +#define STATE_OPTIONS_K 6
    2.32 +#define STATE_OPTIONS_V 7
    2.33 +#define STATE_TERMINAL  8
    2.34 +int libxl_device_pci_parse_bdf(libxl_ctx *ctx, libxl_device_pci *pcidev, const char *str)
    2.35 +{
    2.36 +    unsigned state = STATE_DOMAIN;
    2.37 +    unsigned dom, bus, dev, func, vslot = 0;
    2.38 +    char *buf2, *tok, *ptr, *end, *optkey = NULL;
    2.39 +
    2.40 +    if ( NULL == (buf2 = ptr = strdup(str)) )
    2.41          return ERROR_NOMEM;
    2.42  
    2.43 -    p = strtok(buf2, ",");
    2.44 -
    2.45 -    if ( sscanf(str, PCI_BDF, &dom, &bus, &dev, &func) != 4 ) {
    2.46 -        dom = 0;
    2.47 -        if ( sscanf(str, PCI_BDF_SHORT, &bus, &dev, &func) != 3 ) {
    2.48 -            rc = ERROR_FAIL;
    2.49 -            goto out;
    2.50 +    for(tok = ptr, end = ptr + strlen(ptr) + 1; ptr < end; ptr++) {
    2.51 +        switch(state) {
    2.52 +        case STATE_DOMAIN:
    2.53 +            if ( *ptr == ':' ) {
    2.54 +                state = STATE_BUS;
    2.55 +                *ptr = '\0';
    2.56 +                if ( hex_convert(tok, &dom, 0xffff) )
    2.57 +                    goto parse_error;
    2.58 +                tok = ptr + 1;
    2.59 +            }
    2.60 +            break;
    2.61 +        case STATE_BUS:
    2.62 +            if ( *ptr == ':' ) {
    2.63 +                state = STATE_DEV;
    2.64 +                *ptr = '\0';
    2.65 +                if ( hex_convert(tok, &bus, 0xff) )
    2.66 +                    goto parse_error;
    2.67 +                tok = ptr + 1;
    2.68 +            }else if ( *ptr == '.' ) {
    2.69 +                state = STATE_FUNC;
    2.70 +                *ptr = '\0';
    2.71 +                if ( dom & ~0xff )
    2.72 +                    goto parse_error;
    2.73 +                bus = dom;
    2.74 +                dom = 0;
    2.75 +                if ( hex_convert(tok, &dev, 0xff) )
    2.76 +                    goto parse_error;
    2.77 +                tok = ptr + 1;
    2.78 +            }
    2.79 +            break;
    2.80 +        case STATE_DEV:
    2.81 +            if ( *ptr == '.' ) {
    2.82 +                state = STATE_FUNC;
    2.83 +                *ptr = '\0';
    2.84 +                if ( hex_convert(tok, &dev, 0xff) )
    2.85 +                    goto parse_error;
    2.86 +                tok = ptr + 1;
    2.87 +            }
    2.88 +            break;
    2.89 +        case STATE_FUNC:
    2.90 +            if ( *ptr == '\0' || *ptr == '@' || *ptr == ',' ) {
    2.91 +                switch( *ptr ) {
    2.92 +                case '\0':
    2.93 +                    state = STATE_TERMINAL;
    2.94 +                    break;
    2.95 +                case '@':
    2.96 +                    state = STATE_VSLOT;
    2.97 +                    break;
    2.98 +                case ',':
    2.99 +                    state = STATE_OPTIONS_K;
   2.100 +                    break;
   2.101 +                }
   2.102 +                *ptr = '\0';
   2.103 +                if ( hex_convert(tok, &func, 0x7) )
   2.104 +                    goto parse_error;
   2.105 +                tok = ptr + 1;
   2.106 +            }
   2.107 +            break;
   2.108 +        case STATE_VSLOT:
   2.109 +            if ( *ptr == '\0' || *ptr == ',' ) {
   2.110 +                state = ( *ptr == ',' ) ? STATE_OPTIONS_K : STATE_TERMINAL;
   2.111 +                *ptr = '\0';
   2.112 +                if ( hex_convert(tok, &vslot, 0xff) )
   2.113 +                    goto parse_error;
   2.114 +                tok = ptr + 1;
   2.115 +            }
   2.116 +            break;
   2.117 +        case STATE_OPTIONS_K:
   2.118 +            if ( *ptr == '=' ) {
   2.119 +                state = STATE_OPTIONS_V;
   2.120 +                *ptr = '\0';
   2.121 +                optkey = tok;
   2.122 +                tok = ptr + 1;
   2.123 +            }
   2.124 +            break;
   2.125 +        case STATE_OPTIONS_V:
   2.126 +            if ( *ptr == ',' || *ptr == '\0' ) {
   2.127 +                state = (*ptr == ',') ? STATE_OPTIONS_K : STATE_TERMINAL;
   2.128 +                *ptr = '\0';
   2.129 +                if ( !strcmp(optkey, "msitranslate") ) {
   2.130 +                    pcidev->msitranslate = atoi(tok);
   2.131 +                }else if ( !strcmp(optkey, "power_mgmt") ) {
   2.132 +                    pcidev->power_mgmt = atoi(tok);
   2.133 +                }else{
   2.134 +                    XL_LOG(ctx, XL_LOG_WARNING,
   2.135 +                           "Unknown PCI BDF option: %s", optkey);
   2.136 +                }
   2.137 +                tok = ptr + 1;
   2.138 +            }
   2.139 +        default:
   2.140 +            break;
   2.141          }
   2.142      }
   2.143  
   2.144 -    rc = pcidev_init(pcidev, dom, bus, dev, func, 0);
   2.145 +    free(buf2);
   2.146 +
   2.147 +    if ( tok != ptr || state != STATE_TERMINAL )
   2.148 +        goto parse_error;
   2.149  
   2.150 -    while ((p = strtok(NULL, ",=")) != NULL) {
   2.151 -        while (*p == ' ')
   2.152 -            p++;
   2.153 -        if (!strcmp(p, "msitranslate")) {
   2.154 -            p = strtok(NULL, ",=");
   2.155 -            pcidev->msitranslate = atoi(p);
   2.156 -        } else if (!strcmp(p, "power_mgmt")) {
   2.157 -            p = strtok(NULL, ",=");
   2.158 -            pcidev->power_mgmt = atoi(p);
   2.159 -        }
   2.160 -    }
   2.161 -out:
   2.162 -    free(buf2);
   2.163 -    return rc;
   2.164 +    pcidev_init(pcidev, dom, bus, dev, func, vslot << 3);
   2.165 +
   2.166 +    return 0;
   2.167 +
   2.168 +parse_error:
   2.169 +    printf("parse error: %s\n", str);
   2.170 +    return ERROR_INVAL;
   2.171  }
   2.172  
   2.173  static int libxl_create_pci_backend(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num)
     3.1 --- a/tools/libxl/xl_cmdimpl.c	Wed Aug 04 14:24:43 2010 +0100
     3.2 +++ b/tools/libxl/xl_cmdimpl.c	Wed Aug 04 14:43:00 2010 +0100
     3.3 @@ -965,7 +965,7 @@ skip_vfb:
     3.4  
     3.5              pcidev->msitranslate = pci_msitranslate;
     3.6              pcidev->power_mgmt = pci_power_mgmt;
     3.7 -            if (!libxl_device_pci_parse_bdf(pcidev, buf))
     3.8 +            if (!libxl_device_pci_parse_bdf(&ctx, pcidev, buf))
     3.9                  d_config->num_pcidevs++;
    3.10          }
    3.11      }
    3.12 @@ -1997,7 +1997,7 @@ void pcidetach(char *dom, char *bdf)
    3.13      find_domain(dom);
    3.14  
    3.15      memset(&pcidev, 0x00, sizeof(pcidev));
    3.16 -    if (libxl_device_pci_parse_bdf(&pcidev, bdf)) {
    3.17 +    if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
    3.18          fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
    3.19          exit(2);
    3.20      }
    3.21 @@ -2037,7 +2037,7 @@ void pciattach(char *dom, char *bdf, cha
    3.22      find_domain(dom);
    3.23  
    3.24      memset(&pcidev, 0x00, sizeof(pcidev));
    3.25 -    if (libxl_device_pci_parse_bdf(&pcidev, bdf)) {
    3.26 +    if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
    3.27          fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
    3.28          exit(2);
    3.29      }