2017-02-15 13 views
7

그래서 qemu kvm을 사용하고 있습니다. 이제는 PCI 장치를 통과해야합니다. 나는이 작업을하기 위해 필요한 모든 절차를 수행했다. iommu, modprobed vfio 모듈, vfio에 바인드 된 장치를 확인하고 vfio 그룹이 실제로 생성되었는지 확인했다. 그러나 어떤 pci 장치로도 qemu를 시작할 때 오류 메시지가 나타납니다.vfio pci 장치의 파일 설명자에서 프리드 (pread)를 사용할 수 없습니다.

vfio : 장치 설정 공간

을 읽지 못했습니다 나는 문제가 될 일을보고 QEMU의 코드에 발굴하고 문제가 장치에 pread에 발생하는 것을 발견했다. 오프셋이 0 일 때도이 문제가 발생하고 파일 설명자를 정상적으로 읽는 것이 문제없이 작동합니다. 코드를 변경하여 테스트합니다. 오류가 발생하여 errno를 확인하면 'Illegal seek'오류 메시지가 표시됩니다.

나는이 문제가 qemu 컨텍스트 (장치를 간섭하는 qemu의 코드에있을 수 있다고 생각하는) 외부에서 발생했는지 확인하기 위해 몇 가지 코드를 작성했으며 동일한 문제가있었습니다.

#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); 
: 나는 또한 pread와 일반 파일을 읽기를 시도하고 내가 그것을 테스트하기 위해 작성한 코드를 완벽하게 ... 여기 작동, 나는 더 많은 관련 부분을 지적 할 수 있도록 조금을 무너 뜨

이 읽기가 잘 작동 는 나에게 RET의

ret = read(fd,buf,nbytes); 
    if(ret<1){  
     printf("ERROR: %m \n"); 
    } 

이 pread는 RET 코드와 함께 실패 nbytes의 코드 -1 errno는이

ret = pread(fd,buf,nbytes,0); 

    if(ret<0){  
     printf("ERROR: %m \n"); 
    } 
0 '불법 추구를'제공 여기

나는 읽기 시도와 sysfs에있는 일반적인 파일에 pread는 pread이 실패 할 경우보고, 모두이 경우에 잘 pread 작업을 읽고에 할 : 나는 일반적인 리눅스 커널을 사용하고

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로 컴파일 된 v4.7.8 .... 왜 이런 일이 일어날 지에 대한 아이디어가 있습니까? 나는 지금 우둔 해! T.

업데이트 : 동일한 컴퓨터에 우분투 16.04 (kernel v4.4.0)를 설치하고 단계를 반복하면 pci 패스 스루가 잘 작동하고 테스트 코드의 프리드도 완벽하게 작동합니다. 따라서 커스텀 제네릭 커널에 어떤 문제가 있는지 잘 모르겠습니다.

아싸 쉬 제안에 따라 예고편 (fd, buf, nbytes, SEEK_CUR)을 시도해 보았고 동일한 '잘못된 탐색'오류가 발생했습니다. ftell에서 얻은 오프셋은 우분투와 일반 커널 모두에서 0xffffffff입니다.

+0

[pread] (https://github.com/lattera/glibc/blob/master/sysdeps/posix/pread.c)에는 (1) seek (2) 요청 오프셋에 대한 탐색, (3) 읽기, (4) 마침내 원래 오프셋 (old_offset)으로 되돌아 간다.외관상으로는, 당신이 보는 무엇을이 탐구의 적어도 한개가 불법이다이다. 나는 이것이'pread (fd, buf, nbytes, SEEK_CUR)'또는'long int ftell (FILE * stream) '의 현재 오프셋의 값인 지 궁금합니다. – Arash

+0

QEMU 명령 행을 게시하십시오. config vfio devices) – Codeguard

+0

qemu-system-x86_64 -enable-kvm -m 1024 -device vfio-pci, host = 01 : 00.0 -drive file =/disk0/vdisk.qcow2, id = 디스크, 형식 = qcow2. 이것은 우분투에서 잘 작동합니다. – igalvez

답변