Basic Launch of Higher half kernel

We now can launch the kernel at 0xC0000000 (or 3 GiB mark) with paging enabled.
A lot of early main is currently not executed to keep debugging as simple as possible
during the initial testing of higher half kernel loading.

A lot of the implementation is straight from wiki.osdev.org/Higher_Half_x86_Bare_Bones. Thanks to all the folks
who keep that wiki updated, its really resourceful.
dev
Nigel Barink 2022-08-18 01:26:49 +02:00
parent bbfea39c23
commit 7d6c823d79
5 changed files with 141 additions and 60 deletions

View File

@ -3,7 +3,7 @@ EMULATOR = qemu-system-i386
AS = ${HOME}/opt/cross/bin/i686-elf-as AS = ${HOME}/opt/cross/bin/i686-elf-as
CC = ${HOME}/opt/cross/bin/i686-elf-gcc CC = ${HOME}/opt/cross/bin/i686-elf-gcc
CPP = ${HOME}/opt/cross/bin/i686-elf-g++ CPP = ${HOME}/opt/cross/bin/i686-elf-g++
CFLAGS = -ffreestanding -O2 -Wall -Wextra CFLAGS = -ffreestanding -Og -ggdb -Wall -Wextra
OFILES =$(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/memory.o $(BUILD_DIR)/paging.o $(BUILD_DIR)/pit.o $(BUILD_DIR)/time.o $(BUILD_DIR)/keyboard.o $(BUILD_DIR)/io.o $(BUILD_DIR)/gdtc.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/sv-terminal.o $(BUILD_DIR)/string.o OFILES =$(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/memory.o $(BUILD_DIR)/paging.o $(BUILD_DIR)/pit.o $(BUILD_DIR)/time.o $(BUILD_DIR)/keyboard.o $(BUILD_DIR)/io.o $(BUILD_DIR)/gdtc.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/sv-terminal.o $(BUILD_DIR)/string.o
@ -34,11 +34,14 @@ iso: clean_iso clean build
grub-mkrescue -o build/barinkOS.iso root grub-mkrescue -o build/barinkOS.iso root
run: all run: all
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std -display gtk -m 2G -cpu core2duo $(EMULATOR) -cdrom build/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo
debug: all
$(EMULATOR) -cdrom build/barinkOS.iso -serial stdio -vga std -display gtk -m 2G -cpu core2duo -s -d int
build_kernel: $(OBJ_LINK_LIST) build_kernel: $(OBJ_LINK_LIST)
$(CC) -T $(SRC_DIR)/kernel//linker.ld -o $(BUILD_DIR)/myos.bin \ $(CC) -T $(SRC_DIR)/kernel//linker.ld -o $(BUILD_DIR)/myos.bin \
-ffreestanding -O2 -nostdlib $(OBJ_LINK_LIST) -lgcc -ffreestanding -ggdb -Og -nostdlib $(OBJ_LINK_LIST) -lgcc
build_x86_64: build_x86_64:
$(AS) $(SRC_DIR)/cgc/x86_64/crti.s -o $(BUILD_DIR)/crti_64.o $(AS) $(SRC_DIR)/cgc/x86_64/crti.s -o $(BUILD_DIR)/crti_64.o

View File

@ -7,30 +7,104 @@
.set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */ .set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
.set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */ .set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */
.section .multiboot .section .multiboot.data, "aw"
.align 4 .align 4
.long MAGIC .long MAGIC
.long FLAGS .long FLAGS
.long CHECKSUM .long CHECKSUM
/*
.section .bss * Allocate initial stack
.align 16 */
.section .bootstrap_stack, "aw", @nobits
stack_bottom: stack_bottom:
.skip 16384 # 16 KiB .skip 16384 # 16 KiB
stack_top: stack_top:
.section .text
.include "./src/kernel/Memory/GDT/gdt.s"
.include "./src/kernel/irs_table.s"
.include "./src/kernel/irq_table.s"
.include "./src/kernel/Interrupts/idt/idt.s"
.include "./src/kernel/Memory/paging.s"
.include "./src/kernel/cpu.s"
/*
* Preallocate a couple pages to get us bootstrapped
* Being carefull to not use any address the bootloader might
* be using for its multiboot structures
*/
.section .bss, "aw", @nobits
.align 4096
boot_page_directory:
.skip 4096
boot_page_table:
.skip 4096
# More page tables may be required
# Entry point
.section .multiboot.text, "a"
.global _start .global _start
.type _start, @function .type _start, @function
_start: _start:
# Get physical address of the boot_page_table
movl $(boot_page_table - 0xC0000000), %edi
# Map address 0
movl $0, %esi
# Map 1023 pages the 1024th being the VGA text buffer
movl $1023, %ecx
1: # Map the kernel
cmpl $_kernel_start, %esi
jl 2f
cmpl $(_kernel_end - 0xC0000000), %esi
jge 3f
# Map physical address as "present and writable"
movl %esi, %edx
orl $0x003, %edx
movl %edx, (%edi)
2: # Size of page is 4096 bytes
addl $4096, %esi
# Size of entries in boot_page_table is 4 bytes
addl $4, %edi
# Loop to the next entry if we haven't finished.
loop 1b
3: # Map VGA video memory to 0xC03FF00 as "present, writable"
movl $(0x000B8000 | 0x003), boot_page_table - 0xC0000000 + 1023 * 4
# IMPORTANT NOTE FROM WIKI.OSDEV.ORG/HIGHER_HALF_X86_BARE_BONES
# The page table is used at both page directory entry 0 (virtually from 0x0
# to 0x3FFFFF) (thus identity mapping the kernel) and page directory entry
# 768 (virtually from 0xC0000000 to 0xC03FFFFF) (thus mapping it in the
# higher half). The kernel is identity mapped because enabling paging does
# not change the next instruction, which continues to be physical. The CPU
# would instead page fault if there was no identity mapping.\
# Map the page table to both virtual addresss 0x00000000 and 0xC0000000
movl $(boot_page_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
movl $(boot_page_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
# Set cr3 to the address of the boot_page_directory
movl $(boot_page_directory - 0xC0000000), %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 4f, %ecx
jmp *%ecx
.section .text
4:
# At this point, paging is fully set up and enabled
isPaging:
# Unmap the identity mapping as it is now unnecessary
movl $0, boot_page_directory + 0
# Reload cr3 to force tlb flush
movl %cr3, %ecx
movl %ecx, %cr3
/*Setup the stack pointer to point to the beginning of our stack */ /*Setup the stack pointer to point to the beginning of our stack */
/* I believe its a high address growing down to lower adress for the stack on x86*/ /* I believe its a high address growing down to lower adress for the stack on x86*/
mov $stack_top, %esp mov $stack_top, %esp
@ -44,16 +118,15 @@ _start:
/* push the magic value */ /* push the magic value */
pushl %eax pushl %eax
call early_main
call early_main
mov %cr0, %eax mov %cr0, %eax
or $1, %eax or $1, %eax
mov %eax, %cr0 mov %eax, %cr0
call kernel_main //call kernel_main
cli cli
@ -61,6 +134,11 @@ _start:
jmp 1b jmp 1b
.size _start, . - _start .include "./src/kernel/Memory/GDT/gdt.s"
.include "./src/kernel/irs_table.s"
.include "./src/kernel/irq_table.s"
.include "./src/kernel/Interrupts/idt/idt.s"
.include "./src/kernel/Memory/paging.s"
.include "./src/kernel/cpu.s"

View File

@ -21,7 +21,7 @@ void kterm_init () {
kterm_row = 0; kterm_row = 0;
kterm_column = 0; kterm_column = 0;
kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK); kterm_color = vga_entry_color ( VGA_COLOR_LIGHT_GREY , VGA_COLOR_BLACK);
kterm_buffer = (uint16_t*) 0xB8000; kterm_buffer = (uint16_t*) 0xC03FF000;
for (size_t y = 0; y < VGA_HEIGHT; y++ ){ for (size_t y = 0; y < VGA_HEIGHT; y++ ){
for( size_t x = 0; x < VGA_WIDTH; x++){ for( size_t x = 0; x < VGA_WIDTH; x++){
const size_t index = y * VGA_WIDTH + x; const size_t index = y * VGA_WIDTH + x;

View File

@ -1,11 +1,9 @@
#include "kernel.h" #include "kernel.h"
extern "C" void kernel_main (BootInfo* bootinfo) { extern "C" void kernel_main (BootInfo* bootinfo) {
init_serial(); init_serial();
pit_initialise(); //pit_initialise();
//InitializePaging();
//Enable();
startSuperVisorTerminal(bootinfo); startSuperVisorTerminal(bootinfo);
} }
@ -16,8 +14,12 @@ extern "C" void early_main(unsigned long magic, unsigned long addr){
* Initialize terminal interface * Initialize terminal interface
* NOTE: This should be done later on , the magic value should be checked first. * NOTE: This should be done later on , the magic value should be checked first.
*/ */
initGDT();
kterm_init(); kterm_init();
init_serial();
print_serial("Hello Higher half kernel!");
printf("DDDDDDDDDDDDDDDD");
return;
/** /**
* Check Multiboot magic number * Check Multiboot magic number
* NOTE: Printf call should not be a thing this early on ... * NOTE: Printf call should not be a thing this early on ...
@ -31,7 +33,7 @@ extern "C" void early_main(unsigned long magic, unsigned long addr){
* Show a little banner for cuteness * Show a little banner for cuteness
*/ */
printf("|=== BarinkOS ===|\n"); printf("|=== BarinkOS ===|\n");
printf("Kernel Begin AT(0x%x)", kernel_begin);
/** /**
* Use the address given as an argument as the pointer * Use the address given as an argument as the pointer
@ -107,17 +109,17 @@ extern "C" void early_main(unsigned long magic, unsigned long addr){
//memAlloc.free_block((void*) memory); //memAlloc.free_block((void*) memory);
//InitializePaging(); //InitializePaging();
IdentityMap(); //IdentityMap();
Enable(); //Enable();
} }
initGDT(); //initGDT();
init_idt(); //init_idt();
// Enable interrupts // Enable interrupts
asm volatile("STI"); //asm volatile("STI");
CheckMBT( (multiboot_info_t *) addr); //CheckMBT( (multiboot_info_t *) addr);
kernel_main(&bootinfo); kernel_main(&bootinfo);

View File

@ -1,47 +1,45 @@
/* The bootloader will look at this image and start execution at the symbol
designated as the entry point. */
ENTRY(_start) ENTRY(_start)
/* Tell where the various sections of the object files will be put in the final /* Tell where the various sections of the object files will be put in the final
kernel image. */ kernel image. */
SECTIONS SECTIONS
{ {
. = 0x00100000; /* place code at 1MB mark*/
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
loaded at by the bootloader. */ _kernel_start = .;
. = 1M; kernel_begin = .; /* For legacy reasons */
kernel_begin = .;
/* 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. .multiboot.data : {
Next we'll put the .text section. */ *(.multiboot.data)
.text BLOCK(4K) : ALIGN(4K) }
.multiboot.text : {
*(multiboot.text)
}
. += 0xC0000000; /* Addresses in the following code need to be above the 3Gb mark */
.text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
{ {
*(.multiboot)
*(.text) *(.text)
} }
.rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000)
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
{ {
*(.rodata) *(.rodata)
} }
.data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000)
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
{ {
*(.data) *(.data)
} }
.bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000)
/* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : ALIGN(4K)
{ {
*(COMMON) *(COMMON)
*(.bss) *(.bss)
*(.bootstrap_stack)
} }
_kernel_end = .;
/* The compiler may produce other sections, by default it will put them in kernel_end = .; /* For legacy reasons */
a segment with the same name. Simply add stuff here as needed. */
kernel_end = .;
} }