libxl: introduce libxl_pci_bdf_assignable_add/remove/list/list_free(), ...

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>
This commit is contained in:
Paul Durrant authored and Wei Liu committed 2020-12-15 16:24:26 +00:00
1 parent 66c2fbc6e8
commit 5ab684cb3e
2 files changed
+173 -33

No files matched your search

+29 -7
View File
@@ -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
*
@@ -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
@@ -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 */
+144 -26
View File
@@ -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;
@@ -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)++;
@@ -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);
}
@@ -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);
@@ -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;
@@ -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 */
@@ -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
@@ -868,32 +891,85 @@ 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 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, pcibdf, name, rebind);
GC_FREE;
return rc;
}
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_add(gc, &pci->bdf, rebind);
rc = libxl__pci_bdf_assignable_remove(gc, pcibdf, rebind);
GC_FREE;
return rc;
}
int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
int rebind)
libxl_pci_bdf *libxl_pci_bdf_assignable_name2bdf(libxl_ctx *ctx,
const char *name)
{
GC_INIT(ctx);
int rc;
char **bdfs;
libxl_pci_bdf *pcibdf = NULL;
unsigned int i, n;
rc = libxl__pci_bdf_assignable_remove(gc, &pci->bdf, rebind);
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 rc;
return name;
}
/*
@@ -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;
}
@@ -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;
}
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.