Using Grub 2 to load a 64-Bit Kernel

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.
Post Reply
User avatar
CodeJunkie
Posts: 4
Joined: Sat Dec 11, 2010 11:24 am

Using Grub 2 to load a 64-Bit Kernel

Post by CodeJunkie »

Last night during my Grub2 explorations, I discovered Grub2 could load a 64-bit kernel without too much trouble O.o; however, I want to know if I will have any issues loading the kernel this way....

So 64-Bit Kernel Compiled as Flat Binary, loaded by grub as a module
A 32-Bit Entry program that just parses through the loaded modules, grabs the address of the start and end of the 64-Bit Kernel ... then I just jump to it. :shock:

QEMU Doesn't die when I do this, so it must be ok right ?? ...

~~~
Theoretically, if I never use the compatibility modes provided by 64-bit that means I don't have to worry about higher-half mapping? Or should I use higher-half mapping?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Using Grub 2 to load a 64-Bit Kernel

Post by gerryg400 »

CodeJunkie wrote:Last night during my Grub2 explorations, I discovered Grub2 could load a 64-bit kernel without too much trouble O.o; however, I want to know if I will have any issues loading the kernel this way....

So 64-Bit Kernel Compiled as Flat Binary, loaded by grub as a module
A 32-Bit Entry program that just parses through the loaded modules, grabs the address of the start and end of the 64-Bit Kernel ... then I just jump to it. :shock:

QEMU Doesn't die when I do this, so it must be ok right ?? ...

~~~
Theoretically, if I never use the compatibility modes provided by 64-bit that means I don't have to worry about higher-half mapping? Or should I use higher-half mapping?
I'm not 100% sure Grub2 loads 64 bit ELF files as well as it claims to, so your method is the better way.

There are several advantages to having a higher half kernel. 64bit code runs slightly faster and is smaller if you use the 'small' or 'kernel' memory models. If you put your kernel in the -2GB region and load your apps in the 0 to 2GB region, you'll get those slight speed and size benefits.
If a trainstation is where trains stop, what is a workstation ?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Using Grub 2 to load a 64-Bit Kernel

Post by xenos »

I never used this fancy 64 bit loading feature of GRUB2. Instead, I build my 64 bit kernel in such a way that it can be loaded by both GRUB 1 and 2. It is a 64 bit ELF file, but it has a Multiboot 1 header within the first 8k, which makes it look to GRUB as if it was just a flat 32 bit binary. GRUB then simply loads the file into memory without performing any ELF magic, and jumps to the entry point defined in my Multiboot header. At this point the CPU is still in 32 bit mode. The first thing my kernel does is set up some simple 64 bit paging structures and switch to long mode. This is done completely in assembler. After this initialization, it jumps to the C(++) part of the kernel.

The next thing I plan to do is to put a Multiboot 2 header before the Multiboot 1 stuff, so GRUB2 sees a Multiboot 2 kernel and I can play around a bit with the new Multiboot 2 info structures, while still recognizing the Multiboot 1 structures if the kernel is loaded with GRUB1.

There is another important difference betweei GRUB 1 and 2: While GRUB1 places modules right after the kernel, GRUB2 loads them to rather high memory regions.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Using Grub 2 to load a 64-Bit Kernel

Post by Neolander »

As far as I know, GRUB 2 can load load ELF64 binaries, but does not make the switch to long mode. So you'll have to write a 32-bit binary which makes the switch to 64-bit mode yourself.

I didn't use GRUB 2 for my kernel because there is only a small amount of doc about it on the web and because I don't trust a multiboot2 spec which is not even finalized yet. Moreover, I couldn't see a big benefit in using it.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Using Grub 2 to load a 64-Bit Kernel

Post by gerryg400 »

Judging from the grub 2 (v 1.98) source, it does not follow the multiboot 2 spec. There is a file in Grub2 called multiboot2.h but it uses the same structure as the original multiboot spec. However, IIRC, the magic number is different. Totally broken and quite sad.
If a trainstation is where trains stop, what is a workstation ?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Using Grub 2 to load a 64-Bit Kernel

Post by xenos »

I mainly adapted my kernel for working with GRUB 2 because it is installed on many of my Linux PCs, so I can simply put my kernel on them and run it with the already existing bootloader. But it still follows the Multiboot 1 specification and I won't include any fancy Multiboot 2 stuff unless the specification is finalized - digging into Multiboot 2 recently showed me that it is a complete mess, and indeed, GRUB 2 does not even follow these specs. Very sad...
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Neolander
Member
Member
Posts: 228
Joined: Tue Mar 23, 2010 3:01 pm
Location: Uppsala, Sweden
Contact:

Re: Using Grub 2 to load a 64-Bit Kernel

Post by Neolander »

XenOS wrote:There is another important difference betweei GRUB 1 and 2: While GRUB1 places modules right after the kernel, GRUB2 loads them to rather high memory regions.
Wait... Couldn't that be highly problematic, resulting in your kernel being mapped where a module is even if it is mapped at a high linear address, forcing you to check that anytime you want to use a module ?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Using Grub 2 to load a 64-Bit Kernel

Post by xenos »

It is not a real problem, although it makes things a bit difficult:

First, I should have mentioned that GRUB 2 loads modules to a high physical address. For example, in a simulated 256MB RAM machine I find them around 192MB. But this physical address has nothing to do with the linear / virtual addresses I use in my kernel.

Second, there are some difficulties as soon as one starts to map new physical memory into some address space. One needs to make sure not to overwrite any modules by simply mapping their memory regions as if they were free pages, I have solved this by declaring every memory region that is initially needed by my kernel in the linker script, so it is marked as reserved in the ELF kernel file and GRUB (1 / 2) preserves this space when the kernel is loaded. My physical memory manager is located completely within this reserved region of kernel memory, so it does not need to claim any additional memory for its initialization. At startup, it checks the Multiboot info to find out where modules have been loaded, and marks these regions as occupied.

When the kernel has initialized itself, it looks at the modules, which are just further ELF executables, sets up additional address spaces for them, sets up program segments, copies the executable code from the initial load address to the newly created address space, performs relocations, adds the module to the run queue and frees the initial copy of the module loaded by GRUB.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Post Reply