From 7d6c823d79dcfb819cec7c7ab1eab33255c26dfd Mon Sep 17 00:00:00 2001 From: Nigel Date: Thu, 18 Aug 2022 01:26:49 +0200 Subject: [PATCH] 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. --- Makefile | 9 ++- src/kernel/KernelLauncher/boot.s | 114 ++++++++++++++++++++++++++----- src/kernel/Terminal/kterm.cpp | 2 +- src/kernel/kernel.cpp | 26 +++---- src/kernel/linker.ld | 50 +++++++------- 5 files changed, 141 insertions(+), 60 deletions(-) diff --git a/Makefile b/Makefile index d5443c0..c8a3fa1 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ EMULATOR = qemu-system-i386 AS = ${HOME}/opt/cross/bin/i686-elf-as CC = ${HOME}/opt/cross/bin/i686-elf-gcc 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 @@ -34,11 +34,14 @@ iso: clean_iso clean build grub-mkrescue -o build/barinkOS.iso root 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) $(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: $(AS) $(SRC_DIR)/cgc/x86_64/crti.s -o $(BUILD_DIR)/crti_64.o diff --git a/src/kernel/KernelLauncher/boot.s b/src/kernel/KernelLauncher/boot.s index 722c2d2..8b61af0 100644 --- a/src/kernel/KernelLauncher/boot.s +++ b/src/kernel/KernelLauncher/boot.s @@ -7,30 +7,104 @@ .set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */ .set CHECKSUM, -(MAGIC + FLAGS) /* checksum of above, to prove we are multiboot */ -.section .multiboot +.section .multiboot.data, "aw" .align 4 .long MAGIC .long FLAGS .long CHECKSUM - -.section .bss -.align 16 +/* +* Allocate initial stack +*/ +.section .bootstrap_stack, "aw", @nobits stack_bottom: .skip 16384 # 16 KiB 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 -.type _start, @function +.type _start, @function _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 */ /* I believe its a high address growing down to lower adress for the stack on x86*/ mov $stack_top, %esp @@ -44,16 +118,15 @@ _start: /* push the magic value */ pushl %eax - - call early_main + call early_main mov %cr0, %eax or $1, %eax - mov %eax, %cr0 + mov %eax, %cr0 - call kernel_main + //call kernel_main cli @@ -61,6 +134,11 @@ _start: 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" diff --git a/src/kernel/Terminal/kterm.cpp b/src/kernel/Terminal/kterm.cpp index 94bc3f1..95573c6 100644 --- a/src/kernel/Terminal/kterm.cpp +++ b/src/kernel/Terminal/kterm.cpp @@ -21,7 +21,7 @@ void kterm_init () { kterm_row = 0; kterm_column = 0; 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 x = 0; x < VGA_WIDTH; x++){ const size_t index = y * VGA_WIDTH + x; diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 25666ef..3251521 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -1,11 +1,9 @@ #include "kernel.h" + extern "C" void kernel_main (BootInfo* bootinfo) { init_serial(); - pit_initialise(); - - //InitializePaging(); - //Enable(); + //pit_initialise(); startSuperVisorTerminal(bootinfo); } @@ -16,8 +14,12 @@ extern "C" void early_main(unsigned long magic, unsigned long addr){ * Initialize terminal interface * NOTE: This should be done later on , the magic value should be checked first. */ + initGDT(); kterm_init(); - + init_serial(); + print_serial("Hello Higher half kernel!"); + printf("DDDDDDDDDDDDDDDD"); + return; /** * Check Multiboot magic number * 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 */ printf("|=== BarinkOS ===|\n"); - + printf("Kernel Begin AT(0x%x)", kernel_begin); /** * 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); //InitializePaging(); - IdentityMap(); - Enable(); + //IdentityMap(); + //Enable(); } - initGDT(); - init_idt(); + //initGDT(); + //init_idt(); // Enable interrupts - asm volatile("STI"); + //asm volatile("STI"); - CheckMBT( (multiboot_info_t *) addr); + //CheckMBT( (multiboot_info_t *) addr); kernel_main(&bootinfo); diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld index eb1aae8..bcb2584 100644 --- a/src/kernel/linker.ld +++ b/src/kernel/linker.ld @@ -1,47 +1,45 @@ -/* The bootloader will look at this image and start execution at the symbol - designated as 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; - 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. - Next we'll put the .text section. */ - .text BLOCK(4K) : ALIGN(4K) + . = 0x00100000; /* place code at 1MB mark*/ + + _kernel_start = .; + kernel_begin = .; /* For legacy reasons */ + + + .multiboot.data : { + *(.multiboot.data) + } + + .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) } - - /* Read-only data. */ - .rodata BLOCK(4K) : ALIGN(4K) + .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000) { *(.rodata) } - - /* Read-write data (initialized) */ - .data BLOCK(4K) : ALIGN(4K) + .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000) { *(.data) } - - /* Read-write data (uninitialized) and stack */ - .bss BLOCK(4K) : ALIGN(4K) + .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000) { *(COMMON) *(.bss) + *(.bootstrap_stack) } - - /* The compiler may produce other sections, by default it will put them in - a segment with the same name. Simply add stuff here as needed. */ - - kernel_end = .; + _kernel_end = .; + kernel_end = .; /* For legacy reasons */ }