stillconfused wrote:
I've been reading through every thread on here I can find for more information on how people have implemented higher-half kernels. I've seen a few people here recommend using the page directory set up during the boot process as only a preliminary page directory to begin executing in the higher half, then setting up a permanent one after the jump to higher-level code. Are there any resources available that anyone could recommend which explain the theory behind this? I can see how I would accomplish this, but I'm still a bit confused about what my next steps are and why.
There isn't a "theory" reason for this per-se, at least not in the strict sense of the meaning of OS system theory. However, there are practical considerations that make this an oft-used approach. First, before initialization of paging, all code used either needs to be specifically compiled to work at the low-memory boot adresses, or be position independent. This can be quite a hastle, so people generally try to keep this code small. That in turn usually means that a rather simplistic approach is used to create the page directory, usually by using a buffer pre-allocated during build in the kernel's data segment. However, doing this means these structures are allocated differently than paging structures created during normal operations. This isn't neccessarily a problem if you want to keep using them, but you then need to ensure that all the runtime code for manipulating paging structures can handle these special boot structures, either by special casing them or by making them act similar enough that the differences don't matter. As both of these options can be a bit of a hassle, it is just a lot easier to discard the boot paging structures once everything else is sufficiently initialized and proceed circumvent all that.
stillconfused wrote:
Prior to implementing the higher-half initialization code for my kernel, I was using the physical memory allocator to give me page frames at runtime to use for my kernel page directory/first kernel table. Now I've just reserved some space in the linker script for the boot page dir/table. I imagine my next step is just to create a permanent page dir/table and begin working towards userspace.
Is there a good example anyone can think of to show how and why these steps are accomplished? I've looked at the Linux/BSD source code and it seems like they have their own approaches to this. I haven't had enough time to decipher them properly to get any guidance.
This is a harder question to answer. The (in my opinion) best thing to do is get a picture of what your finished run time state should look like, and what pieces should function at that time. Then start working out how those bits should work, and how they interrelate. After you have done that, you'll probably find just how the various bits and pieces depend on each other, which should give you a good feel both for what order would be useful in implementing them, and how the rest of your initialization code then has to work.
A lot of the decisions here depend intimately on how various parts of your kernel, such as the scheduler and memory management subsystems, interact and function, so a specific order is hard to indicate.