首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能在vfio pci设备的文件描述符上使用扩展

不能在vfio pci设备的文件描述符上使用扩展
EN

Stack Overflow用户
提问于 2017-02-15 10:43:55
回答 1查看 738关注 0票数 7

因此,我正在使用qemu一段时间,现在我需要通过PCI设备。我做了所有必要的过程来完成这一工作:启用iommu,module vfio模块,将设备绑定到vfio,检查是否确实创建了vfio组,等等。但是,当我使用任何pci设备启动qemu时,都会得到错误消息:

vfio:读取设备配置空间失败

我深入研究qemu的代码,看看问题可能是什么,并发现问题发生在扩展到设备上。即使偏移量为0时也会发生这种情况,并且对文件描述符执行正常读取没有问题,因为我更改了代码来测试它。因为扩展失败而检查errno会给我一个‘非法查找’错误消息。

我编写了一些代码来查看这种情况是否发生在qemu上下文之外(认为这可能是qemu代码中干扰设备的东西),并且有同样的问题。我还试着读了一个普通的文件,它运行得很好.下面是我为测试它而编写的代码,我对其进行了一些细分,以便指出更相关的部分:

代码语言:javascript
复制
#define BUF_SIZE 4096

int main(){     
    char buf[BUF_SIZE], buf1[BUF_SIZE], buf2[BUF_SIZE];         
    int ret,group_fd, fd, fd2;  
    size_t nbytes = 4096;   
    ssize_t bytes_read;     
    int iommu1, iommu2;

    int container, group, device, i;
    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) };    
    container = open("/dev/vfio/vfio",O_RDWR);        

    if(ioctl(container,VFIO_GET_API_VERSION)!=VFIO_API_VERSION){
        printf("Unknown api version: %m\n");    
    }   
    group_fd = open("/dev/vfio/22",O_RDWR);     printf("Group fd = %d\n", group_fd);
    ioctl(group_fd, VFIO_GROUP_GET_STATUS, &group_status);
    if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)){
        printf("Group not viable\n");
        return 1;
    }   
    ret = ioctl(group_fd, VFIO_GROUP_SET_CONTAINER,&container);     
    ret = ioctl(container,VFIO_SET_IOMMU,VFIO_TYPE1_IOMMU);         
    ioctl(container, VFIO_IOMMU_GET_INFO, &iommu_info);         

    /* Allocate some space and setup a DMA mapping */            
    dma_map.vaddr = (unsigned long int) 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;

    ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);         
    printf("\n\nGETTING DEVICE FD\n");      
    fd = ioctl(group_fd,VFIO_GROUP_GET_DEVICE_FD,"0000:08:00.0");


    printf("Fd = %d\n",fd);     
    printf("VFIO_GROUP_GET_DEV_ID = %lu\n",VFIO_GROUP_GET_DEVICE_FD);   

--这个读取很好,给出了一个n字节的重新编码。

代码语言:javascript
复制
    ret = read(fd,buf,nbytes);  
    if(ret<1){      
       printf("ERROR: %m \n");  
    }

使用ret代码-1和错误的“非法搜索”,此扩展失败。

代码语言:javascript
复制
    ret = pread(fd,buf,nbytes,0);

    if(ret<0){      
       printf("ERROR: %m \n");  
    }   

这里的我尝试在sysfs中的一个公共文件上读取和扩展,以查看扩展是否失败,在本例中,在读取和扩展工作上都很好:

代码语言:javascript
复制
    printf("TESTING PREAD ON A COMMON FILE\n");     

    fd2 = open("/sys/bus/pci/devices/0000:08:00.0/device",O_RDONLY);       
    ret = read(fd2,buf1,nbytes);    
    if(ret<0){
        printf("ERROR: %m\n");  
    }   
    printf("Result from read: ret = %d, content = %s\n",ret,buf1);  
    ret = pread(fd2,buf2,nbytes,2);     
    if(ret<0){
        printf("ERROR: %m\n");  #
    }   
    printf("Result from pread: ret = %d, content = %s\n",ret,buf2);         
    close(fd2);
    getchar();
    close(fd);
    close(container);   
    close(group_fd);    
    return 0; 
}

我正在为嵌入式系统使用用uClibc编译的通用linux内核v4.7.8 .有人知道为什么会发生这种事吗?我现在毫无头绪!!T.T

更新:我在同一台机器上安装了ubuntu16.04(内核v4.4.0),重复了这些步骤,pci通操作也很好,测试代码上的扩展也运行得很好。因此,我不知道定制的通用内核到底出了什么问题。

根据arash的建议,我尝试了扩展(fd、buf、n字节、SEEK_CUR),它给了我同样的“非法搜索”错误。我从The获得的偏移量是0 0xffffffff,无论是在ubuntu还是在通用内核中。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-25 23:05:34

我发现了问题所在,并打算在这里张贴一段时间,供任何可能撞到这堵墙的人使用。结果显示,uClibc版本0.9.33的扩展和pwrite功能中断,导致这些函数无法在大于4G的偏移上工作。下面链接中的补丁为我解决了问题:http://uclibc.10924.n7.nabble.com/backport-pread-pwrite-fix-for-0-9-33-branch-td11921.html

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42247093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档