Page 1 of 1
Higher-Half Startup
Posted: Wed Sep 29, 2010 8:13 pm
by Rusky
So, my kernel has some normal sections (e.g. .text, .data) and an .init section. The .text section and friends are linked at 0xF0000000 but loaded at 0x100000, while the .init section is both linked and loaded at the same address low in physical memory. Thus, bootstrapping the kernel involves enabling paging and setting up the correct mapping for the kernel proper.
This involves some dependency juggling- the code to construct the page tables needs to be called before paging is enabled, which means that 1) the page directory, which goes in the kernel proper, is not at its final address and 2) I potentially also need access to the kernel heap, which is also not at its final address.
L4 (the Pistachio reference implementation) solves this by using a temporary page directory with PSE enabled- the temp directory can go in the .init section and there's no need to allocate page tables. This kind of bothers me and I'd like to do this without this kind of throwaway table.
I could initialize the page directory through a pointer to &kernel_directory - kernel_offset and use a temporary heap allocator that just grabs chunks from the beginning using the same pointer technique, but that doesn't sound much better. So, my question is this: has anyone done this kind of setup before in a cleaner way than Pistachio or I have?
Re: Higher-Half Startup
Posted: Wed Sep 29, 2010 8:34 pm
by TylerH
A common method is to take advantage of segmentation offsets. IMO, it sounds like the easiest way.
Re: Higher-Half Startup
Posted: Wed Sep 29, 2010 8:44 pm
by gerryg400
It depends a little on how you intend to load your kernel. From a boot sector ? Your own loader ? Or Grub ?
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 6:00 am
by Rusky
Ah, yeah. I'm booting from GRUB. I suppose if I wrote my own bootloader or a third-stage bootloader that set up the processor state more to my liking that could work, but the segmentation idea sounds a little cleaner- a temporary GDT is a lot simpler than a temporary page directory.
At the risk of sounding obsessive, I don't quite like the GDT trick either. Is there a better way to set up a mapping like that with the GDT? Also, out of curiosity, does anyone know how any mainstream kernels do it?
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 6:45 am
by thepowersgang
Afaik, most kernels have the higher half mapping set up using paging and link the entire kernel to the high address.
There is a small assembly stub that is linked to low memory that handles the initial setup (so, enables paging)
Personally, I see the GDT trick as a bit of an unnecessary hack, but others see it as cleaner.
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 7:37 am
by Rusky
Indeed. I am using a small stub to map the kernel, but just setting up paging appears to require less-clean hacks, because neither the page directory nor the kernel heap are at the address in the symbol table until paging is enabled. I could do some pointer fiddling, but that requires a temporary heap allocator to use the physical address of the heap.
It seems I need a temporary something- a page directory, a GDT or a heap allocator. The first two require temporary tables and the second requires extra messing with pointers, so at this point it's just a question of which one is more understandable, I guess.
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 7:55 am
by thepowersgang
it shouldn't be that difficult, just make a compile-time page directory and table with physical addresses, and take that address using "mov eax, gPageDir - KERNEL_BASE"
I have this code in a single ASM file that handles switching to higher half all on it's own, meaning I can assume that I'm already there everywhere else.
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 8:02 am
by Solar
Just throwing this in without really knowing whether it's appropriate:
Higher Half bare bones.
(Consider this a drive-by linking. No idea whether it solves OP's problem.)
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 8:54 am
by Rusky
The problem with making a compile-time page directory with 4k pages is that technically the number of tables isn't set, so I'm not sure how I would go about building it without a lot of tedium and the risk of going over one page and having it not mapped in the future.
It also looks better to map things in a while loop. A language with a better macro system could solve this, but the only one I even know
of with that kind of power is Lisp, which isn't exactly optimal for this kind of project. :/
The higher-half barebones does things the same as Pistachio but is a lot simpler, so good link.
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 8:55 am
by Owen
Rusky wrote:The problem with making a compile-time page directory with 4k pages is that technically the number of tables isn't set, so I'm not sure how I would go about building it without a lot of tedium and the risk of going over one page and having it not mapped in the future.
It also looks better to map things in a while loop. A language with a better macro system could solve this, but the only one I even know
of with that kind of power is Lisp, which isn't exactly optimal for this kind of project. :/
The higher-half barebones does things the same as Pistachio but is a lot simpler, so good link.
Turn on PSE. Map your kernel with a 4 or 2MB page built into the binary. Use those paging structures for the kernel/task 0 as appropriate. Job done.
(The only time I would do things differently is if i wanted a position independent kernel)
Re: Higher-Half Startup
Posted: Thu Sep 30, 2010 9:07 am
by Rusky
4Mib pages can be used along with 4Kib ones, duh. Thanks for sort-of pointing that out, Owen. That gets rid of the heap requirement, but the kernel could still go above 4Mib... initializing the page directory at its physical address would still work, it would just require a bit of pointer trickery- a lot simpler than a completely separate heap allocator.
Thanks all for putting up with my slowness.