Long Mode

Aus Lowlevel
Wechseln zu: Navigation, Suche

Der Long Mode ist ein CPU-Modus neuerer CPUs, in dem erstmals 64-Bit-Allzweckregister zur Verfügung stehen. Wie auch beim Protected Mode starten Prozessoren, die diesen Modus unterstützen, aus Kompatibilitätsgründen zunächst im Real Mode mit deaktiviertem A20-Gate.

Eigenschaften

  • Address-/Registerbreite beträgt 64 Bit
  • Viele neue Register (z.B. R8-R15, CR8-CR15, ...)
  • ...

Überprüfung der Unterstützung

CPUs, die den Long Mode unterstützen, setzen bei einem Aufruf der CPUID Funktion 0x80000001 das Long-Mode-Capable-Bit (Bit 29) im EDX-Register auf 1. Sicherheitshalber sollte man auch noch überprüfen, ob Physical Address Extensions unterstützt werden.

<asm> mov eax, 0x80000001 cpuid  ; CPUID Funktion 0x8000_0001 aufrufen and edx, 0x20000000  ; LM-Bit isolieren test edx, edx  ; Wenn EDX jetzt 0 ist, war das LM-Bit nicht gesetzt jz long_unsupported  ; Long Mode nicht unterstützt!

mov eax, 0x00000001 cpuid  ; CPUID Funktion 0x0000_0001 aufrufen and edx, 0x00000040  ; PAE-Bit isolieren test edx, edx  ; Wenn EDX jetzt 0 ist, war das PAE-Bit nicht gesetzt jz long_unsupported  ; Long Mode nicht unterstützt! jmp long_supported  ; Long Mode unterstützt! </asm>

Aktivierung des Long Mode

Um in den Long Mode umschalten zu können, muss erst einmal der Protected Mode aktiviert werden. Eine weitere Voraussetzung ist, dass das Physical Address Extension-Bit (Bit 5) im CR4 Register gesetzt und Paging aktiviert ist. Jetzt kann der Long Mode mit dem Setzen des LME-Bits (Bit 8) im MSR 0xC0000080 aktiviert werden. Im eigentlichen Long Mode befindet man sich aber erst, wenn man in ein 64-Bit-Code-Segment wechselt, das im Vergleich zu den 32-Bit-Code-Segmenten in seinem Descriptor das L-Bit (Bit 21) im 2. DWord gesetzt hat. Die entsprechenden Einträge in der GDT sind natürlich vorher vorzunehmen.

Achtung!

Das Paging funktioniert im Long Mode ein wenig anders als im Protected Mode.

Dieser Beispielcode zeigt beispielhaft, wie man denn Long Mode aktiviert. Die hier verwendeten Pagingstrukturen sind nur provisorisch angedacht und sollten möglichst durch eigene ersetzt werden, sonst wird das Ganze ganz schnell nicht mehr ganz so schön.

<asm> mov eax, cr4  ; CR4 einlesen or eax, 0x20  ; Physical Address Extension-Bit setzen mov cr4, eax  ; CR4 beschreiben

mov edi, 0x300000  ; Pagingstrukturen liegen bei 0x300000

mov eax, 0x30100F  ; Eintrag für die Page Directory Pointer Table stosd mov ecx, 0x03FF xor eax, eax rep stosd  ; Rest mit Nullen auffüllen

mov eax, 0x30200F  ; Eintrag für die Page Directory Table stosd mov ecx, 0x03FF xor eax, eax rep stosd  ; Rest mit Nullen auffüllen

mov ecx, 0x0200 mov esi, 0x008B  ; Die Attribute für die Einträge im Page Directory

map.loop:  ; Hier werden die ersten 512 MiB Identity-Mapped mov eax, esi  ; Page eintragen stosd xor eax, eax  ; Jeder Eintrag besteht aus 8 Byte, also die oberen 4 auffüllen stosd add esi, 0x200000  ; Wir benutzen hier 2 MiB Pages sub ecx, 1 jnz map.loop

mov eax, 0x300000  ; Die Adresse des Page Map Level 4 hier eintragen mov cr3, eax

mov ecx, 0xC0000080  ; Wir brauchen Zugriff aus das MSR-Register 0xC0000080 rdmsr  ; MSR-Register einlesen or eax, 0x00000100 ; Long Mode einschalten wrmsr  ; MSR-Register beschreiben

mov eax, cr0  ; CR0 einlesen or eax, 0x80000000  ; Das Paging-Bit setzen mov cr0, eax  ; CR0 beschreiben, ab jetzt sind wir im Long Mode

jmp 0x30:kernel.longmode; Far Jmp in 64-Bit Code Segment


[bits 64] kernel.longmode: ; Jetzt führen wir auch endlich 64-Bit Code aus jmp $  ; Endlosschleife xD </asm>

Links