0

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, &reg);
    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

ArcPro
  • 1
  • 1

0 Answers0