1790588f0SJosh Hilke // SPDX-License-Identifier: GPL-2.0 2790588f0SJosh Hilke #include <uapi/linux/types.h> 3790588f0SJosh Hilke #include <linux/limits.h> 4790588f0SJosh Hilke #include <linux/sizes.h> 5790588f0SJosh Hilke #include <linux/vfio.h> 6790588f0SJosh Hilke #include <linux/iommufd.h> 7790588f0SJosh Hilke 8790588f0SJosh Hilke #include <stdint.h> 9790588f0SJosh Hilke #include <stdio.h> 10790588f0SJosh Hilke #include <sys/ioctl.h> 11790588f0SJosh Hilke #include <unistd.h> 12790588f0SJosh Hilke 13790588f0SJosh Hilke #include <vfio_util.h> 14790588f0SJosh Hilke #include "../kselftest_harness.h" 15790588f0SJosh Hilke 16790588f0SJosh Hilke static const char iommu_dev_path[] = "/dev/iommu"; 17*118e073eSDavid Matlack static const char *cdev_path; 18790588f0SJosh Hilke 19790588f0SJosh Hilke static int vfio_device_bind_iommufd_ioctl(int cdev_fd, int iommufd) 20790588f0SJosh Hilke { 21790588f0SJosh Hilke struct vfio_device_bind_iommufd bind_args = { 22790588f0SJosh Hilke .argsz = sizeof(bind_args), 23790588f0SJosh Hilke .iommufd = iommufd, 24790588f0SJosh Hilke }; 25790588f0SJosh Hilke 26790588f0SJosh Hilke return ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, &bind_args); 27790588f0SJosh Hilke } 28790588f0SJosh Hilke 29790588f0SJosh Hilke static int vfio_device_get_info_ioctl(int cdev_fd) 30790588f0SJosh Hilke { 31790588f0SJosh Hilke struct vfio_device_info info_args = { .argsz = sizeof(info_args) }; 32790588f0SJosh Hilke 33790588f0SJosh Hilke return ioctl(cdev_fd, VFIO_DEVICE_GET_INFO, &info_args); 34790588f0SJosh Hilke } 35790588f0SJosh Hilke 36790588f0SJosh Hilke static int vfio_device_ioas_alloc_ioctl(int iommufd, struct iommu_ioas_alloc *alloc_args) 37790588f0SJosh Hilke { 38790588f0SJosh Hilke *alloc_args = (struct iommu_ioas_alloc){ 39790588f0SJosh Hilke .size = sizeof(struct iommu_ioas_alloc), 40790588f0SJosh Hilke }; 41790588f0SJosh Hilke 42790588f0SJosh Hilke return ioctl(iommufd, IOMMU_IOAS_ALLOC, alloc_args); 43790588f0SJosh Hilke } 44790588f0SJosh Hilke 45790588f0SJosh Hilke static int vfio_device_attach_iommufd_pt_ioctl(int cdev_fd, u32 pt_id) 46790588f0SJosh Hilke { 47790588f0SJosh Hilke struct vfio_device_attach_iommufd_pt attach_args = { 48790588f0SJosh Hilke .argsz = sizeof(attach_args), 49790588f0SJosh Hilke .pt_id = pt_id, 50790588f0SJosh Hilke }; 51790588f0SJosh Hilke 52790588f0SJosh Hilke return ioctl(cdev_fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_args); 53790588f0SJosh Hilke } 54790588f0SJosh Hilke 55790588f0SJosh Hilke static int vfio_device_detach_iommufd_pt_ioctl(int cdev_fd) 56790588f0SJosh Hilke { 57790588f0SJosh Hilke struct vfio_device_detach_iommufd_pt detach_args = { 58790588f0SJosh Hilke .argsz = sizeof(detach_args), 59790588f0SJosh Hilke }; 60790588f0SJosh Hilke 61790588f0SJosh Hilke return ioctl(cdev_fd, VFIO_DEVICE_DETACH_IOMMUFD_PT, &detach_args); 62790588f0SJosh Hilke } 63790588f0SJosh Hilke 64790588f0SJosh Hilke FIXTURE(vfio_cdev) { 65790588f0SJosh Hilke int cdev_fd; 66790588f0SJosh Hilke int iommufd; 67790588f0SJosh Hilke }; 68790588f0SJosh Hilke 69790588f0SJosh Hilke FIXTURE_SETUP(vfio_cdev) 70790588f0SJosh Hilke { 71790588f0SJosh Hilke ASSERT_LE(0, (self->cdev_fd = open(cdev_path, O_RDWR, 0))); 72790588f0SJosh Hilke ASSERT_LE(0, (self->iommufd = open(iommu_dev_path, O_RDWR, 0))); 73790588f0SJosh Hilke } 74790588f0SJosh Hilke 75790588f0SJosh Hilke FIXTURE_TEARDOWN(vfio_cdev) 76790588f0SJosh Hilke { 77790588f0SJosh Hilke ASSERT_EQ(0, close(self->cdev_fd)); 78790588f0SJosh Hilke ASSERT_EQ(0, close(self->iommufd)); 79790588f0SJosh Hilke } 80790588f0SJosh Hilke 81790588f0SJosh Hilke TEST_F(vfio_cdev, bind) 82790588f0SJosh Hilke { 83790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_bind_iommufd_ioctl(self->cdev_fd, self->iommufd)); 84790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_get_info_ioctl(self->cdev_fd)); 85790588f0SJosh Hilke } 86790588f0SJosh Hilke 87790588f0SJosh Hilke TEST_F(vfio_cdev, get_info_without_bind_fails) 88790588f0SJosh Hilke { 89790588f0SJosh Hilke ASSERT_NE(0, vfio_device_get_info_ioctl(self->cdev_fd)); 90790588f0SJosh Hilke } 91790588f0SJosh Hilke 92790588f0SJosh Hilke TEST_F(vfio_cdev, bind_bad_iommufd_fails) 93790588f0SJosh Hilke { 94790588f0SJosh Hilke ASSERT_NE(0, vfio_device_bind_iommufd_ioctl(self->cdev_fd, -2)); 95790588f0SJosh Hilke } 96790588f0SJosh Hilke 97790588f0SJosh Hilke TEST_F(vfio_cdev, repeated_bind_fails) 98790588f0SJosh Hilke { 99790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_bind_iommufd_ioctl(self->cdev_fd, self->iommufd)); 100790588f0SJosh Hilke ASSERT_NE(0, vfio_device_bind_iommufd_ioctl(self->cdev_fd, self->iommufd)); 101790588f0SJosh Hilke } 102790588f0SJosh Hilke 103790588f0SJosh Hilke TEST_F(vfio_cdev, attach_detatch_pt) 104790588f0SJosh Hilke { 105790588f0SJosh Hilke struct iommu_ioas_alloc alloc_args; 106790588f0SJosh Hilke 107790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_bind_iommufd_ioctl(self->cdev_fd, self->iommufd)); 108790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_ioas_alloc_ioctl(self->iommufd, &alloc_args)); 109790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_attach_iommufd_pt_ioctl(self->cdev_fd, alloc_args.out_ioas_id)); 110790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_detach_iommufd_pt_ioctl(self->cdev_fd)); 111790588f0SJosh Hilke } 112790588f0SJosh Hilke 113790588f0SJosh Hilke TEST_F(vfio_cdev, attach_invalid_pt_fails) 114790588f0SJosh Hilke { 115790588f0SJosh Hilke ASSERT_EQ(0, vfio_device_bind_iommufd_ioctl(self->cdev_fd, self->iommufd)); 116790588f0SJosh Hilke ASSERT_NE(0, vfio_device_attach_iommufd_pt_ioctl(self->cdev_fd, UINT32_MAX)); 117790588f0SJosh Hilke } 118790588f0SJosh Hilke 119790588f0SJosh Hilke int main(int argc, char *argv[]) 120790588f0SJosh Hilke { 121790588f0SJosh Hilke const char *device_bdf = vfio_selftests_get_bdf(&argc, argv); 122790588f0SJosh Hilke 123*118e073eSDavid Matlack cdev_path = vfio_pci_get_cdev_path(device_bdf); 124790588f0SJosh Hilke printf("Using cdev device %s\n", cdev_path); 125790588f0SJosh Hilke 126790588f0SJosh Hilke return test_harness_run(argc, argv); 127790588f0SJosh Hilke } 128