So this issue is occurring again. I can confirm that my exception handlers work and that grub isn't launching my entry symbol (start), so I know this isn't because of a triple fault. I checked this by attaching gdb to the qemu instance and setting a breakpoint (both software and hardware) on the start symbol then continuing execution, but it keeps looping and never reaches the breakpoint.
Useful links:
*
Link script*
Boot assembly fileYou can check the dev branch in the above links for working examples (but without the higher half).
Here are some relevant extracts:
Code:
ENTRY(start)
KERNEL_ADDR_OFFSET = 0xC0000000;
KERNEL_VADDR_START = 0xC0100000;
SECTIONS
{
/* The kernel will be loaded at 1MB, but will be mapped to 3GB + 1MB */
. = KERNEL_VADDR_START;
.text ALIGN(4K) : AT (ADDR (.text) - KERNEL_ADDR_OFFSET)
{
*(.multiboot)
*(.text)
}
.rodata ALIGN(4K) : AT (ADDR (.rodata) - KERNEL_ADDR_OFFSET)
{
*(.rodata)
}
.data ALIGN(4K) : AT (ADDR (.data) - KERNEL_ADDR_OFFSET)
{
*(.data)
}
.bss ALIGN(4K) : AT (ADDR (.bss) - KERNEL_ADDR_OFFSET)
{
*(COMMON)
*(.bss)
}
KERNEL_VADDR_END = .;
}
Code:
.align 4096
boot_page_directory:
.fill 4096
boot_page_table1:
.fill 4096
.section .text
.global start
.global kernel_stack
.extern kmain
start:
mov $(boot_page_directory - KERNEL_ADDR_OFFSET), %esi
# Start with first page
mov $0, %esi
# Fill 1023 pages to map 4MB. WIll need to change if the kernel's size goes beyond that
mov $1023, %ecx
1:
# Make sure we're not mapping beyond the kernel
cmpl $(KERNEL_VADDR_START - KERNEL_ADDR_OFFSET), %esi
jl 2f
cmpl $(KERNEL_VADDR_END - KERNEL_ADDR_OFFSET), %esi
jge 3f
movl %esi, %edx
# Make this page present and writable. Note this will make readonly sections wriable, which can be bad
orl $0x003, %edx
# Move into current page
movl %edx, (%esi)
2:
# Go to next page 4KB up
addl $4096, %esi
# Entries are 4 bytes large
addl $4, %edi
loop 1b
3:
# Map VGA video memory to 0xC03FF000 as present and writable.
movl $(0x000B8000 | 0x003), boot_page_table1 - KERNEL_ADDR_OFFSET + 1023 * 4
# Map the page table to both virtual addresses 0x00000000 and 0xC0000000.
movl $(boot_page_table1 - KERNEL_ADDR_OFFSET + 0x003), boot_page_directory - KERNEL_ADDR_OFFSET
movl $(boot_page_table1 - KERNEL_ADDR_OFFSET + 0x003), boot_page_directory - KERNEL_ADDR_OFFSET + 768 * 4
# Load the page directory
movl $(boot_page_directory - KERNEL_ADDR_OFFSET), %ecx
movl %ecx, %cr3
# Enable paging and the write-protect bit.
movl %cr0, %ecx
orl $0x80010000, %ecx
movl %ecx, %cr0
# Jump to higher half with an absolute jump.
lea start_higher_half, %ecx
jmp *%ecx
start_higher_half:
# Unmap the identity mapping as it is now unnecessary.
movl $0, boot_page_directory
mov $kernel_stack_end, %esp
# Flush the TLB so the changes to take effect.
movl %cr3, %ecx
movl %ecx, %cr3
# Push magic number from bootloader
push %eax
# Push multiboot header address
push %ebx
cli
call kmain
loop: jmp loop