OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 25, 2024 2:15 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: QEMU error
PostPosted: Tue Oct 02, 2018 2:52 pm 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
I'm trying to implement an higher-half kernel like in the tutorial in the wiki (before setting up paging), but when I run it in QEMU it throws "qemu: fatal: Trying to execute code outside RAM or ROM at 0x00100029" with all the registers.
It stops while setting cr0 at:
Code:
mov %ecx, %cr0

Can't understand why... Can you help me with this?

Thanks in advance

boot.S
Code:
# AT&T's Syntax
.global _loader

# Declare multiboot headers constants.
.set ALIGN,    1<<0                                         # align loaded modules on page boundaries
.set MEMINFO,  1<<1                                         # provide memory map
.set FLAGS,    ALIGN | MEMINFO                              # this is the Multiboot 'flag' field
.set MAGIC,    0x1BADB002                                   # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS)                             # checksum of above, to prove we are multiboot

# This is the virtual base address of kernel space.
# It must be used to convert virtual addresses into physical addresses
# until paging is enabled.
# Note that this is not the virtual address where the kernel image itself is loaded
# just the amount that must be subtracted from a virtual address to get physical address.
.set KERNEL_VIRTUAL_BASE, 0xC0000000                         # 3 GB
.set KERNEL_PAGE_NUMBER, (KERNEL_VIRTUAL_BASE >> 2)          # Page directory index of kernel's 4MB PTE

.section .multiboot
.align 4
    .long MAGIC
    .long FLAGS
    .long CHECKSUM

.section .data
.align 0x1000
BootPageDirectory:
    push %ecx
    # This page directory entry identity-maps the first 4MB of the 32-bit physical address space.
    # All bits are clear except the following: 
    #   - bit 7: PS The kernel page is 4MB.
    #   - bit 1: RW The kernel page is read/write.
    #   - bit 0: P  The kernel page is present (in RAM).
    # This entry must be here -- otherwise the kernel will crash immediately after paging is enabled
    # because it can't fetch the next instruction! It's ok to unmap this page later.
    .quad 0x00000083
    mov $(KERNEL_PAGE_NUMBER - 1), %ecx
    1:
        .quad 0                                             # Pages afetr the kernel image
        cmp $0, %ecx
        jnz 1
    # This page directory entry defines a 4MB page containing the kernel
    .quad 0x00000083
    mov $(1024 - KERNEL_PAGE_NUMBER - 1), %ecx
    2:
        .quad 0                                             # Pages afetr the kernel image
        cmp $0, %ecx
        jnz 2
   
    pop %ecx

# Declare a header as in the Multiboot Standard.
.section .text
# Reserve initial kernel stack space -- that's 16k
.set STACKSIZE, 0x4000

# Setting up entry point for linker.
# The kernel entry point.
.global __start__
.set __start__, (setup)
setup:   
    # NOTE: Until paging is set up, the code must be position-independent and
    # use physical addresses, not virtual ones!
    mov $(BootPageDirectory - KERNEL_VIRTUAL_BASE), %ecx
    mov %ecx, %cr3                                          # Load Page Directory Base Register.

    mov %cr4, %ecx
    or $0x00000010, %ecx                                    # Set PSE bit in CR4 to enable 4MB pages.
    mov %ecx, %cr4   

    mov %cr0, %ecx
    or $0x80000000, %ecx                                    # Set PG bit in CR0 to enable paging.
    mov %ecx, %cr0

    # Start fetching instructions in kernel space.
    # Since 'eip' at this point holds physical address of this command (approximately 0x00100000)
    # we need to do a long jump to the correct virtual address of
    # StartInHigherHalf which is approximately in 0xC0100000.
    lea (StartInHigherHalf), %ecx
    jmp *(%ecx)                                                # Note: Must be absolute jump!

StartInHigherHalf:
    # Unmap the identity-mapped firts 4MB of physical address space.
    # It should not be needed anymore.
    movw $0, (BootPageDirectory)
    invlpg (0)

    # Note: From now on, paging should enabled. The first 4MB of physical address space
    # is mapped starting at KERNEL_VIRTUAL_BASE. Everything is linked to this address,
    # so no more position-independent code or funny business with virtual-to-physical address
    # translation should be necessary. We now have a higher-half kernel.
    mov $(stack + STACKSIZE), %esp                          # Setup the stack
    push %eax                                               # Pass Multiboot magic number

    # Pass Multiboot info structure --
    # WARNING: This is a physical address and may not be in the first 4 MB!
    push %ebx

    # Call the global constructors.
    call _init

    # Transfer control to the main kernel.
    call kmain

    # Hang if kmain unexpectedly returns.
    cli
    1:   hlt
        jmp 1

# Reserve a stack for the initial thread.
.section .bss
.align 32

.lcomm stack, STACKSIZE                                 # Reserve 16k stack on a uint64_t boundary


# This part is not reachable (beacuse of the endless loop),
# except if you call _gdtFlush


# This will set up our new segment registers. We need to do
# something special in order to set CS. We do what is called a
# far jump. A jump that includes a segment as well as an offset. 

.global gdtFlush                                        # Allows the C code to link to this
.extern gp                                              # Says that 'gp' is in another file

gdtFlush:
    # Set our own GDT, can't rely GDT register being valid after bootloader
    # transfers control to our entry point 
    lgdt (gp)                                           # Load the GDT with 'gp' which is a special pointer

    mov $0x10, %eax                                     # 0x10 is the offset in the GDT to our data segment
    mov %eax, %ds               
    mov %eax, %es
    mov %eax, %gs
    mov %eax, %fs
    mov %eax, %ss

    ljmp $0x08, $setcs                                  # Set new CS at 0x08

    setcs:
        ret

linker.ld
Code:
/* The bootloader will look at this image and start execution at the symbol
   designated at the entry point. */
ENTRY(__start__)
OUTPUT_FORMAT(elf32-i386)

/* Tell where the various sections of the object files will be put in the final
   kernel image. */
SECTIONS {
   /* The kernel will live at 3GB + 1MB in the virtual address space,
      which will be mapped to 1MB in the physical address space. */
   . = 0xC0100000;

   /* First put the multiboot header, as it is required to be put very early
      early in the image or the bootloader won't recognize the file format.
      Next we'll put the .text section. */
   .text ALIGN(0x1000) : AT(ADDR(.text) - 0xC0000000) {
      *(.multiboot)
      *(.text)
   }

   .rodata ALIGN(0x1000) : AT(ADDR(.rodata) - 0xC0000000) {
      /* Read-only data */
      *(.rodata*)
   }

   /* Read-write data (initialized) */
   .data ALIGN(0x1000) : AT(ADDR(.data) - 0xC0000000) {
      *(.data)
   }

   /* Read-write data (uninitialized) and stack */
   .bss ALIGN(0x1000) : AT(ADDR(.bss) - 0xC0000000) {
      _sbss = .;
      *(COMMON)
      *(.bss)
      _ebss = .;
   }

   /* The compiler may produce other sections, put them in the proper place in
      in this file, if you'd like to include them in the final kernel. */
}


Top
 Profile  
 
 Post subject: Re: QEMU error
PostPosted: Tue Oct 02, 2018 7:16 pm 
Offline
Member
Member
User avatar

Joined: Tue Dec 25, 2007 6:03 am
Posts: 734
Location: Perth, Western Australia
You have code in the page directory it seems, which is being interpreted as the page directory (instead of being executed, which is what I think you thought it would do).

You'll want to use the assembler's macro support to generate the boot-time paging structures.

_________________
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc


Top
 Profile  
 
 Post subject: Re: QEMU error
PostPosted: Tue Oct 02, 2018 10:55 pm 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
With this
Code:
mov $(KERNEL_PAGE_NUMBER - 1), %ecx
    1:
        .quad 0                                             # Pages afetr the kernel image
        cmp $0, %ecx
        jnz 1
I'm trying to emulate the "times" prefix which in GAS isn't an instruction. What macro should I use to replace it?


Top
 Profile  
 
 Post subject: Re: QEMU error
PostPosted: Tue Oct 02, 2018 11:59 pm 
Offline
Member
Member
User avatar

Joined: Tue Dec 25, 2007 6:03 am
Posts: 734
Location: Perth, Western Australia
Gas should have similar features (I believe it has `.rept/.endr` directives that do a similar thing).

It might be worth reading through the "Assembler Directives" page of the GAS manual - https://sourceware.org/binutils/docs/as/Pseudo-Ops.html

_________________
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc


Top
 Profile  
 
 Post subject: Re: QEMU error
PostPosted: Wed Oct 03, 2018 12:55 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4597
Location: Chichester, UK
You are confusing assembler directives and run-time behaviour. A loop/jmp can't repeat an assembler directive. As thepowersgang says, use
Code:
.rept KERNEL_PAGE_NUMBER
.quad 0
.endr


Top
 Profile  
 
 Post subject: Re: QEMU error
PostPosted: Wed Oct 03, 2018 10:21 am 
Offline
Member
Member

Joined: Sun Sep 16, 2018 6:46 am
Posts: 56
I've fixed a shift on the set of KERNEL_PAGE_NUMBER (">> 2" in ">> 22") and used the .rept and .endr directives but the error still remains... Other advices?


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: Bing [Bot], Majestic-12 [Bot] and 219 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