I followed along with the details on the "x86 Paging" article on osdev.org. Looking at it in GDB shows that kernel_early_main returns to the address 0x0 instead of continuing on afterwards in boot.S. I would like to have higher half paging working so that execution can reach kernel_main. I removed most of the extra things that don't affect this problem. Also, all of the source code can be found at https://github.com/ResistingGuide4/rOSes
Boot.S
Code: Select all
# Declare constants for the multiboot 2 header.
.set FLAGS, 0 # this is the Multiboot 'flag' field
.set MAGIC, 0xE85250D6 # 'magic number' lets bootloader find the header
.set SIZE, header_end - header_start
.set CHECKSUM, -(MAGIC + FLAGS + SIZE) # checksum of above, to prove we are multiboot
# Declare a header as in the Multiboot Standard.
.section .multiboot,"a",@progbits
.align 8
header_start:
.long MAGIC
.long FLAGS
.long SIZE
.long CHECKSUM
# Tags go here
# Ending tag
.align 8
.short 0
.short 0
.long 8
header_end:
# Reserve a stack for the initial thread.
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
.global stack_top
stack_top:
.section .data
.align 4096
.global page_directory_start
page_directory_start:
.skip 4096
.global page_table1_start
page_table1_start:
.skip 4096
.global page_table768_start
page_table768_start:
.skip 4096
# The kernel entry point.
.section .boot,"ax",@progbits
.global _start
.type _start, @function
_start:
# Initialize Stack
movl $stack_top, %esp
# Push Data Requested from Bootloader to Stack
pushl %eax
pushl %ebx
# Setup necessary components like Memory Management
call kernel_early_main
movl page_directory_start, %eax
movl %eax, %cr3
movl %cr0, %eax
orl $0x80000001, %eax
movl %eax, %cr0
ljmp $0x08, $higher_half_start
.size _start, . - _start
.section .text
higher_half_start:
# Call the global constructors.
call _init
# Transfer control to the main kernel.
call kernel_main
# Hang if kernel_main unexpectedly returns.
cli
1: hlt
jmp 1b
.size higher_half_start, . - higher_half_start
Code: Select all
#include <stdint.h>
#include <stdlib.h>
#include <stddef.h>
#include <kernel/multiboot2.h>
extern uint32_t stack_top;
extern uint32_t page_directory_start[1024];
extern uint32_t page_table1_start[1024];
extern uint32_t page_table768_start[1024];
void __attribute__((section(".boot"), used)) kernel_early_main() {
for (int i = 0; i < 1024; i++) {
page_table1_start[i] = (i * 0x1000) | 0x3;
page_table768_start[i] = (i * 0x1000) | 0x3;
}
asm volatile("between:");
page_directory_start[0] = (uint32_t)page_table1_start | 0x3;
page_directory_start[768] = (uint32_t)page_table768_start | 0x3;
page_directory_start[1023] = (uint32_t)page_directory_start | 0x3;
}
Code: Select all
/* The bootloader will look at this image and start execution at the symbol
designated at the entry point. */
ENTRY(_start)
/* Tell where the various sections of the object files will be put in the final
kernel image. */
SECTIONS
{
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
loaded at by the bootloader. */
. = 1M;
.boot BLOCK(4K) : ALIGN(4K)
{
. = ALIGN(8);
KEEP(*(.multiboot))
*(.boot)
}
/* 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. */
. = 0xC0000000;
.text BLOCK(4K) : AT(ADDR(.text) - 0xC0000000) ALIGN(4K)
{
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : AT(ADDR(.rodata) - 0xC0000000) ALIGN(4K)
{
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : AT(ADDR(.data) - 0xC0000000) ALIGN(4K)
{
*(.data)
}
/* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : AT(ADDR(.bss) - 0xC0000000) ALIGN(4K)
{
*(COMMON)
*(.bss)
}
/* 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. */
}
