Also erstmal, ab User-VMM sagen wir einfach mal, das ist kein Problem.
Meine Aufteilung ist 3/1, sprich 3GB für den Prozess und 1GB für den Kernel. Das alle PDs immer in den Kernel gemappt sind, will ich einfach nicht, finde ich unschön und unnötig.
Das malloc()/free() kann ja auch nicht für jede Page den Kernel fragen ob es die benutzen kann oder nicht.
Da muss ich dir wiedersprechen, genau das muss es machen. Nicht malloc() bestimmt was es nutzen darf, sondern es fragt beim Kernel nach neuem Speicher. Sonst ist sowas wie ASLR gar nicht möglich. Denn woher soll malloc() wisse wie der Adressraum aussieht?
Dann kommt noch hinzu, das der Kernel den Stack für UserThreads alloziert, wie soll das gehen, wenn der Kernel nicht weiß was malloc() alles für sich beansprucht?
Selbst unter Linux wird doch sbrk() aufgerufen wenn neuer Speicher benltigt wird, das ist doch nix anderes als das Fragen welchen Speicher man nutzen darf!?
Der Kernel-VMM kann also auch nicht so funktionieren wie das User malloc(). Es ist ja schließlich auch ohne weiteres möglich ein User malloc() im Kernel zu nutzen, genau aus dem Grund, weil malloc() halt eine Funktion aufruft um sich neuen Speicher zu holen und dann kommt noch hinzu, dass malloc() für alle Größen "zuständig" ist. Damit meine ich das man malloc() nicht dafür nutzt (nutzen kann) einfach mal ein paar Pages zu allozieren, weil halt gewisse Informationen mit gespeichert werden, sprich wenn du von malloc() 4096 bytes allozierst, dann verbaucht malloc() mind. 4100bytes (4byte um die Größe des Blocks zu wissen).
Ein VMM hingegen gibt grundsätzlich nur vielfaches der Pagegröße raus und das muss auch so sein, z.B. für Shared-Memory oder halt um Pages zu mappen.
Deswegen kommst du auch nicht mit ein oder zwei statischen Pointer weg. Es gibt einen Weg, wie man sich eine "zusätzliche" Datenstruktur sparen kann und das ist indem man jedes Mal das PD (und alle PageTables) auf freie Einträge untersucht und guckt ob man einen Bereich findet der groß genug ist. Dass das aber nicht wirklich das wahre ist, sollte klar sein.
Also muss man irgendwie darüber Buch führen welche Bereiche noch frei sind. Um einfach mal den worst-case zu nehmen, eine Page benutzt, eine Page frei ... und das für den "ganzen" (weil ja in die letzten 4MB das PD gemappt ist) KernelSpace. Wo und wie willst du dir merken welche Pages frei sind und welche nicht? Immerhin sind das 130560 Bereiche und den Speicher wollte ich eigentlich nicht statisch vorreservieren. Dann kommt noch hinzu das man natürlich die Bereiche noch sortiert haben will, um schnell einen Bereich nach der Größe oder der Startadresse zu finden.
Um es ganz einfach zu machen, du sagst ja auch, dass der User-VMM seine Datenstruktur im KernelSpace speichert und dafür den Kernel-VMM nutzt. Nun unterscheide ich aber nicht wirklich zw. Kernel- und User-VMM (wieso auch?). Beide verwalten einfach einen Adressraum einer gewissen Größe und mit einer gewissen Startadresse. Problem beim Kernel-VMM ist halt nur, dass es darunter keinen VMM gibt der genutzt werden kann (Kreisabhängigkeit).
Ich hatte, wie gesagt, am Anfang mal nen VMM der einfach geguckt hat, ich brauche jetzt z.B. ne neue Node und es sind beim SlabAllocator keine mehr vorrätig, also packe ich einfach mal nen neuen ObjectCache in den SlabAllocator für die Nodes. Das ist ersten ein riesiger Hack und zweitens gab das bei mir doch einige Probleme bei vielen CPUs und halt das typische Multithreading Problem, mal funktions mal nicht.
Also habe ich das jetzt alles schön voneinander getrennt und habe für den Kernel-VMM nen "einfachen" Allocator geschrieben, der statisch nen kleinen Bereich (der groß genug ist, um auch den worst-case im Kernel bewältigen zu können) verwaltet.