QEMU error
Posted: Tue Oct 02, 2018 2:52 pm
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:
Can't understand why... Can you help me with this?
Thanks in advance
boot.S
linker.ld
It stops while setting cr0 at:
Code: Select all
mov %ecx, %cr0
Can't understand why... Can you help me with this?
Thanks in advance
boot.S
Code: Select all
# 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
Code: Select all
/* 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. */
}