Ich bin ziemlich verwirrt darüber, wie Linux den gemeinsam genutzten E/A-Speicher verwaltet, um mit Geräten zu kommunizieren, die ihn verwenden.
Wenn ich es richtig verstanden habe, startet der Linux-Kernel mit der Zuordnung bei 0x100000 (um die ersten Megabyte Legacy-RAM-Daten zu vermeiden und sie in zusammenhängenden Speicherorten zu speichern) und dann nach dem Wechsel in den geschützten Modus:
- auf 32-Bit-Systemen gibt es eine Zuordnung wie diese
ZONE_NORMAL sollte unter 896 MB liegen, damit die Zuordnung zwischen den linearen 1 GB des Kernels und den physischen 896 MB immer möglich ist. Lassen Sie uns ZONE_DMA vorerst ignorieren (ich habe gelesen, dass dies nur für ältere Systeme gilt, da PCI jetzt überall im Speicher DMA-Übertragungen verwenden kann).
- Auf 64-Bit-Systemen sollte der lineare Kernel-Adressraum bei PAGE_OFFSET= 0xffff810000000000 beginnen und weiter
In beiden Fällen gilt: Wenn eine Adresse im Kernelbereich größer als PAGE_OFFSET ist, sollte sie auf eine ioremap-Zuordnung verweisen (wird durch Paginierung aufgelöst); wenn sie kleiner als PAGE_OFFSET ist, kann sie mit einem einfachen NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET aufgelöst werden. Ist das richtig?
Bonusfrage: Wenn der Kernel läuft und die Aufräumarbeiten abgeschlossen sind, befindet er sich dann physisch immer noch zwischen 0x100000 und weiter (innerhalb des ersten GB)? Auch auf 64-Bit-Systemen?
Antwort1
Auf PCs werden hardwareseitig zugeordnete IO-Bereiche vom BIOS physischen Speicheradressen zwischen 3 und 4 GiB zugewiesen. Wenn ein Treiber Zugriff auf den Speicher anfordert, ordnet der Kernel ihn irgendwo im virtuellen Adressraum des Kernels zu.
Keine Ihrer beiden anderen Fragen scheint etwas mit Shared Memory zu tun zu haben, aber:
In beiden Fällen gilt: Wenn eine Adresse im Kernelbereich größer als PAGE_OFFSET ist, sollte sie auf eine ioremap-Zuordnung verweisen (wird durch Paginierung aufgelöst); wenn sie kleiner als PAGE_OFFSET ist, kann sie mit einem einfachen NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET aufgelöst werden. Ist das richtig?
Mental, ja. Die Hardware verwendet in beiden Fällen die Seitentabellen.
Antwort2
Ich denke, Ihre Frage sieht so aus: Wie funktioniert ioremap?
vaddr = ioremap(paddr_io_mapped_device, Größe);
vaddr ist die zurückgegebene virtuelle Adresse im Kernel-Speicher. Der Kernel erstellt die Seitentabelleneinträge für den virtuellen Adressbereich (vaddr, size) und ordnet sie der physischen Adresse paddr_io_shared_device zu. Wenn Sie also auf den virtuellen Adressbereich zugreifen, ist dies genauso gut, als würden Sie auf die physische Adresse innerhalb des io_mapped-Geräts zugreifen.
Wichtig ist, dass die zurückgegebene V-Adressenicht zwischenspeicherbar. Jedes Mal, wenn Sie den Adressbereich lesen/schreiben, wird er vom io_mapped-Gerät gelesen/geschrieben und nicht vom Cache.