___ qstnhdr ___ Wie ordne ich einen DMA-Puffer, der von 1GB HugePages unterstützt wird, in einem Linux-Kernelmodul zu?
___ answer19697182 ___
Dies wird normalerweise nicht im Kernelraum gemacht, also nicht zu viele Beispiele.
Wie bei jeder anderen Seite werden riesige Seiten mit alloc_pages zur Melodie zugeordnet:
%Vor%
HPAGE_PMD_ORDER ist ein Makro, das die Reihenfolge einer einzelnen großen Seite in Bezug auf normale Seiten definiert. Das bedeutet, dass transparente große Seiten im Kernel aktiviert sind.
Dann können Sie den erhaltenen Seitenzeiger wie gewohnt mit kmap () abbilden.
Disclaimer: Ich habe es nie selbst versucht, also müssen Sie vielleicht etwas experimentieren. Eine Sache, auf die Sie achten sollten, ist folgende: HPAGE_PMD_SHIFT repräsentiert eine Reihenfolge einer kleineren "großen" Seite. Wenn Sie diese riesigen 1GB-Seiten verwenden möchten, müssen Sie wahrscheinlich eine andere Reihenfolge versuchen, wahrscheinlich PUD_SHIFT - PAGE_SHIFT.
___ tag123linuxkernel ___ Dieses Tag ist für Fragen zu den Interna des Linux-Kernels selbst gedacht - insbesondere zum Schreiben von Code, der im Kontext des Kernels läuft (wie Kernel-Module oder Treiber).
Fragen zum Schreiben von Userspace-Code in Linux sollten stattdessen mit [linux] getaggt werden.
Da sich die Interna des Linux-Kernels ständig ändern, ist es hilfreich, genau die Kernel-Version (en) anzugeben, an denen Sie interessiert sind.
___ tag123linux ___ LINUX FRAGEN MÜSSEN PROGRAMMIEREN VERWANDT SEIN. Verwenden Sie dieses Tag nur, wenn sich Ihre Frage auf das Programmieren mit Linux-APIs oder das Linux-spezifische Verhalten bezieht, nicht nur, weil Sie Ihren Code unter Linux ausführen. Wenn Sie Linux-Unterstützung benötigen, können Sie https://unix.stackexchange.com oder https://askubuntu.com ausprobieren
___ qstntxt ___
Ich versuche, einen DMA-Puffer für eine HPC-Arbeitslast zuzuordnen. Es benötigt 64 GB Pufferspeicher. Zwischen der Berechnung werden einige Daten auf eine PCIe-Karte ausgelagert. Anstatt Daten in eine Reihe von dinky 4MB Puffern zu kopieren, die von pci_alloc_consistent vergeben werden, möchte ich nur 64 1GB Puffer erstellen, die von 1GB HugePages unterstützt werden.
Einige Hintergrundinformationen:
Kernel-Version: CentOS 6.4 / 2.6.32-358.el6.x86_64
Kernel-Boot-Optionen: hugepagesz = 1g hugepages = 64 default_hugepagesz = 1g
relevanter Teil von / proc / meminfo:
AnonHugeSeiten: 0 kB
HugePages_Total: 64
HugePages_Free: 64
HugePages_Rsvd: 0
HugePages_Surp: 0
Riesenseitengröße: 1048576 kB
DirectMap4k: 848 kB
DirectMap2M: 2062336 kB
DirectMap1G: 132120576 kB
Ich kann -t hugetlbfs nodev / mnt / hugepages montieren. CONFIG_HUGETLB_PAGE ist wahr. MAP_HUGETLB ist definiert.
Ich habe einige Informationen über die Verwendung von libhugetlbfs gelesen, um get_huge_pages () im Userspace aufzurufen, aber idealerweise würde dieser Puffer im Kernelraum zugewiesen werden. Ich habe versucht, do_mmap () mit MAP_HUGETLB aufzurufen, aber es schien nicht die Anzahl der freien hugepages zu ändern, also glaube ich nicht, dass es tatsächlich die mmap mit riesigen Seiten unterstützt.
Ich schätze, worauf ich hinaus will, gibt es any Weise, wie ich einen Puffer zu einer 1GB HugePage im Kernel-Space zuordnen kann, oder muss es im Userspace gemacht werden? Oder wenn jemand eine andere Möglichkeit kennt, kann ich einen riesigen (1 - 64 GB) zusammenhängenden physischen Speicher als Kernel-Puffer zur Verfügung stellen?
___ answer44756753 ___
PROBLEM
- Normalerweise, wenn Sie einen DMA-Puffer reservieren oder eine physikalische Adresse erhalten wollen, geschieht dies im Kernel-Bereich, da der Benutzercode niemals mit physischen Adressen herumhacken sollte.
- Hugetlbfs stellt nur User-Space-Mappings zur Verfügung, um 1 GB große Seiten zuzuordnen und virtuelle User-Space-Adressen zu erhalten
- Es existiert keine Funktion zum Zuordnen einer virtuellen Adresse einer virtuellen rightpage zu einer physischen Adresse
EUREKA
Aber die Funktion existiert! Burried tief im 2.6 Kernel-Quellcode liegt diese Funktion vor, um eine Strukturseite von einer virtuellen Adresse zu erhalten, die als "nur zum Testen" markiert und mit #if 0:
blockiert ist
%Vor%
LÖSUNG:
Da die obige Funktion nicht tatsächlich in den Kernel kompiliert wird, müssen Sie sie zu Ihrer Treiberquelle hinzufügen.
BENUTZER-SEITEN-WORKFLOW
- Ordnen Sie 1gb rigipages beim Booten mit Kernel-Boot-Optionen zu
- Rufen Sie get_huge_pages () mit hugetlbfs auf, um den User Space Pointer (virtuelle Adresse)
zu erhalten
- Übergeben Sie die virtuelle Benutzeradresse (normaler Pointer an unsigned long) an den Treiber ioctl
KERN-TREIBER-WORKFLOW
- Übernehmen Sie die virtuelle Benutzeradresse über ioctl
- Rufen Sie follow_huge_addr auf, um die Strukturseite *
zu erhalten
- Rufen Sie page_to_phys auf der Strukturseite * auf, um die physische Adresse
zu erhalten
- Geben Sie die physische Adresse für das Gerät für DMA
an
- Rufen Sie kmap auf der Strukturseite * auf, wenn Sie auch einen virtuellen Kernel-Zeiger
möchten
DISCLAIMER
- Die obigen Schritte werden einige Jahre später wiederholt. Ich habe den Zugriff auf den ursprünglichen Quellcode verloren. Tu deine Due Diligence und stelle sicher, dass ich keinen Schritt vergesse.
- Der einzige Grund dafür ist, dass 1 GB große Seiten beim Booten zugewiesen werden und ihre physischen Adressen permanent gesperrt sind. Versuchen Sie nicht, eine virtuelle Adresse, die nicht von 1GBhugepage gesichert wurde, einer physischen DMA-Adresse zuzuordnen! Du wirst eine schlimme Zeit haben!
- Testen Sie sorgfältig auf Ihrem System, um zu bestätigen, dass Ihre 1 GB großen Seiten tatsächlich im physischen Speicher gespeichert sind und alles genau funktioniert. Dieser Code funktionierte einwandfrei auf meinem Setup, aber hier besteht große Gefahr, wenn etwas schief geht.
- Dieser Code wird nur für die x86 / x64-Architektur (physische Adresse == Busadresse) und für die Kernel-Version 2.6.XX verwendet. Es kann einen leichteren Weg geben, dies bei späteren Kernel-Versionen zu tun, oder es kann jetzt völlig unmöglich sein.
___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt.
___ tag123dma ___ Direkter Speicherzugriff (Direct Memory Access, DMA) ist eine Eigenschaft moderner Computer und Mikroprozessoren, die es bestimmten Hardware-Untersystemen innerhalb des Computers ermöglicht, unabhängig von der Zentraleinheit auf den Systemspeicher zum Lesen und / oder Schreiben zuzugreifen.
___ tag123hugpages ___ Hugepages ist ein Mechanismus, der es dem Linux-Kernel ermöglicht, die mehrseitigen Seitengrößen moderner Hardwarearchitekturen zu nutzen.
___