DEAR ALL , No I have know the root cause , the issue ouccured when below code run my AMD test PC. So could you guys give some suggestion ? Will very much appreciate if you feel free to reply!! From: XueMei Yue
hi, I am an firmware engineer from china . I want to test the function ATS that need the support
of “iommufd+pasid”
Now I will test some new function
,will use pasid + iommufd, i used your patch from https://lore.kernel.org/linux-iommu/20240412082121.33382-1-yi.l.liu@xxxxxxxxx/
my test step is
1 use spdk
, run ./scripts/setup, the nvme device drive is changed from nvme to vfio-pci
2 run my example
,see the attchment ,using g++ to compile
when run my example . the below error occurs
,could you give some suggestion
? Will very much appreciate if you feel free to reply!!
Best regards
XueMei |
#include <stdio.h> #include <unistd.h> #include <stdint.h> #include <stdlib.h> #include <linux/vfio.h> #include <inttypes.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <string> #include <iostream> #include <cstring> #include <linux/iommufd.h> struct args { __u64 iova; /* IO virtual address */ __u64 size; std::string vfioX; std::string bdf; }; int main(int argc, char *argv[]) { int ret = 0; int cdev_fd, iommufd, i; std::cout << "Program name: " << argv[0] << std::endl; struct args para={0}; for (int i = 1; i < argc; ++i) { std::cout << "Argument " << i << ": " << argv[i] << std::endl; if(!std::strcmp(argv[i], "-help")) { printf("-iova: input the map address iova\n"); printf("-size: input the Number of bytes to copy and map\n"); printf("-device: input the bdf\n"); printf("-vfio : input the vfioX\n"); return 0; } if(!std::strcmp(argv[i], "-iova")) { i++; char *address = argv[i]; sscanf(address, "%" SCNx64, ¶.iova); printf("The address is: %" PRIx64 "\n", para.iova); } if(!std::strcmp(argv[i], "-size")) { i++; para.size = atoi(argv[i]); std::cout << "the size is "<< para.size << std::endl; } if(!std::strcmp(argv[i], "-vfio")) { i++; para.vfioX = argv[i]; std::cout << "vfioX is "<< para.vfioX << std::endl; } if(!std::strcmp(argv[i] , "-device")) { i++; char *input_string = argv[i]; para.bdf = input_string ; } } struct vfio_device_bind_iommufd bind = { .argsz = sizeof(bind), .flags = 0, }; struct iommu_ioas_alloc alloc_data = { .size = sizeof(alloc_data), .flags = 0, }; struct vfio_device_attach_iommufd_pt attach_data = { .argsz = sizeof(attach_data), .flags = 0, }; struct iommu_ioas_map map = { .size = sizeof(map), .flags = IOMMU_IOAS_MAP_READABLE | IOMMU_IOAS_MAP_WRITEABLE | IOMMU_IOAS_MAP_FIXED_IOVA, .__reserved = 0, }; struct iommu_ioas_unmap unmap = { .size = sizeof(unmap), }; struct vfio_device_pasid_attach_iommufd_pt pasid = { .argsz = sizeof(pasid), .flags = 0, }; struct vfio_device_pasid_detach_iommufd_pt detach_pasid = { .argsz = sizeof(detach_pasid), .flags = 0, }; /* Open the group */ std::string vfio; if(!para.vfioX.empty()) { vfio = "/dev/vfio/devices/" + para.vfioX; } else { vfio = "/dev/vfio/devices/vfio0"; } cdev_fd = open(vfio.c_str(), O_RDWR); iommufd = open("/dev/iommu", O_RDWR); if (cdev_fd < 0 || iommufd <0) { /* if file not found, it's not an error */ if (errno != ENOENT) { std::cout << "Cannot open "<< iommufd << " or "<< cdev_fd <<" , error is : " << strerror(errno); return -1; } } bind.iommufd = iommufd; if(ioctl(cdev_fd, VFIO_DEVICE_BIND_IOMMUFD, &bind)) { std::cout << "VFIO_DEVICE_BIND_IOMMUFD failed! "<<strerror(errno)<<std::endl; return 1; } if(ioctl(iommufd, IOMMU_IOAS_ALLOC, &alloc_data)) { std::cout << "IOMMU_IOAS_ALLOC failed! "<< strerror(errno) << std::endl ; return 1; } attach_data.pt_id = alloc_data.out_ioas_id; if(ioctl(cdev_fd, VFIO_DEVICE_ATTACH_IOMMUFD_PT, &attach_data)) { std::cout << "VFIO_DEVICE_ATTACH_IOMMUFD_PT failed! "<< std::endl; return 1; } /* Allocate some space and setup a DMA mapping */ map.length = 1024 * 1024; map.iova = 0; /* 1MB starting at 0x0 from device view */ if(para.size) { map.length = para.size; } if(para.iova!= map.iova) { map.iova = para.iova; /* 1MB starting at 0x0 from device view */ } map.user_va = (int64_t)mmap(0, map.length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); map.ioas_id = alloc_data.out_ioas_id; printf("the map va is : %llx,the iova is % llx,the size is %d\n",map.user_va,map.iova,map.length); if(ioctl(iommufd, IOMMU_IOAS_MAP, &map)) { std::cout << "IOMMU_IOAS_MAP failed! "<< std::endl; return 1; } /*attachAssociate a pasid (of a cdev device) with an address space within the bound iommufd*/ pasid.pasid = 0; pasid.pt_id = alloc_data.out_ioas_id; if(ioctl(cdev_fd, VFIO_DEVICE_PASID_ATTACH_IOMMUFD_PT, &pasid)) { std::cout << "VFIO_DEVICE_PASID_ATTACH_IOMMUFD_PT failed! error is "<<strerror(errno)<< std::endl; return 1; } /*attachAssociate a pasid (of a cdev device) with an address space within the bound iommufd*/ pasid.pasid = 1; pasid.pt_id = alloc_data.out_ioas_id; if(ioctl(cdev_fd, VFIO_DEVICE_PASID_ATTACH_IOMMUFD_PT, &pasid)) { std::cout << "VFIO_DEVICE_PASID_ATTACH_IOMMUFD_PT failed! "<< std::endl; return 1; } while(1) { char input[5]; sleep(150); printf("could you want EXIT ?enter [yes|no]? : "); scanf("%s", input); if(!std::strcmp(input, "yes")) { break; } } detach_pasid.pasid = alloc_data.out_ioas_id; if(ioctl(cdev_fd, VFIO_DEVICE_PASID_DETACH_IOMMUFD_PT, &detach_pasid)) { std::cout << "VFIO_DEVICE_PASID_DETACH_IOMMUFD_PT failed! "<< std::endl; return 1; } /*DMA unmapping */ unmap.ioas_id = map.ioas_id; unmap.iova = map.iova; unmap.length = map.length; if(ioctl(iommufd, IOMMU_IOAS_UNMAP, &unmap)) { std::cout << "IOMMU_IOAS_UNMAP failed! "<< std::endl; return 1; } sleep(150); return 0; /* Other device operations as stated in "VFIO Usage Example" */ }