#define PCI_BDF_XSPATH "%04x-%02x-%02x-%01x"
#define PCI_PT_QDEV_ID "pci-pt-%02x_%02x.%01x"
-static unsigned int pci_encode_bdf(libxl_pci_bdf *pcibdf)
+static unsigned int pci_encode_bdf(libxl_device_pci *pci)
{
unsigned int value;
- value = pcibdf->domain << 16;
- value |= (pcibdf->bus & 0xff) << 8;
- value |= (pcibdf->dev & 0x1f) << 3;
- value |= (pcibdf->func & 0x7);
+ value = pci->domain << 16;
+ value |= (pci->bus & 0xff) << 8;
+ value |= (pci->dev & 0x1f) << 3;
+ value |= (pci->func & 0x7);
return value;
}
-static void pcibdf_struct_fill(libxl_pci_bdf *pcibdf, unsigned int domain,
- unsigned int bus, unsigned int dev,
- unsigned int func)
-{
- pcibdf->domain = domain;
- pcibdf->bus = bus;
- pcibdf->dev = dev;
- pcibdf->func = func;
-}
-
static void pci_struct_fill(libxl_device_pci *pci, unsigned int domain,
unsigned int bus, unsigned int dev,
unsigned int func, unsigned int vdevfn)
{
- pcibdf_struct_fill(&pci->bdf, domain, bus, dev, func);
+ pci->domain = domain;
+ pci->bus = bus;
+ pci->dev = dev;
+ pci->func = func;
pci->vdevfn = vdevfn;
}
int num,
const libxl_device_pci *pci)
{
- if (pci->name) {
- flexarray_append(back, GCSPRINTF("name-%d", num));
- flexarray_append(back, GCSPRINTF("%s", pci->name));
- }
flexarray_append(back, GCSPRINTF("key-%d", num));
- flexarray_append(back, GCSPRINTF(PCI_BDF, pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func));
+ flexarray_append(back, GCSPRINTF(PCI_BDF, pci->domain, pci->bus, pci->dev, pci->func));
flexarray_append(back, GCSPRINTF("dev-%d", num));
- flexarray_append(back, GCSPRINTF(PCI_BDF, pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func));
+ flexarray_append(back, GCSPRINTF(PCI_BDF, pci->domain, pci->bus, pci->dev, pci->func));
if (pci->vdevfn)
flexarray_append_pair(back, GCSPRINTF("vdevfn-%d", num), GCSPRINTF("%x", pci->vdevfn));
flexarray_append(back, GCSPRINTF("opts-%d", num));
unsigned int domain = 0, bus = 0, dev = 0, func = 0;
xsdev = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/dev-%d", be_path, i));
sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
- if (domain == pci->bdf.domain && bus == pci->bdf.bus &&
- pci->bdf.dev == dev && pci->bdf.func == func) {
+ if (domain == pci->domain && bus == pci->bus &&
+ pci->dev == dev && pci->func == func) {
break;
}
}
retry_transaction2:
t = xs_transaction_start(ctx->xsh);
- xs_rm(ctx->xsh, t, GCSPRINTF("%s/name-%d", be_path, i));
xs_rm(ctx->xsh, t, GCSPRINTF("%s/state-%d", be_path, i));
xs_rm(ctx->xsh, t, GCSPRINTF("%s/key-%d", be_path, i));
xs_rm(ctx->xsh, t, GCSPRINTF("%s/dev-%d", be_path, i));
xs_write(ctx->xsh, t, GCSPRINTF("%s/vdevfn-%d", be_path, j - 1), tmp, strlen(tmp));
xs_rm(ctx->xsh, t, tmppath);
}
- tmppath = GCSPRINTF("%s/name-%d", be_path, j);
- tmp = libxl__xs_read(gc, t, tmppath);
- if (tmp) {
- xs_write(ctx->xsh, t, GCSPRINTF("%s/name-%d", be_path, j - 1), tmp, strlen(tmp));
- xs_rm(ctx->xsh, t, tmppath);
- }
}
if (!xs_transaction_end(ctx->xsh, t, 0))
if (errno == EAGAIN)
}
/* Write the standard BDF into the sysfs path given by sysfs_path. */
-static int sysfs_write_bdf(libxl__gc *gc, const char *sysfs_path,
- libxl_pci_bdf *pcibdf)
+static int sysfs_write_bdf(libxl__gc *gc, const char * sysfs_path,
+ libxl_device_pci *pci)
{
int rc, fd;
char *buf;
return ERROR_FAIL;
}
- buf = GCSPRINTF(PCI_BDF, pcibdf->domain, pcibdf->bus,
- pcibdf->dev, pcibdf->func);
+ buf = GCSPRINTF(PCI_BDF, pci->domain, pci->bus,
+ pci->dev, pci->func);
rc = write(fd, buf, strlen(buf));
/* Annoying to have two if's, but we need the errno */
if (rc < 0)
#define PCI_INFO_PATH "/libxl/pci"
-static char *pci_info_xs_path(libxl__gc *gc, libxl_pci_bdf *pcibdf,
+static char *pci_info_xs_path(libxl__gc *gc, libxl_device_pci *pci,
const char *node)
{
return node ?
GCSPRINTF(PCI_INFO_PATH"/"PCI_BDF_XSPATH"/%s",
- pcibdf->domain, pcibdf->bus, pcibdf->dev, pcibdf->func,
+ pci->domain, pci->bus, pci->dev, pci->func,
node) :
GCSPRINTF(PCI_INFO_PATH"/"PCI_BDF_XSPATH,
- pcibdf->domain, pcibdf->bus, pcibdf->dev, pcibdf->func);
+ pci->domain, pci->bus, pci->dev, pci->func);
}
-static int pci_info_xs_write(libxl__gc *gc, libxl_pci_bdf *pcibdf,
+static int pci_info_xs_write(libxl__gc *gc, libxl_device_pci *pci,
const char *node, const char *val)
{
- char *path = pci_info_xs_path(gc, pcibdf, node);
+ char *path = pci_info_xs_path(gc, pci, node);
int rc = libxl__xs_printf(gc, XBT_NULL, path, "%s", val);
if (rc) LOGE(WARN, "Write of %s to node %s failed.", val, path);
return rc;
}
-static char *pci_info_xs_read(libxl__gc *gc, libxl_pci_bdf *pcibdf,
+static char *pci_info_xs_read(libxl__gc *gc, libxl_device_pci *pci,
const char *node)
{
- char *path = pci_info_xs_path(gc, pcibdf, node);
+ char *path = pci_info_xs_path(gc, pci, node);
return libxl__xs_read(gc, XBT_NULL, path);
}
-static void pci_info_xs_remove(libxl__gc *gc, libxl_pci_bdf *pcibdf,
+static void pci_info_xs_remove(libxl__gc *gc, libxl_device_pci *pci,
const char *node)
{
- char *path = pci_info_xs_path(gc, pcibdf, node);
+ char *path = pci_info_xs_path(gc, pci, node);
libxl_ctx *ctx = libxl__gc_owner(gc);
/* Remove the xenstore entry */
xs_rm(ctx->xsh, XBT_NULL, path);
}
-libxl_pci_bdf *libxl_pci_bdf_assignable_list(libxl_ctx *ctx, int *num)
+libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num)
{
GC_INIT(ctx);
- libxl_pci_bdf *pcibdfs = NULL, *new;
+ libxl_device_pci *pcis = NULL, *new;
struct dirent *de;
DIR *dir;
if (sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4)
continue;
- new = realloc(pcibdfs, ((*num) + 1) * sizeof(*new));
+ new = realloc(pcis, ((*num) + 1) * sizeof(*new));
if (NULL == new)
continue;
- pcibdfs = new;
- new = pcibdfs + *num;
+ pcis = new;
+ new = pcis + *num;
- libxl_pci_bdf_init(new);
- pcibdf_struct_fill(new, dom, bus, dev, func);
+ libxl_device_pci_init(new);
+ pci_struct_fill(new, dom, bus, dev, func, 0);
if (pci_info_xs_read(gc, new, "domid")) /* already assigned */
continue;
closedir(dir);
out:
GC_FREE;
- return pcibdfs;
+ return pcis;
}
-void libxl_pci_bdf_assignable_list_free(libxl_pci_bdf *list, int num)
+void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num)
{
int i;
for (i = 0; i < num; i++)
- libxl_pci_bdf_dispose(&list[i]);
+ libxl_device_pci_dispose(&list[i]);
free(list);
}
/* Unbind device from its current driver, if any. If driver_path is non-NULL,
* store the path to the original driver in it. */
-static int sysfs_dev_unbind(libxl__gc *gc, libxl_pci_bdf *pcibdf,
+static int sysfs_dev_unbind(libxl__gc *gc, libxl_device_pci *pci,
char **driver_path)
{
char * spath, *dp = NULL;
struct stat st;
spath = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/driver",
- pcibdf->domain,
- pcibdf->bus,
- pcibdf->dev,
- pcibdf->func);
+ pci->domain,
+ pci->bus,
+ pci->dev,
+ pci->func);
if ( !lstat(spath, &st) ) {
/* Find the canonical path to the driver. */
dp = libxl__zalloc(gc, PATH_MAX);
/* Unbind from the old driver */
spath = GCSPRINTF("%s/unbind", dp);
- if ( sysfs_write_bdf(gc, spath, pcibdf) < 0 ) {
+ if ( sysfs_write_bdf(gc, spath, pci) < 0 ) {
LOGE(ERROR, "Couldn't unbind device");
return -1;
}
{
char *pci_device_vendor_path =
GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/vendor",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
uint16_t read_items;
uint16_t pci_device_vendor;
if (!f) {
LOGE(ERROR,
"pci device "PCI_BDF" does not have vendor attribute",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
return 0xffff;
}
read_items = fscanf(f, "0x%hx\n", &pci_device_vendor);
if (read_items != 1) {
LOGE(ERROR,
"cannot read vendor of pci device "PCI_BDF,
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
return 0xffff;
}
{
char *pci_device_device_path =
GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/device",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
uint16_t read_items;
uint16_t pci_device_device;
if (!f) {
LOGE(ERROR,
"pci device "PCI_BDF" does not have device attribute",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
return 0xffff;
}
read_items = fscanf(f, "0x%hx\n", &pci_device_device);
if (read_items != 1) {
LOGE(ERROR,
"cannot read device of pci device "PCI_BDF,
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
return 0xffff;
}
unsigned long *class)
{
char *pci_device_class_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/class",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
int read_items, ret = 0;
FILE *f = fopen(pci_device_class_path, "r");
if (!f) {
LOGE(ERROR,
"pci device "PCI_BDF" does not have class attribute",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
ret = ERROR_FAIL;
goto out;
}
if (read_items != 1) {
LOGE(ERROR,
"cannot read class of pci device "PCI_BDF,
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
ret = ERROR_FAIL;
}
* already exist.
*/
-/* Scan through /sys/.../pciback/slots looking for BDF */
-static int pciback_dev_has_slot(libxl__gc *gc, libxl_pci_bdf *pcibdf)
+/* Scan through /sys/.../pciback/slots looking for pci's BDF */
+static int pciback_dev_has_slot(libxl__gc *gc, libxl_device_pci *pci)
{
FILE *f;
int rc = 0;
}
while (fscanf(f, "%x:%x:%x.%d\n", &dom, &bus, &dev, &func) == 4) {
- if (dom == pcibdf->domain
- && bus == pcibdf->bus
- && dev == pcibdf->dev
- && func == pcibdf->func) {
+ if (dom == pci->domain
+ && bus == pci->bus
+ && dev == pci->dev
+ && func == pci->func) {
rc = 1;
goto out;
}
return rc;
}
-static int pciback_dev_is_assigned(libxl__gc *gc, libxl_pci_bdf *pcibdf)
+static int pciback_dev_is_assigned(libxl__gc *gc, libxl_device_pci *pci)
{
char * spath;
int rc;
}
spath = GCSPRINTF(SYSFS_PCIBACK_DRIVER"/"PCI_BDF,
- pcibdf->domain, pcibdf->bus,
- pcibdf->dev, pcibdf->func);
+ pci->domain, pci->bus,
+ pci->dev, pci->func);
rc = lstat(spath, &st);
if( rc == 0 )
return -1;
}
-static int pciback_dev_assign(libxl__gc *gc, libxl_pci_bdf *pcibdf)
+static int pciback_dev_assign(libxl__gc *gc, libxl_device_pci *pci)
{
int rc;
- if ( (rc = pciback_dev_has_slot(gc, pcibdf)) < 0 ) {
+ if ( (rc = pciback_dev_has_slot(gc, pci)) < 0 ) {
LOGE(ERROR, "Error checking for pciback slot");
return ERROR_FAIL;
} else if (rc == 0) {
if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/new_slot",
- pcibdf) < 0 ) {
+ pci) < 0 ) {
LOGE(ERROR, "Couldn't bind device to pciback!");
return ERROR_FAIL;
}
}
- if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/bind", pcibdf) < 0 ) {
+ if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/bind", pci) < 0 ) {
LOGE(ERROR, "Couldn't bind device to pciback!");
return ERROR_FAIL;
}
return 0;
}
-static int pciback_dev_unassign(libxl__gc *gc, libxl_pci_bdf *pcibdf)
+static int pciback_dev_unassign(libxl__gc *gc, libxl_device_pci *pci)
{
/* Remove from pciback */
- if ( sysfs_dev_unbind(gc, pcibdf, NULL) < 0 ) {
+ if ( sysfs_dev_unbind(gc, pci, NULL) < 0 ) {
LOG(ERROR, "Couldn't unbind device!");
return ERROR_FAIL;
}
/* Remove slot if necessary */
- if ( pciback_dev_has_slot(gc, pcibdf) > 0 ) {
+ if ( pciback_dev_has_slot(gc, pci) > 0 ) {
if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/remove_slot",
- pcibdf) < 0 ) {
+ pci) < 0 ) {
LOGE(ERROR, "Couldn't remove pciback slot");
return ERROR_FAIL;
}
return 0;
}
-static int libxl__pci_bdf_assignable_add(libxl__gc *gc,
- libxl_pci_bdf *pcibdf,
- const char *name,
- int rebind)
+static int libxl__device_pci_assignable_add(libxl__gc *gc,
+ libxl_device_pci *pci,
+ int rebind)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
unsigned dom, bus, dev, func;
int rc;
struct stat st;
- /* Sanitise any name that was passed */
- if (name) {
- unsigned int i, n = strlen(name);
-
- if (n > 64) { /* Reasonable upper bound on name length */
- LOG(ERROR, "Name too long");
- return ERROR_FAIL;
- }
-
- for (i = 0; i < n; i++) {
- if (!isgraph(name[i])) {
- LOG(ERROR, "Names may only include printable characters");
- return ERROR_FAIL;
- }
- }
- }
-
/* Local copy for convenience */
- dom = pcibdf->domain;
- bus = pcibdf->bus;
- dev = pcibdf->dev;
- func = pcibdf->func;
+ dom = pci->domain;
+ bus = pci->bus;
+ dev = pci->dev;
+ func = pci->func;
/* See if the device exists */
spath = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF, dom, bus, dev, func);
}
/* Check to see if it's already assigned to pciback */
- rc = pciback_dev_is_assigned(gc, pcibdf);
+ rc = pciback_dev_is_assigned(gc, pci);
if ( rc < 0 ) {
return ERROR_FAIL;
}
if ( rc ) {
LOG(WARN, PCI_BDF" already assigned to pciback", dom, bus, dev, func);
- goto name;
+ goto quarantine;
}
/* Check to see if there's already a driver that we need to unbind from */
- if ( sysfs_dev_unbind(gc, pcibdf, &driver_path ) ) {
+ if ( sysfs_dev_unbind(gc, pci, &driver_path ) ) {
LOG(ERROR, "Couldn't unbind "PCI_BDF" from driver",
dom, bus, dev, func);
return ERROR_FAIL;
/* Store driver_path for rebinding to dom0 */
if ( rebind ) {
if ( driver_path ) {
- pci_info_xs_write(gc, pcibdf, "driver_path", driver_path);
+ pci_info_xs_write(gc, pci, "driver_path", driver_path);
} else if ( (driver_path =
- pci_info_xs_read(gc, pcibdf, "driver_path")) != NULL ) {
+ pci_info_xs_read(gc, pci, "driver_path")) != NULL ) {
LOG(INFO, PCI_BDF" not bound to a driver, will be rebound to %s",
dom, bus, dev, func, driver_path);
} else {
dom, bus, dev, func);
}
} else {
- pci_info_xs_remove(gc, pcibdf, "driver_path");
+ pci_info_xs_remove(gc, pci, "driver_path");
}
- if ( pciback_dev_assign(gc, pcibdf) ) {
+ if ( pciback_dev_assign(gc, pci) ) {
LOG(ERROR, "Couldn't bind device to pciback!");
return ERROR_FAIL;
}
-name:
- if (name)
- pci_info_xs_write(gc, pcibdf, "name", name);
- else
- pci_info_xs_remove(gc, pcibdf, "name");
-
+quarantine:
/*
* DOMID_IO is just a sentinel domain, without any actual mappings,
* so always pass XEN_DOMCTL_DEV_RDM_RELAXED to avoid assignment being
* unnecessarily denied.
*/
- rc = xc_assign_device(ctx->xch, DOMID_IO, pci_encode_bdf(pcibdf),
+ rc = xc_assign_device(ctx->xch, DOMID_IO, pci_encode_bdf(pci),
XEN_DOMCTL_DEV_RDM_RELAXED);
if ( rc < 0 ) {
LOG(ERROR, "failed to quarantine "PCI_BDF, dom, bus, dev, func);
return 0;
}
-static int libxl__pci_bdf_assignable_remove(libxl__gc *gc,
- libxl_pci_bdf *pcibdf,
- int rebind)
+static int libxl__device_pci_assignable_remove(libxl__gc *gc,
+ libxl_device_pci *pci,
+ int rebind)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
int rc;
char *driver_path;
/* De-quarantine */
- rc = xc_deassign_device(ctx->xch, DOMID_IO, pci_encode_bdf(pcibdf));
+ rc = xc_deassign_device(ctx->xch, DOMID_IO, pci_encode_bdf(pci));
if ( rc < 0 ) {
- LOG(ERROR, "failed to de-quarantine "PCI_BDF, pcibdf->domain,
- pcibdf->bus, pcibdf->dev, pcibdf->func);
+ LOG(ERROR, "failed to de-quarantine "PCI_BDF, pci->domain, pci->bus,
+ pci->dev, pci->func);
return ERROR_FAIL;
}
/* Unbind from pciback */
- if ( (rc = pciback_dev_is_assigned(gc, pcibdf)) < 0 ) {
+ if ( (rc = pciback_dev_is_assigned(gc, pci)) < 0 ) {
return ERROR_FAIL;
} else if ( rc ) {
- pciback_dev_unassign(gc, pcibdf);
+ pciback_dev_unassign(gc, pci);
} else {
LOG(WARN, "Not bound to pciback");
}
/* Rebind if necessary */
- driver_path = pci_info_xs_read(gc, pcibdf, "driver_path");
+ driver_path = pci_info_xs_read(gc, pci, "driver_path");
if ( driver_path ) {
if ( rebind ) {
if ( sysfs_write_bdf(gc,
GCSPRINTF("%s/bind", driver_path),
- pcibdf) < 0 ) {
+ pci) < 0 ) {
LOGE(ERROR, "Couldn't bind device to %s", driver_path);
return -1;
}
- pci_info_xs_remove(gc, pcibdf, "driver_path");
+ pci_info_xs_remove(gc, pci, "driver_path");
}
} else {
if ( rebind ) {
}
}
- pci_info_xs_remove(gc, pcibdf, "name");
-
return 0;
}
-int libxl_pci_bdf_assignable_add(libxl_ctx *ctx, libxl_pci_bdf *pcibdf,
- const char *name, int rebind)
+int libxl_device_pci_assignable_add(libxl_ctx *ctx, libxl_device_pci *pci,
+ int rebind)
{
GC_INIT(ctx);
int rc;
- rc = libxl__pci_bdf_assignable_add(gc, pcibdf, name, rebind);
+ rc = libxl__device_pci_assignable_add(gc, pci, rebind);
GC_FREE;
return rc;
}
-int libxl_pci_bdf_assignable_remove(libxl_ctx *ctx, libxl_pci_bdf *pcibdf,
- int rebind)
+int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
+ int rebind)
{
GC_INIT(ctx);
int rc;
- rc = libxl__pci_bdf_assignable_remove(gc, pcibdf, rebind);
+ rc = libxl__device_pci_assignable_remove(gc, pci, rebind);
GC_FREE;
return rc;
}
-libxl_pci_bdf *libxl_pci_bdf_assignable_name2bdf(libxl_ctx *ctx,
- const char *name)
-{
- GC_INIT(ctx);
- char **bdfs;
- libxl_pci_bdf *pcibdf = NULL;
- unsigned int i, n;
-
- bdfs = libxl__xs_directory(gc, XBT_NULL, PCI_INFO_PATH, &n);
- if (!n)
- goto out;
-
- pcibdf = calloc(1, sizeof(*pcibdf));
- if (!pcibdf)
- goto out;
-
- for (i = 0; i < n; i++) {
- unsigned dom, bus, dev, func;
- const char *tmp;
-
- if (sscanf(bdfs[i], PCI_BDF_XSPATH, &dom, &bus, &dev, &func) != 4)
- continue;
-
- pcibdf_struct_fill(pcibdf, dom, bus, dev, func);
-
- tmp = pci_info_xs_read(gc, pcibdf, "name");
- if (tmp && !strcmp(tmp, name))
- goto out;
- }
-
- free(pcibdf);
- pcibdf = NULL;
-
-out:
- GC_FREE;
- return pcibdf;
-}
-
-char *libxl_pci_bdf_assignable_bdf2name(libxl_ctx *ctx,
- libxl_pci_bdf *pcibdf)
-{
- GC_INIT(ctx);
- char *name = NULL, *tmp = pci_info_xs_read(gc, pcibdf, "name");
-
- if (tmp)
- name = strdup(tmp);
-
- GC_FREE;
- return name;
-}
-
/*
* This function checks that all functions of a device are bound to pciback
* driver. It also initialises a bit-mask of which function numbers are present
if ( sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
continue;
- if ( pci->bdf.domain != dom )
+ if ( pci->domain != dom )
continue;
- if ( pci->bdf.bus != bus )
+ if ( pci->bus != bus )
continue;
- if ( pci->bdf.dev != dev )
+ if ( pci->dev != dev )
continue;
path = GCSPRINTF("%s/" PCI_BDF, SYSFS_PCIBACK_DRIVER, dom, bus, dev, func);
path = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "/parameter");
if (pci->vdevfn) {
libxl__xs_printf(gc, XBT_NULL, path, PCI_BDF_VDEVFN","PCI_OPTIONS,
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev,
- pci->bdf.func, pci->vdevfn, pci->msitranslate,
+ pci->domain, pci->bus, pci->dev,
+ pci->func, pci->vdevfn, pci->msitranslate,
pci->power_mgmt);
} else {
libxl__xs_printf(gc, XBT_NULL, path, PCI_BDF","PCI_OPTIONS,
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev,
- pci->bdf.func, pci->msitranslate, pci->power_mgmt);
+ pci->domain, pci->bus, pci->dev,
+ pci->func, pci->msitranslate, pci->power_mgmt);
}
libxl__qemu_traditional_cmd(gc, domid, "pci-ins");
libxl__qmp_param_add_string(gc, &args, "driver",
"xen-pci-passthrough");
QMP_PARAMETERS_SPRINTF(&args, "id", PCI_PT_QDEV_ID,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->bus, pci->dev, pci->func);
QMP_PARAMETERS_SPRINTF(&args, "hostaddr",
- "%04x:%02x:%02x.%01x", pci->bdf.domain,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ "%04x:%02x:%02x.%01x", pci->domain,
+ pci->bus, pci->dev, pci->func);
if (pci->vdevfn) {
QMP_PARAMETERS_SPRINTF(&args, "addr", "%x.%x",
PCI_SLOT(pci->vdevfn),
*/
asked_id = GCSPRINTF(PCI_PT_QDEV_ID,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->bus, pci->dev, pci->func);
for (i = 0; (bus = libxl__json_array_get(response, i)); i++) {
devices = libxl__json_map_get("devices", bus, JSON_ARRAY);
if (isstubdom)
starting = false;
- sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->bdf.domain,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->domain,
+ pci->bus, pci->dev, pci->func);
f = fopen(sysfs_path, "r");
start = end = flags = size = 0;
irq = 0;
}
}
fclose(f);
- sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->bdf.domain,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
+ pci->bus, pci->dev, pci->func);
f = fopen(sysfs_path, "r");
if (f == NULL) {
LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
/* Don't restrict writes to the PCI config space from this VM */
if (pci->permissive) {
if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/permissive",
- &pci->bdf) < 0 ) {
+ pci) < 0 ) {
LOGD(ERROR, domainid, "Setting permissive for device");
rc = ERROR_FAIL;
goto out;
rc = ERROR_FAIL;
goto out;
}
- r = xc_assign_device(ctx->xch, domid, pci_encode_bdf(&pci->bdf),
- flag);
+ r = xc_assign_device(ctx->xch, domid, pci_encode_bdf(pci), flag);
if (r < 0 && (hvm || errno != ENOSYS)) {
LOGED(ERROR, domainid, "xc_assign_device failed");
rc = ERROR_FAIL;
return AO_INPROGRESS;
}
-static bool is_bdf_assignable(libxl_ctx *ctx, libxl_pci_bdf *pcibdf)
+static bool libxl_pci_assignable(libxl_ctx *ctx, libxl_device_pci *pci)
{
- libxl_pci_bdf *pcibdfs;
- int num, i;
-
- pcibdfs = libxl_pci_bdf_assignable_list(ctx, &num);
-
- for (i = 0; i < num; i++) {
- if (COMPARE_BDF(pcibdf, &pcibdfs[i]))
- break;
- }
+ libxl_device_pci *pcis;
+ int num;
+ bool assignable;
- libxl_pci_bdf_assignable_list_free(pcibdfs, num);
+ pcis = libxl_device_pci_assignable_list(ctx, &num);
+ assignable = is_pci_in_array(pcis, num, pci);
+ libxl_device_pci_assignable_list_free(pcis, num);
- return i < num;
+ return assignable;
}
static void device_pci_add_stubdom_wait(libxl__egc *egc,
pas->starting = starting;
pas->callback = device_pci_add_stubdom_done;
- if (pci->name) {
- libxl_pci_bdf *pcibdf =
- libxl_pci_bdf_assignable_name2bdf(CTX, pci->name);
-
- if (!pcibdf) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- LOGD(DETAIL, domid, "'%s' -> %04x:%02x:%02x.%u", pci->name,
- pcibdf->domain, pcibdf->bus, pcibdf->dev, pcibdf->func);
-
- libxl_pci_bdf_copy(CTX, &pci->bdf, pcibdf);
- libxl_pci_bdf_dispose(pcibdf);
- free(pcibdf);
- }
-
if (libxl__domain_type(gc, domid) == LIBXL_DOMAIN_TYPE_HVM) {
- rc = xc_test_assign_device(ctx->xch, domid,
- pci_encode_bdf(&pci->bdf));
+ rc = xc_test_assign_device(ctx->xch, domid, pci_encode_bdf(pci));
if (rc) {
LOGD(ERROR, domid,
"PCI device %04x:%02x:%02x.%u %s?",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func,
+ pci->domain, pci->bus, pci->dev, pci->func,
errno == EOPNOTSUPP ? "cannot be assigned - no IOMMU"
: "already assigned to a different guest");
goto out;
rc = libxl__device_pci_setdefault(gc, domid, pci, !starting);
if (rc) goto out;
- if (pci->seize && !pciback_dev_is_assigned(gc, &pci->bdf)) {
- rc = libxl__pci_bdf_assignable_add(gc, &pci->bdf, NULL, 1);
+ if (pci->seize && !pciback_dev_is_assigned(gc, pci)) {
+ rc = libxl__device_pci_assignable_add(gc, pci, 1);
if ( rc )
goto out;
}
- if (!is_bdf_assignable(ctx, &pci->bdf)) {
+ if (!libxl_pci_assignable(ctx, pci)) {
LOGD(ERROR, domid, "PCI device %x:%x:%x.%x is not assignable",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->domain, pci->bus, pci->dev, pci->func);
rc = ERROR_FAIL;
goto out;
}
- rc = pci_info_xs_write(gc, &pci->bdf, "domid", GCSPRINTF("%u", domid));
+ rc = pci_info_xs_write(gc, pci, "domid", GCSPRINTF("%u", domid));
if (rc) goto out;
- libxl__device_pci_reset(gc, pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ libxl__device_pci_reset(gc, pci->domain, pci->bus, pci->dev, pci->func);
stubdomid = libxl_get_stubdom_id(ctx, domid);
if (stubdomid != 0) {
pci->vfunc_mask &= pfunc_mask;
/* so now vfunc_mask == pfunc_mask */
}else{
- pfunc_mask = (1 << pci->bdf.func);
+ pfunc_mask = (1 << pci->func);
}
for (rc = 0, i = 7; i >= 0; --i) {
if ( (1 << i) & pfunc_mask ) {
if ( pci->vfunc_mask == pfunc_mask ) {
- pci->bdf.func = i;
+ pci->func = i;
pci->vdevfn = orig_vdev | i;
} else {
/* if not passing through multiple devices in a block make
libxl_device_pci *pci = &pas->pci;
if (rc) {
- if (pci->name) {
- LOGD(ERROR, domid,
- "libxl__device_pci_add failed for "
- "PCI device '%s' (rc %d)",
- pci->name,
- rc);
- } else {
- LOGD(ERROR, domid,
- "libxl__device_pci_add failed for "
- "PCI device %x:%x:%x.%x (rc %d)",
- pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func,
- rc);
- }
- pci_info_xs_remove(gc, &pci->bdf, "domid");
+ LOGD(ERROR, domid,
+ "libxl__device_pci_add failed for "
+ "PCI device %x:%x:%x.%x (rc %d)",
+ pci->domain, pci->bus, pci->dev, pci->func,
+ rc);
+ pci_info_xs_remove(gc, pci, "domid");
}
libxl_device_pci_dispose(pci);
aodev->rc = rc;
path = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "/state");
state = libxl__xs_read(gc, XBT_NULL, path);
path = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "/parameter");
- libxl__xs_printf(gc, XBT_NULL, path, PCI_BDF, pci->bdf.domain,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ libxl__xs_printf(gc, XBT_NULL, path, PCI_BDF, pci->domain,
+ pci->bus, pci->dev, pci->func);
/* Remove all functions at once atomically by only signalling
* device-model for function 0 */
} else {
assert(type == LIBXL_DOMAIN_TYPE_PV);
- char *sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->bdf.domain,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ char *sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->domain,
+ pci->bus, pci->dev, pci->func);
FILE *f = fopen(sysfs_path, "r");
unsigned int start = 0, end = 0, flags = 0, size = 0;
int irq = 0;
}
fclose(f);
skip1:
- sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->bdf.domain,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
+ pci->bus, pci->dev, pci->func);
f = fopen(sysfs_path, "r");
if (f == NULL) {
LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
if (rc) goto out;
QMP_PARAMETERS_SPRINTF(&args, "id", PCI_PT_QDEV_ID,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->bus, pci->dev, pci->func);
prs->qmp.callback = pci_remove_qmp_device_del_cb;
rc = libxl__ev_qmp_send(egc, &prs->qmp, "device_del", args);
if (rc) goto out;
libxl__ev_qmp_dispose(gc, qmp);
asked_id = GCSPRINTF(PCI_PT_QDEV_ID,
- pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ pci->bus, pci->dev, pci->func);
/* query-pci response:
* [{ 'devices': [ 'qdev_id': 'str', ... ], ... }]
libxl_device_pci *const pci = &prs->pci;
LOGD(WARN, prs->domid, "timed out waiting for DM to remove "
- PCI_PT_QDEV_ID, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ PCI_PT_QDEV_ID, pci->bus, pci->dev, pci->func);
/* If we timed out, we might still want to keep destroying the device
* (when force==true), so let the next function decide what to do on
/* don't do multiple resets while some functions are still passed through */
if ((pci->vdevfn & 0x7) == 0) {
- libxl__device_pci_reset(gc, pci->bdf.domain, pci->bdf.bus, pci->bdf.dev, pci->bdf.func);
+ libxl__device_pci_reset(gc, pci->domain, pci->bus, pci->dev, pci->func);
}
if (!isstubdom) {
- rc = xc_deassign_device(CTX->xch, domid,
- pci_encode_bdf(&pci->bdf));
+ rc = xc_deassign_device(CTX->xch, domid, pci_encode_bdf(pci));
if (rc < 0 && (prs->hvm || errno != ENOSYS))
LOGED(ERROR, domainid, "xc_deassign_device failed");
}
libxl__ev_time_init(&prs->timeout);
libxl__ev_time_init(&prs->retry_timer);
- if (pci->name) {
- libxl_pci_bdf *pcibdf =
- libxl_pci_bdf_assignable_name2bdf(CTX, pci->name);
-
- if (!pcibdf) {
- rc = ERROR_FAIL;
- goto out;
- }
-
- LOGD(DETAIL, domid, "'%s' -> %04x:%02x:%02x.%u", pci->name,
- pcibdf->domain, pcibdf->bus, pcibdf->dev, pcibdf->func);
-
- libxl_pci_bdf_copy(CTX, &prs->pci.bdf, pcibdf);
- libxl_pci_bdf_dispose(pcibdf);
- free(pcibdf);
- }
-
prs->orig_vdev = pci->vdevfn & ~7U;
if ( pci->vfunc_mask == LIBXL_PCI_FUNC_ALL ) {
}
pci->vfunc_mask &= prs->pfunc_mask;
} else {
- prs->pfunc_mask = (1 << pci->bdf.func);
+ prs->pfunc_mask = (1 << pci->func);
}
rc = 0;
prs->next_func--;
if ( (1 << i) & pfunc_mask ) {
if ( pci->vfunc_mask == pfunc_mask ) {
- pci->bdf.func = i;
+ pci->func = i;
pci->vdevfn = orig_vdev | i;
} else {
pci->vdevfn = orig_vdev;
libxl__ev_time_deregister(gc, &prs->timeout);
libxl__ev_time_deregister(gc, &prs->retry_timer);
- if (!rc) pci_info_xs_remove(gc, &pci->bdf, "domid");
+ if (!rc) pci_info_xs_remove(gc, pci, "domid");
libxl_device_pci_dispose(pci);
aodev->rc = rc;
} while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
}
- s = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name-%d", be_path, nr));
- if (s)
- pci->name = strdup(s);
-
return 0;
}
.from_xenstore = libxl__device_pci_from_xs_be,
);
-int libxl_device_pci_assignable_add(libxl_ctx *ctx, libxl_device_pci *pci,
- int rebind)
-{
- return libxl_pci_bdf_assignable_add(ctx, &pci->bdf, NULL, rebind);
-}
-
-int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
- int rebind)
-{
- return libxl_pci_bdf_assignable_remove(ctx, &pci->bdf, rebind);
-}
-
-libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx,
- int *num)
-{
- libxl_pci_bdf *pcibdfs = libxl_pci_bdf_assignable_list(ctx, num);
- libxl_device_pci *pcis;
- unsigned int i;
-
- if (!pcibdfs)
- return NULL;
-
- pcis = calloc(*num, sizeof(*pcis));
- if (!pcis) {
- libxl_pci_bdf_assignable_list_free(pcibdfs, *num);
- return NULL;
- }
-
- for (i = 0; i < *num; i++) {
- libxl_device_pci_init(&pcis[i]);
- libxl_pci_bdf_copy(ctx, &pcis[i].bdf, &pcibdfs[i]);
- }
-
- libxl_pci_bdf_assignable_list_free(pcibdfs, *num);
- return pcis;
-}
-
-void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num)
-{
- libxl_device_pci_list_free(list, num);
-}
-
/*
* Local variables:
* mode: C
#define _GNU_SOURCE
-#include <ctype.h>
-
#include "libxlu_internal.h"
#include "libxlu_disk_l.h"
#include "libxlu_disk_i.h"
#define XLU__PCI_ERR(_c, _x, _a...) \
if((_c) && (_c)->report) fprintf((_c)->report, _x, ##_a)
-static int parse_bdf(libxl_pci_bdf *bdfp, uint32_t *vfunc_maskp,
- const char *str, const char **endp)
+static int hex_convert(const char *str, unsigned int *val, unsigned int mask)
{
- const char *ptr = str;
- unsigned int colons = 0;
- unsigned int domain, bus, dev, func;
- int n;
-
- /* Count occurrences of ':' to detrmine presence/absence of the 'domain' */
- while (isxdigit(*ptr) || *ptr == ':') {
- if (*ptr == ':')
- colons++;
- ptr++;
- }
-
- ptr = str;
- switch (colons) {
- case 1:
- domain = 0;
- if (sscanf(ptr, "%x:%x.%n", &bus, &dev, &n) != 2)
- return ERROR_INVAL;
- break;
- case 2:
- if (sscanf(ptr, "%x:%x:%x.%n", &domain, &bus, &dev, &n) != 3)
- return ERROR_INVAL;
- break;
- default:
- return ERROR_INVAL;
- }
-
- if (domain > 0xffff || bus > 0xff || dev > 0x1f)
- return ERROR_INVAL;
-
- ptr += n;
- if (*ptr == '*') {
- if (!vfunc_maskp)
- return ERROR_INVAL;
- *vfunc_maskp = LIBXL_PCI_FUNC_ALL;
- func = 0;
- ptr++;
- } else {
- if (sscanf(ptr, "%x%n", &func, &n) != 1)
- return ERROR_INVAL;
- if (func > 7)
- return ERROR_INVAL;
- if (vfunc_maskp)
- *vfunc_maskp = 1;
- ptr += n;
- }
-
- bdfp->domain = domain;
- bdfp->bus = bus;
- bdfp->dev = dev;
- bdfp->func = func;
-
- if (endp)
- *endp = ptr;
-
+ 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 parse_vslot(uint32_t *vdevfnp, const char *str, const char **endp)
+static int pci_struct_fill(libxl_device_pci *pci, unsigned int domain,
+ unsigned int bus, unsigned int dev,
+ unsigned int func, unsigned int vdevfn)
{
- const char *ptr = str;
- unsigned int val;
- int n;
-
- if (sscanf(ptr, "%x%n", &val, &n) != 1)
- return ERROR_INVAL;
-
- if (val > 0x1f)
- return ERROR_INVAL;
-
- ptr += n;
-
- *vdevfnp = val << 3;
-
- if (endp)
- *endp = ptr;
-
+ pci->domain = domain;
+ pci->bus = bus;
+ pci->dev = dev;
+ pci->func = func;
+ pci->vdevfn = vdevfn;
return 0;
}
-static int parse_key_val(char **keyp, char**valp, const char *str,
- const char **endp)
+#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
+#define STATE_TYPE 9
+#define STATE_RDM_STRATEGY 10
+#define STATE_RESERVE_POLICY 11
+#define INVALID 0xffffffff
+int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_device_pci *pci, const char *str)
{
- const char *ptr = str;
- char *key, *val;
-
- while (*ptr != '=' && *ptr != '\0')
- ptr++;
+ unsigned state = STATE_DOMAIN;
+ unsigned dom = INVALID, bus = INVALID, dev = INVALID, func = INVALID, vslot = 0;
+ char *buf2, *tok, *ptr, *end, *optkey = NULL;
- if (*ptr == '\0')
- return ERROR_INVAL;
-
- key = strndup(str, ptr - str);
- if (!key)
- return ERROR_NOMEM;
-
- str = ++ptr; /* skip '=' */
- while (*ptr != ',' && *ptr != '\0')
- ptr++;
-
- val = strndup(str, ptr - str);
- if (!val) {
- free(key);
+ if ( NULL == (buf2 = ptr = strdup(str)) )
return ERROR_NOMEM;
- }
-
- if (*ptr == ',')
- ptr++;
- *keyp = key;
- *valp = val;
- *endp = ptr;
-
- return 0;
-}
-
-static int parse_rdm_policy(XLU_Config *cfg, libxl_rdm_reserve_policy *policy,
- const char *str)
-{
- int ret = libxl_rdm_reserve_policy_from_string(str, policy);
-
- if (ret)
- XLU__PCI_ERR(cfg, "Unknown RDM policy: %s", str);
-
- return ret;
-}
-
-int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_pci_bdf *bdf, const char *str)
-{
- return parse_bdf(bdf, NULL, str, NULL);
-}
-
-int xlu_pci_parse_spec_string(XLU_Config *cfg, libxl_device_pci *pcidev,
- const char *str)
-{
- const char *ptr = str;
- bool bdf_present = false;
- bool name_present = false;
- int ret;
-
- /* Attempt to parse 'bdf' as positional parameter */
- ret = parse_bdf(&pcidev->bdf, &pcidev->vfunc_mask, ptr, &ptr);
- if (!ret) {
- bdf_present = true;
-
- /* Check whether 'vslot' if present */
- if (*ptr == '@') {
- ret = parse_vslot(&pcidev->vdevfn, ++ptr, &ptr);
- if (ret)
- return ret;
+ 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, "*") ) {
+ pci->vfunc_mask = LIBXL_PCI_FUNC_ALL;
+ }else{
+ if ( hex_convert(tok, &func, 0x7) )
+ goto parse_error;
+ pci->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") ) {
+ pci->msitranslate = atoi(tok);
+ }else if ( !strcmp(optkey, "power_mgmt") ) {
+ pci->power_mgmt = atoi(tok);
+ }else if ( !strcmp(optkey, "permissive") ) {
+ pci->permissive = atoi(tok);
+ }else if ( !strcmp(optkey, "seize") ) {
+ pci->seize = atoi(tok);
+ } else if (!strcmp(optkey, "rdm_policy")) {
+ if (!strcmp(tok, "strict")) {
+ pci->rdm_policy = LIBXL_RDM_RESERVE_POLICY_STRICT;
+ } else if (!strcmp(tok, "relaxed")) {
+ pci->rdm_policy = LIBXL_RDM_RESERVE_POLICY_RELAXED;
+ } else {
+ XLU__PCI_ERR(cfg, "%s is not an valid PCI RDM property"
+ " policy: 'strict' or 'relaxed'.",
+ tok);
+ goto parse_error;
+ }
+ } else {
+ XLU__PCI_ERR(cfg, "Unknown PCI BDF option: %s", optkey);
+ }
+ tok = ptr + 1;
+ }
+ default:
+ break;
}
- if (*ptr == ',')
- ptr++;
- else if (*ptr != '\0')
- return ERROR_INVAL;
}
- /* Parse the rest as 'key=val' pairs */
- while (*ptr != '\0') {
- char *key, *val;
-
- ret = parse_key_val(&key, &val, ptr, &ptr);
- if (ret)
- return ret;
-
- if (!strcmp(key, "bdf")) {
- ret = parse_bdf(&pcidev->bdf, &pcidev->vfunc_mask, val, NULL);
- bdf_present = !ret;
- } else if (!strcmp(key, "vslot")) {
- ret = parse_vslot(&pcidev->vdevfn, val, NULL);
- } else if (!strcmp(key, "permissive")) {
- pcidev->permissive = atoi(val);
- } else if (!strcmp(key, "msitranslate")) {
- pcidev->msitranslate = atoi(val);
- } else if (!strcmp(key, "seize")) {
- pcidev->seize= atoi(val);
- } else if (!strcmp(key, "power_mgmt")) {
- pcidev->power_mgmt = atoi(val);
- } else if (!strcmp(key, "rdm_policy")) {
- ret = parse_rdm_policy(cfg, &pcidev->rdm_policy, val);
- } else if (!strcmp(key, "name")) {
- name_present = true;
- pcidev->name = strdup(val);
- if (!pcidev->name) ret = ERROR_NOMEM;
- } else {
- XLU__PCI_ERR(cfg, "Unknown PCI_SPEC_STRING option: %s", key);
- ret = ERROR_INVAL;
- }
+ if ( tok != ptr || state != STATE_TERMINAL )
+ goto parse_error;
- free(key);
- free(val);
+ assert(dom != INVALID && bus != INVALID && dev != INVALID && func != INVALID);
- if (ret)
- return ret;
- }
+ /* Just a pretty way to fill in the values */
+ pci_struct_fill(pci, dom, bus, dev, func, vslot << 3);
- if (!(bdf_present ^ name_present))
- return ERROR_INVAL;
+ free(buf2);
return 0;
+
+parse_error:
+ free(buf2);
+ return ERROR_INVAL;
}
int xlu_rdm_parse(XLU_Config *cfg, libxl_rdm_reserve *rdm, const char *str)
{
-#define STATE_TYPE 0
-#define STATE_RDM_STRATEGY 1
-#define STATE_RESERVE_POLICY 2
-#define STATE_TERMINAL 3
-
unsigned state = STATE_TYPE;
char *buf2, *tok, *ptr, *end;
if (*ptr == ',' || *ptr == '\0') {
state = *ptr == ',' ? STATE_TYPE : STATE_TERMINAL;
*ptr = '\0';
- if (!parse_rdm_policy(cfg, &rdm->policy, tok))
+ if (!strcmp(tok, "strict")) {
+ rdm->policy = LIBXL_RDM_RESERVE_POLICY_STRICT;
+ } else if (!strcmp(tok, "relaxed")) {
+ rdm->policy = LIBXL_RDM_RESERVE_POLICY_RELAXED;
+ } else {
+ XLU__PCI_ERR(cfg, "Unknown RDM property policy value: %s",
+ tok);
goto parse_error;
+ }
tok = ptr + 1;
}
default:
parse_error:
free(buf2);
return ERROR_INVAL;
-
-#undef STATE_TYPE
-#undef STATE_RDM_STRATEGY
-#undef STATE_RESERVE_POLICY
-#undef STATE_TERMINAL
}
/*