diff --git a/kernel/Makefile b/kernel/Makefile index a58207a0..ced0695b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -8,7 +8,7 @@ CXX := x86_64-elf-g++ AS := x86_64-elf-as NASM := nasm -CFLAGS := -Wall -Wextra -Werror -Os -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std +CFLAGS := -g -Wall -Wextra -Werror -Os -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std CXXFLAGS := -fno-rtti -fno-exceptions NASMFLAGS := -felf64 ASFLAGS := diff --git a/kernel/include/memory/KernelMemoryManager.h b/kernel/include/memory/KernelMemoryManager.h new file mode 100644 index 00000000..b9645333 --- /dev/null +++ b/kernel/include/memory/KernelMemoryManager.h @@ -0,0 +1,14 @@ +#pragma once +#include + +namespace KernelMemoryManager +{ + void* get_mapping(void* physicalAddress); + void release_mapping(void* mapping); + + void* get_page(); + void* get_pages(uint64_t count); + + void release_page(void* page); + void release_pages(void* pages, uint64_t count); +} \ No newline at end of file diff --git a/kernel/include/memory/RangeAllocator.h b/kernel/include/memory/RangeAllocator.h index eb4feb0e..d02edf21 100644 --- a/kernel/include/memory/RangeAllocator.h +++ b/kernel/include/memory/RangeAllocator.h @@ -35,4 +35,4 @@ class RangeAllocator uint64_t start_index = 0; }; -extern RangeAllocator physical_allocator; \ No newline at end of file +extern RangeAllocator kernelPMM; \ No newline at end of file diff --git a/kernel/include/memory/VMM.h b/kernel/include/memory/VMM.h index 0309195d..6be6a86b 100644 --- a/kernel/include/memory/VMM.h +++ b/kernel/include/memory/VMM.h @@ -11,6 +11,7 @@ namespace Paging void map(uint64_t virtualAddress, uint64_t physicalAddress); void unmap(uint64_t virtualAddress); + uint64_t getPhysical(uint64_t virtualAddress); private: PageTable* PML4; diff --git a/kernel/src/init/Init.cpp b/kernel/src/init/Init.cpp index 25a63c27..41b6bb3d 100644 --- a/kernel/src/init/Init.cpp +++ b/kernel/src/init/Init.cpp @@ -32,6 +32,6 @@ void Init::early_init() ASSERT(Draw::try_initialize()); // ASSERT(TextRenderer::try_initialize()); - physical_allocator.init_from_mmap(); + kernelPMM.init_from_mmap(); kernelVMM.init(); } \ No newline at end of file diff --git a/kernel/src/interrupts/Entry.cpp b/kernel/src/interrupts/Entry.cpp index 9319036a..9e7e48f8 100644 --- a/kernel/src/interrupts/Entry.cpp +++ b/kernel/src/interrupts/Entry.cpp @@ -13,6 +13,11 @@ extern "C" void common_handler(SavedContext* context) context->rsp, context->error_code, context->cr2); while (1) halt(); } + if (context->number == 14) + { + printf("Page fault at 0x%zx\n"); + hang(); + } if (context->number >= 0x20 && context->number < 0x30) { IRQ::interrupt_handler(context); } return; } \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index b23fbebb..5be2e0a0 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -13,6 +13,7 @@ #include "io/Serial.h" #include "log/Log.h" #include "memory/KernelHeap.h" +#include "memory/KernelMemoryManager.h" #include "memory/Memory.h" #include "memory/RangeAllocator.h" #include "panic/hang.h" @@ -74,27 +75,6 @@ extern "C" void _start() kinfoln("Interrupts enabled"); - printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024, - physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024, - physical_allocator.get_reserved() / 1024); - - void* address = physical_allocator.request_page(); - printf("Allocated page at address 0x%zx\n", address); - - void* address2 = physical_allocator.request_page(); - printf("Allocated page at address 0x%zx\n", address2); - - printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024, - physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024, - physical_allocator.get_reserved() / 1024); - - physical_allocator.free_page(address); - printf("Freed page\n"); - - printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024, - physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024, - physical_allocator.get_reserved() / 1024); - Debug::DebugStatus::the()->StartBootStage(Color{0x33, 0x33, 0x00, 0xFF}); ACPI::SDTHeader* rootSDT = ACPI::GetRSDTOrXSDT(); bool isXSDT = false; diff --git a/kernel/src/memory/KernelMemoryManager.cpp b/kernel/src/memory/KernelMemoryManager.cpp new file mode 100644 index 00000000..7a72577b --- /dev/null +++ b/kernel/src/memory/KernelMemoryManager.cpp @@ -0,0 +1,58 @@ +#include "memory/KernelMemoryManager.h" +#include "assert.h" +#include "memory/KernelHeap.h" +#include "memory/RangeAllocator.h" +#include "memory/VMM.h" + +void* KernelMemoryManager::get_mapping(void* physicalAddress) +{ + uint64_t virtualAddress = KernelHeap::request_virtual_page(); + kernelVMM.map(virtualAddress, (uint64_t)physicalAddress); + return (void*)virtualAddress; +} + +void KernelMemoryManager::release_mapping(void* mapping) +{ + kernelVMM.unmap((uint64_t)mapping); +} + +void* KernelMemoryManager::get_page() +{ + void* physicalAddress = kernelPMM.request_page(); + uint64_t virtualAddress = KernelHeap::request_virtual_page(); + kernelVMM.map(virtualAddress, (uint64_t)physicalAddress); + return (void*)virtualAddress; +} + +void KernelMemoryManager::release_page(void* page) +{ + uint64_t physicalAddress = kernelVMM.getPhysical((uint64_t)page); + ASSERT(physicalAddress != UINT64_MAX); + kernelVMM.unmap((uint64_t)page); + kernelPMM.free_page((void*)physicalAddress); + KernelHeap::free_virtual_page((uint64_t)page); +} + +void* KernelMemoryManager::get_pages(uint64_t count) +{ + uint64_t virtualAddress = KernelHeap::request_virtual_pages(count); + for (uint64_t i = 0; i < count; i++) + { + void* physicalAddress = kernelPMM.request_page(); + kernelVMM.map(virtualAddress + (i * 4096), (uint64_t)physicalAddress); + } + return (void*)virtualAddress; +} + +void KernelMemoryManager::release_pages(void* pages, uint64_t count) +{ + for (uint64_t i = 0; i < count; i++) + { + void* page = (void*)((uint64_t)pages + (i * 4096)); + uint64_t physicalAddress = kernelVMM.getPhysical((uint64_t)page); + ASSERT(physicalAddress != UINT64_MAX); + kernelVMM.unmap((uint64_t)page); + kernelPMM.free_page((void*)physicalAddress); + } + KernelHeap::free_virtual_pages((uint64_t)pages, count); +} \ No newline at end of file diff --git a/kernel/src/memory/RangeAllocator.cpp b/kernel/src/memory/RangeAllocator.cpp index ab25349e..65a42cdf 100644 --- a/kernel/src/memory/RangeAllocator.cpp +++ b/kernel/src/memory/RangeAllocator.cpp @@ -6,7 +6,7 @@ extern BOOTBOOT bootboot; -RangeAllocator physical_allocator; +RangeAllocator kernelPMM; void RangeAllocator::init_from_mmap() { diff --git a/kernel/src/memory/VMM.cpp b/kernel/src/memory/VMM.cpp index 029627b2..874c49c6 100644 --- a/kernel/src/memory/VMM.cpp +++ b/kernel/src/memory/VMM.cpp @@ -1,4 +1,5 @@ #include "memory/VMM.h" +#include "log/Log.h" #include "memory/RangeAllocator.h" #include "std/string.h" @@ -59,6 +60,47 @@ namespace Paging PT->entries[P_i] = PDE; } + uint64_t VirtualMemoryManager::getPhysical(uint64_t virtualAddress) + { + virtualAddress >>= 12; + uint64_t P_i = virtualAddress & 0x1ff; + virtualAddress >>= 9; + uint64_t PT_i = virtualAddress & 0x1ff; + virtualAddress >>= 9; + uint64_t PD_i = virtualAddress & 0x1ff; + virtualAddress >>= 9; + uint64_t PDP_i = virtualAddress & 0x1ff; + + PageDirectoryEntry PDE; + + PDE = PML4->entries[PDP_i]; + PageTable* PDP; + if (!PDE.Present) + { + return UINT64_MAX; // Not mapped + } + else { PDP = (PageTable*)((uint64_t)PDE.Address << 12); } + + PDE = PDP->entries[PD_i]; + PageTable* PD; + if (!PDE.Present) + { + return UINT64_MAX; // Not mapped + } + else { PD = (PageTable*)((uint64_t)PDE.Address << 12); } + + PDE = PD->entries[PT_i]; + PageTable* PT; + if (!PDE.Present) + { + return UINT64_MAX; // Not mapped + } + else { PT = (PageTable*)((uint64_t)PDE.Address << 12); } + + PDE = PT->entries[P_i]; + return PDE.Address; + } + void VirtualMemoryManager::map(uint64_t virtualAddress, uint64_t physicalAddress) { virtualAddress >>= 12; @@ -76,7 +118,7 @@ namespace Paging PageTable* PDP; if (!PDE.Present) { - PDP = (PageTable*)physical_allocator.request_page(); + PDP = (PageTable*)kernelPMM.request_page(); memset(PDP, 0, 0x1000); PDE.Address = (uint64_t)PDP >> 12; PDE.Present = true; @@ -89,8 +131,8 @@ namespace Paging PageTable* PD; if (!PDE.Present) { - PD = (PageTable*)physical_allocator.request_page(); - memset(PDP, 0, 0x1000); + PD = (PageTable*)kernelPMM.request_page(); + memset(PD, 0, 0x1000); PDE.Address = (uint64_t)PD >> 12; PDE.Present = true; PDE.ReadWrite = true; @@ -102,8 +144,8 @@ namespace Paging PageTable* PT; if (!PDE.Present) { - PT = (PageTable*)physical_allocator.request_page(); - memset(PDP, 0, 0x1000); + PT = (PageTable*)kernelPMM.request_page(); + memset(PT, 0, 0x1000); PDE.Address = (uint64_t)PT >> 12; PDE.Present = true; PDE.ReadWrite = true; diff --git a/kernel/src/std/stdio.cpp b/kernel/src/std/stdio.cpp index 4ab5cd23..084db751 100644 --- a/kernel/src/std/stdio.cpp +++ b/kernel/src/std/stdio.cpp @@ -52,13 +52,13 @@ static int internal_printf(const char* format, PutString put_string_callback, ss { if (format_index + 1 == format_size) // end of format string { + format_index++; continue; } else { if (!preserve_format) format_index++; - else - preserve_format = false; + preserve_format = false; current_char = format[format_index]; switch (current_char) { diff --git a/tools/debug.sh b/tools/debug.sh index d05795a6..b4f2c047 100755 --- a/tools/debug.sh +++ b/tools/debug.sh @@ -5,4 +5,4 @@ source $(dirname $0)/env.sh tools/build-iso.sh -qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s \ No newline at end of file +qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s -no-reboot \ No newline at end of file