Deine Frage lautet kurz:
Was ist Paging und wie funktioniert es, brauche ich es und überhaupt und so? Grundsätzlich brauchst du kein Paging, ein Betriebssystem funktioniert auch ohne. Wenn du dich auf x86 im Protected Mode beschränkst, kannst du Speicherschutz auch mit Segmentierung allein herstellen. Außerdem beherrscht auch nicht jede CPU Paging.
Eine pagingfähige MMU enthält nur eine Tabelle, die aus einer "CPU-Adresse" eine "RAM-Adresse" macht, im Sinne von "wenn die CPU 0x12340000 sagt, meint sie in Wirklichkeit 0x43210000". Diese Tabelle beschreibt Blöcke von jeweils 4 KB, enthält damit 1 Mio Einträge (4 GB Adressraum / 4 KB Pagegröße) und belegt damit 4 MB RAM. Das ist zu viel.
Also hat man die Tabelle in kleinere Teiltabellen zerteilt, die jeweils nur 1024 Einträge (4 MB Adressraum / 4 KB Pagegröße) haben und damit zufällig genau eine Page groß sind. Diese heißen Page Table - und die große Tabelle heißt Page Directory. Alle Page Tables zusammen belegen zwar auch 4 MB, aber sie müssen nicht existieren (dann kann man auf die dadurch beschriebenen Adressen halt nicht zugreifen) - das spart Speicher.
Jeder Task hat sein eigenes Page Directory, damit sich verschiedene Tasks nicht in die Quere kommen (Speicherschutz). Aber Teile der Page Directories können gleich sein (normalerweise ist der Kernel in allen Tasks gleich gemappt, und gemeinsam genutzter Speicher taucht auch in mehreren Tasks auf).
Ein vmm_create_context() erzeugt ein Page Directory und initialisiert es mit den Mapping, die sowieso überall sind. Ein vmm_alloc() sucht sich ein (oder mehrere) Speicherblöcke und mappt die als einzelnen, großen Block in ein Page Directory.
Wie du es im Detail implementierst, bleibt dir überlassen.
In Qemu kannst du mit "info mem" und "info tlb" anzeigen lassen, was gerade aktuell ist.