Page 1 of 1

Higher Half Kernel and how linker work

Posted: Wed Feb 02, 2022 7:14 am
by mrjbom
Hello.

I'm following the tutorial on creating a higher half kernel, but I can't figure out why, when accessing each symbol in the code, 0xC0000000 is subtracted

In the first line in the _start function, when accessing the boot page table, 0xC0000000 is subtracted from it

Code: Select all

# Physical address of boot_page_table1.
movl $(boot_page_table1 - 0xC0000000), %edi
or there

Code: Select all

# Map the page table to both virtual addresses 0x00000000 and 0xC0000000.
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
Why do this? After all, in the linker using AT(addr) we indicate the real location of the section in the lower half, then why subtract?
I assume that the changed

Code: Select all

. += 0xC0000000;
value of the "." operator affects the symbol table and they really point to the higher half, but I did not find confirmation of this in the linker documentation.

Re: Higher Half Kernel and how linker work

Posted: Wed Feb 02, 2022 8:17 am
by nexos
To be honest, the wiki example doesn't make a lot of sense. The page table probably should go in the .multiboot.data section. Then the AT directives would be unnecessary, and the example would be a lot cleaner.

Re: Higher Half Kernel and how linker work

Posted: Wed Feb 02, 2022 10:00 am
by mrjbom
nexos wrote:To be honest, the wiki example doesn't make a lot of sense. The page table probably should go in the .multiboot.data section. Then the AT directives would be unnecessary, and the example would be a lot cleaner.
However, this does not negate the issue.
Why, despite the AT directive, when accessing page table and page directory, 0xC0000000 is subtracted? Shouldn't the symbol itself refer to the lower half?

Re: Higher Half Kernel and how linker work

Posted: Wed Feb 02, 2022 11:06 am
by vhaudiquet
The "AT" directive specifies the *load address* of the section, not the address of the symbols (cf https://ftp.gnu.org/old-gnu/Manuals/ld- ... ld_21.html).

Here, the symbol 'boot_page_table1' is in the bss section, which is loaded at physical 0x100000 + sizeof(text) + sizeof(rodata) + sizeof(data), and has symbols with addresses at 0xC0100000 + ..., because of the linker script. This makes sense because C code in higher half will need to access bss, but if we want to use bss before jumping higher we have to do conversions by hand, thus substracting 0xC0000000. Another option could have been to make a specific '.bss.boot' section, but i would not do it for bss, as i want to be able to access boot allocated objects in C code later.

Re: Higher Half Kernel and how linker work

Posted: Wed Feb 02, 2022 12:27 pm
by mrjbom
vhaudiquet wrote:The "AT" directive specifies the *load address* of the section, not the address of the symbols (cf https://ftp.gnu.org/old-gnu/Manuals/ld- ... ld_21.html).
That's exactly what I assumed, just wanted to make sure.
I was confused by the fact that the linker documentation does not say anywhere about how the address referenced by the symbol is calculated.

So the address to which the symbol refers is calculated using the operator "." and what section contains the data to which it refers?
All symbols that do not refer to the data declared in the .multiboot.data and .multiboot.data sections will work fine when I switch to the higher half?