Ich interpretiere deinen Mechanismus mit den "Permission-Registern" als Versuch bestimmte Funktionen als privilegiert zu markieren. Und du willst, dass nur diese privilegierten Funktionen Operationen an dem Mapping zwischen virtuellen und physischen Adressen ausführen dürfen. Dadurch soll gewährleistet werden, dass kein Programm Änderungen an dem Mapping vornehmen kann, um den Kernel bzw. andere Programme unzulässig zu beeinflussen. Ist das richtig?
Das reicht nämlich nicht. Du brauchst definitiv eine konkrete Trennung zwischen User-Mode und Kernel-Mode mit einem definierten Übergang. Ein Problem ist folgendes: Einzelne Funktionen als privilegiert zu markieren reicht nicht, weil es funktionale Abhängigkeiten zwischen den Kernelbestandteilen gibt. Eine privilegierte Funktion, die die Page Tables ändert, ist ja kein Selbstzweck, sondern wird von vielen anderen Funktionen, z.B. aus der Speicherverwaltung (sowas wie malloc und free, ganze Seiten anfordern/freigeben für Treiber, ...), Prozessverwaltung (z.B. Erstellung eines neuen Adressraums), oder Interprozesskommunikation (Shared Memory) aufgerufen. Und natürlich ruft vermutlich jeder Bestandteil im Kernel malloc/free auf, also irgendwann landet jeder mal in einer privilegierten Funktion. Das Problem ist, dass eine privilegierte Funktion nicht feststellen kann, zu welchem dieser Zwecke sie verwendet wird. Sie kann ohne definierten Übergang zwischen User-Space und Kernel-Space auch nicht feststellen, ob sie gerade von einem Programm aufgerufen wird. Ein Programm könnte den System-Zustand (Registerinhalte und Stack) so hindrehen, dass es aussieht, als ob die Funktion aus dem Kernel aufgerufen wird, obwohl das nicht der Fall ist. Das kannst du nur verhindern, indem du dafür sorgst, dass jeder Aufruf vom User-Space in den Kernel durch eine "Schleuse" (Interrupt/Syscall) geht.
Ein weiteres Problem ist, dass du mit dem Mechanismus nur Code schützt. Daten sind entweder ungeschützt, unzugänglich für nicht privilegierte Funktionen oder nicht gemappt. Wenn sie nicht gemappt sind, müssen sie erst von einer privilegierten Funktion gemappt werden, was ebenfalls die eben beschriebenen mit sich bringt, und darüberhinaus langsam ist. Das verkompliziert die Kernel-Entwicklung erheblich.