Hi, I'm trying to get a 64-bit higher half kernel working, which has been somewhat challenging. I opted to go with a 32-bit bootstrap placed in the physical address space, in which I set up identity mapping and enter Long Mode, then set up real higher-half page tables and then jump into the higher-half. The relevant part of the bootstrap code is:
Code:
extern Entry64
InLongMode:
; Reload every data segment with 0 (Long-mode doesn't use segmentation)
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; This sets up the higher half page tables
call MapHigherHalf
; Correct the address of the Multiboot structure
add rdi, 0xffffff0000000000
lea rax, [Entry64]
jmp rax
Entry64 is defined in another file (linked into the virtual address space with a base of 0xffffff0000100000):
Code:
bits 64
section .text
global Entry64
Entry64:
; Print OKAY
mov rax, 0x2f592f412f4b2f4f
mov qword [0xb8000], rax ; TODO: use proper virtual address (this would only work because the identity mapping is still also in place)
hlt
This is all linked into one executable (with the bootstrap at 0x100000 and the rest of the kernel at 0xffffff0000100000) with:
Code:
KERNEL_LMA = 0x100000;
KERNEL_VMA = 0xffffff0000100000;
SECTIONS
{
/*
* First, we physically-map a bootstrap section that will load the 64-bit code. This is required
* because we haven't enabled paging yet, and so code that uses virtual addresses won't work.
*/
. = KERNEL_LMA;
.bootstrap.text :
{
KEEP(*(.multiboot))
*bootstrap.o (.text .text.*)
. = ALIGN(4K);
}
.bootstrap.bss :
{
*bootstrap.o (.bss)
. = ALIGN(4K);
}
.bootstrap.rodata :
{
*bootstrap.o (.rodata .rodata.*)
. = ALIGN(4K);
}
/*
* Then, we place everything else at proper virtual addresses
*/
. = KERNEL_VMA;
.rodata : AT(ADDR(.rodata) - KERNEL_VMA)
{
*(EXCLUDE_FILE(bootstrap.o) .rodata .rodata.*)
. = ALIGN(4K);
}
...
However, it seems to emit the incorrect relocation to load the address of Entry64 (I don't understand why this doesn't output a R86_64_64 type relocation):
Code:
relocation truncated to fit: R_X86_64_32S against symbol `Entry64' defined in .text section in /home/isaac/Documents/RustOS/build/x86_64/entry64.o
There also seem to be problems with Entry64:
Code:
entry64.s:11:(.stab+0x14): relocation truncated to fit: R_X86_64_32 against `.text'
entry64.s:11:(.stab+0x20): relocation truncated to fit: R_X86_64_32 against `.text'
entry64.s:12:(.stab+0x2c): relocation truncated to fit: R_X86_64_32 against `.text'
entry64.s:12:(.stab+0x38): relocation truncated to fit: R_X86_64_32 against `.text'
What's causing these issues, and is this even a sensible approach to 64-bit higher half? I came across
this thread and tried to find the NASM version of movabs without success, but I think it should've just loaded the 64-bit addresses correctly? Thank you in advance, and sorry if I've cluttered the post with too much code etc.