I am using the code from the official document, but I can only get null values,and only the mmap return value of the first region is available in 9 regions. I have tried various methods such as memcpy, read, pread, etc., all of which are null values. I hope to be able to read and write all regions.
My code is as follows
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/ioctl.h>
#include<fcntl.h>
#include<linux/vfio.h>
#include<sys/mman.h>
#include<stdint.h>
#include<string.h>
#include<unistd.h>
int main(int argc, char *agrv[]){
int container, group, device, i;
void *region_ptr;
struct vfio_group_status group_status =
{ .argsz = sizeof(group_status) };
struct vfio_iommu_type1_info iommu_info = { .argsz = sizeof(iommu_info) };
struct vfio_iommu_type1_dma_map dma_map = { .argsz = sizeof(dma_map) };
struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
/* Create a new container */
container = open("/dev/vfio/vfio", O_RDWR);
printf("container:%d\n",container);
if (ioctl(container, VFIO_GET_API_VERSION) != VFIO_API_VERSION)
/* Unknown API version */
if(!ioctl(container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU))
printf("iommu ok\n");
/* Doesn't support the IOMMU driver we want. */
/* Open the group */
group = open("/dev/vfio/161", O_RDWR);
if (group < 0) {
perror("Failed to open /dev/vfio/161");
}
printf("group:%d\n",group);
// Test the group is viable and availabl
int ans=ioctl(group, VFIO_GROUP_GET_STATUS, &group_status);
printf("gruop ok?%d\n",ans);
if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE))
printf("group_status.flagsok\n");/* Group is not viable (ie, not all devices bound for vfio) */
/* Add the group to the container */
if(!ioctl(group, VFIO_GROUP_SET_CONTAINER, &container))
printf("gruop to container");
/* Enable the IOMMU model we want */
if(!ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU))
printf("iommu ok\n");
/* Get addition IOMMU info */
if(!ioctl(container, VFIO_IOMMU_GET_INFO, &iommu_info))
printf("get iommuinfo\n");
/* Allocate some space and setup a DMA mapping */
dma_map.vaddr = (__u64)mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
dma_map.size = 1024 * 1024;
dma_map.iova = 0; /* 1MB starting at 0x0 from device view */
dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
if(!ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map))
printf("map ok\n");
/* Get a file descriptor for the device */
device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, "0000:cb:00.0");
/* Test and setup the device */
ioctl(device, VFIO_DEVICE_GET_INFO, &device_info);
printf("flag:%u\n",device_info.flags);
printf("device:%d\n",device);
printf("device_info.num_regions:%d\n",device_info.num_regions);
for (i = 0; i < device_info.num_regions; i++) {
struct vfio_region_info reg = { .argsz = sizeof(reg) };
reg.index = i;
ioctl(device, VFIO_DEVICE_GET_REGION_INFO, ®);
printf("reg.flags:%u\n",reg.flags);
uint32_t *mem;
mem = (uint32_t *)mmap(NULL, reg.size, PROT_READ | PROT_WRITE, MAP_SHARED, device, reg.offset);
printf("reg.size:%lld\n",reg.size);
printf("mem:%p\n",mem);
//msync(region_ptr,reg.size,MS_SYNC);
printf("test end\n");
/* Setup mappings... read/write offsets, mmaps
* For PCI devices, config space is a region */
//munmap(mem,reg.size);
}
/*
for (i = 0; i < device_info.num_irqs; i++) {
struct vfio_irq_info irq = { .argsz = sizeof(irq) };
irq.index = i;
ioctl(device, VFIO_DEVICE_GET_IRQ_INFO, &irq);
Setup IRQs... eventfds, VFIO_DEVICE_SET_IRQS
}
*/
/* Gratuitous device reset and go... */
ioctl(device, VFIO_DEVICE_RESET);
}
The output of this program
container:3
group:4
gruop ok?0
gruop to containeriommu ok
get iommuinfo
map ok
flag:3
device:5
device_info.num_regions:9
reg.flags:15
reg.size:16384
mem:0x7fb35cb47000
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
test end
reg.flags:1
reg.size:65536
mem:0xffffffffffffffff
test end
reg.flags:3
reg.size:4096
mem:0xffffffffffffffff
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
test end
If I join the process of read and write
printf("mem2:%u\n",*(mem));
uint64_t buf = 12345678;
*((uint64_t *)(mem + reg.offset+20))=buf;
uint64_t buf2 = *((uint64_t *)(mem + reg.offset+20));
printf("Ret from read buf = %lu\n",buf2);
The output of new program
container:3
group:4
gruop ok?0
gruop to containeriommu ok
get iommuinfo
map ok
flag:3
device:5
device_info.num_regions:9
reg.flags:15
reg.size:16384
mem:0x7f54d892c000
mem2:67178495
Ret from read buf = 0
test end
reg.flags:0
reg.size:0
mem:0xffffffffffffffff
[1] 50770 segmentation fault (core dumped) ./a.out
I would like to know the reason and the modification method. Thank you very much for your help