mirror of https://github.com/torvalds/linux.git
vfio: selftests: update DMA map/unmap helpers to support more test kinds
Add __vfio_pci_dma_*() helpers which return -errno from the underlying ioctls. Add __vfio_pci_dma_unmap_all() to test more unmapping code paths. Add an out unmapped arg to report the unmapped byte size. The existing vfio_pci_dma_*() functions, which are intended for happy-path usage (assert on failure) are now thin wrappers on top of the double-underscore helpers. Reviewed-by: David Matlack <dmatlack@google.com> Signed-off-by: Alex Mastro <amastro@fb.com> Link: https://lore.kernel.org/r/20251028-fix-unmap-v6-4-2542b96bcc8e@fb.com Signed-off-by: Alex Williamson <alex@shazbot.org>
This commit is contained in:
parent
ef270ec446
commit
16950b60c1
|
|
@ -206,10 +206,29 @@ struct vfio_pci_device *vfio_pci_device_init(const char *bdf, const char *iommu_
|
|||
void vfio_pci_device_cleanup(struct vfio_pci_device *device);
|
||||
void vfio_pci_device_reset(struct vfio_pci_device *device);
|
||||
|
||||
void vfio_pci_dma_map(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region);
|
||||
void vfio_pci_dma_unmap(struct vfio_pci_device *device,
|
||||
int __vfio_pci_dma_map(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region);
|
||||
int __vfio_pci_dma_unmap(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region,
|
||||
u64 *unmapped);
|
||||
int __vfio_pci_dma_unmap_all(struct vfio_pci_device *device, u64 *unmapped);
|
||||
|
||||
static inline void vfio_pci_dma_map(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
{
|
||||
VFIO_ASSERT_EQ(__vfio_pci_dma_map(device, region), 0);
|
||||
}
|
||||
|
||||
static inline void vfio_pci_dma_unmap(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
{
|
||||
VFIO_ASSERT_EQ(__vfio_pci_dma_unmap(device, region, NULL), 0);
|
||||
}
|
||||
|
||||
static inline void vfio_pci_dma_unmap_all(struct vfio_pci_device *device)
|
||||
{
|
||||
VFIO_ASSERT_EQ(__vfio_pci_dma_unmap_all(device, NULL), 0);
|
||||
}
|
||||
|
||||
void vfio_pci_config_access(struct vfio_pci_device *device, bool write,
|
||||
size_t config, size_t size, void *data);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -141,7 +142,7 @@ static void vfio_pci_irq_get(struct vfio_pci_device *device, u32 index,
|
|||
ioctl_assert(device->fd, VFIO_DEVICE_GET_IRQ_INFO, irq_info);
|
||||
}
|
||||
|
||||
static void vfio_iommu_dma_map(struct vfio_pci_device *device,
|
||||
static int vfio_iommu_dma_map(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
{
|
||||
struct vfio_iommu_type1_dma_map args = {
|
||||
|
|
@ -152,10 +153,13 @@ static void vfio_iommu_dma_map(struct vfio_pci_device *device,
|
|||
.size = region->size,
|
||||
};
|
||||
|
||||
ioctl_assert(device->container_fd, VFIO_IOMMU_MAP_DMA, &args);
|
||||
if (ioctl(device->container_fd, VFIO_IOMMU_MAP_DMA, &args))
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iommufd_dma_map(struct vfio_pci_device *device,
|
||||
static int iommufd_dma_map(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
{
|
||||
struct iommu_ioas_map args = {
|
||||
|
|
@ -169,54 +173,108 @@ static void iommufd_dma_map(struct vfio_pci_device *device,
|
|||
.ioas_id = device->ioas_id,
|
||||
};
|
||||
|
||||
ioctl_assert(device->iommufd, IOMMU_IOAS_MAP, &args);
|
||||
if (ioctl(device->iommufd, IOMMU_IOAS_MAP, &args))
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vfio_pci_dma_map(struct vfio_pci_device *device,
|
||||
int __vfio_pci_dma_map(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (device->iommufd)
|
||||
iommufd_dma_map(device, region);
|
||||
ret = iommufd_dma_map(device, region);
|
||||
else
|
||||
vfio_iommu_dma_map(device, region);
|
||||
ret = vfio_iommu_dma_map(device, region);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_add(®ion->link, &device->dma_regions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vfio_iommu_dma_unmap(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
static int vfio_iommu_dma_unmap(int fd, u64 iova, u64 size, u32 flags,
|
||||
u64 *unmapped)
|
||||
{
|
||||
struct vfio_iommu_type1_dma_unmap args = {
|
||||
.argsz = sizeof(args),
|
||||
.iova = region->iova,
|
||||
.size = region->size,
|
||||
.iova = iova,
|
||||
.size = size,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
ioctl_assert(device->container_fd, VFIO_IOMMU_UNMAP_DMA, &args);
|
||||
if (ioctl(fd, VFIO_IOMMU_UNMAP_DMA, &args))
|
||||
return -errno;
|
||||
|
||||
if (unmapped)
|
||||
*unmapped = args.size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iommufd_dma_unmap(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
static int iommufd_dma_unmap(int fd, u64 iova, u64 length, u32 ioas_id,
|
||||
u64 *unmapped)
|
||||
{
|
||||
struct iommu_ioas_unmap args = {
|
||||
.size = sizeof(args),
|
||||
.iova = region->iova,
|
||||
.length = region->size,
|
||||
.ioas_id = device->ioas_id,
|
||||
.iova = iova,
|
||||
.length = length,
|
||||
.ioas_id = ioas_id,
|
||||
};
|
||||
|
||||
ioctl_assert(device->iommufd, IOMMU_IOAS_UNMAP, &args);
|
||||
if (ioctl(fd, IOMMU_IOAS_UNMAP, &args))
|
||||
return -errno;
|
||||
|
||||
if (unmapped)
|
||||
*unmapped = args.length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vfio_pci_dma_unmap(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region)
|
||||
int __vfio_pci_dma_unmap(struct vfio_pci_device *device,
|
||||
struct vfio_dma_region *region, u64 *unmapped)
|
||||
{
|
||||
if (device->iommufd)
|
||||
iommufd_dma_unmap(device, region);
|
||||
else
|
||||
vfio_iommu_dma_unmap(device, region);
|
||||
int ret;
|
||||
|
||||
list_del(®ion->link);
|
||||
if (device->iommufd)
|
||||
ret = iommufd_dma_unmap(device->iommufd, region->iova,
|
||||
region->size, device->ioas_id,
|
||||
unmapped);
|
||||
else
|
||||
ret = vfio_iommu_dma_unmap(device->container_fd, region->iova,
|
||||
region->size, 0, unmapped);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_del_init(®ion->link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __vfio_pci_dma_unmap_all(struct vfio_pci_device *device, u64 *unmapped)
|
||||
{
|
||||
int ret;
|
||||
struct vfio_dma_region *curr, *next;
|
||||
|
||||
if (device->iommufd)
|
||||
ret = iommufd_dma_unmap(device->iommufd, 0, UINT64_MAX,
|
||||
device->ioas_id, unmapped);
|
||||
else
|
||||
ret = vfio_iommu_dma_unmap(device->container_fd, 0, 0,
|
||||
VFIO_DMA_UNMAP_FLAG_ALL, unmapped);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_for_each_entry_safe(curr, next, &device->dma_regions, link)
|
||||
list_del_init(&curr->link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vfio_pci_region_get(struct vfio_pci_device *device, int index,
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ TEST_F(vfio_dma_mapping_test, dma_map_unmap)
|
|||
struct vfio_dma_region region;
|
||||
struct iommu_mapping mapping;
|
||||
u64 mapping_size = size;
|
||||
u64 unmapped;
|
||||
int rc;
|
||||
|
||||
region.vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
|
|
@ -184,7 +185,9 @@ TEST_F(vfio_dma_mapping_test, dma_map_unmap)
|
|||
}
|
||||
|
||||
unmap:
|
||||
vfio_pci_dma_unmap(self->device, ®ion);
|
||||
rc = __vfio_pci_dma_unmap(self->device, ®ion, &unmapped);
|
||||
ASSERT_EQ(rc, 0);
|
||||
ASSERT_EQ(unmapped, region.size);
|
||||
printf("Unmapped IOVA 0x%lx\n", region.iova);
|
||||
ASSERT_EQ(INVALID_IOVA, __to_iova(self->device, region.vaddr));
|
||||
ASSERT_NE(0, iommu_mapping_get(device_bdf, region.iova, &mapping));
|
||||
|
|
|
|||
Loading…
Reference in New Issue