Protected Mode
# Protected Mode

Der Begriff Protected Mode (englisch; deutsch: geschützter Modus oder Schutzmodus) bezeichnet einen Betriebsmodus von x86-Prozessoren, der seit dem 80286er-Prozessor von Intel vorhanden ist. Er erlaubt die Begrenzung von Speicherzugriffsrechten für verschiedene Software, außerdem erhöhte sich mit ihm der direkt zugreifbare Speicher auf 16 MiB Hauptspeicher (16-Bit-Protected-Mode des 80286). Mit dem 80386er und dessen 32-Bit-Protected-Mode wurde der lineare Zugriff auf bis zu 4 GiB Hauptspeicher möglich. Der Protected Mode wird von allen weiterentwickelten 16-Bit- und 32-Bit-PC-Betriebssystemen genutzt.

## Hintergründe und Idee

Ursprünglich existierte nur der retronym ab dem 80286 so bezeichnete Real Mode der 8086-Prozessoren, dem Begründer der x86-Architektur, der aus Kompatibilitätsgründen immer noch bei 32-Bit- und 64-Bit-x86-Prozessoren der Startmodus ist, so dass ältere Software wie etwa das auf IBM-PC-kompatiblen Computern bis in die 1990er Jahre am weitesten verbreitete Betriebssystem DOS lauffähig ist. In diesem Modus gab es keine Speicherschutzmechanismen oder Policies, das Betriebssystem und auch jedes einzelne Programm konnte jederzeit sowohl lesend auch schreibend auf jede Speicheradresse zugreifen. Dies bedeutet die unrealistische Anforderung der völligen Fehlerfreiheit an Software, da schon ein einziger fehlerhafter Zugriff auf eine Adresse einer anderen Software (z. B. des Betriebssystems) zu Datenverlust oder Instabilität des gesamten Systems führen kann.
Bei der Weiterentwicklung der x86-Architektur hat Intel daher Mechanismen eingeführt, mit denen die Zugriffsrechte von Programmen auf verschiedene Speicherbereiche feingranularer einstellbar sind, was Speicherschutz zwischen verschiedener Software ermöglicht und die ursprüngliche Situation im Real Mode entschärft. Der Prozessor muss dazu allerdings in den Protected Mode versetzt werden, mit dem bestehende Software – allen voran MS-DOS und PC DOS der mit dem IBM PC begründeten Plattform – nicht mehr kompatibel war. Ab dem 80386 wurde mit dem Virtual 8086 Mode ein Kompatibilitätsmodus integriert, der die Ausführung von 16-Bit-Software im 32-Bit-Protected-Mode ermöglicht.

## Konzept und Charakteristika

Im Protected Mode unterstützt der Prozessor sowohl Segmentierung (ab dem 80286) als auch Paging (ab dem 80386). Aus Kompatibilitätsgründen entschied sich Intel für die virtuelle Speicherverwaltung als Methode, da hier jedem Programm durch die Speicherverwaltungseinheit, kurz „MMU“ für englisch Memory Management Unit, weiterhin ein vollständiger Adressraum wie im Real Mode vorgegaukelt werden kann. Jedes Programm wird in seiner eigenen, von anderer Software abgeschotteten Kopie des physischen Adressraums ausgeführt. Betriebssystembereiche (typischerweise im oberen Bereich des Adressraums 2 bis 4 GiB) können mit einer höheren Befugnisstufe ausgestattet sein (englisch „privilege level“).
Der namensgebenden Speicherschutz des Protected Mode ist auf vier verschiedene Schutzebenen auf Segmentebene und zwei Schutzebenen auf Page-Ebene aufgebaut. Die vier verschiedenen im x86-Schutzmodus existierenden und als Ringe oder „Domain“ bezeichneten Schutzebenen bzw. Befugnisstufen gewähren den darauf ablaufenden Codesegmenten unterschiedliche Rechte. Dies ermöglicht unter anderem die Unterscheidung zwischen Kernel-Modus (Ring 0) und Benutzer-Modus (Ring 3), welche in modernen Betriebssystemen umgesetzt ist. Dadurch wird verhindert, dass fehlerhafte oder böswillige Anwendungsprogramme das Betriebssystem überschreiben und somit verändern oder zum Absturz bringen können oder Daten anderer Programme ausspähen können, was auf dem 8086er-Prozessor noch ohne weiteres möglich war und nicht verhindert werden konnte.
Ein x86-Prozessor schaltet in den Protected Mode um, indem das PE-Bit, für englisch Protection Enable, im Control Register 0 (CR0) gesetzt wird.
Ebenfalls aus Kompatibilitätsgründen integrierte Intel im 32-Bit-Protected-Mode ab dem 80386 einen Sondermodus, den Virtual 8086 Mode (auch „Virtual Real Mode“ genannt), der die Ausführung von existierenden Real-Mode-Programmen im Protected Mode ermöglicht.

### 16-Bit Protected Mode

Der ursprüngliche Protected Mode wurde mit dem 80286 von Intel eingeführt und ist wie dieser ein reiner 16-Bit-Modus. Dieser wird daher retronym meist mit „16-Bit Protected Mode“ bezeichnet. Damit konnten maximal 16 MB physischer Hauptspeicher über 2 Tabellen mit jeweils 8.192 Segmenten zu je maximal 64 KB angesprochen werden. Damit steht ein theoretischer Speicherraum von 1 GB zur Verfügung. Der Zugriff auf diese Segmente erfolgt über sogenannte Segmentdeskriptortabellen, welche vom Betriebssystem angelegt und verwaltet werden. Es ist möglich, mehr virtuelle Adressen anzusprechen, als physischer Arbeitsspeicher vorhanden ist. Über eine virtuelle Speicherverwaltung können einzelne Segmente beispielsweise auf Festplatte ausgelagert werden und anschließend in der Deskriptortabelle als „nicht vorhanden“ gekennzeichnet werden. Sobald ein Lese- oder Schreibzugriff auf so ein Segment erfolgt, löst der Prozessor eine „Segment not present“-Ausnahme aus, die vom Betriebssystem abgefangen wird, um das angeforderte Segment wieder zu laden und das Programm fortzusetzen.
Der 16-Bit-Protected-Mode wurde unter anderem von Concurrent DOS 286 (1985), FlexOS 286 (1986/1987), IBM 4680 OS (1986), OS/2 1.x (1987) und Windows 3.x im „Standardmodus“ verwendet. Auf 32- und 64-Bit-Systemen hat der ursprüngliche Protected Mode keine Bedeutung mehr.

#### Deskriptortabellen

Es existieren drei Arten von Deskriptortabellen:
* Global descriptor table (GDT) – diese ist für alle Tasks identisch
* Local descriptor table (LDT) – jeder Task kann eine eigene LDT besitzen
* Interrupt descriptor table (IDT) – wird beim Anspringen von Interrupt Service Routinen verwendet.
Die Deskriptortabellen liegen im Hauptspeicher und werden vom Betriebssystem verwaltet. In speziellen Registern wird ihre jeweilige (Basis-)Adresse gespeichert:
* GDTR – speichert die physische Basisadresse der GDT (24 Bits)
* IDTR – speichert die physische Basisadresse der IDT (24 Bits)
* LDTR – ist ein (16-Bit-)Segmentselektor für das Segment, in dem die LDT liegt.
Jede Deskriptortabelle enthält maximal 8.192 Einträge, sogenannte Segmentdeskriptoren. Jeder Segmentdeskriptor beschreibt ein Speichersegment und enthält dafür folgende Felder:
* die Segmentlänge (segment limit – 1 Byte bis 64 KiB)
* die Startadresse (base address – auf 1 Byte genau)
* Segmenttyp (type und S: S=0 bedeutet Systemsegment, S=1 bedeutet Benutzersegment)
* Descriptor Privilege level (dpl, wobei der Wert 0 die Stufe mit den höchsten Rechten, 3 die Stufe mit den niedrigsten Rechten bedeutet)
* Present – Nur Segmente, deren P-Bit im Deskriptor auf 1 gesetzt ist, sind im physischen Hauptspeicher vorhanden. Dies kann zum Auslagern von Speichersegmenten („Swapping“) genutzt werden, da bei Zugriff auf Segmenten mit P-Bit = 0 vom Prozessor eine Ausnahme ausgelöst wird, die vom Betriebssystem abgefangen werden kann.
Der erste Eintrag (mit Index 0) der GDT ist als Nullselektor reserviert und darf auf keinen Speicherbereich verweisen.

#### Segmentselektoren

Im Real Mode enthalten die Segmentregister direkt die Startadresse des Speichersegments (genauer: die obersten 16 Bits der 20-Bit-Real-Mode-Speicheradresse). Im Protected Mode dagegen enthalten die Segmentregister einen Verweis auf eine der beiden Deskriptortabellen (GDT oder LDT), in denen die Eigenschaften der Speichersegmente festgehalten sind.
Die Segmentselektoren sind 16 Bits groß und haben den nebenstehenden Aufbau: Das Bit 2 (TI=table indicator) legt fest, auf welche der beiden Tabellen sich der Index (in den Bits 3…15) bezieht.

### 32-Bit Protected Mode

Mit dem 80386 wurde der Protected Mode von Intel auf 32 Bits erweitert, der über bisher ungenutzte Felder in den Deskriptortabellen den Zugriff auf bis zu 4 GiB physischer Hauptspeicher in 8.192 Segmenten zu je maximal 4 GiB ermöglicht. Durch Erweiterung der Paging-Einheit, bezeichnet mit englisch Physical Address Extension oder kurz „PAE“, ist der maximal nutzbare Hauptspeicher im 32-Bit-Modus sogar bis theoretisch 4.096 TiB erweiterbar.
32-Bit-Software für die x86-Architektur IA-32 ist immer für den Protected Mode des „i386“ oder neuer geschrieben, da es keinen anderen 32-Bit-Modus gibt.
Im Vergleich zum ursprünglichen 16-Bit-Protected-Mode weist der 32-Bit-Protected-Mode folgende Erweiterungen auf:
* Segmentlimit – Es wurde auf 20 Bits erweitert, so dass ein Segment bis zu 1 MiB groß sein kann. Um größere Segmente zu unterstützen, ohne das Längenfeld noch größer zu machen, wurde ein zusätzliches „Granularitätsbit“ (G) eingeführt. Ist dieses Bit gesetzt, wird die Segmentlänge nicht mehr in Bytes, sondern in 4-KiB-Blöcken interpretiert. Damit sind Segmentgrößen bis 4 GiB möglich.
* Startadresse – Sie wurde auf 32 Bits erweitert, so dass die Startadresse den gesamten physischen Adressraum abbilden kann.
* Operandengröße – Dieses Bit legt fest, ob ein Codesegment 16- oder 32-Bit-Code enthält, oder ob ein Stacksegment über den 16-Bit-Stackpointer SP oder den 32-Bit-Stackpointer ESP angesprochen werden soll.
Diese Erweiterungen beherrscht der 80386er und alle Nachfolgeprozessoren auch im 16-Bit-Protected-Mode, so dass 16-Bit-Programme, die die 32-Bit-Befehlserweiterungen IA-32 benutzen, den zusätzlichen Speicher auch ansprechen können. Zusätzlich bietet jeder 32-Bit-x86-Prozessor die Möglichkeit, Seitenverwaltung (Paging) zu aktivieren, welche der Segmentierung nachgeschaltet ist.
Der 32-Bit-Protected-Mode wird von allen 32-Bit-Betriebssystemen verwendet, beispielsweise:
* bei Microsoft fakultativ bereits seit Windows 2.0 (wenn es auf einem 32-Bit-Prozessor läuft), zwingend seit Windows für Workgroups 3.1 und Windows NT 3.1
* bei IBM seit OS/2 2.0
* von Apple nach der Umstellung auf die Intel-Plattform, also mit Erscheinen von Mac OS X Tiger/Intel
* der Linux-Kernel wurde ursprünglich für den 32-Bit-Protected-Mode des 80386 geschrieben

### 64-Bit-Modus

Mit der Einführung der AMD64-Architektur in der K8-Prozessorgeneration von AMD, welche wenig später auch von Intel unter dem Namen EM64T (auch IA-32e) bzw. inzwischen Intel 64 übernommen wurde, wurde ein neuer 64-Bit-Betriebsmodus bei x86-Prozessoren eingeführt, der sich von dem bisherigen Protected Mode grundlegend unterscheidet. Neben einigen anderen Modernisierungen der Prozessorarchitektur gibt es in diesem Modus de-facto keine Segmentation mehr (mit einer Ausnahme, siehe weiter im Text). Die Basisadresse der Segmente ist fest auf 0 gesetzt. Der Deskriptor für das Codesegment wird nur noch zur Ermittlung des Sub-Modus, der „Default Operation Size“ und der Privilegienstufe des in diesem Segment ausgeführten Codes verwendet. Einzig die Segmentregister FS und GS können vom Ring 0 aus über spezielle Maschinenbefehle direkt (ohne auf Segmentdeskriptoren zuzugreifen) eine 64-Bit-Segmentbasisadresse erhalten.
Die Sub-Modi bei x64 werden „Long Mode“ (64-Bit-Modus; bei Intel auch „IA-32e Mode“) und „Compatibility Mode“ (32-Bit) bezeichnet. Der 32-Bit-Kompatibilitätsmodus ermöglicht die Ausführung von 32-Bit-Programmen unter einem 64-Bit-Betriebssystem.
Für Systemsegmente wurde das Format der Segmentdeskriptoren erweitert, so dass sie 64-bittige Basisadressen bzw. Offsets enthalten. Diese Deskriptoren belegen damit effektiv 2 Einträge in den Deskriptortabellen.

## Paging und Speicherauslagerung

Betriebssysteme für die x86-Architektur, wie zum Beispiel Windows, Linux, PC-BSD oder macOS, arbeiten im 32-Bit-Protected-Mode oder bieten, als 64-Bit-Betriebssysteme in dessen Nachfolger „Long Mode“, mit dem „Compatibility Mode“ essentiell ebenfalls einen 32-Bit-Protected-Mode. Dabei wird zur Realisierung des Speicherschutzes im Wesentlichen nur noch das Paging eingesetzt, während die Segmentierung nicht mehr benutzt wird. Mit diesem Mechanismus kann jedem Prozess in einem Betriebssystem ein eigener, von den anderen Prozessen getrennter virtueller Adressraum bereitgestellt werden. Gleichzeitig lassen sich dadurch aber auch die gemeinsame Speichernutzung zwischen Prozessen, Copy-On-Write-Mechanismen oder Speicherauslagerung sowie eine klare Trennung in Kernel- und Benutzeradressraum realisieren (Speicherschutz des Kernels vor Fehlern von Anwendungsprogrammen). Dieses Flat Memory Model ist allerdings nicht sicher vor Pufferüberläufen.