aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxl/Makefile2
-rw-r--r--tools/libxl/libxl.h7
-rw-r--r--tools/libxl/libxl_pci.c155
-rw-r--r--tools/libxl/libxlu_pci.c172
-rw-r--r--tools/libxl/libxlutil.h5
-rw-r--r--tools/libxl/xl_cmdimpl.c16
-rw-r--r--tools/python/xen/lowlevel/xl/xl.c3
7 files changed, 199 insertions, 161 deletions
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index e44fcfaa87..748d0571f2 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -57,7 +57,7 @@ $(LIBXL_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_lib
AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h _libxl_list.h
AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o \
- libxlu_disk_l.o libxlu_disk.o
+ libxlu_disk_l.o libxlu_disk.o libxlu_pci.o
$(LIBXLU_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h
CLIENTS = xl testidl
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 098b680e6f..2aec91076d 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -653,13 +653,6 @@ int libxl_device_pci_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *p
libxl_device_pci *libxl_device_pci_list(libxl_ctx *ctx, uint32_t domid, int *num);
/*
- * Parse a PCI BDF into a PCI device structure.
- */
-int libxl_device_pci_parse_bdf(libxl_ctx *ctx,
- libxl_device_pci *pcidev,
- const char *str);
-
-/*
* Similar to libxl_device_pci_list but returns all devices which
* could be assigned to a domain (i.e. are bound to the backend
* driver) but are not currently.
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
index 622abd4d50..94077c94d2 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -34,9 +34,9 @@ static unsigned int pcidev_encode_bdf(libxl_device_pci *pcidev)
return value;
}
-static int pcidev_init(libxl_device_pci *pcidev, unsigned int domain,
- unsigned int bus, unsigned int dev,
- unsigned int func, unsigned int vdevfn)
+static int pcidev_struct_fill(libxl_device_pci *pcidev, unsigned int domain,
+ unsigned int bus, unsigned int dev,
+ unsigned int func, unsigned int vdevfn)
{
pcidev->domain = domain;
pcidev->bus = bus;
@@ -46,149 +46,6 @@ static int pcidev_init(libxl_device_pci *pcidev, unsigned int domain,
return 0;
}
-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;
-
- 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 ( !strcmp(tok, "*") ) {
- pcidev->vfunc_mask = LIBXL_PCI_FUNC_ALL;
- }else{
- if ( hex_convert(tok, &func, 0x7) )
- goto parse_error;
- pcidev->vfunc_mask = (1 << 0);
- }
- 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{
- LIBXL__LOG(ctx, LIBXL__LOG_WARNING,
- "Unknown PCI BDF option: %s", optkey);
- }
- tok = ptr + 1;
- }
- default:
- break;
- }
- }
-
- free(buf2);
-
- if ( tok != ptr || state != STATE_TERMINAL )
- goto parse_error;
-
- pcidev_init(pcidev, dom, bus, dev, func, vslot << 3);
-
- return 0;
-
-parse_error:
- return ERROR_INVAL;
-}
-
static void libxl_create_pci_backend_device(libxl__gc *gc, flexarray_t *back, int num, libxl_device_pci *pcidev)
{
flexarray_append(back, libxl__sprintf(gc, "key-%d", num));
@@ -436,7 +293,7 @@ static int get_all_assigned_devices(libxl__gc *gc, libxl_device_pci **list, int
*list = realloc(*list, sizeof(libxl_device_pci) * ((*num) + 1));
if (*list == NULL)
return ERROR_NOMEM;
- pcidev_init(*list + *num, dom, bus, dev, func, 0);
+ pcidev_struct_fill(*list + *num, dom, bus, dev, func, 0);
(*num)++;
}
}
@@ -507,7 +364,7 @@ libxl_device_pci *libxl_device_pci_list_assignable(libxl_ctx *ctx, int *num)
new = pcidevs + *num;
memset(new, 0, sizeof(*new));
- pcidev_init(new, dom, bus, dev, func, 0);
+ pcidev_struct_fill(new, dom, bus, dev, func, 0);
(*num)++;
}
@@ -1086,7 +943,7 @@ static void libxl__device_pci_from_xs_be(libxl__gc *gc,
if (s)
vdevfn = strtol(s, (char **) NULL, 16);
- pcidev_init(pci, domain, bus, dev, func, vdevfn);
+ pcidev_struct_fill(pci, domain, bus, dev, func, vdevfn);
s = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/opts-%d", be_path, nr));
if (s) {
diff --git a/tools/libxl/libxlu_pci.c b/tools/libxl/libxlu_pci.c
new file mode 100644
index 0000000000..cc70d9fdf5
--- /dev/null
+++ b/tools/libxl/libxlu_pci.c
@@ -0,0 +1,172 @@
+#include "libxl_osdeps.h" /* must come before any other headers */
+#include "libxlu_internal.h"
+#include "libxlu_disk_l.h"
+#include "libxlu_disk_i.h"
+#include "libxlu_cfg_i.h"
+
+
+#define XLU__PCI_ERR(_c, _x, _a...) \
+ if((_c) && (_c)->report) fprintf((_c)->report, _x, ##_a)
+
+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;
+}
+
+static int pcidev_struct_fill(libxl_device_pci *pcidev, unsigned int domain,
+ unsigned int bus, unsigned int dev,
+ unsigned int func, unsigned int vdevfn)
+{
+ pcidev->domain = domain;
+ pcidev->bus = bus;
+ pcidev->dev = dev;
+ pcidev->func = func;
+ pcidev->vdevfn = vdevfn;
+ 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 xlu_pci_parse_bdf(XLU_Config *cfg, 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;
+
+ 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 ( !strcmp(tok, "*") ) {
+ pcidev->vfunc_mask = LIBXL_PCI_FUNC_ALL;
+ }else{
+ if ( hex_convert(tok, &func, 0x7) )
+ goto parse_error;
+ pcidev->vfunc_mask = (1 << 0);
+ }
+ 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{
+ XLU__PCI_ERR(cfg, "Unknown PCI BDF option: %s", optkey);
+ }
+ tok = ptr + 1;
+ }
+ default:
+ break;
+ }
+ }
+
+ free(buf2);
+
+ if ( tok != ptr || state != STATE_TERMINAL )
+ goto parse_error;
+
+ /* Just a pretty way to fill in the values */
+ pcidev_struct_fill(pcidev, dom, bus, dev, func, vslot << 3);
+
+ return 0;
+
+parse_error:
+ return ERROR_INVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxlutil.h b/tools/libxl/libxlutil.h
index 620b9dbb47..1b05f4c343 100644
--- a/tools/libxl/libxlutil.h
+++ b/tools/libxl/libxlutil.h
@@ -88,6 +88,11 @@ int xlu_disk_parse(XLU_Config *cfg, int nspecs, const char *const *specs,
* resulting disk struct is used with libxl.
*/
+/*
+ * PCI specification parsing
+ */
+int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_device_pci *pcidev, const char *str);
+
#endif /* LIBXLUTIL_H */
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 7868ce798c..fd458a61c5 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1010,7 +1010,7 @@ skip_vfb:
pcidev->msitranslate = pci_msitranslate;
pcidev->power_mgmt = pci_power_mgmt;
- if (!libxl_device_pci_parse_bdf(ctx, pcidev, buf))
+ if (!xlu_pci_parse_bdf(config, pcidev, buf))
d_config->num_pcidevs++;
}
if (d_config->num_pcidevs && c_info->type == LIBXL_DOMAIN_TYPE_PV)
@@ -2253,11 +2253,16 @@ int main_pcilist(int argc, char **argv)
static void pcidetach(const char *dom, const char *bdf, int force)
{
libxl_device_pci pcidev;
+ XLU_Config *config;
find_domain(dom);
memset(&pcidev, 0x00, sizeof(pcidev));
- if (libxl_device_pci_parse_bdf(ctx, &pcidev, bdf)) {
+
+ config = xlu_cfg_init(stderr, "command line");
+ if (!config) { perror("xlu_cfg_inig"); exit(-1); }
+
+ if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
fprintf(stderr, "pci-detach: malformed BDF specification \"%s\"\n", bdf);
exit(2);
}
@@ -2293,11 +2298,16 @@ int main_pcidetach(int argc, char **argv)
static void pciattach(const char *dom, const char *bdf, const char *vs)
{
libxl_device_pci pcidev;
+ XLU_Config *config;
find_domain(dom);
memset(&pcidev, 0x00, sizeof(pcidev));
- if (libxl_device_pci_parse_bdf(ctx, &pcidev, bdf)) {
+
+ config = xlu_cfg_init(stderr, "command line");
+ if (!config) { perror("xlu_cfg_inig"); exit(-1); }
+
+ if (xlu_pci_parse_bdf(config, &pcidev, bdf)) {
fprintf(stderr, "pci-attach: malformed BDF specification \"%s\"\n", bdf);
exit(2);
}
diff --git a/tools/python/xen/lowlevel/xl/xl.c b/tools/python/xen/lowlevel/xl/xl.c
index bbbf2a9cb6..c4f7c52714 100644
--- a/tools/python/xen/lowlevel/xl/xl.c
+++ b/tools/python/xen/lowlevel/xl/xl.c
@@ -40,6 +40,7 @@
#include <libxl.h>
#include <libxl_utils.h>
+#include <libxlutil.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -556,7 +557,7 @@ static PyObject *pyxl_pci_parse(XlObject *self, PyObject *args)
return NULL;
}
- if ( libxl_device_pci_parse_bdf(self->ctx, &pci->obj, str) ) {
+ if ( xlu_pci_parse_bdf(NULL, &pci->obj, str) ) {
PyErr_SetString(xl_error_obj, "cannot parse pci device spec (BDF)");
Py_DECREF(pci);
return NULL;