| Zeile 45: | Zeile 45: | ||
Und nun zum Hauptteil des Tutorials. Auch hier brauchen wir zuerst ein paar Konstanten: | Und nun zum Hauptteil des Tutorials. Auch hier brauchen wir zuerst ein paar Konstanten: | ||
| + | <freebasic> | ||
'// constants for all Paging-tables | '// constants for all Paging-tables | ||
const Page_present = &b1 | const Page_present = &b1 | ||
| Zeile 57: | Zeile 58: | ||
'// constants only for the PageTable | '// constants only for the PageTable | ||
const Page_noTLBupdate = &b100000000 | const Page_noTLBupdate = &b100000000 | ||
| + | </freebasic> | ||
Die benutzen wir später um die Flags der Tabellen-Einträge zu setzen. | Die benutzen wir später um die Flags der Tabellen-Einträge zu setzen. | ||
| + | <freebasic> | ||
dim shared PageDirectoryPTR as UINTEGER PTR = cast(UINTEGER PTR, 2*1024*1024 - 4*1024) '// The PageDirectory lies at 2MB-4kb | dim shared PageDirectoryPTR as UINTEGER PTR = cast(UINTEGER PTR, 2*1024*1024 - 4*1024) '// The PageDirectory lies at 2MB-4kb | ||
dim shared PageTablesPTR as UINTEGER PTR = cast(UINTEGER PTR, 2*1024*1024) '// The PageTables lie at 2MB | dim shared PageTablesPTR as UINTEGER PTR = cast(UINTEGER PTR, 2*1024*1024) '// The PageTables lie at 2MB | ||
| + | </freebasic> | ||
Hier setzen wir Pointer, wo die Tabellen später liegen. Warum ich das so mache? So kann ich festlegen, das die Tabellen 4kb-aligned sind, und muss mich nicht auf irgendwelche seltsamen Memory-Manager verlassen. | Hier setzen wir Pointer, wo die Tabellen später liegen. Warum ich das so mache? So kann ich festlegen, das die Tabellen 4kb-aligned sind, und muss mich nicht auf irgendwelche seltsamen Memory-Manager verlassen. | ||
| + | <freebasic> | ||
sub Paging_initDirectory | sub Paging_initDirectory | ||
dim counter as UINTEGER | dim counter as UINTEGER | ||
| Zeile 74: | Zeile 79: | ||
next | next | ||
end sub | end sub | ||
| + | </freebasic> | ||
Wir setzen hier die Einträge des Page-Directory so, dass sie auf die Page-Tables verweisen. Man kann hier sehen, das wir zwei Flags setzen. Damit sorgen wie dafür, das wir auf diesen Speicherbereich schreiben dürfen, und wie sagen der CPU das der Speicherbereich im physischen Speicher liegt, also present ist. | Wir setzen hier die Einträge des Page-Directory so, dass sie auf die Page-Tables verweisen. Man kann hier sehen, das wir zwei Flags setzen. Damit sorgen wie dafür, das wir auf diesen Speicherbereich schreiben dürfen, und wie sagen der CPU das der Speicherbereich im physischen Speicher liegt, also present ist. | ||
| + | <freebasic> | ||
sub Paging_map4kb (vmem as UINTEGER, pmem as UINTEGER) | sub Paging_map4kb (vmem as UINTEGER, pmem as UINTEGER) | ||
dim PDentry as UINTEGER | dim PDentry as UINTEGER | ||
| Zeile 87: | Zeile 94: | ||
*(PageTablesPTR+PTentry+PDentry*1024) = pmem OR Page_present OR Page_writeable | *(PageTablesPTR+PTentry+PDentry*1024) = pmem OR Page_present OR Page_writeable | ||
end sub | end sub | ||
| + | </freebasic> | ||
Das ist also unsere Routine, die einen 4kb Block in den virtuellen Speicher mappt. Wer oben aufgepasst hat, weiß auch, wie wir die Einträge der Tabellen berechnen: | Das ist also unsere Routine, die einen 4kb Block in den virtuellen Speicher mappt. Wer oben aufgepasst hat, weiß auch, wie wir die Einträge der Tabellen berechnen: | ||
| Zeile 96: | Zeile 104: | ||
Auch hier setzen wir ein paar Bits. | Auch hier setzen wir ein paar Bits. | ||
| + | <freebasic> | ||
sub Paging_mapPhysicalMemory (vstart as UINTEGER, pstart as UINTEGER, pend as UINTEGER) | sub Paging_mapPhysicalMemory (vstart as UINTEGER, pstart as UINTEGER, pend as UINTEGER) | ||
dim vmemPTR as UINTEGER = vstart | dim vmemPTR as UINTEGER = vstart | ||
| Zeile 106: | Zeile 115: | ||
loop | loop | ||
end sub | end sub | ||
| + | </freebasic> | ||
Diese Routine mappt den Speicher von pstart bis pend an die virtuelle Adresse vstart. Sie ruft dabei in 4kb-Schritten unsere obige Routine auf. Damit können wir große Speicherbereiche schnell und einfach mappen. | Diese Routine mappt den Speicher von pstart bis pend an die virtuelle Adresse vstart. Sie ruft dabei in 4kb-Schritten unsere obige Routine auf. Damit können wir große Speicherbereiche schnell und einfach mappen. | ||
| + | <freebasic> | ||
sub SetPageDirectoryAddress (address as UINTEGER PTR) | sub SetPageDirectoryAddress (address as UINTEGER PTR) | ||
'// we set the address when we write it into cr3 | '// we set the address when we write it into cr3 | ||
| Zeile 116: | Zeile 127: | ||
END ASM | END ASM | ||
end sub | end sub | ||
| + | </freebasic> | ||
Wir schreiben die Adresse zuerst in eax, und laden den Wert dann nach cr3, damit der Prozessor weiß wo unser Page-Directory liegt. | Wir schreiben die Adresse zuerst in eax, und laden den Wert dann nach cr3, damit der Prozessor weiß wo unser Page-Directory liegt. | ||
| + | <freebasic> | ||
sub Paging_activate | sub Paging_activate | ||
'// we activate paging by enabling the last bit of cr0. | '// we activate paging by enabling the last bit of cr0. | ||
| Zeile 127: | Zeile 140: | ||
END ASM | END ASM | ||
end sub | end sub | ||
| + | </freebasic> | ||
Hier holen wir den Inhalt von cr0 nach eax, setzen das Paging-Bit und schreiben den neuen Wert zurück. Und schon ist Paging aktiviert! | Hier holen wir den Inhalt von cr0 nach eax, setzen das Paging-Bit und schreiben den neuen Wert zurück. Und schon ist Paging aktiviert! | ||
| Zeile 134: | Zeile 148: | ||
Als Beispiel zeige ich hier einen Auszug aus meinem Kernel [[FROST]]: | Als Beispiel zeige ich hier einen Auszug aus meinem Kernel [[FROST]]: | ||
| + | <freebasic> | ||
print "Initializing page-directory..." | print "Initializing page-directory..." | ||
Paging_initDirectory | Paging_initDirectory | ||
| Zeile 142: | Zeile 157: | ||
print "Enabling paging..." | print "Enabling paging..." | ||
Paging_activate | Paging_activate | ||
| + | </freebasic> | ||
Das ganze geschieht nach dem initialisieren der IDT und vor dem initialisieren von Multitasking. | Das ganze geschieht nach dem initialisieren der IDT und vor dem initialisieren von Multitasking. | ||