Fix higher half kernels by identity mapping context switch fn earlier#161
Fix higher half kernels by identity mapping context switch fn earlier#161
Conversation
|
@phil-opp now it works perfectly! Though setting the physical memory offset to |
|
Great to hear that!
Hmm, could you show the ELF program header of your kernel, e.g. via |
We used to reverve two frames to allow the context switch function to identity-map itself after creating the boot info. This works for kernels that use the standard mapping since they don't need to create new level 3/2 page tables for that. For kernels that are mapped differently (e.g. to the higher half), two frames aren't enough and a frame allocation error occurs. While we could fix this by reserving a larger number of frames, this would result in lost frames for normally-mapped kernels. So we instead do the identity-mapping already in the `set_up_mappings` function, where the normal frame allocator still exists. This way, we no longer need the `TwoFrames` workaaround at all. To ensure that this all works as intended, this PR also adds a new `higher_half` test kernel that maps itself to address `0xFFFF800000000000` via its custom target. By reading the `rip` register, the test kernel can verify that it was indeed loaded to the higher half.
d34e44f to
3be235b
Compare
ENTRY(_start)
OUTPUT_FORMAT(elf64-x86-64)
KERNEL_OFFSET = 0xFFFF800000100000;
SECTIONS {
. = KERNEL_OFFSET;
. += SIZEOF_HEADERS;
. = ALIGN(4096);
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
__text_start = .;
*(.text*)
. = ALIGN(4096);
__text_end = .;
}
.rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
__rodata_start = .;
*(.rodata*)
. = ALIGN(4096);
__rodata_end = .;
}
.data : AT(ADDR(.data) - KERNEL_OFFSET) {
__data_start = .;
*(.data*)
. = ALIGN(4096);
__data_end = .;
__bss_start = .;
*(.bss*)
. = ALIGN(4096);
__bss_end = .;
}
.tdata : AT(ADDR(.tdata) - KERNEL_OFFSET) {
__tdata_start = .;
*(.tdata*)
. = ALIGN(4096);
__tdata_end = .;
__tbss_start = .;
*(.tbss*)
. += 8;
. = ALIGN(4096);
__tbss_end = .;
}
__kernel_end = .;
/DISCARD/ : {
*(.comment*)
*(.eh_frame*)
*(.gcc_except_table*)
*(.note*)
*(.rel.eh_frame*)
}
} |
|
@Andy-Python-Programmer Thanks! I don't see anything problematic. Normally the bootloader should just ignore the |
|
Thanks a lot, that was quick :D. It looks like you tried to map both the kernel and the physical memory mapping at address |
|
Ah all good! Thanks @phil-opp! |
|
You're welcome! Thanks for the help in debugging this! |
|
Published as v0.10.4. |


We used to reverve two frames to allow the context switch function to identity-map itself after creating the boot info. This works for kernels that use the standard mapping since they don't need to create new level 3/2 page tables for that. For kernels that are mapped differently (e.g. to the higher half), two frames aren't enough and a frame allocation error occurs. While we could fix this by reserving a larger number of frames, this would result in lost frames for normally-mapped kernels. So we instead do the identity-mapping already in the
set_up_mappingsfunction, where the normal frame allocator still exists. This way, we no longer need theTwoFramesworkaaround at all.To ensure that this all works as intended, this PR also adds a new
higher_halftest kernel that maps itself to address0xFFFF800000000000via its custom target. By reading theripregister, the test kernel can verify that it was indeed loaded to the higher half.Fixes #159