OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Nov 21, 2017 11:06 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: [SOLVED] 64-bit Higher Half relocation issues
PostPosted: Sun Oct 08, 2017 3:09 pm 
Offline
Member
Member

Joined: Sun Sep 06, 2015 5:40 am
Posts: 29
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.


Last edited by BaconWraith on Tue Oct 10, 2017 11:41 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: 64-bit Higher Half relocation issues
PostPosted: Sun Oct 08, 2017 3:41 pm 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 373
Code:
entry64.s:11:(.stab+0x14): relocation truncated to fit: R_X86_64_32 against `.text'

means that the linker cannot satisfy a relocation that has an offset larger than 4 GiB.

In 64-bit code things like loads from memory and jumps/calls are still limited to 4 GiB. As the address space is much larger, instead of 32-bit absolute offsets RIP-relative offsets are used. If you want absolute 64-bit addressing, you need to load the address into a register first (using movabs).

The offending code is
Code:
lea rax, [Entry64]

Use
Code:
movabs rax, Entry64

instead. (I'm not sure if your assembler uses the mov mnenomic for the movabs instruction but considering that your code does assemble with 64-bit mov instructions, I guess it does.)


Top
 Profile  
 
 Post subject: Re: 64-bit Higher Half relocation issues
PostPosted: Sun Oct 08, 2017 4:05 pm 
Offline
Member
Member

Joined: Sun Sep 06, 2015 5:40 am
Posts: 29
Okay, so NASM doesn't provide movabs, but I've replaced the
Code:
lea rax, [Entry64]

with:
Code:
mov rax, qword Entry64

which seems to disassemble to (obviously it won't be clear whether this actually does the relocation correctly until the link succeeds):
Code:
48 b8 00 00 00 00 00 00 00 00 movabs rax, 0x0


However, I still have problems. This hasn't got rid of the relocation problems in Entry64, nor has it produced correct code for this (with or without the 'qword'):
Code:
add rdi, qword 0xffffff0000000000

turns into:
Code:
48 83 c7 00       add rdi, 0x0

The 0x48 prefix leads me to think its worked out it needs to produce 64-bit code, but then it only emits a 1-byte immediate!


Top
 Profile  
 
 Post subject: Re: 64-bit Higher Half relocation issues
PostPosted: Sun Oct 08, 2017 4:46 pm 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 373
There is no "add r/m64, imm64". movabs is the only instruction that takes a 64-bit immediate value. So load the value into a register first and then add it.


Top
 Profile  
 
 Post subject: Re: 64-bit Higher Half relocation issues
PostPosted: Sun Oct 08, 2017 6:39 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 1179
BaconWraith wrote:
What's causing these issues, and is this even a sensible approach to 64-bit higher half?

Most instructions can only use 32-bit immediates and offsets, even though you're in 64-bit mode. The only instruction that can use a 64-bit immediate or offset is MOV. (AT&T syntax calls this "movabs".)

Most developers choose a kernel base address around -2GB (0xFFFFFFFF80000000) so kernel symbols can use R_X86_64_32S relocations. This choice also gives the most freedom to user-mode software, since the lowest 2GB of address space may use both R_X86_64_32 and R_X86_64_32S relocations.

BaconWraith wrote:
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?

The NASM equivalent of movabs looks like this:
Code:
mov <r64>, qword <symbol>
mov al/ax/eax/rax, [qword <symbol>]
mov [qword <symbol>], al/ax/eax/rax


Top
 Profile  
 
 Post subject: Re: 64-bit Higher Half relocation issues
PostPosted: Tue Oct 10, 2017 11:41 am 
Offline
Member
Member

Joined: Sun Sep 06, 2015 5:40 am
Posts: 29
Thank you both for your replies! I've read up a little on that and probably should've known that I needed to use mov to load 64-bit immediates :oops: . I've moved the kernel base to 0xffffffff80000000, but this doesn't get rid of the .stab relocation truncations. Looking into it, .stab seems to be a obsolete debug symbol format, so I tried making NASM use DWARF with -Fdwarf and this seems to fix the relocation issues with that. Of course, it still doesn't work, but I'll try to figure out that on my own! Thank you very much again for your help and advice, and sorry for it being such a simple set of fixes


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: AwfulMint, Bing [Bot], Google [Bot] and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group