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.
This commit is contained in:
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
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

View File

@ -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"

View File

@ -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;

View File

@ -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);

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)
/* 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 */
}