Hallo!
Schön, dass ich dieses Forum entdeckt habe, ich hoffe ihr könnt mir helfen, deshalb fange ich mal beim Urschleim an, damit auch jeder weiß, was mein Problem ist.
Ich bin dabei einen Microkernel zu schreiben und habe mittlerweile fast alles nötige drin, also GDTs, IDTs, Paging, Multitasking (mit Ring Trasistions) etc.
Nun wollte ich aber, dass jeder Task (alle laufen im Usermode) eine eigene Page Directory hat, der Sicherheit halber. Auf OS-Code können Sie natürlich nicht zugreifen (nur WRITE+SUPERVISOR), aber sonst untereinander, das ist nicht schön.
Mein bisheriges Paging funktionierte so:
Vor dem Paging wurde an eine feste Adresse (4k aligned) die Page directory geladen und direkt danach eine Seite weiter die Page Tables, also 4 MB + 4096 Byte Page Dir insgesamt. Das ist gerade noch zu verkraften. Ruft man malloc() auf wird in der entsprechenden PageDir falls nicht vorhanden die PageTab verlinkt und dann in den Pagetabs (linear, aufeinanderfolgend) die angeforderte Größe auf physikalischen (teils wahllosen Speicher) gemappt. (wahllos = ein Stack der freie phys. Pages zurückgiebt, können also quer verteilt liegen... )
Funktioniert auch alles wunderbar und ist durch den Stack-basierten malloc auch schön schnell. Nach aktiviertem Paging kann man die PageTables natürlich nur über virt. Adressen ändern, da der feste 4MB-Block aber 1:1 gemappt ist, kann ich die Page-Dir-Adressen ohne Übersetzung verwenden.
So nun finde ich aber 4MB für jeden Task einfach mal freizuhalten nicht das Schlauste. Also, meine neue Implementierung:
Vor dem paging:
* Pagedir wird an einer feste Stelle erstellt
* ein Eintrag wird harcoded bei 0xC0000000 (virt.) auf die Page-Dir gemapped.
* Paging an!
soo, nun möchte ich für einen Usermode-Task neunen speicher allozieren. Die Funktion (wird im Kernelmode ausgeführt) dazu funktioniert ungefähr so (ist nicht malloc, nur eine wichtige Unterfunktion)
POINTER VirtualAlloc(UINT32 *pageDirectory, UINT32 reqAllocSize, UINT32 *physAddress, UINT32 Attributes) {
UINT32 reservedVirtAddress;
UINT32 tmpFreeVirtAddress;
UINT32 pageCount = reqAllocSize>>PAGE_BITS;
/* genug phys. Speicher frei? */
if (memFree < reqAllocSize) {
return NULL;
}
/* ist genug virtueller Frei? */
tmpFreeVirtAddress = FindFreeVirtMem(pageDirectory, pageCount);
if (tmpFreeVirtAddress == 0) {
/* no, it isn't */
return NULL;
}
/* jap, also (zufällige) phys. Speicher auf den virtuellen lin. mappen */
reservedVirtAddress = tmpFreeVirtAddress;
while (pageCount--) {
*physAddress = GetFreePhysChunk();
MapPhysToVirt(pageDirectory, reservedVirtAddress, *physAddress, Attributes);
reservedVirtAddress += PAGE_SIZE;
}
return (tmpFreeVirtAddress);
}
Ich denke die Funktionen sind selbsterklärend, wenn nicht poste/erkläre ich sie gern.
Bemerkung: physAddress ist dazu da die letze physikalische Adresse zurückzugeben, ist manchmal sinnvoll (z.B. beim Erstellen von Page Tables, damit man die phys. Adresse in die PageDir einträgt)
So, jetzt das Problem:
Angenommen in der usermode PageDir existiert ein Eintrag für eine PageTab. Nun kommen zu dieser schon existierenden Tab welche hinzu (malloc z.B.)
Also liest der Code die Adresse der Tab aus der Dir und kann natürlich nicht zugreifen, da sie phys. ist. Also eine funktion für die Kernel-Page-Dir namens MapPhysToVirt( bla bla, UINT32 *physAddress); damit man darauf zugreifen kann.
Die Funktion MapPhysToVirt() hingegen muss im Kernel-PageDir/Tab einen Eintrag machen damit der Speicher sichtbar wird. Dazu muss sie die PageTabs ändern, dazu brauch sie also MapPhysToVirt()...
usw, usw.... bin ich zu blöd? Das kann doch nicht sein?!
Hab schon einiges programmiert, die neue Revision mit mehreren PageDirs aber noch nicht getestet, weil mir aufgefallen ist, dass ich ja ne unendliche Rekursion drin hab.
Ich nehm an es ist ein einfacher Denkfehler, verknüpft mit einem Henne-Ei-Problem, aber ich weiß nicht mehr weiter...
Vllt hilft auch ne Wochen ruhen lassen, nur hab ich da irgendwie keinen Nerv, weil ich grade mal Zeit habe weiterzuprogrammieren.
Vielen Dank schonmal (allein fürs Lesen des vielen Textes ;)
Gruß
nurnware