Hallo
Ich möchte Paging in meinem Kernel implementieren. Die Grundidee hinter dem virtuellen Adressraum habe ich verstanden, allerdings ergeben sich trotzdem ein paar Fragen.
Auf der
Wikiseite zu Paging heißt es bei der Page-Directory Tabelle:
Gibt die Größe der Page an. 0 steht für 4 kB, 1 für 4 MB (oder 2 MB bei Verwendung von PAE). Das S-Bit ist wirkungslos, wenn nicht im Steuerregister CR4 das PSE-Bit (4-MB-Pages) oder PAE-Bit (2-MB-Pages) gesetzt ist.
Ich dachte bisher, dass Pages immer 4kb seien, daher verstehe ich nicht, warum es hier eine Fallunterscheidung gibt
Außerdem frage ich mich, ob sich Bit 1 und Bit 2 nur auf den Page Directory Eintrag selbst beziehen oder auch auf die untergeordnete Pagetable. Wenn z.b. Bit 2 nicht gesetzt ist, können Ring 3 Tasks dann trotzdem auf untergeordnete Pagetable Einträge zugreifen, wenn bei diesen dann das 2. Bit gesetzt ist, oder "vererbt" sich das quasi von dem Page Directory auf die untergeordnete Page Table?
Im
Tutorial zu Paging steht unter
Dynamisches Mapping, dass es einen Trick gäbe, um die Paging-Strukturen zu mappen:
Für das Mappen eines Page Directory und allen zugehörigen Page Tables gibt es einen Trick: Wenn ein Eintrag eines Page Directory wieder auf ein Page Directory (z.B. sich selbst) zeigt, dann wird dieses Page Directory an dieser Stelle als Page Table verwendet. Dadurch werden alle enthaltenen Page Tables hintereinander in den virtuellen Speicher gemappt. Dieser Trick wird oft für das aktuelle Page Directory benutzt, d.h. ein bestimmter Eintrag in jedem PD zeigt wieder auf das PD selbst.
Das heißt, wenn ein Page Directory Eintrag auf sich selbst zeigt, dann wird es selbst zum ersten Page Table Eintrag und alle anderen Page Directory Einträge müssten dann ja zu weiteren Page Table Einträge werden, wodurch dann die gesamte Page Directory Tabelle gemappt wird, oder wie? Das heißt, es gäbe Sinn, den ersten Page Directory Eintrag immer auf sich selbst zeigen zu lassen - habe ich das richtig verstanden?
Beim Kernelstart müssen einige Bereiche gemappt werden:
- Der Kernelcode selbst
- Der Videospeicher von B8000 bis BFFFF
- Evtl. Multiboot-Strukturen, die noch verwendet werden sollen
- Zum Zeitpunkt der Paging-Initialisierung schon dynamisch angelegte Kerneldaten, z.B. die Bitmap der physischen Speicherverwaltung
Dass die ganzen Bereiche, die vor der Paging Initialisierung erstellt wurden, gemappt werden müssen erscheint mir ja logisch. Nur bin ich mir nicht sicher, woher ich denn weiß, wo der Kernelcode selbst im Speicher zu finden ist. Also dem Linkscript kann ich entnehmen, dass mein Kernel bei
0x100000 beginnt und der Stack ist zu Beginn an der 2MB Grenze gesetzt. Heißt das denn auch, dass mein Kernelcode also vollständig zwischen
0x100000 und
0x200000 liegt und mit einer Größe von 1MB also 256 Pages beansprucht? (Ich vermute mal: nein
)
Zudem heißt es, dass z.b. Daten, wie die Bitmap der physischen Speicherverwaltung als dynamisch angelegte Kerneldaten gemappt werden müssten. Die Bitmap selbst habe ich aber garnicht dynamisch angelegt und das
Tutorial zur physischen Speicherverwaltung legt sie ebenso statisch auf dem Stack an wie ich, was bedeutet, dass sie doch mit dem Kernelcode automatisch mitgemappt werden müsste - korrekt?
Ich hoffe ich habe nicht allzu wenig verstanden
,
lg
Developer30