Higher-Half Startup
Higher-Half Startup
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?
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
A common method is to take advantage of segmentation offsets. IMO, it sounds like the easiest way.
Re: Higher-Half Startup
It depends a little on how you intend to load your kernel. From a boot sector ? Your own loader ? Or Grub ?
If a trainstation is where trains stop, what is a workstation ?
Re: Higher-Half Startup
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?
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?
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
Re: Higher-Half Startup
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.
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.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Re: Higher-Half Startup
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.
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.
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
Re: Higher-Half Startup
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.
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.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Re: Higher-Half Startup
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.)
(Consider this a drive-by linking. No idea whether it solves OP's problem.)
Every good solution is obvious once you've found it.
Re: Higher-Half Startup
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.
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.
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: Higher-Half Startup
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.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.
(The only time I would do things differently is if i wanted a position independent kernel)
Re: Higher-Half Startup
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.
Thanks all for putting up with my slowness.