代码之家  ›  专栏  ›  技术社区  ›  ArcPro

如何使用vfio读写SSD

  •  0
  • ArcPro  · 技术社区  · 3 年前

    我使用的是官方文档中的代码,但我只能获得null值,并且在9个区域中只有第一个区域的mmap返回值可用。 我尝试过各种方法,如memcpy、read、spread等,它们都是空值。我希望能够阅读和写作所有地区。

    我的代码如下

    #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);
    }
    

    此程序的输出

    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
    
    

    如果我加入读写的过程

    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);
    

    新程序的输出

    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
    
    

    我想知道原因和修改方法。非常感谢你的帮助

    0 回复  |  直到 3 年前
    推荐文章