Da ich nun die physische Speicherverwaltung soweit habe wollte ich Paging einschalten:
Meine Überlegung:
- Ich will den gesamten Speicher Mappen.
- Ein PageDirectory anlegen mit 1024 einträgen
- Solange PageTables mit 1024 einträgen hinzufügen bis mir unsigned int getFreeMemory() sagt: "DA GIBBET KEINEN SPEICHER MEHR"
Das solltest du so nicht tun. Dann mappst du den gesamten freien Speicher linear hintereinander. Ich gehe mal davon aus, dass dein Kernel ist in der Bitmap nicht als freier Speicher markiert ist. Der würde dann nicht gemappt werden.
Deine Methode getPageTableEntry ist vielleicht in abgewandelter Form brauchbar um einem Prozess eine Menge x an virtuellem Speicher zur Verfügung zu stellen, aber zur Initialisierung des Kernels taugt sich nicht.
Der Ablauf des Fehlers ist vermutlich in etwa so:
- du aktivierst Paging
- da du nur Seiten gemappt hast, die du mit getFreeMemory() bekommen hast, befindest sich an der Stelle von EIP nicht mehr der Code deines Kernels, sondern welche zufälligen Bytes
- die CPU führt diese unbeirrt weiter hintereinander aus, und landet irgendwann an der Adresse 0x3fffff (vermutlich waren diese Bytes alles Nullen)
- dann gibt es einen Page Fault, weil an der Adresse 0x3fffff eine mindestens 2 Byte große Instruktion steht. Das erkennt man im Bochslog:
00139631503i[CPU0 ] | RIP=00000000003fffff (00000000003fffff)
00139631503i[CPU0 ] | CR0=0xe0000011 CR1=0x0 CR2=0x0000000000400000
00139631503i[CPU0 ] | CR3=0x00136000 CR4=0x00000000
Dass die Adresse 0x0000000000400000 nicht gemappt ist, bedeutet, dass beim Erstellen vom Page Directory vermutlich auch noch irgendwas schief gegangen ist. Was genau, kann ich auf die Schnelle nicht sagen.
Allerdings ist wie gesagt deine Idee, wie du den Speicher mappen willst, nicht korrekt. Du solltest für den Anfang den gesamten Speicher 1:1 mappen (identity mapping). So ungefähr könnte das aussehen:
void initPaging() {
...
for (i = 0; i < 1024; i++) {
unsigned int *pageTable = (unsigned int *)getFreeMemory();
/* 4 MB beginnend an der physischen Adresse i * 4 MB mappen */
for (j = 0; j < 1024; j++) {
pageTable[j] = (i * 4096 * 1024 + j * 4096) | MEMORY_PRESENT | PAGE_WRITEABLE | EVERYONE_ACCESSABLE;
}
/* diese 4 MB an die virtuelle Adresse i * 4 MB mappen */
pageDirectory[i] = (unsigned int)pageTable | MEMORY_PRESENT | PAGE_WRITEABLE | EVERYONE_ACCESSABLE;
}
...
}
So sind alle virtuelle Adressen gleich den physischen Adressen.