Skip to content

Commit 2607a43

Browse files
dmatlackawilliam
authored andcommitted
vfio: selftests: Move IOVA allocator into iova_allocator.c
Move the IOVA allocator into its own file, to provide better separation between the allocator and the struct vfio_pci_device helper code. The allocator could go into iommu.c, but it is standalone enough that a separate file seems cleaner. This also continues the trend of having a .c for every major object in VFIO selftests (vfio_pci_device.c, vfio_pci_driver.c, iommu.c, and now iova_allocator.c). No functional change intended. 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-13-dmatlack@google.com Signed-off-by: Alex Williamson <alex@shazbot.org>
1 parent 2aca571 commit 2607a43

3 files changed

Lines changed: 95 additions & 71 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <dirent.h>
3+
#include <fcntl.h>
4+
#include <libgen.h>
5+
#include <stdint.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <unistd.h>
9+
10+
#include <sys/eventfd.h>
11+
#include <sys/ioctl.h>
12+
#include <sys/mman.h>
13+
14+
#include <uapi/linux/types.h>
15+
#include <linux/iommufd.h>
16+
#include <linux/limits.h>
17+
#include <linux/mman.h>
18+
#include <linux/overflow.h>
19+
#include <linux/types.h>
20+
#include <linux/vfio.h>
21+
22+
#include <vfio_util.h>
23+
24+
struct iova_allocator *iova_allocator_init(struct vfio_pci_device *device)
25+
{
26+
struct iova_allocator *allocator;
27+
struct iommu_iova_range *ranges;
28+
u32 nranges;
29+
30+
ranges = vfio_pci_iova_ranges(device, &nranges);
31+
VFIO_ASSERT_NOT_NULL(ranges);
32+
33+
allocator = malloc(sizeof(*allocator));
34+
VFIO_ASSERT_NOT_NULL(allocator);
35+
36+
*allocator = (struct iova_allocator){
37+
.ranges = ranges,
38+
.nranges = nranges,
39+
.range_idx = 0,
40+
.range_offset = 0,
41+
};
42+
43+
return allocator;
44+
}
45+
46+
void iova_allocator_cleanup(struct iova_allocator *allocator)
47+
{
48+
free(allocator->ranges);
49+
free(allocator);
50+
}
51+
52+
iova_t iova_allocator_alloc(struct iova_allocator *allocator, size_t size)
53+
{
54+
VFIO_ASSERT_GT(size, 0, "Invalid size arg, zero\n");
55+
VFIO_ASSERT_EQ(size & (size - 1), 0, "Invalid size arg, non-power-of-2\n");
56+
57+
for (;;) {
58+
struct iommu_iova_range *range;
59+
iova_t iova, last;
60+
61+
VFIO_ASSERT_LT(allocator->range_idx, allocator->nranges,
62+
"IOVA allocator out of space\n");
63+
64+
range = &allocator->ranges[allocator->range_idx];
65+
iova = range->start + allocator->range_offset;
66+
67+
/* Check for sufficient space at the current offset */
68+
if (check_add_overflow(iova, size - 1, &last) ||
69+
last > range->last)
70+
goto next_range;
71+
72+
/* Align iova to size */
73+
iova = last & ~(size - 1);
74+
75+
/* Check for sufficient space at the aligned iova */
76+
if (check_add_overflow(iova, size - 1, &last) ||
77+
last > range->last)
78+
goto next_range;
79+
80+
if (last == range->last) {
81+
allocator->range_idx++;
82+
allocator->range_offset = 0;
83+
} else {
84+
allocator->range_offset = last - range->start + 1;
85+
}
86+
87+
return iova;
88+
89+
next_range:
90+
allocator->range_idx++;
91+
allocator->range_offset = 0;
92+
}
93+
}
94+

tools/testing/selftests/vfio/lib/libvfio.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ARCH ?= $(SUBARCH)
44
LIBVFIO_SRCDIR := $(selfdir)/vfio/lib
55

66
LIBVFIO_C := iommu.c
7+
LIBVFIO_C += iova_allocator.c
78
LIBVFIO_C += vfio_pci_device.c
89
LIBVFIO_C += vfio_pci_driver.c
910

tools/testing/selftests/vfio/lib/vfio_pci_device.c

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,77 +24,6 @@
2424

2525
#define PCI_SYSFS_PATH "/sys/bus/pci/devices"
2626

27-
struct iova_allocator *iova_allocator_init(struct vfio_pci_device *device)
28-
{
29-
struct iova_allocator *allocator;
30-
struct iommu_iova_range *ranges;
31-
u32 nranges;
32-
33-
ranges = vfio_pci_iova_ranges(device, &nranges);
34-
VFIO_ASSERT_NOT_NULL(ranges);
35-
36-
allocator = malloc(sizeof(*allocator));
37-
VFIO_ASSERT_NOT_NULL(allocator);
38-
39-
*allocator = (struct iova_allocator){
40-
.ranges = ranges,
41-
.nranges = nranges,
42-
.range_idx = 0,
43-
.range_offset = 0,
44-
};
45-
46-
return allocator;
47-
}
48-
49-
void iova_allocator_cleanup(struct iova_allocator *allocator)
50-
{
51-
free(allocator->ranges);
52-
free(allocator);
53-
}
54-
55-
iova_t iova_allocator_alloc(struct iova_allocator *allocator, size_t size)
56-
{
57-
VFIO_ASSERT_GT(size, 0, "Invalid size arg, zero\n");
58-
VFIO_ASSERT_EQ(size & (size - 1), 0, "Invalid size arg, non-power-of-2\n");
59-
60-
for (;;) {
61-
struct iommu_iova_range *range;
62-
iova_t iova, last;
63-
64-
VFIO_ASSERT_LT(allocator->range_idx, allocator->nranges,
65-
"IOVA allocator out of space\n");
66-
67-
range = &allocator->ranges[allocator->range_idx];
68-
iova = range->start + allocator->range_offset;
69-
70-
/* Check for sufficient space at the current offset */
71-
if (check_add_overflow(iova, size - 1, &last) ||
72-
last > range->last)
73-
goto next_range;
74-
75-
/* Align iova to size */
76-
iova = last & ~(size - 1);
77-
78-
/* Check for sufficient space at the aligned iova */
79-
if (check_add_overflow(iova, size - 1, &last) ||
80-
last > range->last)
81-
goto next_range;
82-
83-
if (last == range->last) {
84-
allocator->range_idx++;
85-
allocator->range_offset = 0;
86-
} else {
87-
allocator->range_offset = last - range->start + 1;
88-
}
89-
90-
return iova;
91-
92-
next_range:
93-
allocator->range_idx++;
94-
allocator->range_offset = 0;
95-
}
96-
}
97-
9827
static void vfio_pci_irq_set(struct vfio_pci_device *device,
9928
u32 index, u32 vector, u32 count, int *fds)
10029
{

0 commit comments

Comments
 (0)