]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
vfio: selftests: Allow passing multiple BDFs on the command line
authorDavid Matlack <dmatlack@google.com>
Wed, 26 Nov 2025 23:17:18 +0000 (23:17 +0000)
committerAlex Williamson <alex@shazbot.org>
Fri, 28 Nov 2025 17:58:06 +0000 (10:58 -0700)
Add support for passing multiple device BDFs to a test via the command
line. This is a prerequisite for multi-device tests.

Single-device tests can continue using vfio_selftests_get_bdf(), which
will continue to return argv[argc - 1] (if it is a BDF string), or the
environment variable $VFIO_SELFTESTS_BDF otherwise.

For multi-device tests, a new helper called vfio_selftests_get_bdfs() is
introduced which will return an array of all BDFs found at the end of
argv[], as well as the number of BDFs found (passed back to the caller
via argument). The array of BDFs returned does not need to be freed by
the caller.

The environment variable VFIO_SELFTESTS_BDF continues to support only a
single BDF for the time being.

Reviewed-by: Alex Mastro <amastro@fb.com>
Tested-by: Alex Mastro <amastro@fb.com>
Reviewed-by: Raghavendra Rao Ananta <rananta@google.com>
Signed-off-by: David Matlack <dmatlack@google.com>
Link: https://lore.kernel.org/r/20251126231733.3302983-4-dmatlack@google.com
Signed-off-by: Alex Williamson <alex@shazbot.org>
tools/testing/selftests/vfio/lib/include/vfio_util.h
tools/testing/selftests/vfio/lib/vfio_pci_device.c

index 69ec0c85648106e90536b908bddde94101623aa1..0b9a5628d23e93a6be3624b380ece3f7aab772bd 100644 (file)
@@ -208,6 +208,8 @@ struct iova_allocator {
  * If BDF cannot be determined then the test will exit with KSFT_SKIP.
  */
 const char *vfio_selftests_get_bdf(int *argc, char *argv[]);
+char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs);
+
 const char *vfio_pci_get_cdev_path(const char *bdf);
 
 extern const char *default_iommu_mode;
index b479a359da121c4c884c84b5617aa3f4e40b80b3..eda8f14de79711fde3c5c9dbc153c99c88440491 100644 (file)
@@ -868,29 +868,64 @@ static bool is_bdf(const char *str)
        return count == 4 && length == strlen(str);
 }
 
-const char *vfio_selftests_get_bdf(int *argc, char *argv[])
+static char **get_bdfs_cmdline(int *argc, char *argv[], int *nr_bdfs)
 {
-       char *bdf;
+       int i;
 
-       if (*argc > 1 && is_bdf(argv[*argc - 1]))
-               return argv[--(*argc)];
+       for (i = *argc - 1; i > 0 && is_bdf(argv[i]); i--)
+               continue;
+
+       i++;
+       *nr_bdfs = *argc - i;
+       *argc -= *nr_bdfs;
+
+       return *nr_bdfs ? &argv[i] : NULL;
+}
+
+static char *get_bdf_env(void)
+{
+       char *bdf;
 
        bdf = getenv("VFIO_SELFTESTS_BDF");
-       if (bdf) {
-               VFIO_ASSERT_TRUE(is_bdf(bdf), "Invalid BDF: %s\n", bdf);
-               return bdf;
+       if (!bdf)
+               return NULL;
+
+       VFIO_ASSERT_TRUE(is_bdf(bdf), "Invalid BDF: %s\n", bdf);
+       return bdf;
+}
+
+char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs)
+{
+       static char *env_bdf;
+       char **bdfs;
+
+       bdfs = get_bdfs_cmdline(argc, argv, nr_bdfs);
+       if (bdfs)
+               return bdfs;
+
+       env_bdf = get_bdf_env();
+       if (env_bdf) {
+               *nr_bdfs = 1;
+               return &env_bdf;
        }
 
-       fprintf(stderr, "Unable to determine which device to use, skipping test.\n");
+       fprintf(stderr, "Unable to determine which device(s) to use, skipping test.\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "To pass the device address via environment variable:\n");
        fprintf(stderr, "\n");
-       fprintf(stderr, "    export VFIO_SELFTESTS_BDF=segment:bus:device.function\n");
+       fprintf(stderr, "    export VFIO_SELFTESTS_BDF=\"segment:bus:device.function\"\n");
        fprintf(stderr, "    %s [options]\n", argv[0]);
        fprintf(stderr, "\n");
-       fprintf(stderr, "To pass the device address via argv:\n");
+       fprintf(stderr, "To pass the device address(es) via argv:\n");
        fprintf(stderr, "\n");
-       fprintf(stderr, "    %s [options] segment:bus:device.function\n", argv[0]);
+       fprintf(stderr, "    %s [options] segment:bus:device.function ...\n", argv[0]);
        fprintf(stderr, "\n");
        exit(KSFT_SKIP);
 }
+
+const char *vfio_selftests_get_bdf(int *argc, char *argv[])
+{
+       int nr_bdfs;
+
+       return vfio_selftests_get_bdfs(argc, argv, &nr_bdfs)[0];
+}