Skip to contentSkip to conversation

xl: implement basic PCI passthrough sanity checks

PATCH New Gianni Tedesco 2 participants 10 messages Jul 27, 2010 – Jul 28, 2010

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 xl: implement basic PCI passthrough sanity checks

Following patch series implements basic safety checks for PCI passthrough in libxl. Specifically it deals with the case where the same PCI device may be multiply assigned in to one or more domU's. As a bonus, implement the pci-list-assignable-devices xl command.

 tools/libxl/Makefile      |    2 +-
 tools/libxl/libxl.c       |  501 ------------------------------------------
 tools/libxl/libxl_pci.c   |  538 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h       |    1 +
 tools/libxl/libxl_pci.c   |  123 ++++++++++
 tools/libxl/xl.h          |    1 +
 tools/libxl/xl_cmdimpl.c  |   34 ++
 tools/libxl/xl_cmdtable.c |    5 +
 tools/libxl/libxl_pci.c   |   11 +-
 9 files changed, 713 insertions(+), 503 deletions(-)
#1 lore raw

PATCH 1/1 Move PCI specific function definitions in to libxl_pci.c

 tools/libxl/Makefile    |    2 +-
 tools/libxl/libxl.c     |  501 --------------------------------------------
 tools/libxl/libxl_pci.c |  538 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 539 insertions(+), 502 deletions(-)
tools/libxl/Makefile +1 -1
diff -r ac7e4c6ec6c7 -r 20b2e15131c7 tools/libxl/Makefile
@@ -18,7 +18,7 @@ CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_
 LIBS = $(LDFLAGS_libxenctrl) $(LDFLAGS_libxenguest) $(LDFLAGS_libxenstore) $(LDFLAGS_libblktapctl) -lutil
 
 LIBXL_OBJS-y = osdeps.o libxl_paths.o libxl_bootloader.o
-LIBXL_OBJS = flexarray.o libxl.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o xenguest.o libxl_utils.o $(LIBXL_OBJS-y)
+LIBXL_OBJS = flexarray.o libxl.o libxl_pci.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o xenguest.o libxl_utils.o $(LIBXL_OBJS-y)
 
 AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
 AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
tools/libxl/libxl.c +0 -501

507 lines not on this page · raw message

tools/libxl/libxl_pci.c new file +538 -0

538 lines not on this page · raw message

#2 lore raw

PATCH 1/1 xl, implement pci-list-assignable-devices

In reply to Gianni Tedesco
 tools/libxl/libxl.h       |    1 +
 tools/libxl/libxl_pci.c   |  123 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl.h          |    1 +
 tools/libxl/xl_cmdimpl.c  |   34 ++++++++++++
 tools/libxl/xl_cmdtable.c |    5 +
 5 files changed, 164 insertions(+), 0 deletions(-)
tools/libxl/libxl.h +1 -0
diff -r 20b2e15131c7 -r 214733749470 tools/libxl/libxl.h
@@ -496,6 +496,7 @@ int libxl_device_pci_add(struct libxl_ct
 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev);
 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num);
+libxl_device_pci *libxl_device_pci_list_assignable(struct libxl_ctx *ctx, int *num);
 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
                           unsigned int bus, unsigned int dev,
                           unsigned int func, unsigned int vdevfn);
tools/libxl/libxl_pci.c +123 -0

141 lines not on this page · raw message

tools/libxl/xl.h +1 -0
diff -r 20b2e15131c7 -r 214733749470 tools/libxl/xl.h
@@ -32,6 +32,7 @@ int main_cd_insert(int argc, char **argv
 int main_console(int argc, char **argv);
 int main_vncviewer(int argc, char **argv);
 int main_pcilist(int argc, char **argv);
+int main_pcilist_assignable(int argc, char **argv);
 int main_pcidetach(int argc, char **argv);
 int main_pciattach(int argc, char **argv);
 int main_restore(int argc, char **argv);
tools/libxl/xl_cmdimpl.c +34 -0
diff -r 20b2e15131c7 -r 214733749470 tools/libxl/xl_cmdimpl.c
@@ -1706,6 +1706,40 @@ int main_vncviewer(int argc, char **argv
     exit(0);
 }
 
+void pcilist_assignable(void)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_list_assignable(&ctx, &num);
+    if (!num)
+        return;
+    for (i = 0; i < num; i++) {
+        printf("%04x:%02x:%02x:%01x\n",
+                pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+    }
+    free(pcidevs);
+}
+
+int main_pcilist_assignable(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-list-assignable-devices");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    pcilist_assignable();
+    exit(0);
+}
+
 void pcilist(char *dom)
 {
     libxl_device_pci *pcidevs;
tools/libxl/xl_cmdtable.c +5 -0
diff -r 20b2e15131c7 -r 214733749470 tools/libxl/xl_cmdtable.c
@@ -68,6 +68,11 @@ struct cmd_spec cmd_table[] = {
       "List pass-through pci devices for a domain",
       "<Domain>",
     },
+    { "pci-list-assignable-devices",
+      &main_pcilist_assignable,
+      "List all the assignable pci devices",
+      "",
+    },
     { "pause",
       &main_pause,
       "Pause execution of a domain",
#3 lore raw

Re: [PATCH 2 of 3] xl, implement pci-list-assignable-devices

Quoted 6 lines · Gianni Tedesco
tools/libxl/libxl_pci.c +6 -0
+                bdf = libxl_xs_read(ctx, XBT_NULL, devpath);
+                if ( bdf ) {
+                    unsigned dom, bus, dev, func;
+                    if ( sscanf(bdf, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
+                        continue;
+

tools/libxl/libxl_pci.c retry_transaction2: · line 298

Quoted 10 lines
tools/libxl/libxl_pci.c +10 -0
+                    new = realloc(pcidevs, ((*num) + 1) * sizeof(*new));
+                    if ( NULL == new )
+                        continue;
+
+                    pcidevs = new;
+                    new = pcidevs + *num;
+
+                    libxl_device_pci_init(new, dom, bus, dev, func, ~0);
+                    (*num)++;
+                }

Please don't apply patch 2 and therefore 3 from this set. This part is erroneous. Fixed in my tree and will submit the latest batch of updates soon.

Thanks

#4 lore raw

Re: [PATCH 2 of 3] xl, implement pci-list-assignable-devices

In reply to Gianni Tedesco
Quoted 72 lines · On Tue, 27 Jul 2010, Gianni Tedesco (3P) wrote:
 tools/libxl/libxl.h       |    1 +
 tools/libxl/libxl_pci.c   |  123 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl.h          |    1 +
 tools/libxl/xl_cmdimpl.c  |   34 ++++++++++++
 tools/libxl/xl_cmdtable.c |    5 +
 5 files changed, 164 insertions(+), 0 deletions(-)

diff -r 20b2e15131c7 -r 214733749470 tools/libxl/libxl.h

tools/libxl/libxl.h +1 -0
@@ -496,6 +496,7 @@ int libxl_device_pci_add(struct libxl_ct
 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev);
 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid);
 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num);
+libxl_device_pci *libxl_device_pci_list_assignable(struct libxl_ctx *ctx, int *num);
 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
                           unsigned int bus, unsigned int dev,
                           unsigned int func, unsigned int vdevfn);

diff -r 20b2e15131c7 -r 214733749470 tools/libxl/libxl_pci.c

tools/libxl/libxl_pci.c +39 -0
@@ -28,6 +28,7 @@
 #include <unistd.h> /* for write, unlink and close */
 #include <stdint.h>
 #include <inttypes.h>
+#include <dirent.h>
 #include <assert.h>
 
 #include "libxl.h"
@@ -258,6 +259,75 @@ retry_transaction2:
     return 0;
 }
 
+static libxl_device_pci *get_all_assigned_devices(struct libxl_ctx *ctx, int *num)
+{
+    libxl_device_pci *new, *pcidevs = NULL;
+    char **domlist;
+    unsigned int nd, i;
+
+    *num = 0;
+
+    domlist = libxl_xs_directory(ctx, XBT_NULL, "/local/domain", &nd);
+    for(i = 0; i < nd; i++) {
+        char *path, *num_devs;
+
+        path = libxl_sprintf(ctx, "/local/domain/0/backend/pci/%s/0/num_devs", domlist[i]);
+        num_devs = libxl_xs_read(ctx, XBT_NULL, path);
+        if ( num_devs ) {
+            int ndev = atoi(num_devs), j;
+            char *devpath, *bdf;
+
+            for(j = 0; j < ndev; j++) {
+                devpath = libxl_sprintf(ctx, "/local/domain/0/backend/pci/%s/0/dev-%u",
+                                        domlist[i], j);
+                bdf = libxl_xs_read(ctx, XBT_NULL, devpath);
+                if ( bdf ) {
+                    unsigned dom, bus, dev, func;
+                    if ( sscanf(bdf, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
+                        continue;
+
+                    new = realloc(pcidevs, ((*num) + 1) * sizeof(*new));
+                    if ( NULL == new )
+                        continue;
+
+                    pcidevs = new;
+                    new = pcidevs + *num;
+
+                    libxl_device_pci_init(new, dom, bus, dev, func, ~0);
+                    (*num)++;
+                }
+                libxl_free(ctx, bdf);

tools/libxl/libxl_pci.c retry_transaction2: · line 309

Quoted 10 lines
tools/libxl/libxl_pci.c +10 -0
+                libxl_free(ctx, devpath);
+            }
+            libxl_free(ctx, num_devs);
+        }
+        libxl_free(ctx, path);
+    }
+    libxl_free(ctx, domlist);
+
+    return pcidevs;
+}

You shouldn't use libxl_free explicitly on variables allocated in the context. Actually I like explicit free's but we have to keep the style consistent, so the memory management refactoring should come in as a separate patch, and here there shouldn't be any libxl_free's. The realloc is correct because it is used on a variable that is going to be returned to the caller.

Also I would prefer this function to return an integer and take the libxl_device_pci array as a parameter.

Quoted 71 lines
tools/libxl/libxl_pci.c +64 -0
+
+static int is_assigned(libxl_device_pci *assigned, int num_assigned,
+                       int dom, int bus, int dev, int func)
+{
+    int i;
+
+    for(i = 0; i < num_assigned; i++) {
+        if ( assigned[i].domain != dom )
+            continue;
+        if ( assigned[i].bus != bus )
+            continue;
+        if ( assigned[i].dev != dev )
+            continue;
+        if ( assigned[i].func != func )
+            continue;
+        return 1;
+    }
+
+    return 0;
+}
+
 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
 {
     char *path;
@@ -466,6 +536,59 @@ out:
     return 0;
 }
 
+static libxl_device_pci *scan_sys_pcidir(libxl_device_pci *pcidevs, libxl_device_pci *assigned,
+                                         int num_assigned, const char *path, int *num)
+{
+    libxl_device_pci *new;
+    struct dirent *de;
+    DIR *dir;
+
+    dir = opendir(path);
+    if ( NULL == dir )
+        return pcidevs;
+
+    while( (de = readdir(dir)) ) {
+        unsigned dom, bus, dev, func;
+        if ( sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
+            continue;
+
+        if ( is_assigned(assigned, num_assigned, dom, bus, dev, func) )
+            continue;
+
+        new = realloc(pcidevs, ((*num) + 1) * sizeof(*new));
+        if ( NULL == new )
+            continue;
+
+        pcidevs = new;
+        new = pcidevs + *num;
+
+        libxl_device_pci_init(new, dom, bus, dev, func, ~0);
+        (*num)++;
+    }
+
+    closedir(dir);
+    return pcidevs;
+}
+
+libxl_device_pci *libxl_device_pci_list_assignable(struct libxl_ctx *ctx, int *num)
+{
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_pci *assigned;
+    int num_assigned;
+
+    *num = 0;
+
+    assigned = get_all_assigned_devices(ctx, &num_assigned);

tools/libxl/libxl_pci.c out: · line 591

Quoted 10 lines
tools/libxl/libxl_pci.c +10 -0
+
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pciback", num);
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pcistub", num);
+
+    free(assigned);
+    return pcidevs;
+}
+

Same comment about returning an integer, also I don't like the way you are "assuming" scan_sys_pcidir is going to use realloc on pcidevs: that should be an implementation detail of scan_sys_pcidir that callers shouldn't rely upon.
Consider that devices bound to pcistub cannot be assigned to PV guests, so I would remove scan_sys_pcidir on pcistub from here. Please define "/sys/bus/pci/drivers/pciback" in a macro.

Quoted 74 lines
tools/libxl/libxl_pci.c +0 -0
 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
 {
     char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;

diff -r 20b2e15131c7 -r 214733749470 tools/libxl/xl.h

tools/libxl/xl.h +1 -0
@@ -32,6 +32,7 @@ int main_cd_insert(int argc, char **argv
 int main_console(int argc, char **argv);
 int main_vncviewer(int argc, char **argv);
 int main_pcilist(int argc, char **argv);
+int main_pcilist_assignable(int argc, char **argv);
 int main_pcidetach(int argc, char **argv);
 int main_pciattach(int argc, char **argv);
 int main_restore(int argc, char **argv);

diff -r 20b2e15131c7 -r 214733749470 tools/libxl/xl_cmdimpl.c

tools/libxl/xl_cmdimpl.c +34 -0
@@ -1706,6 +1706,40 @@ int main_vncviewer(int argc, char **argv
     exit(0);
 }
 
+void pcilist_assignable(void)
+{
+    libxl_device_pci *pcidevs;
+    int num, i;
+
+    pcidevs = libxl_device_pci_list_assignable(&ctx, &num);
+    if (!num)
+        return;
+    for (i = 0; i < num; i++) {
+        printf("%04x:%02x:%02x:%01x\n",
+                pcidevs[i].domain, pcidevs[i].bus, pcidevs[i].dev, pcidevs[i].func);
+    }
+    free(pcidevs);
+}
+
+int main_pcilist_assignable(int argc, char **argv)
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("pci-list-assignable-devices");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    pcilist_assignable();
+    exit(0);
+}
+
 void pcilist(char *dom)
 {
     libxl_device_pci *pcidevs;

diff -r 20b2e15131c7 -r 214733749470 tools/libxl/xl_cmdtable.c

tools/libxl/xl_cmdtable.c +5 -0
@@ -68,6 +68,11 @@ struct cmd_spec cmd_table[] = {
       "List pass-through pci devices for a domain",
       "<Domain>",
     },
+    { "pci-list-assignable-devices",
+      &main_pcilist_assignable,
+      "List all the assignable pci devices",
+      "",
+    },
     { "pause",
       &main_pause,
       "Pause execution of a domain",
#5 lore raw

Re: [PATCH 2 of 3] xl, implement pci-list-assignable-devices

Quoted 11 lines · Stefano Stabellini
Quoted 11 lines
tools/libxl/libxl_pci.c +11 -0
+                }
+                libxl_free(ctx, bdf);
+                libxl_free(ctx, devpath);
+            }
+            libxl_free(ctx, num_devs);
+        }
+        libxl_free(ctx, path);
+    }
+    libxl_free(ctx, domlist);
+
+    return pcidevs;
Quoted 8 lines
Quoted 1 line

+}

You shouldn't use libxl_free explicitly on variables allocated in the context. Actually I like explicit free's but we have to keep the style consistent, so the memory management refactoring should come in as a separate patch, and here there shouldn't be any libxl_free's. The realloc is correct because it is used on a variable that is going to be returned to the caller.

OK, this was written before the idea for refactoring memory management and just done out of habit. Are you saying just remove the libxl_free's and re-submit it like that?

Quoted 2 lines

Also I would prefer this function to return an integer and take the libxl_device_pci array as a parameter.

Hmm, OK.

Quoted 16 lines
Quoted 16 lines
tools/libxl/libxl_pci.c +16 -0
+libxl_device_pci *libxl_device_pci_list_assignable(struct libxl_ctx *ctx, int *num)
+{
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_pci *assigned;
+    int num_assigned;
+
+    *num = 0;
+
+    assigned = get_all_assigned_devices(ctx, &num_assigned);
+
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pciback", num);
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pcistub", num);
+
+    free(assigned);
Quoted 8 lines

tools/libxl/libxl_pci.c retry_transaction2: · line 310

Quoted 3 lines
tools/libxl/libxl_pci.c +3 -0
+    return pcidevs;
+}
+

Same comment about returning an integer, also I don't like the way you are "assuming" scan_sys_pcidir is going to use realloc on pcidevs: that should be an implementation detail of scan_sys_pcidir that callers shouldn't rely upon.

Actually it's a static function with only one caller, this makes the implementation of list_assignable as simple as possible.

Quoted 3 lines

Consider that devices bound to pcistub cannot be assigned to PV guests, so I would remove scan_sys_pcidir on pcistub from here. Please define "/sys/bus/pci/drivers/pciback" in a macro.

But they can be assigned to HVM guests? Nothing in the add-device path uses this list of devices anyway. What actually happens is a check whether a device appears in the get_all_assigned_devices() list. Even after this patch-set the user can always specify BDF's which aren't really assignable (eg. the Host's PCI-to-ISA bridge or PCI root for maximum amusement) That is to be addressed in a future patch.

Whether-or-not a specific device can be added is an issue for the add-device path. I think that the best approach there would then be just to stat the relevant sysfs paths to make sure the device is available.

As for the macro, of course, I will change that.

Thanks for the comments.

Gianni

#6 lore raw

Re: [PATCH 2 of 3] xl, implement pci-list-assignable-devices

Quoted 21 lines · On Wed, 28 Jul 2010, Gianni Tedesco (3P) wrote:
Quoted 11 lines · Stefano Stabellini
Quoted 11 lines
tools/libxl/libxl_pci.c +11 -0
+                }
+                libxl_free(ctx, bdf);
+                libxl_free(ctx, devpath);
+            }
+            libxl_free(ctx, num_devs);
+        }
+        libxl_free(ctx, path);
+    }
+    libxl_free(ctx, domlist);
+
+    return pcidevs;
Quoted 8 lines
Quoted 1 line

+}

You shouldn't use libxl_free explicitly on variables allocated in the context. Actually I like explicit free's but we have to keep the style consistent, so the memory management refactoring should come in as a separate patch, and here there shouldn't be any libxl_free's. The realloc is correct because it is used on a variable that is going to be returned to the caller.

Quoted 4 lines

OK, this was written before the idea for refactoring memory management and just done out of habit. Are you saying just remove the libxl_free's and re-submit it like that?

Yep

Quoted 32 lines
Quoted 16 lines
Quoted 16 lines
tools/libxl/libxl_pci.c +16 -0
+libxl_device_pci *libxl_device_pci_list_assignable(struct libxl_ctx *ctx, int *num)
+{
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_pci *assigned;
+    int num_assigned;
+
+    *num = 0;
+
+    assigned = get_all_assigned_devices(ctx, &num_assigned);
+
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pciback", num);
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pcistub", num);
+
+    free(assigned);
Quoted 8 lines

tools/libxl/libxl_pci.c retry_transaction2: · line 310

Quoted 3 lines
tools/libxl/libxl_pci.c +3 -0
+    return pcidevs;
+}
+

Same comment about returning an integer, also I don't like the way you are "assuming" scan_sys_pcidir is going to use realloc on pcidevs: that should be an implementation detail of scan_sys_pcidir that callers shouldn't rely upon.

Actually it's a static function with only one caller, this makes the implementation of list_assignable as simple as possible.

Quoted 3 lines

Consider that devices bound to pcistub cannot be assigned to PV guests, so I would remove scan_sys_pcidir on pcistub from here. Please define "/sys/bus/pci/drivers/pciback" in a macro.

Quoted 7 lines

But they can be assigned to HVM guests? Nothing in the add-device path uses this list of devices anyway. What actually happens is a check whether a device appears in the get_all_assigned_devices() list. Even after this patch-set the user can always specify BDF's which aren't really assignable (eg. the Host's PCI-to-ISA bridge or PCI root for maximum amusement) That is to be addressed in a future patch.

Yes but libxl_device_pci_list_assignable is a public function, we don't know what libxl users are going to do with it.
In particular it seems reasonable to call libxl_device_pci_list_assignable before assigning a device even if xl doesn't do it at the moment.

#7 lore raw

Re: [PATCH 2 of 3] xl, implement pci-list-assignable-devices

Quoted 40 lines · Stefano Stabellini
Quoted 32 lines
Quoted 16 lines
Quoted 16 lines
tools/libxl/libxl_pci.c +16 -0
+libxl_device_pci *libxl_device_pci_list_assignable(struct libxl_ctx *ctx, int *num)
+{
+    libxl_device_pci *pcidevs = NULL;
+    libxl_device_pci *assigned;
+    int num_assigned;
+
+    *num = 0;
+
+    assigned = get_all_assigned_devices(ctx, &num_assigned);
+
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pciback", num);
+    pcidevs = scan_sys_pcidir(pcidevs, assigned, num_assigned,
+                              "/sys/bus/pci/drivers/pcistub", num);
+
+    free(assigned);
Quoted 8 lines

tools/libxl/libxl_pci.c retry_transaction2: · line 310

Quoted 3 lines
tools/libxl/libxl_pci.c +3 -0
+    return pcidevs;
+}
+

Same comment about returning an integer, also I don't like the way you are "assuming" scan_sys_pcidir is going to use realloc on pcidevs: that should be an implementation detail of scan_sys_pcidir that callers shouldn't rely upon.

Actually it's a static function with only one caller, this makes the implementation of list_assignable as simple as possible.

Quoted 3 lines

Consider that devices bound to pcistub cannot be assigned to PV guests, so I would remove scan_sys_pcidir on pcistub from here. Please define "/sys/bus/pci/drivers/pciback" in a macro.

Quoted 7 lines

But they can be assigned to HVM guests? Nothing in the add-device path uses this list of devices anyway. What actually happens is a check whether a device appears in the get_all_assigned_devices() list. Even after this patch-set the user can always specify BDF's which aren't really assignable (eg. the Host's PCI-to-ISA bridge or PCI root for maximum amusement) That is to be addressed in a future patch.

Quoted 5 lines

Yes but libxl_device_pci_list_assignable is a public function, we don't know what libxl users are going to do with it.
In particular it seems reasonable to call libxl_device_pci_list_assignable before assigning a device even if xl doesn't do it at the moment.

Yes but the realloc semantics don't apply to libxl_device_pci_list_assignable only scan_sys_pcidir. Callers of the former are free to do what they like with what is returned. My argument is that implementation of the latter is wholly appropriate to it's only caller. In other words, scan_sys_pcidir is not going to have any new callers ever, as far as I can see anyway.

As for whether a device is assigned to picback or pcistub, I think the semantics of list_assignable() ought to be that it returns anything which may potentially be assignable at the time of calling. Unless we want to implement some specific way of signalling which devices are bound to which backend drivers. Personally I think these additional details should be handled by letting an add-device fail with an ERROR_INVAL so that callers don't need to know about backend-specific details.

In other words I'd like to keep the code here as it is (modulo putting sysfs paths in macros) Unless there's something deeper to this?

Gianni

#8 lore raw

PATCH 1/1 xl, check a PCI device is assignable before adding it to a domU

In reply to Gianni Tedesco
 tools/libxl/libxl_pci.c |  11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

This prevents PCI devices from being added multiply to the same domain or multiple different domains simultaneously.

tools/libxl/libxl_pci.c +10 -1
diff -r 214733749470 -r dbfc4f30efe2 tools/libxl/libxl_pci.c
@@ -334,8 +334,17 @@ int libxl_device_pci_add(struct libxl_ct
     char *state, *vdevfn;
     int rc, hvm;
     int stubdomid = 0;
+    libxl_device_pci *assigned;
+    int num_assigned;
 
-    /* TODO: check if the device can be assigned */
+    assigned = get_all_assigned_devices(ctx, &num_assigned);
+    if ( is_assigned(assigned, num_assigned, pcidev->domain,
+                     pcidev->bus, pcidev->dev, pcidev->func) ) {
+        XL_LOG(ctx, XL_LOG_ERROR, "PCI device already attached to a domain");
+        free(assigned);
+        return ERROR_FAIL;
+    }
+    free(assigned);
 
     libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
Acked-by on v1 1/1
#9 lore raw

Re: [PATCH 3 of 3] xl, check a PCI device is assignable before adding it to a domU

Quoted 6 lines · On Tue, 27 Jul 2010, Gianni Tedesco (3P) wrote:
 tools/libxl/libxl_pci.c |  11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

This prevents PCI devices from being added multiply to the same domain or multiple different domains simultaneously.

Quoted 24 lines

diff -r 214733749470 -r dbfc4f30efe2 tools/libxl/libxl_pci.c

tools/libxl/libxl_pci.c +10 -1
@@ -334,8 +334,17 @@ int libxl_device_pci_add(struct libxl_ct
     char *state, *vdevfn;
     int rc, hvm;
     int stubdomid = 0;
+    libxl_device_pci *assigned;
+    int num_assigned;
 
-    /* TODO: check if the device can be assigned */
+    assigned = get_all_assigned_devices(ctx, &num_assigned);
+    if ( is_assigned(assigned, num_assigned, pcidev->domain,
+                     pcidev->bus, pcidev->dev, pcidev->func) ) {
+        XL_LOG(ctx, XL_LOG_ERROR, "PCI device already attached to a domain");
+        free(assigned);
+        return ERROR_FAIL;
+    }
+    free(assigned);
 
     libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);