However I have a couple of concerns. They are:
- What happens if the page lies inside a page table that hasn't been setup yet?
- If I allocate a page table through pm_alloc_page() directly the page table won't be directly usable when paging is enabled will it?
For your first concern, if your page lies inside a page table which hasn't been set up yet, it will page fault when any of the pages that would be in that directory try to get translated. The key thing to note is that the page translation occurs in two steps, first the directory, and then the page itself, so if the first step fails, it just pagefaults and doesn't try the second step. So if you mark an entry in the page directory, it won't bother looking up the page table, it will just pagefault.
To put this into practice in your page fault handler, after you calculate the page directory entry, you should check that entry to see if the page table it points to is present. If not, then you can allocate another page of physical memory, set it up as an empty page directory, and then continue on with the rest of the handler.
Thanks, that's actually explained a lot to me! I think i'd missed that the translation was happening in two steps in other documentation that I read.
As for your second concern, I'm not exactly sure what you mean, do you mean that if you create and fill in a new page table in your pm_alloc_page function, will it immediately be in effect? If so, the answer is... kind of. If you make changes to the paging structures, they take effect immediately, but something to note is that the CPU uses a buffer (called the traslation lookaside buffer, or TLB) to store recent page translations, so that it doesn't have to do them for every single memory reference. Because of this, if you change something in the paging directory, you need to let the CPU know that the buffer isn't correct any more. The easiest way to do this is to reload the CR3 register, which clears out this buffer. In short, if you change any paging structures, reload CR3. You can also use the INVLPG instruction, feel free to look up how that works too.
OK, I think I get that. Does this reload simply require rewriting the page directory location to CR3? If so does it matter if I set the same value. Does it still pick that up as a change?
As a side note, you mention that user programs might be loaded at an address like 0x10000000. That means you only get 256 MB of kernel *address* space. It might seem like a lot now, but maybe not so in the future, just something to think about. If you think you only need that much kernel space, feel free to use that.
Haha, no I fully get that. For now it's just a nice round number for clearly seeing boundaries in debugging. Once I get to user programs I'll deal with that address. I'm trying to design my VMM to be able to move these boundaries relatively easily if required.