Doing Paging Right
Posted: Tue Oct 28, 2008 2:47 am
Hi guys,
I've lately been fixing up my old OS attempt (Mattise) while I have spare minutes (I'm kind of on hold on the Pedigree project thanks to other commitments such as school).
So far I've done things like rewrite the physical frame allocator to work off a stack instead of a bitmap, and pretty much almost totally rewritten the process code to use process queues instead of static arrays. I've also fixed up a lot of bugs and mistakes I made.
However, the one thing I still can't seem to get right is paging. Every time my OS crashes it's thanks to a page fault, never anything else. So I decided to post here and ask some questions about designing and implementing a decent paging system.
A good first example is my process creation code. To create the process and load the file contents (ELF), I need to write to the virtual address in the new page directory. However, I can't simply write to the physical pages returned by my frame allocator, they need to be mapped into the address space. The double mapping can be extremely confusing at times and uses up extra pages I could use elsewhere. Is there a better way to pull this off, other than COW or similar?
As I write I have started considering passing an extra argument to the kernel-based thread entry function which could load the binary into the address space. Is this a good idea? In my kernel-based thread entry function the CPU is still in ring0, so there wouldn't be any privilege problems.
Another example is, ironically, my page mapping code, which internally calls itself. At the moment, I check whether the page directory to map into is the current page directory - if so, then I use the "map the page directory to itself" trick. This works well. However, there do come times when I need to map into a different page directory than the current one - mainly when doing things like creating and putting data onto new thread stacks. This can't be solved by the "do it in the thread entry function" method because the thread entry function uses this stack.
In this page mapping function I have to map the page directory into the current address space, then map the page table as well. This does cause extra overhead and I'm sure there's a better way to do this.
I'm willing to take the time to rewrite a fair bit if it'll make it easier to do things in the future, so your advice and ideas would be greatly appreciated. Thanks in advance.
I've lately been fixing up my old OS attempt (Mattise) while I have spare minutes (I'm kind of on hold on the Pedigree project thanks to other commitments such as school).
So far I've done things like rewrite the physical frame allocator to work off a stack instead of a bitmap, and pretty much almost totally rewritten the process code to use process queues instead of static arrays. I've also fixed up a lot of bugs and mistakes I made.
However, the one thing I still can't seem to get right is paging. Every time my OS crashes it's thanks to a page fault, never anything else. So I decided to post here and ask some questions about designing and implementing a decent paging system.
A good first example is my process creation code. To create the process and load the file contents (ELF), I need to write to the virtual address in the new page directory. However, I can't simply write to the physical pages returned by my frame allocator, they need to be mapped into the address space. The double mapping can be extremely confusing at times and uses up extra pages I could use elsewhere. Is there a better way to pull this off, other than COW or similar?
As I write I have started considering passing an extra argument to the kernel-based thread entry function which could load the binary into the address space. Is this a good idea? In my kernel-based thread entry function the CPU is still in ring0, so there wouldn't be any privilege problems.
Another example is, ironically, my page mapping code, which internally calls itself. At the moment, I check whether the page directory to map into is the current page directory - if so, then I use the "map the page directory to itself" trick. This works well. However, there do come times when I need to map into a different page directory than the current one - mainly when doing things like creating and putting data onto new thread stacks. This can't be solved by the "do it in the thread entry function" method because the thread entry function uses this stack.
In this page mapping function I have to map the page directory into the current address space, then map the page table as well. This does cause extra overhead and I'm sure there's a better way to do this.
I'm willing to take the time to rewrite a fair bit if it'll make it easier to do things in the future, so your advice and ideas would be greatly appreciated. Thanks in advance.