2014-04-23 9 views
9

Ich habe ein PCIe-Gerät mit einem Userspace-Treiber. Ich schreibe Befehle über eine BAR an das Gerät, die Befehle sind latenzempfindlich und die Datenmenge ist klein (~ 64 Bytes), daher möchte ich DMA nicht verwenden.Aktivieren Schreib-Kombinieren IO-Zugriff in Benutzerbereich

Wenn ich die physikalische Adresse des BAR im Kernel unter Verwendung ioremap_wc und dann schreibe 64-Bytes an die BAR innerhalb des Kernels neu zuordnen, kann ich sehen, daß das 64-Bytes als eine einzige TLP über PCIe geschrieben werden. Wenn ich mein Userspace-Programm auf mmap die Region mit dem MAP_SHARED-Flag und dann 64-Byte schreibe, sehe ich mehrere TPLs auf dem PCIe-Bus statt einer einzelnen Transaktion.

Nach dem Kernel PAT documentation Ich sollte Zuschreibung kombinierenden Seiten bis hin zu User-Space exportieren können: einige Seiten wollen

Treiber exportieren, um den Userspace tun durch mmap -Schnittstelle und eine Kombination aus

1) pgprot_noncached()

2) io_remap_pfn_range() oder remap_pfn_range() oder vm_insert_pfn()

Mit PAT-Unterstützung wird eine neue API pgprot_writecombine hinzugefügt. So können Treiber weiterhin die obige Sequenz verwenden, mit beiden pgprot_noncached() oder pgprot_writecombine() in Schritt 1, gefolgt von Schritt 2.

Auf der Grundlage dieser Dokumentation, die entsprechenden Kernel-Code von meinem mmap-Handler wie folgt aussieht :

vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 

return io_remap_pfn_range(vma, 
          vma->vm_start, 
          info->mem[vma->vm_pgoff].addr >> PAGE_SHIFT, 
          vma->vm_end - vma->vm_start, 
          vma->vm_page_prot); 

Mein PCIe-Gerät zeigt in lspci up mit den Stäben als prefetchable wie erwartet markiert:

Latency: 0, Cache Line Size: 64 bytes 
    Interrupt: pin A routed to IRQ 11 
    Region 0: Memory at d8000000 (64-bit, prefetchable) [size=32M] 
    Region 2: Memory at d4000000 (64-bit, prefetchable) [size=64M] 

Als ich mmap von Anwenderseite aufrufen sehe ich eine Log-Meldung (debugpat Kernel-Boot-Parameter eingestellt haben):

reserve_memtype hat [mem 0xd4000000-0xd7ffffff], Track Write-Combining, erf Write-Combining aD write-combining

ich auch in /sys/kernel/debug/x86/pat_memtype_list, dass ein PAT Eintrag korrekt aussieht und es gibt keine überlappenden Bereiche sehen:

write-combining @ 0xd4000000-0xd8000000 
uncached-minus @ 0xd8000000-0xda000000 

Ich habe auch überprüft, dass es keine MTRR-Einträge gibt, die mit der PAT-Konfiguration in Konflikt kämen. Soweit ich sehen kann, ist alles korrekt eingerichtet, damit das Write-Combining im Userspace abläuft. Unter Verwendung eines PCIe-Analyzers zur Beobachtung der Transaktionen auf dem PCIe-Bus unterscheidet sich das Userspace-Zugriffsmuster jedoch vollständig vom gleichen vom Kernel ausgeführten Schreiben nach einem ioremap_wc Anruf.

Warum funktioniert Write-Combining nicht wie erwartet vom Benutzerbereich?

Was kann ich tun, um weiter zu debuggen?

Ich bin derzeit auf einem einzigen Sockel 6-Core i7-3930K läuft.

+0

Was die User-Space für den Bereich sichtbaren Adresse ist? Vielleicht ist es nicht richtig ausgerichtet? – wallyk

+0

@wallyk Guter Vorschlag, aber die sichtbare Adresse des Userspace sieht aus, als wäre sie ausgerichtet. – Chiggs

Antwort

1

Ich weiß nicht, ob dies helfen wird, aber das ist, wie ich Schreib-Kombination arbeiten auf PCIe. Zugegeben, es war im Kernel-Bereich, aber das entspricht der Intel-Dokumentation. Es ist einen Versuch wert, wenn Sie stecken bleiben.

global definiert:

unsigned int __attribute__ ((aligned(0x20))) srcArr[ARR_SIZE]; 

In Ihrer Funktion:

int *pDestAddr 

for (i = 0; i < ARR_SIZE; i++) { 
    _mm_stream_si32(pDestAddr + i, pSrcAddr[i]); 
} 
+0

Danke für die Antwort, aber das gibt das gleiche Muster von TLPs: Kernel Space ein einzelnes 64-Byte-TLP, Userspace einen Strom von einzelnen TLPs. – Chiggs