When initializing my kernel, I have a few things that need to happen: 1) paging needs to be enabled, 2) the physical memory manager needs to parse the memory map from grub, and 3) assorted startup code needs to access data that needs to stay there for later (e.g. the GDT, IDT, memory management structures).
The dependencies between these steps are driving me crazy. With higher-half, the kernel is linked at its virtual address and so the options I've come up with are 1) enable paging in assembly, which would involve following all the multiboot pointers (in assembly) so they'll still be accessible to the physical memory manager and then later unmapping them all, 2) link the startup code at its physical address and then do some pointer manipulation to access kernel structures at their physical addresses as well, or 3) don't use a higher-half kernel.
Also involved is bootstrapping the physical memory manager without knowing the amount of physical memory at compile time. I'm pretty sure I have to either carefully avoid all the multiboot structures when allocating the first structures, or use them all first and then don't worry about overwriting them (although I'd still have to deal with modules and this approach probably involves copying the multiboot tables to a known location as I need them while setting up the physical memory manager).
These problems are why I've avoided a higher half kernel up to now. Does anyone have a good system for resolving these dependencies? Maybe some variation on this GDT trick to access both the kernel at its linked/virtual address and the multiboot tables at their physical address, or using some kind of pre-defined page tables that avoid the problems above, maybe involving PSE?