Higher half and kernel linking

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Higher half and kernel linking

Post by Rusky »

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 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 the 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?
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Higher half and kernel linking

Post by neon »

Hello,

System data structures (GDT,IDT) can and should be setup during kernel initialization -- before or after memory management. So all of (3) can be setup later on. By having the kernel copy the data structures used by Grub locally (on a stack), the memory manager can work off of this copy without error.

This is what we do with regards to enabling paging: We link using a virtual base address but tell the bootloader to load it to a physical address and call it there. Enabling paging must then be done using position independent code.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Higher half and kernel linking

Post by xenos »

In my linker script I reserve some space for the GDT, IDT, page tables and so on. When GRUB loads my kernel, it reads the ELF header and keeps its data structures (multiboot info, memory map, modules...) out of the reserved space. The startup code can then simply fill the reseved space with GDT, IDT and so on, without trashing any important data.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Higher half and kernel linking

Post by egos »

It's bad idea.
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Higher half and kernel linking

Post by Combuster »

It's bad idea.
proof wanted.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Higher half and kernel linking

Post by egos »

A "higher-half userspace" requires to store fixup information into application executable module and relocate it (in most cases) if kernel space resizing allowed.

To topic starter: maybe to use "binary" output format (instead ELF) is better solution for you.
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Re: Higher half and kernel linking

Post by Rusky »

I think I'm going with a small, identity-mapped startup routine where I'll copy the MBI to a temporary heap, enable paging with temporary page tables, and then initialize the rest (with the physical memory manager accessing the copied MBI and running from its virtual address).

Flat binaries would just make things more complicated in this case, because GRUB already understands ELF section physical addresses.
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Higher half and kernel linking

Post by egos »

berkus wrote:1G/3G kernel/user split is no different from 3G/1G user/kernel split, although slightly simpler (no need to remap low memory).
They differ from one another. What fixed base address should user space have for 1G/2G kernel space? 2G? If so then no reason to have kernel space smaller than with size 2G. And what can I do if I shall have experimental kernel with 3G space?
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: Higher half and kernel linking

Post by Velko »

I use something similar to XenOS's method - reserve some space (128K I think) at the end of kernel using linker script. Then with help of one extra variable it's easy (even in assembly) to "grab" some pages for stack, PD, PT, etc. from there.

What remains after "grabbing" is handed over to kmalloc(). And memory for GDT, IDT and whatever else I need is kmalloc()ated.
If something looks overcomplicated, most likely it is.
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: Higher half and kernel linking

Post by egos »

Rusky wrote:Flat binaries would just make things more complicated in this case, because GRUB already understands ELF section physical addresses.
Well, if you want to use complicated ELF instead complicated "binary" format, it's your business. GRUB uses one type of section address (not physical and virtual separately) to load sections into memory at physical addresses.
If you have seen bad English in my words, tell me what's wrong, please.
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Re: Higher half and kernel linking

Post by Rusky »

egos wrote:Well, if you want to use complicated ELF instead complicated "binary" format, it's your business. GRUB uses one type of section address (not physical and virtual separately) to load sections into memory at physical addresses.
ELF is complicated, sure, but GRUB handles it all for you. I need separate physical and virtual addresses for whichever format I use, to tell the linker where code should run and to tell GRUB where it should be loaded, so switching to flat binaries would introduce more complexity on my end.

A higher-half kernel seems like a good idea to me, since growing it down would just move the application's stack, not its code. The stack is just a run-time pointer, but moving code means recompiling or relocating. It's not all that important, but I need the mechanisms to set up a higher-half kernel anyway, and whether I should use higher-half wasn't even the question here.

One other question I do have is how to deal with code that needs to run both before and after initialization- mostly the strings library with strlen, strcpy, memcpy, etc. Is there a good way to duplicate those functions into the init section and then get things to link correctly?
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Higher half and kernel linking

Post by bluemoon »

strlen, strcpy, memcpy, etc should be easy to code as position independent.

Then the question is how to call the function with proper address.
You can link them as virtual address,
to call it before paging is enabled (which I don't see a need), you can use a macro to translate it to physical address, eg.

Code: Select all

%define PhysicalAddress(x) ((x) - kernel_base)
call PhysicalAddress(strlen)

OR

%define phy_strlen   (strlen - kernel_base)
call phy_strlen
after paging is initialized you call the function as usual.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Higher half and kernel linking

Post by Chandra »

Rusky wrote:The dependencies between these steps are driving me crazy. With higher-half, the kernel is linked at its virtual address and so the options 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.
I like the third option. :wink:
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Higher half and kernel linking

Post by Owen »

4) The kernel binary contains paging structures to map itself, and a page table into which temporary mappings can be placed. As you walk the Multiboot structures, map and unmap them from this table as needed
User avatar
Rusky
Member
Member
Posts: 792
Joined: Wed Jan 06, 2010 7:07 pm

Re: Higher half and kernel linking

Post by Rusky »

Shall we move past the higher-half debate?

It's simpler to copy the multiboot structures- the question is how to call the string functions. I think it should work to just make some static const function pointers in the C startup code that needs to call the string library, but they'd need to use different names...?
Post Reply