Moving to x86_64 (Solved)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
blacky
Posts: 20
Joined: Mon Apr 06, 2015 3:59 am

Moving to x86_64 (Solved)

Post by blacky »

Hello together,

since I recently managed to conquer the challenges of the x86 bootstrap process with my 32-bit mini-kernel, I wanted to go a step further and port my code base to x86_64 and finally enter long mode. From this point on, my progress got frozen: For some reason, qemu and bochs do not recognize the multiboot header of my image. I tried the same with a multiboot2 header - without any success. I found a lot of similar issues on the web and as well here in the forum but, they did not help. Which is why I am reopening this topic and really hope for constructive hints.

In other threads, a wrong placement of the multiboot header appeared to be the issue. However in my case, at least according to readelf and objdump, the multibootheader is placed correctly within the first page at the start address 0x100000.

Here is my bootstrap entry code (Within the code, a multiboot and multiboot2 header are present: Please note that I used only one multiboot header at a time for testing):

Code: Select all

.intel_syntax noprefix
.code32

# ----------------------------------------------------------------------
# .multiboot: declare header in mutliboot standard

.section .multiboot
.code32
.align 8 

	# constants for multiboot header:
	.set ALIGN, 1<<0                # align loaded modules on page boundaries
	.set MEMINFO, 1<<1              # provide memory map
	.set FLAGS, ALIGN | MEMINFO     # multiboot flags
	.set MAGIC, 0x1BADB002          # 'magic number' lets bootloader find header
	.set CHECKSUM, (-(MAGIC + FLAGS) & 0xffffffff) # checksum of the mboot header

     /* multiboot header */
    .long MAGIC
    .long FLAGS
    .long CHECKSUM

     /* performing tests with the multiboot2 header */
mboot2_start:
    .long 0xe85250d6
    .long mboot2_end - mboot2_start
    .long (-(0xe85250d6 + 0 + (mboot2_end - mboot2_start)) & 0xffffffff)
mboot2_end:


# ----------------------------------------------------------------------
# allocate some stack space

.section .bootstrap.stack, "aw", @nobits

stack_bottom:
	.skip 16384    # 16 KB
stack_top:



# ----------------------------------------------------------------------
# .text: the global function _start represents our kernel entry point in
#        our .text segment

.section .text
.code32

    .globl _start
	.type _start, @function

_start:
    cli
    lea esp, stack_top    

.hang:
    cli
    hlt
    jmp .hang
And here is my linker script:

Code: Select all

NTRY(_start)

SECTIONS
{
    . = 0x00100000;

    .text ALIGN(0x1000) :
    {
        *(.multiboot)
        *(.text .text.* .gnu.linkonce.t.*)
    }
    
    .rodata ALIGN(0x10) :
    {
        PROVIDE (_srodata = .);
        
        start_ctors = .;
        *(SORT(.ctors*))
        end_ctors = .;

        start_dtors = .;
        *(SORT(.dtors*))
        end_dtors = .;
        
        *(.rodata*)
        *(.gnu.linkonce.r*)
        
        PROVIDE (_erodata = .);
    }

    .data ALIGN(0x10) :
    {
        PROVIDE (_sdata = .);
        
        *(.data*)
        *(.gnu.linkonce.d*)
        
        PROVIDE (_edata = .);
    }

    .bss ALIGN(0x10) :
    {
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(.bootstrap.stack)
    }

    /DISCARD/ :
    {
        *(.note)
        *(.comment)
        /* *(.eh_frame) */ /* discard this, unless you are implementing runtime support for C++ exceptions. */
    }
}
Again, thank you very much in advance :)
Last edited by blacky on Thu May 07, 2015 9:34 am, edited 1 time in total.
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: Moving to x86_64

Post by thepowersgang »

Actually... neither grub nor qemu can load ELF64 binaries, which is what I assume you're linking to. You will either want to write a stub loader, or do the semi-evil hack of using 'objcopy' to convert the elf64 output from ld into an elf32 binary.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
User avatar
Roman
Member
Member
Posts: 568
Joined: Thu Mar 27, 2014 3:57 am
Location: Moscow, Russia
Contact:

Re: Moving to x86_64

Post by Roman »

What bootloader do you use? GRUB2 should be fine with ELF64 (but with a 32-bit bootstrap!).
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay
blacky
Posts: 20
Joined: Mon Apr 06, 2015 3:59 am

Re: Moving to x86_64

Post by blacky »

Thank you very much! I have been using grub (not grub2 -.-), which explains my issue. Didn't know that grub does not support elf64 binaries.
I will try to solve my issue soon.
blacky
Posts: 20
Joined: Mon Apr 06, 2015 3:59 am

Re: Moving to x86_64

Post by blacky »

To close this thread, I would like to post my approach that led to success:

As stated above, the idea was to jump into long mode right after initial bootstrapping. My first approach was to combine my 64 bit kernel with a smaller 32 bit bootstrap code in one ELF file. To satisfy the linker, both files needed to be compiled as ELF64 binaries (using .code32 directives for the bootstrap code). Although GRUB2 should be able to load ELF64 binaries, I got pretty fast into troubles as the bootloader did not recognize neither the multiboot 1 nor the multiboot 2 header. Unfortunately, I did not find a solution and tried another approach.

My second approach was to create two binaries: an ELF32 file for the bootstrap code and an ELF64 file for the actual kernel. In addition to the initial system setup, the process of bootstrapping took over the responsibility of loading and parsing the ELF64 kernel image that has been loaded as a grub module The kernel is then mapped to an appropriate virtual address after paging and long mode initialization. Finally, the mapped 64 bit kernel can be executed in long mode :)
Post Reply