From 65b8e7773ee3bb7c06ec7d82bae67257905faef4 Mon Sep 17 00:00:00 2001 From: Xnoe Date: Mon, 11 Oct 2021 12:26:11 +0100 Subject: [PATCH] Added initial paging support. --- Makefile | 4 +- boot_stage2.ld | 2 +- kernel.ld | 2 +- src/boot_stage2/main.c | 159 ++++++++++++++++++++++++++++------------- src/kernel/paging.c | 41 +++++++++++ src/kernel/paging.h | 37 ++++++++++ 6 files changed, 193 insertions(+), 52 deletions(-) create mode 100644 src/kernel/paging.c create mode 100644 src/kernel/paging.h diff --git a/Makefile b/Makefile index c12ad33..1a5ea81 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CFLAGS = -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-le LDFLAGS = DISK_IMG_FILES = kernel.bin -KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o c_code_entry.o kernel.o +KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o c_code_entry.o kernel.o paging.o run: disk.img qemu-system-x86_64 disk.img @@ -26,7 +26,7 @@ boot.sector: boot.asm boot.stage2: boot_stage2.ld boot.stage2.o ld $(LDFLAGS) -T $< boot.stage2.o -boot.stage2.o: src/boot_stage2/main.c io.o atapio.o strings.o c_code_entry.o screenstuff.o +boot.stage2.o: src/boot_stage2/main.c io.o atapio.o strings.o c_code_entry.o screenstuff.o paging.o gcc $(CFLAGS) -o $@ -c $< %.bin: %.asm diff --git a/boot_stage2.ld b/boot_stage2.ld index 0641d2c..b98d550 100644 --- a/boot_stage2.ld +++ b/boot_stage2.ld @@ -1,7 +1,7 @@ OUTPUT_FORMAT(binary) OUTPUT_ARCH(i386:i386) -INPUT(io.o atapio.o strings.o c_code_entry.o screenstuff.o) +INPUT(io.o atapio.o strings.o c_code_entry.o screenstuff.o paging.o) OUTPUT(boot.stage2) SECTIONS { diff --git a/kernel.ld b/kernel.ld index 1706cd3..ca526ef 100644 --- a/kernel.ld +++ b/kernel.ld @@ -4,7 +4,7 @@ OUTPUT_ARCH(i386:i386) OUTPUT(kernel.bin) SECTIONS { - . = 0x80000; + . = 0xc0000000; .text : { c_code_entry.o(.text) diff --git a/src/boot_stage2/main.c b/src/boot_stage2/main.c index 663a601..6363ff7 100644 --- a/src/boot_stage2/main.c +++ b/src/boot_stage2/main.c @@ -1,5 +1,6 @@ #include "../kernel/atapio.h" #include "../kernel/screenstuff.h" +#include "../kernel/paging.h" typedef struct { uint32_t base_low; @@ -10,66 +11,128 @@ typedef struct { uint32_t acpi3_extended; }__attribute__((packed)) e820entry; -void set_bit(uint32_t offset, uint8_t* buffer) { - uint32_t index = offset / 8; - uint32_t bit = offset % 8; +uint8_t* bitmap = 0x100000; - buffer[index] |= (1<<(7 - bit)); +void set_bit(uint32_t offset, uint8_t* buffer) { + uint32_t index = offset / 8; + uint32_t bit = offset % 8; + + buffer[index] |= (1<<(7 - bit)); +} + +void unset_bit(uint32_t offset, uint8_t* buffer) { + uint32_t index = offset / 8; + uint32_t bit = offset % 8; + + buffer[index] &= (255 - (1<<(7 - bit))); +} + +void memset(uint8_t* base, uint32_t count, uint8_t to) { + for (int i=0; i add_offset) { - base += add_offset; - length -= add_offset; - } - } - uint32_t page_index = base / 4096; - - printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096); - - for (int j=0; length > 4096; length -= 4096, j++) { - uint32_t index = (page_index+j) / 8; - uint32_t bit = (page_index+j) % 8; - - bitmap[index] |= (1<<(7 - bit)); - } + if (base % 4096) { + // Memory isn't page aligned, we need to fix that. + uint32_t add_offset = 4096 - (base % 4096); + if (length > add_offset) { + base += add_offset; + length -= add_offset; + } } + uint32_t page_index = base / 4096; - uint8_t* kernel_location = 0x80000; - load_file("KERNEL BIN", kernel_location); + printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096); - printf("Stage2 success!\n"); + for (int j=0; length > 4096; length -= 4096, j++) { + set_bit(page_index + j, bitmap); + } + } - while (1); - ((void(*)(void))kernel_location)(); + mark_unavailble(bitmap, 0x20000); + + // Page Directory + PDE* kernel_page_directory = bitmap + 0x20000; + // Clear the PD + memset((uint8_t*)kernel_page_directory, 4096, 0); + + // Clear 4MB of RAM from 0x121000 to 0x521000 for the 1024 page tables + memset((uint8_t*)0x121000, 0x400000, 0); + + // Construct a 1024 long PTE** at 0x521000 + for (int i=0; i<1024; i++) { + ((uint32_t*)0x521000)[i] = 0x121000 + 0x1000*i; + } + + PTE** kernel_page_tables = 0x521000; + + // Mark unavailable bitmap to 0x522000 + mark_unavailble(bitmap, 0x522000 - (uint32_t)bitmap); + + // Now we want to map some stuff. + // But first, we should load the kernel somewhere + + uint8_t* kernel_location = 0x522000; // Just load it at 0x522000 for now + mark_unavailble(0x522000, 32768); // Just treat the kernel as not growing beyong 32k for now. + + map_many_4k_phys_to_virt(0x522000, 0xc0000000, kernel_page_directory, kernel_page_tables, 8); // Map 8 pages from 0x522000 to 0xc0000000; + map_4k_phys_to_virt((uint32_t)kernel_page_directory, 0xc0100000, kernel_page_directory, kernel_page_tables); // Map the page directory to 0xc0100000 + map_many_4k_phys_to_virt(0x121000, 0xc0101000, kernel_page_directory, kernel_page_tables, 1024); // Map 1024 pages from 0x121000 to 0xc0101000 + map_4k_phys_to_virt(0xb8000, 0xc0501000, kernel_page_directory, kernel_page_tables); // Map 0xb8000 (video) to 0xc0501000 + + map_4k_phys_to_virt(0x8000, 0x8000, kernel_page_directory, kernel_page_tables); + + load_file("KERNEL BIN", kernel_location); + + printf("Stage2 success!\n"); + + asm ("mov %0, %%eax;" + "mov %%eax, %%cr3" : : "m" (kernel_page_directory)); + + asm ("mov %cr0, %eax;" + "or $0x80000001, %eax;" + "mov %eax, %cr0"); + + while (1); + ((void(*)(void))0xc0000000)(); } \ No newline at end of file diff --git a/src/kernel/paging.c b/src/kernel/paging.c new file mode 100644 index 0000000..24a884c --- /dev/null +++ b/src/kernel/paging.c @@ -0,0 +1,41 @@ +#include "paging.h" + +void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) { + uint32_t pd_index = (virtual & (1023 << 20)) >> 20; + uint32_t pt_index = (virtual & (1023 << 10)) >> 10; + + page_directory[pd_index] = (PDE){ + .address = (uint32_t)(page_tables[pd_index]) >> 12, + .available = 0, + .page_4mb = 0, + .accessed = 0, + .disable_cache = 0, + .write_through_cache = 0, + .privilege = 0, + .present = 1, + .read_write = 1, + + .ignored = 0, + .ignored2 = 0 + }; + + page_tables[pd_index][pt_index] = (PTE){ + .address = physical >> 12, + .available = 0, + .global = 0, + .accessed = 0, + .disable_cache = 0, + .dirty = 0, + .write_through_cache = 0, + .privilege = 0, + .present = 1, + .read_write = 1, + + .ignored = 0 + }; +} + +void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) { + for (int i=0; i +#include "types.h" + +typedef struct { + uint32_t address : 20; + uint32_t available : 3; + uint32_t ignored : 1; + uint32_t page_4mb : 1; + uint32_t ignored2 : 1; + uint32_t accessed : 1; + uint32_t disable_cache : 1; + uint32_t write_through_cache : 1; + uint32_t privilege : 1; + uint32_t read_write : 1; + uint32_t present : 1; +}__attribute__((packed)) PDE; + +typedef struct { + uint32_t address : 20; + uint32_t available : 3; + uint32_t global : 1; + uint32_t ignored : 1; + uint32_t dirty : 1; + uint32_t accessed : 1; + uint32_t disable_cache : 1; + uint32_t write_through_cache : 1; + uint32_t privilege : 1; + uint32_t read_write : 1; + uint32_t present : 1; +}__attribute__((packed)) PTE; + +void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables); +void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count); +#endif \ No newline at end of file