2017-02-15 2 views
7

So arbeite ich mit qemu kvm für eine Weile und jetzt muss ich PCI-Geräte durchreichen. Ich habe alle erforderlichen Verfahren durchgeführt, um dies zu erreichen: aktiviert iommu, modprobed vfio-Modul, binded Gerät zu vfio und überprüft, dass vfio Gruppe tatsächlich erstellt wurde, etc ... Aber wenn ich qemu mit irgendwelchen PCI-Geräten starte ich bekomme die Fehlermeldung:Pread kann nicht für einen Dateideskriptor für ein vfio pci-Gerät verwendet werden

VFIO: Fehler beim Gerätekonfiguration Raum

ich grabe in qemu den Code zu sehen, was das Problem sein könnte und fand heraus, dass das Problem tritt auf einem pread auf dem Gerät zu lesen. Dies geschieht sogar, wenn der Offset 0 ist, und das normale Lesen des Dateideskriptors funktioniert ohne Probleme, da ich den Code geändert habe, um ihn zu testen. Überprüfen Errno wegen der Pread Fehler gibt mir eine 'Illegal suchen' Fehlermeldung.

Ich schrieb einen Code, um zu sehen, ob dies außerhalb des Qemu-Kontextes passierte (dachte, es könnte etwas in qemus Code sein, das das Gerät störte) und hatte das gleiche Problem. Ich habe auch versucht, eine normale Datei mit pread zu lesen und das funktioniert perfekt ... Hier ist den Code, den ich um es zu testen schrieb, brach ich es ein wenig nach unten, die relevanten Teile hinweisen zu können:

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

Diese Lese gut funktioniert, gibt mir einen ret Code von nBytes

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

Dieser pread mit ret Code nicht -1 und errno

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

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

Hier versuche ich lesen und pread auf einer gemeinsame Datei in sysfs zu sehen, ob pread ausfällt, und auf Lese- und pread gut funktioniert in diesem Fall:

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

mir einen generischen Linux-Kernel v4.7.8 kompiliert mit uClibc für ein eingebettetes System .... Hat jemand irgendwelche Ideen, warum dies passieren könnte? Ich bin gerade jetzt ahnungslos !! T.

UPDATE: Ich installierte Ubuntu 16.04 (Kernel v4.4.0) auf der gleichen Maschine und wiederholte die Schritte und PCI-Passthrough funktioniert gut und die Pread auf meinem Test-Code funktioniert auch perfekt. Ich bin also nicht sicher, was mit dem benutzerdefinierten generischen Kernel falsch läuft.

Wie pro Arash Vorschlag, versuchte ich pread (fd, buf, nbytes, SEEK_CUR) und es gab mir die gleiche 'illegale Suche' Fehler. Der Offset, den ich von ftell bekomme, ist 0xffffffff sowohl in ubuntu als auch im generischen Kernel.

+0

[pread] (https://github.com/lattera/glibc/blob/master/sysdeps/posix/pread.c) enthält (1) suchen an den Anfang der Datei, um den aktuellen Offset zu erhalten (und speichert ihn als old_offset), (2) eine Suche nach dem Anforderungsoffset, (3) Lesen, (4) schließlich zurück zum ursprünglichen Offset (old_offset) suchen.Anscheinend sehen Sie, dass mindestens einer dieser Suchanfragen illegal ist. Ich frage mich, ob das funktioniert 'pread (fd, buf, nbytes, SEEK_CUR)' oder was ist der Wert des aktuellen Offset von 'long int ftell (FILE * stream)' – Arash

+0

Bitte posten Sie auch Ihre QEMU-Kommandozeile (besonders den Teil, wo Sie config vfio devices) – Codeguard

+0

Dies ist der qemu Befehl, den ich benutze: qemu-system-x86_64 -enable-kvm -m 1024 -device vfio-pci, host = 01: 00.0 -drive datei =/disk0/vdisk.qcow2, id = Festplatte, Format = qcow2. Dies funktioniert gut in Ubuntu – igalvez

Antwort

1

Ich fand, was das Problem war und habe es vorgehabt, es hier für eine Weile für jeden zu veröffentlichen, der diese Wand schlagen könnte. Es stellt sich heraus, dass die pread- und pwrite-Funktionen der uClibc-Version 0.9.33 unterbrochen sind, was dazu führt, dass diese Funktionen bei Offsets, die größer als 4G sind, nicht funktionieren. Die Patches aus dem Link unten behoben das Problem für mich: http://uclibc.10924.n7.nabble.com/backport-pread-pwrite-fix-for-0-9-33-branch-td11921.html

Verwandte Themen