[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] xl: implement pci attach to explicitly defined virtual PCI slot



# HG changeset patch
# User Gianni Tedesco <gianni.tedesco@xxxxxxxxxx>
# Date 1280929380 -3600
# Node ID 9c720d64160b5e98f3b44b37a23de630c96c085f
# Parent  b92dfdc284ddf1c5be14526cb74f5f5571f5eef1
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@xxxxxxxxxx>
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 tools/libxl/libxl.h      |    2 
 tools/libxl/libxl_pci.c  |  166 +++++++++++++++++++++++++++++++++++++----------
 tools/libxl/xl_cmdimpl.c |    6 -
 3 files changed, 138 insertions(+), 36 deletions(-)

diff -r b92dfdc284dd -r 9c720d64160b tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Wed Aug 04 14:24:43 2010 +0100
+++ b/tools/libxl/libxl.h       Wed Aug 04 14:43:00 2010 +0100
@@ -521,7 +521,7 @@ int libxl_device_pci_shutdown(libxl_ctx 
 int libxl_device_pci_shutdown(libxl_ctx *ctx, uint32_t domid);
 int libxl_device_pci_list_assigned(libxl_ctx *ctx, libxl_device_pci **list, 
uint32_t domid, int *num);
 int libxl_device_pci_list_assignable(libxl_ctx *ctx, libxl_device_pci **list, 
int *num);
-int libxl_device_pci_parse_bdf(libxl_device_pci *pcidev, const char *str);
+int libxl_device_pci_parse_bdf(libxl_ctx *ctx, libxl_device_pci *pcidev, const 
char *str);
 
 /*
  * Functions for allowing users of libxl to store private data
diff -r b92dfdc284dd -r 9c720d64160b tools/libxl/libxl_pci.c
--- a/tools/libxl/libxl_pci.c   Wed Aug 04 14:24:43 2010 +0100
+++ b/tools/libxl/libxl_pci.c   Wed Aug 04 14:43:00 2010 +0100
@@ -52,41 +52,143 @@ static int pcidev_init(libxl_device_pci 
     return 0;
 }
 
-int libxl_device_pci_parse_bdf(libxl_device_pci *pcidev, const char *str)
-{
-    unsigned dom, bus, dev, func;
-    char *p, *buf2;
-    int rc;
-
-    if ( NULL == (buf2 = strdup(str)) )
+static int hex_convert(const char *str, unsigned int *val, unsigned int mask)
+{
+    unsigned long ret;
+    char *end;
+
+    ret = strtoul(str, &end, 16);
+    if ( end == str || *end != '\0' )
+        return -1;
+    if ( ret & ~mask )
+        return -1;
+    *val = (unsigned int)ret & mask;
+    return 0;
+}
+
+#define STATE_DOMAIN    0
+#define STATE_BUS       1
+#define STATE_DEV       2
+#define STATE_FUNC      3
+#define STATE_VSLOT     4
+#define STATE_OPTIONS_K 6
+#define STATE_OPTIONS_V 7
+#define STATE_TERMINAL  8
+int libxl_device_pci_parse_bdf(libxl_ctx *ctx, libxl_device_pci *pcidev, const 
char *str)
+{
+    unsigned state = STATE_DOMAIN;
+    unsigned dom, bus, dev, func, vslot = 0;
+    char *buf2, *tok, *ptr, *end, *optkey = NULL;
+
+    if ( NULL == (buf2 = ptr = strdup(str)) )
         return ERROR_NOMEM;
 
-    p = strtok(buf2, ",");
-
-    if ( sscanf(str, PCI_BDF, &dom, &bus, &dev, &func) != 4 ) {
-        dom = 0;
-        if ( sscanf(str, PCI_BDF_SHORT, &bus, &dev, &func) != 3 ) {
-            rc = ERROR_FAIL;
-            goto out;
-        }
-    }
-
-    rc = pcidev_init(pcidev, dom, bus, dev, func, 0);
-
-    while ((p = strtok(NULL, ",=")) != NULL) {
-        while (*p == ' ')
-            p++;
-        if (!strcmp(p, "msitranslate")) {
-            p = strtok(NULL, ",=");
-            pcidev->msitranslate = atoi(p);
-        } else if (!strcmp(p, "power_mgmt")) {
-            p = strtok(NULL, ",=");
-            pcidev->power_mgmt = atoi(p);
-        }
-    }
-out:
+    for(tok = ptr, end = ptr + strlen(ptr) + 1; ptr < end; ptr++) {
+        switch(state) {
+        case STATE_DOMAIN:
+            if ( *ptr == ':' ) {
+                state = STATE_BUS;
+                *ptr = '\0';
+                if ( hex_convert(tok, &dom, 0xffff) )
+                    goto parse_error;
+                tok = ptr + 1;
+            }
+            break;
+        case STATE_BUS:
+            if ( *ptr == ':' ) {
+                state = STATE_DEV;
+                *ptr = '\0';
+                if ( hex_convert(tok, &bus, 0xff) )
+                    goto parse_error;
+                tok = ptr + 1;
+            }else if ( *ptr == '.' ) {
+                state = STATE_FUNC;
+                *ptr = '\0';
+                if ( dom & ~0xff )
+                    goto parse_error;
+                bus = dom;
+                dom = 0;
+                if ( hex_convert(tok, &dev, 0xff) )
+                    goto parse_error;
+                tok = ptr + 1;
+            }
+            break;
+        case STATE_DEV:
+            if ( *ptr == '.' ) {
+                state = STATE_FUNC;
+                *ptr = '\0';
+                if ( hex_convert(tok, &dev, 0xff) )
+                    goto parse_error;
+                tok = ptr + 1;
+            }
+            break;
+        case STATE_FUNC:
+            if ( *ptr == '\0' || *ptr == '@' || *ptr == ',' ) {
+                switch( *ptr ) {
+                case '\0':
+                    state = STATE_TERMINAL;
+                    break;
+                case '@':
+                    state = STATE_VSLOT;
+                    break;
+                case ',':
+                    state = STATE_OPTIONS_K;
+                    break;
+                }
+                *ptr = '\0';
+                if ( hex_convert(tok, &func, 0x7) )
+                    goto parse_error;
+                tok = ptr + 1;
+            }
+            break;
+        case STATE_VSLOT:
+            if ( *ptr == '\0' || *ptr == ',' ) {
+                state = ( *ptr == ',' ) ? STATE_OPTIONS_K : STATE_TERMINAL;
+                *ptr = '\0';
+                if ( hex_convert(tok, &vslot, 0xff) )
+                    goto parse_error;
+                tok = ptr + 1;
+            }
+            break;
+        case STATE_OPTIONS_K:
+            if ( *ptr == '=' ) {
+                state = STATE_OPTIONS_V;
+                *ptr = '\0';
+                optkey = tok;
+                tok = ptr + 1;
+            }
+            break;
+        case STATE_OPTIONS_V:
+            if ( *ptr == ',' || *ptr == '\0' ) {
+                state = (*ptr == ',') ? STATE_OPTIONS_K : STATE_TERMINAL;
+                *ptr = '\0';
+                if ( !strcmp(optkey, "msitranslate") ) {
+                    pcidev->msitranslate = atoi(tok);
+                }else if ( !strcmp(optkey, "power_mgmt") ) {
+                    pcidev->power_mgmt = atoi(tok);
+                }else{
+                    XL_LOG(ctx, XL_LOG_WARNING,
+                           "Unknown PCI BDF option: %s", optkey);
+                }
+                tok = ptr + 1;
+            }
+        default:
+            break;
+        }
+    }
+
     free(buf2);
-    return rc;
+
+    if ( tok != ptr || state != STATE_TERMINAL )
+        goto parse_error;
+
+    pcidev_init(pcidev, dom, bus, dev, func, vslot << 3);
+
+    return 0;
+
+parse_error:
+    printf("parse error: %s\n", str);
+    return ERROR_INVAL;
 }
 
 static int libxl_create_pci_backend(libxl_ctx *ctx, uint32_t domid, 
libxl_device_pci *pcidev, int num)
diff -r b92dfdc284dd -r 9c720d64160b tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c  Wed Aug 04 14:24:43 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c  Wed Aug 04 14:43:00 2010 +0100
@@ -965,7 +965,7 @@ skip_vfb:
 
             pcidev->msitranslate = pci_msitranslate;
             pcidev->power_mgmt = pci_power_mgmt;
-            if (!libxl_device_pci_parse_bdf(pcidev, buf))
+            if (!libxl_device_pci_parse_bdf(&ctx, pcidev, buf))
                 d_config->num_pcidevs++;
         }
     }
@@ -1997,7 +1997,7 @@ void pcidetach(char *dom, char *bdf)
     find_domain(dom);
 
     memset(&pcidev, 0x00, sizeof(pcidev));
-    if (libxl_device_pci_parse_bdf(&pcidev, bdf)) {
+    if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
         fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", 
bdf);
         exit(2);
     }
@@ -2037,7 +2037,7 @@ void pciattach(char *dom, char *bdf, cha
     find_domain(dom);
 
     memset(&pcidev, 0x00, sizeof(pcidev));
-    if (libxl_device_pci_parse_bdf(&pcidev, bdf)) {
+    if (libxl_device_pci_parse_bdf(&ctx, &pcidev, bdf)) {
         fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", 
bdf);
         exit(2);
     }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.