Page 1 of 1

How to make GDB work with a high-half kernel?

Posted: Sun Sep 27, 2020 2:49 am
by technix
Since I am the kind of guy that just hates printf debugging, I need GDB to work when debugging my kernel. However when I attempted to create a high-half kernel, GDB gets itself confused after the kernel relocated itself. How to deal with that?

What I have in mind is to create both a Multiboot/EFI compatible kernel loader that is intended to run as a low half code, and compile the kernel proper as a high half ELF file to be loaded by that kernel loader. However the problem here is that how can the kernel loader load the kernel proper, given it is based on Multiboot?

Re: How to make GDB work with a high-half kernel?

Posted: Sun Sep 27, 2020 6:38 am
by bzt
technix wrote:Since I am the kind of guy that just hates printf debugging, I need GDB to work when debugging my kernel. However when I attempted to create a high-half kernel, GDB gets itself confused after the kernel relocated itself. How to deal with that?
Do it the other way around. Make the higher-half the default, and handle the pre-relocation addresses specially. I mean write the linker script in a way, that when you dump the symbols in your kernel, then you should see higher-half addresses.
technix wrote:What I have in mind is to create both a Multiboot/EFI compatible kernel loader that is intended to run as a low half code, and compile the kernel proper as a high half ELF file to be loaded by that kernel loader. However the problem here is that how can the kernel loader load the kernel proper, given it is based on Multiboot?
This is exactly what the BOOTBOOT Protocol is about. The x86_64-bios version is also Multiboot compatible, and there's a x86_64-efi version. They run in lower-half, and load a kernel into higher-half. This way you don't have to care about the relocation and mappings, you can simply link your kernel at higher-half and you're good to go (example hello world kernel and linker script provided). You can use my loader or you can study its source (Open Source, MIT licensed).

Cheers,
bzt

Re: How to make GDB work with a high-half kernel?

Posted: Sun Sep 27, 2020 11:02 am
by thewrongchristian
technix wrote:Since I am the kind of guy that just hates printf debugging, I need GDB to work when debugging my kernel. However when I attempted to create a high-half kernel, GDB gets itself confused after the kernel relocated itself. How to deal with that?

What I have in mind is to create both a Multiboot/EFI compatible kernel loader that is intended to run as a low half code, and compile the kernel proper as a high half ELF file to be loaded by that kernel loader. However the problem here is that how can the kernel loader load the kernel proper, given it is based on Multiboot?
https://wiki.osdev.org/Higher_Half_x86_ ... #linker.ld

You split your code into bootstrap (pre-paging) code, and regular higher half (post-paging) code.

The bootstrap code will be loaded by grub at, say 0x00100000, and your bootstrap code will be linked to run at that address. The bootstrap code then maps (say) 0xc0100000 VA to 0x00100000 PA, and now all your regular kernel code is mapped to run from 0xc0100000 and your bootstrap code then jumps to the post-paging code.

Re: How to make GDB work with a high-half kernel?

Posted: Mon Sep 28, 2020 2:00 am
by technix
bzt wrote:This is exactly what the BOOTBOOT Protocol is about. The x86_64-bios version is also Multiboot compatible, and there's a x86_64-efi version. They run in lower-half, and load a kernel into higher-half. This way you don't have to care about the relocation and mappings, you can simply link your kernel at higher-half and you're good to go (example hello world kernel and linker script provided). You can use my loader or you can study its source (Open Source, MIT licensed).
Is there a 32-bit version? I am still mostly using 32-bit for my kernel since it mainly targets ARMv5 and ARMv7 platforms.

Re: How to make GDB work with a high-half kernel?

Posted: Mon Sep 28, 2020 8:44 am
by bzt
technix wrote:Is there a 32-bit version? I am still mostly using 32-bit for my kernel since it mainly targets ARMv5 and ARMv7 platforms.
No, BOOTBOOT Protocol is 64 bit (FYI: you need 64 bits to store the characters "BOOTBOOT").

But you can compile almost everything for 32 bit too, only the page table creation needs adjustments (as paging table looks different for 32 bit).

The BIOS and coreboot versions are running in protected mode, they have just a very minimal long mode trampoline code. UEFI mostly written in C. For the RPi version, you'll need to modify boot.S too. Not easy, as AArch64 uses different mnemonics than AArch32. There's a minimal inline assembly for enabling the MMU, that needs to be changed to AArch32 mnemonics too, otherwise it's C, should compile without probs. Good luck porting!

Cheers,
bzt

Re: How to make GDB work with a high-half kernel?

Posted: Mon Sep 28, 2020 8:35 pm
by technix
bzt wrote:
technix wrote:Is there a 32-bit version? I am still mostly using 32-bit for my kernel since it mainly targets ARMv5 and ARMv7 platforms.
No, BOOTBOOT Protocol is 64 bit (FYI: you need 64 bits to store the characters "BOOTBOOT").

But you can compile almost everything for 32 bit too, only the page table creation needs adjustments (as paging table looks different for 32 bit).

The BIOS and coreboot versions are running in protected mode, they have just a very minimal long mode trampoline code. UEFI mostly written in C. For the RPi version, you'll need to modify boot.S too. Not easy, as AArch64 uses different mnemonics than AArch32. There's a minimal inline assembly for enabling the MMU, that needs to be changed to AArch32 mnemonics too, otherwise it's C, should compile without probs. Good luck porting!

Cheers,
bzt
That ARMv5/v7 board normally uses Das U-boot but it requires out-of-tree patches on an extremely outdated version. This is why I want a 32-bit BOOTBOOT for my ARM board so I can do this:
  1. Upon boot, the on-chip ROM reads the boot eMMC for a boot image. The boot image contains three parts: early startup code, BOOTBOOT, and drivers for reading eMMC and UART. Since BOOTBOOT is small enough, it can fit within the on-chip SRAM.
  2. Early startup code prepares the UART and DRAM controller for BOOTBOOT, then control is handed over to BOOTBOOT.
  3. BOOTBOOT reads the eMMC and loads the kernel from there.