2017-02-15 10 views
7

के लिए फ़ाइल डिस्क्रिप्टर पर प्रीड का उपयोग नहीं कर सकता है इसलिए मैं थोड़ी देर के लिए qemu kvm के साथ काम कर रहा हूं और अब मुझे पीसीआई डिवाइसों को पार करने की आवश्यकता है। मैंने यह काम करने के लिए सभी आवश्यक प्रक्रियाएं की हैं: सक्षम iommu, modprobed vfio मॉड्यूल, vfio को बाध्य डिवाइस और जांच की है कि vfio समूह वास्तव में बनाया गया था, आदि ... लेकिन जब मैं किसी भी पीसीआई डिवाइस के साथ qemu शुरू करता हूं तो मुझे त्रुटि संदेश मिलता है:vfio pci डिवाइस

vfio: डिवाइस config अंतरिक्ष

पढ़ने में असफल रहा qemu के कोड में खुदाई को देखने के लिए क्या समस्या हो सकती है और पता चला कि इस मुद्दे को उपकरण के लिए एक pread पर होता है। ऐसा तब भी होता है जब ऑफसेट 0 होता है, और फाइल डिस्क्रिप्टर पर सामान्य पठन करने से समस्याएं होती हैं, क्योंकि मैंने कोड को परीक्षण करने के लिए बदल दिया है। प्रीड विफलता के कारण इरनो की जांच करने से मुझे 'अवैध संदेश' त्रुटि संदेश मिलता है।

मैंने यह देखने के लिए कुछ कोड लिखा था कि यह क्यूमु संदर्भ के बाहर हो रहा था (माना जाता है कि यह क्यूमु के कोड में कुछ हो सकता है जो डिवाइस के साथ हस्तक्षेप कर रहा था), और एक ही समस्या थी। मैंने प्रीड के साथ एक सामान्य फ़ाइल को पढ़ने की भी कोशिश की और यह पूरी तरह से काम करता है ... यहां कोड का परीक्षण करने के लिए मैंने लिखा है, मैंने इसे और अधिक प्रासंगिक भागों को इंगित करने में सक्षम होने के लिए इसे तोड़ दिया:

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

यह पढ़ने ठीक काम करता है, मुझे nbytes के एक सेवानिवृत्त कोड

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

यह pread सेवानिवृत्त कोड के साथ विफल -1 और errno

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

    if(ret<0){  
     printf("ERROR: %m \n"); 
    } 
0 'अवैध तलाश' देता है

यहाँ मैंने पढ़ा है की कोशिश करता है, तो और pread विफल रहता है sysfs में एक आम फ़ाइल पर 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; 
} 

मैं एक सामान्य लिनक्स कर्नेल उपयोग कर रहा हूँ v4.7.8 एक एम्बेडेड सिस्टम के लिए uClibc के साथ संकलित .... किसी के पास कोई विचार है कि यह क्यों हो रहा है? मैं अभी अनजान हूँ !! टीटी

अद्यतन: मैंने उसी मशीन पर उबंटू 16.04 (कर्नेल v4.4.0) स्थापित किया और चरणों को दोहराया और पीसीआई पासथ्रू ठीक काम करता है और मेरे टेस्ट कोड पर प्रीड भी पूरी तरह से काम करता है। तो मुझे यकीन नहीं है कि कस्टम जेनेरिक कर्नेल के साथ क्या गलत हो रहा है।

अराश सुझाव के अनुसार, मैंने प्रीड (एफडी, बफ, एनबाइट्स, SEEK_CUR) की कोशिश की और यह मुझे वही 'अवैध खोज' त्रुटि दे दी। मैं ftell से प्राप्त ऑफ़सेट 0xffffffff दोनों उबंटू और जेनेरिक कर्नेल में है।

+0

[प्रीड] (https://github.com/lattera/glibc/blob/master/sysdeps/posix/pread.c) में शामिल हैं (1) खोज वर्तमान ऑफ़सेट प्राप्त करने के लिए फ़ाइल की शुरुआत में (और इसे पुराने_ऑफसेट के रूप में सहेजना), (2) अनुरोध ऑफसेट की तलाश है, (3) पढ़ें, (4) आखिर में मूल ऑफसेट (old_offset) पर वापस जाएं।जाहिर है, आप जो देखते हैं वह यह है कि इनमें से कम से कम एक इच्छा अवैध है। मुझे आश्चर्य है कि यह 'pread (fd, buf, nbytes, SEEK_CUR)' काम करता है या 'लंबे int ftell (FILE * stream)' – Arash

+0

से वर्तमान ऑफ़सेट का मान क्या है कृपया अपनी QEMU कमांडलाइन भी पोस्ट करें (विशेष रूप से वह हिस्सा जहां आप कॉन्फ़िगरेशन vfio डिवाइस) – Codeguard

+0

यह qemu कमांड है जिसका उपयोग मैं कर रहा हूं: qemu-system-x86_64 -enable-kvm -m 1024 -device vfio-pci, होस्ट = 01: 00.0 -drive फ़ाइल =/disk0/vdisk.qcow2, id = डिस्क, प्रारूप = qcow2। यह उबंटू में ठीक काम करता है – igalvez

उत्तर

1

मुझे पता चला कि यह समस्या क्या थी और इस दीवार को मारने वाले किसी भी व्यक्ति के लिए यहां थोड़ी देर के लिए इसे पोस्ट करने का अर्थ रहा है। यह पता चलता है कि uClibc संस्करण 0.9.33 के प्रीड और पिरिट फ़ंक्शन टूटे हुए हैं, जिसके परिणामस्वरूप वे कार्य 4 जी से बड़े ऑफसेट पर काम करने में विफल रहे हैं। नीचे दिए गए लिंक से पैच ने मेरे लिए समस्या तय की: http://uclibc.10924.n7.nabble.com/backport-pread-pwrite-fix-for-0-9-33-branch-td11921.html

संबंधित मुद्दे