1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <sys/mman.h> 6 7 #include <linux/align.h> 8 9 #include "../../../kselftest.h" 10 #include <libvfio.h> 11 12 static bool is_bdf(const char *str) 13 { 14 unsigned int s, b, d, f; 15 int length, count; 16 17 count = sscanf(str, "%4x:%2x:%2x.%2x%n", &s, &b, &d, &f, &length); 18 return count == 4 && length == strlen(str); 19 } 20 21 static char **get_bdfs_cmdline(int *argc, char *argv[], int *nr_bdfs) 22 { 23 int i; 24 25 for (i = *argc - 1; i > 0 && is_bdf(argv[i]); i--) 26 continue; 27 28 i++; 29 *nr_bdfs = *argc - i; 30 *argc -= *nr_bdfs; 31 32 return *nr_bdfs ? &argv[i] : NULL; 33 } 34 35 static char *get_bdf_env(void) 36 { 37 char *bdf; 38 39 bdf = getenv("VFIO_SELFTESTS_BDF"); 40 if (!bdf) 41 return NULL; 42 43 VFIO_ASSERT_TRUE(is_bdf(bdf), "Invalid BDF: %s\n", bdf); 44 return bdf; 45 } 46 47 char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs) 48 { 49 static char *env_bdf; 50 char **bdfs; 51 52 bdfs = get_bdfs_cmdline(argc, argv, nr_bdfs); 53 if (bdfs) 54 return bdfs; 55 56 env_bdf = get_bdf_env(); 57 if (env_bdf) { 58 *nr_bdfs = 1; 59 return &env_bdf; 60 } 61 62 fprintf(stderr, "Unable to determine which device(s) to use, skipping test.\n"); 63 fprintf(stderr, "\n"); 64 fprintf(stderr, "To pass the device address via environment variable:\n"); 65 fprintf(stderr, "\n"); 66 fprintf(stderr, " export VFIO_SELFTESTS_BDF=\"segment:bus:device.function\"\n"); 67 fprintf(stderr, " %s [options]\n", argv[0]); 68 fprintf(stderr, "\n"); 69 fprintf(stderr, "To pass the device address(es) via argv:\n"); 70 fprintf(stderr, "\n"); 71 fprintf(stderr, " %s [options] segment:bus:device.function ...\n", argv[0]); 72 fprintf(stderr, "\n"); 73 exit(KSFT_SKIP); 74 } 75 76 const char *vfio_selftests_get_bdf(int *argc, char *argv[]) 77 { 78 int nr_bdfs; 79 80 return vfio_selftests_get_bdfs(argc, argv, &nr_bdfs)[0]; 81 } 82 83 void *mmap_reserve(size_t size, size_t align, size_t offset) 84 { 85 void *map_base, *map_align; 86 size_t delta; 87 88 VFIO_ASSERT_GT(align, offset); 89 delta = align - offset; 90 91 map_base = mmap(NULL, size + align, PROT_NONE, 92 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 93 VFIO_ASSERT_NE(map_base, MAP_FAILED); 94 95 map_align = (void *)(ALIGN((uintptr_t)map_base + delta, align) - delta); 96 97 if (map_align > map_base) 98 VFIO_ASSERT_EQ(munmap(map_base, map_align - map_base), 0); 99 100 VFIO_ASSERT_EQ(munmap(map_align + size, map_base + align - map_align), 0); 101 102 return map_align; 103 } 104