Speicherabgebildete E/A - Memory-mapped I/O

Memory-mapped I/O ( MMIO ) und Port- mapped I/O ( PMIO ) sind zwei komplementäre Verfahren zum Durchführen von Eingabe/Ausgabe (I/O) zwischen der Zentraleinheit (CPU) und Peripheriegeräten in einem Computer . Ein alternativer Ansatz besteht darin, dedizierte I/O-Prozessoren zu verwenden, die auf Großrechnern allgemein als Kanäle bekannt sind und ihre eigenen Befehle ausführen .

Memory-mapped I/O verwendet denselben Adressraum , um sowohl den Speicher als auch die E/A-Geräte zu adressieren . Der Speicher und die Register der E/A-Geräte werden auf (assoziierte) Adresswerte abgebildet. Eine Speicheradresse kann sich also entweder auf einen Teil des physischen RAM oder stattdessen auf den Speicher des E/A-Geräts beziehen . Somit können die zum Zugriff auf den Speicher verwendeten CPU-Anweisungen auch zum Zugriff auf Geräte verwendet werden. Jedes E/A-Gerät überwacht den Adressbus der CPU und reagiert auf jeden CPU-Zugriff auf eine diesem Gerät zugewiesene Adresse, indem es den Datenbus mit dem Hardwareregister des gewünschten Geräts verbindet . Um die E/A-Geräte unterzubringen, müssen von der CPU verwendete Adressbereiche für E/A reserviert werden und dürfen nicht für den normalen physikalischen Speicher zur Verfügung stehen. Die Reservierung kann dauerhaft oder temporär sein (wie durch Bankwechsel erreicht ). Ein Beispiel für letzteres ist im Commodore 64 zu finden , der eine Form der Speicherzuordnung verwendet, um RAM oder E/A-Hardware im 0xD000-0xDFFFBereich erscheinen zu lassen.

Port-mapped I/O verwendet häufig eine spezielle Klasse von CPU-Befehlen, die speziell für die Durchführung von I/O entwickelt wurden, wie die inund out-Befehle, die auf Mikroprozessoren basierend auf den x86- und x86-64- Architekturen zu finden sind. Verschiedene Formen dieser beiden Befehle können eine Kopie, zwei oder vier Bytes ( outb, , outwund outl, beziehungsweise) zwischen dem EAX - Register oder einer dieses Registers der Unterteilungen auf der CPU und einer spezifizierten I / O - Port, der mit einem E / A - Gerät zugeordnet ist. E/A-Geräte haben einen vom allgemeinen Speicher getrennten Adressraum, der entweder durch einen zusätzlichen "E/A"-Pin an der physischen Schnittstelle der CPU oder einen ganzen Bus für E/A realisiert wird. Da der Adressraum für E/A vom Hauptspeicher isoliert ist, wird dies manchmal als isolierte E/A bezeichnet.

Überblick

Verschiedene CPU-zu-Gerät-Kommunikationsmethoden, wie z. B. die Speicherzuordnung, wirken sich nicht auf den direkten Speicherzugriff (DMA) für ein Gerät aus, da DMA per Definition eine Speicher-zu-Gerät-Kommunikationsmethode ist, die die CPU umgeht.

Hardware- Interrupts sind eine weitere Kommunikationsmethode zwischen CPU und Peripheriegeräten, jedoch werden Interrupts aus verschiedenen Gründen immer separat behandelt. Ein Interrupt ist geräteinitiiert, im Gegensatz zu den oben erwähnten Verfahren, die CPU-initiiert sind. Es ist auch unidirektional, da Informationen nur vom Gerät zur CPU fließen. Schließlich jede Interrupt - Leitung trägt nur ein Bit von Information mit einer festen Bedeutung, nämlich „ein Ereignis , das der Aufmerksamkeit erfordert , in einer Vorrichtung auf dieser Unterbrechungsleitung aufgetreten“.

E/A-Operationen können den Speicherzugriff verlangsamen, wenn die Adress- und Datenbusse gemeinsam genutzt werden. Dies liegt daran, dass das Peripheriegerät normalerweise viel langsamer ist als der Hauptspeicher. In einigen Architekturen arbeitet Port-mapped I/O über einen dedizierten I/O-Bus, wodurch das Problem gemildert wird.

Ein Vorteil von Memory-mapped I/O besteht darin, dass eine CPU durch Weglassen der zusätzlichen Komplexität, die die Port-I/O mit sich bringt, weniger interne Logik erfordert und somit billiger, schneller, einfacher zu bauen ist, weniger Strom verbraucht und physikalisch kleiner sein kann; dies folgt den Grundprinzipien des Rechnens mit reduziertem Befehlssatz und ist auch in eingebetteten Systemen von Vorteil . Der andere Vorteil besteht darin, dass durch die Verwendung regulärer Speicherbefehle zum Adressieren von Geräten alle Adressierungsmodi der CPU sowohl für die E/A als auch für den Speicher verfügbar sind und Befehle, die eine ALU- Operation direkt an einem Speicheroperanden ausführen (Laden eines Operanden von einem Speicherplatz, Speichern des Ergebnisses an einem Speicherplatz oder beides) können auch mit E/A-Geräteregistern verwendet werden. Im Gegensatz dazu sind Port-mapped I/O-Befehle oft sehr begrenzt und bieten oft nur einfache Lade- und Speicheroperationen zwischen CPU-Registern und I/O-Ports, so dass beispielsweise das Hinzufügen einer Konstante zu einem port-mapped Geräteregister würde drei Befehle erfordern: Lesen Sie den Port in ein CPU-Register, fügen Sie die Konstante zum CPU-Register hinzu und schreiben Sie das Ergebnis zurück in den Port.

Da 16-Bit- Prozessoren obsolet geworden sind und im Allgemeinen durch 32-Bit- und 64-Bit - Prozessoren ersetzt wurden, ist es weniger problematisch, Bereiche des Speicheradressraums für I/O zu reservieren, da der Speicheradressraum des Prozessors normalerweise viel größer ist als der erforderliche Platz für alle Speicher- und E/A-Geräte in einem System. Daher ist es immer praktischer geworden, die Vorteile der speicherabgebildeten E/A zu nutzen. Aber auch wenn der Adressraum keine große Bedeutung mehr hat, ist keine der I/O-Zuordnungsmethoden der anderen universell überlegen, und es wird Fälle geben, in denen die Verwendung von Port-zugeordneten I/O immer noch vorzuziehen ist.

Memory-mapped I/O wird in x86- basierten Architekturen bevorzugt, da die Befehle, die port-based I/O ausführen, auf ein Register beschränkt sind: EAX, AX und AL sind die einzigen Register, in die Daten hinein oder aus denen heraus verschoben werden können. und entweder ein direkter Wert in Byte-Größe im Befehl oder ein Wert im Register DX bestimmt, welcher Port der Quell- oder Zielport der Übertragung ist. Da jedes Universalregister Daten an oder von Speicher und speicherabgebildeten E/A-Geräten senden oder empfangen kann, verwendet speicherabgebildete E/A weniger Befehle und kann schneller als Port-E/A ausgeführt werden. AMD hat die Port-I/O-Anweisungen bei der Definition der x86-64- Architektur nicht erweitert , um 64-Bit-Ports zu unterstützen, sodass 64-Bit-Übertragungen nicht mit Port-I/O durchgeführt werden können.

Speicherbarrieren

Da die Caches Zugriffe auf Speicheradressen vermitteln, können Daten, die an verschiedene Adressen geschrieben werden, den Speicher oder die Register der Peripheriegeräte außerhalb der Programmreihenfolge erreichen, dh wenn die Software Daten an eine Adresse schreibt und dann Daten an eine andere Adresse schreibt, wird der Cache- Schreibpuffer nicht garantieren, dass die Daten die Peripheriegeräte in dieser Reihenfolge erreichen. Jedes Programm, das nach jedem Schreibvorgang in der Sequenz keine Cache-Flushing- Befehle enthält, kann unbeabsichtigte E/A-Effekte sehen, wenn ein Cache-System die Schreibreihenfolge optimiert. Schreibvorgänge in den Speicher können oft neu angeordnet werden, um Redundanz zu reduzieren oder Speicherzugriffszyklen besser zu nutzen, ohne den endgültigen Zustand der gespeicherten Informationen zu ändern. wohingegen dieselben Optimierungen die Bedeutung und Wirkung von Schreibvorgängen in speicherabgebildete E/A-Bereiche vollständig ändern können.

Mangelnde Voraussicht bei der Wahl der speicherabgebildeten I/O-Regionen führte zu vielen der RAM-Kapazitätsbarrieren bei älteren Computergenerationen. Entwickler erwarteten selten, dass Maschinen wachsen, um die theoretische RAM-Kapazität einer Architektur voll auszunutzen, und verwendeten daher oft einige der höherwertigen Bits des Adressraums als Selektoren für speicherabgebildete E/A-Funktionen. Die 640-KB-Barriere bei IBM-PCs und Derivaten ist beispielsweise darauf zurückzuführen, dass der Bereich zwischen 640 und 1024 KB (64k-Segmente 10 bis 16) für den oberen Speicherbereich reserviert wird . Diese Wahl hatte zunächst nur geringe Auswirkungen, begrenzte jedoch schließlich den gesamten verfügbaren Arbeitsspeicher innerhalb des verfügbaren 20-Bit-Adressraums. Die 3-GB-Barriere und das PCI-Loch sind ähnliche Manifestationen mit 32-Bit-Adressräumen, die durch Details des X86- Boot-Prozesses und des MMU- Designs verschärft werden . 64-Bit-Architekturen haben technisch oft ähnliche Probleme, aber diese haben nur selten praktische Konsequenzen.

Beispiele

Ein Beispiel für eine Systemspeicherzuordnung
Adressbereich ( hexadezimal ) Größe Gerät
0000–7FFF 32 KiB RAM
8000–80FF 256 Byte Allzweck-E/A
9000–90FF 256 Byte Soundcontroller
A000–A7FF 2 KiB Video-Controller/Text-Mapping-Anzeige-RAM
C000–FFFF 16 KiB Rom

Ein einfaches System, das auf einem 8-Bit- Mikroprozessor aufgebaut ist , kann 16-Bit-Adressleitungen bereitstellen, wodurch es bis zu 64  Kibibyte (KiB) Speicher adressieren kann. Auf einem solchen System können die ersten 32 KiB Adressraum dem Direktzugriffsspeicher (RAM) zugewiesen werden, weitere 16 KiB dem Nur-Lese-Speicher (ROM) und der Rest einer Vielzahl anderer Geräte wie Timer, Zähler, Videoanzeige Chips, Tonerzeugungsgeräte usw.

Die Hardware des Systems ist so ausgelegt, dass Geräte am Adressbus nur auf bestimmte Adressen antworten, die für sie bestimmt sind, während alle anderen Adressen ignoriert werden. Dies ist die Aufgabe des Adressdecodierungsschaltkreises , und das erstellt die Speicherabbildung des Systems. Als Ergebnis kann die Speicherbelegung des Systems wie in der Tabelle rechts aussehen. Diese Memory Map enthält Lücken, was auch in tatsächlichen Systemarchitekturen recht häufig vorkommt.

Unter der Annahme, dass das vierte Register des Videocontrollers die Hintergrundfarbe des Bildschirms einstellt, kann die CPU diese Farbe einstellen, indem sie unter Verwendung ihres Standardspeicherschreibbefehls einen Wert in die Speicherstelle A003 schreibt. Mit der gleichen Methode können Graphen auf einem Bildschirm angezeigt werden, indem Zeichenwerte in einen speziellen RAM-Bereich innerhalb des Videocontrollers geschrieben werden. Vor billigem RAM , das Bitmap-Anzeigen ermöglichte , war diese Zeichenzellenmethode eine beliebte Technik für Computervideoanzeigen (siehe Textbenutzeroberfläche ).

Grundarten der Adressdecodierung

Zu den Adressdecodierungsarten, bei denen ein Gerät Adressen vollständig oder unvollständig decodieren kann, gehören die folgenden:

Vollständige (erschöpfende) Dekodierung
1:1-Abbildung eindeutiger Adressen auf ein Hardware-Register (physikalischer Speicherort). Beinhaltet die Überprüfung jeder Zeile des Adressbusses .
Unvollständige (teilweise) Dekodierung
n:1 Abbildung von n eindeutigen Adressen auf ein Hardwareregister. Eine teilweise Dekodierung ermöglicht, dass eine Speicherstelle mehr als eine Adresse hat, was es dem Programmierer ermöglicht, eine Speicherstelle unter Verwendung von n verschiedenen Adressen zu referenzieren. Es kann auch getan werden, um die Decodierungshardware zu vereinfachen, indem eine einfachere und oft billigere Logik verwendet wird, die nur einige Adressleitungen untersucht, wenn nicht der gesamte Adressraum der CPU benötigt wird. Üblicherweise ist die Dekodierung selbst programmierbar, so dass das System seine eigene Speicherabbildung nach Bedarf rekonfigurieren kann, obwohl dies eine neuere Entwicklung ist und im Allgemeinen im Widerspruch zu der Absicht steht, billiger zu sein.
Synonyme: Foldback, mehrfach zugeordnet, teilweise zugeordnet, Adressaliasing .
Lineare Dekodierung
Adressleitungen werden direkt ohne Decodierlogik verwendet. Dies geschieht mit Geräten wie RAMs und ROMs, die eine Folge von Adresseingängen aufweisen, und mit Peripheriechips, die eine ähnliche Folge von Eingängen zum Adressieren einer Registerbank aufweisen. Die lineare Adressierung wird selten allein verwendet (nur bei wenigen Geräten am Bus, da die rein lineare Adressierung für mehrere Geräte meist viel Adressraum verschwendet), sondern mit einer der anderen Methoden zur Geräteauswahl kombiniert oder Gruppe von Geräten, innerhalb derer die lineare Adressierung ein einzelnes Register oder eine einzelne Speicherstelle auswählt.

Port-I/O über Gerätetreiber

Auf Windows-basierten Computern kann auch über spezielle Treiber wie DOLLx8KD auf den Speicher zugegriffen werden, was auf den meisten Windows-Plattformen von Windows 95 bis Windows 7 E/A-Zugriff in 8-, 16- und 32-Bit ermöglicht. Installation von E/A Port-Treiber stellen den Speicherzugriff sicher, indem sie die Treiber mit einfachen DLL-Aufrufen aktivieren, die Port-I/O ermöglichen. Wenn der Treiber nicht benötigt wird, kann er geschlossen werden, um unbefugten Zugriff auf die I/O-Ports zu verhindern.

Linux stellt das Dienstprogramm pcimem bereit , um das Lesen von und Schreiben von MMIO-Adressen zu ermöglichen. Der Linux-Kernel ermöglicht auch die Verfolgung des MMIO-Zugriffs von Kernelmodulen (Treibern) mithilfe der mmiotrace- Debug - Funktion des Kernels . Um dies zu ermöglichen, sollte der Linux-Kernel mit der entsprechenden aktivierten Option kompiliert werden. mmiotrace wird zum Debuggen von Closed-Source-Gerätetreibern verwendet.

Siehe auch

Verweise