Skip to content

Commit

Permalink
libxl: introduce libxl_pci_bdf_assignable_add/remove/list/list_free()…
Browse files Browse the repository at this point in the history
…, ...

which support naming and use 'libxl_pci_bdf' rather than 'libxl_device_pci',
as replacements for libxl_device_pci_assignable_add/remove/list/list_free().

libxl_pci_bdf_assignable_add() takes a 'name' parameter which is stored in
xenstore and facilitates two addtional functions added by this patch:
libxl_pci_bdf_assignable_name2bdf() and libxl_pci_bdf_assignable_bdf2name().
Currently there are no callers of these two functions. They will be added in
a subsequent patch.

libxl_device_pci_assignable_add/remove/list/list_free() are left in place
for compatibility but are re-implemented in terms of the newly introduced
functions.

Signed-off-by: Paul Durrant <pdurrant@amazon.com>
Acked-by: Wei Liu <wl@xen.org>
  • Loading branch information
Paul Durrant authored and liuw committed Dec 15, 2020
1 parent 66c2fbc commit 5ab684c
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 31 deletions.
36 changes: 29 additions & 7 deletions tools/include/libxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,13 @@
*/
#define LIBXL_HAVE_PCI_BDF 1

/*
* LIBXL_HAVE_PCI_ASSIGNABLE_BDF indicates that the
* libxl_pci_bdf_assignable_add/remove/list/list_free() functions all
* exist.
*/
#define LIBXL_HAVE_PCI_ASSIGNABLE_BDF 1

/*
* libxl ABI compatibility
*
Expand Down Expand Up @@ -2357,9 +2364,9 @@ int libxl_device_events_handler(libxl_ctx *ctx,
LIBXL_EXTERNAL_CALLERS_ONLY;

/*
* Functions related to making devices assignable -- that is, bound to
* the pciback driver, ready to be given to a guest via
* libxl_pci_device_add.
* Functions related to making PCI devices with the specified BDF
* assignable -- that is, bound to the pciback driver, ready to be given to
* a guest via libxl_pci_device_add.
*
* - ..._add() will unbind the device from its current driver (if
* already bound) and re-bind it to pciback; at that point it will be
Expand All @@ -2371,16 +2378,31 @@ int libxl_device_events_handler(libxl_ctx *ctx,
* rebind is non-zero, attempt to assign it back to the driver
* from whence it came.
*
* - ..._list() will return a list of the PCI devices available to be
* - ..._list() will return a list of the PCI BDFs available to be
* assigned.
*
* add and remove are idempotent: if the device in question is already
* added or is not bound, the functions will emit a warning but return
* SUCCESS.
*/
int libxl_device_pci_assignable_add(libxl_ctx *ctx, libxl_device_pci *pci, int rebind);
int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci, int rebind);
libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num);
int libxl_pci_bdf_assignable_add(libxl_ctx *ctx, libxl_pci_bdf *pcibdf,
const char *name, int rebind);
int libxl_pci_bdf_assignable_remove(libxl_ctx *ctx, libxl_pci_bdf *pcibdf,
int rebind);
libxl_pci_bdf *libxl_pci_bdf_assignable_list(libxl_ctx *ctx, int *num);
void libxl_pci_bdf_assignable_list_free(libxl_pci_bdf *list, int num);
libxl_pci_bdf *libxl_pci_bdf_assignable_name2bdf(libxl_ctx *ctx,
const char *name);
char *libxl_pci_bdf_assignable_bdf2name(libxl_ctx *ctx,
libxl_pci_bdf *pcibdf);

/* Compatibility functions - Use libxl_pci_bdf_assignable_* instead */
int libxl_device_pci_assignable_add(libxl_ctx *ctx, libxl_device_pci *pci,
int rebind);
int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
int rebind);
libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx,
int *num);
void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num);

/* CPUID handling */
Expand Down
166 changes: 142 additions & 24 deletions tools/libs/light/libxl_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,10 @@ static void pci_info_xs_remove(libxl__gc *gc, libxl_pci_bdf *pcibdf,
xs_rm(ctx->xsh, XBT_NULL, path);
}

libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num)
libxl_pci_bdf *libxl_pci_bdf_assignable_list(libxl_ctx *ctx, int *num)
{
GC_INIT(ctx);
libxl_device_pci *pcis = NULL, *new;
libxl_pci_bdf *pcibdfs = NULL, *new;
struct dirent *de;
DIR *dir;

Expand All @@ -450,17 +450,17 @@ libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num)
if (sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4)
continue;

new = realloc(pcis, ((*num) + 1) * sizeof(*new));
new = realloc(pcibdfs, ((*num) + 1) * sizeof(*new));
if (NULL == new)
continue;

pcis = new;
new = pcis + *num;
pcibdfs = new;
new = pcibdfs + *num;

libxl_device_pci_init(new);
pcibdf_struct_fill(&new->bdf, dom, bus, dev, func);
libxl_pci_bdf_init(new);
pcibdf_struct_fill(new, dom, bus, dev, func);

if (pci_info_xs_read(gc, &new->bdf, "domid")) /* already assigned */
if (pci_info_xs_read(gc, new, "domid")) /* already assigned */
continue;

(*num)++;
Expand All @@ -469,15 +469,15 @@ libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num)
closedir(dir);
out:
GC_FREE;
return pcis;
return pcibdfs;
}

void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num)
void libxl_pci_bdf_assignable_list_free(libxl_pci_bdf *list, int num)
{
int i;

for (i = 0; i < num; i++)
libxl_device_pci_dispose(&list[i]);
libxl_pci_bdf_dispose(&list[i]);

free(list);
}
Expand Down Expand Up @@ -745,6 +745,7 @@ static int pciback_dev_unassign(libxl__gc *gc, libxl_pci_bdf *pcibdf)

static int libxl__pci_bdf_assignable_add(libxl__gc *gc,
libxl_pci_bdf *pcibdf,
const char *name,
int rebind)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
Expand All @@ -753,6 +754,23 @@ static int libxl__pci_bdf_assignable_add(libxl__gc *gc,
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;
Expand All @@ -773,7 +791,7 @@ static int libxl__pci_bdf_assignable_add(libxl__gc *gc,
}
if ( rc ) {
LOG(WARN, PCI_BDF" already assigned to pciback", dom, bus, dev, func);
goto quarantine;
goto name;
}

/* Check to see if there's already a driver that we need to unbind from */
Expand Down Expand Up @@ -804,7 +822,12 @@ static int libxl__pci_bdf_assignable_add(libxl__gc *gc,
return ERROR_FAIL;
}

quarantine:
name:
if (name)
pci_info_xs_write(gc, pcibdf, "name", name);
else
pci_info_xs_remove(gc, pcibdf, "name");

/*
* DOMID_IO is just a sentinel domain, without any actual mappings,
* so always pass XEN_DOMCTL_DEV_RDM_RELAXED to avoid assignment being
Expand Down Expand Up @@ -868,34 +891,87 @@ static int libxl__pci_bdf_assignable_remove(libxl__gc *gc,
}
}

pci_info_xs_remove(gc, pcibdf, "name");

return 0;
}

int libxl_device_pci_assignable_add(libxl_ctx *ctx, libxl_device_pci *pci,
int rebind)
int libxl_pci_bdf_assignable_add(libxl_ctx *ctx, libxl_pci_bdf *pcibdf,
const char *name, int rebind)
{
GC_INIT(ctx);
int rc;

rc = libxl__pci_bdf_assignable_add(gc, &pci->bdf, rebind);
rc = libxl__pci_bdf_assignable_add(gc, pcibdf, name, rebind);

GC_FREE;
return rc;
}


int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
int rebind)
int libxl_pci_bdf_assignable_remove(libxl_ctx *ctx, libxl_pci_bdf *pcibdf,
int rebind)
{
GC_INIT(ctx);
int rc;

rc = libxl__pci_bdf_assignable_remove(gc, &pci->bdf, rebind);
rc = libxl__pci_bdf_assignable_remove(gc, pcibdf, 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
Expand Down Expand Up @@ -1490,17 +1566,17 @@ int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid,

static bool is_bdf_assignable(libxl_ctx *ctx, libxl_pci_bdf *pcibdf)
{
libxl_device_pci *pcis;
libxl_pci_bdf *pcibdfs;
int num, i;

pcis = libxl_device_pci_assignable_list(ctx, &num);
pcibdfs = libxl_pci_bdf_assignable_list(ctx, &num);

for (i = 0; i < num; i++) {
if (COMPARE_BDF(pcibdf, &pcis[i].bdf))
if (COMPARE_BDF(pcibdf, &pcibdfs[i]))
break;
}

libxl_device_pci_assignable_list_free(pcis, num);
libxl_pci_bdf_assignable_list_free(pcibdfs, num);

return i < num;
}
Expand Down Expand Up @@ -1551,7 +1627,7 @@ void libxl__device_pci_add(libxl__egc *egc, uint32_t domid,
if (rc) goto out;

if (pci->seize && !pciback_dev_is_assigned(gc, &pci->bdf)) {
rc = libxl__pci_bdf_assignable_add(gc, &pci->bdf, 1);
rc = libxl__pci_bdf_assignable_add(gc, &pci->bdf, NULL, 1);
if ( rc )
goto out;
}
Expand Down Expand Up @@ -2449,6 +2525,48 @@ DEFINE_DEVICE_TYPE_STRUCT(pci, PCI, pcidevs,
.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
Expand Down

0 comments on commit 5ab684c

Please sign in to comment.