From 05151113141bc9d44617d2724bdda106657995cd Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Thu, 22 Dec 2011 14:13:18 +0100 Subject: [PATCH] The initial ramdisk is now mapped onto a special location. This fixes issues where it did not fit into the first few MiB, or that GRUB loaded it someplace weird. The kernel heap is now also protected against growing into the ramdisk and the kernel stack. --- libmaxsi/heap.cpp | 4 +- sortix/initrd.cpp | 19 ++++++++- sortix/initrd.h | 2 +- sortix/kernel.cpp | 10 +++-- sortix/memorymanagement.h | 15 ++++--- sortix/scheduler.cpp | 13 +++++- sortix/x64/memorymanagement.cpp | 42 ++++++++++++++++++++ sortix/x64/scheduler.cpp | 14 ------- sortix/x86-family/memorymanagement.cpp | 55 +++++++++++++++++++++----- sortix/x86/memorymanagement.cpp | 42 ++++++++++++++++++++ sortix/x86/scheduler.cpp | 17 -------- 11 files changed, 173 insertions(+), 60 deletions(-) diff --git a/libmaxsi/heap.cpp b/libmaxsi/heap.cpp index 30189b8f..92498966 100644 --- a/libmaxsi/heap.cpp +++ b/libmaxsi/heap.cpp @@ -68,12 +68,12 @@ namespace Maxsi #ifdef SORTIX_KERNEL addr_t GetHeapStart() { - return Sortix::Memory::HEAPUPPER; + return Sortix::Memory::GetHeapUpper(); } size_t GetHeapMaxSize() { - return Sortix::Memory::HEAPUPPER - Sortix::Memory::HEAPLOWER; + return Sortix::Memory::GetHeapUpper() - Sortix::Memory::GetHeapLower(); } void FreeMemory(addr_t where, size_t bytes) diff --git a/sortix/initrd.cpp b/sortix/initrd.cpp index 2b24da50..426d2756 100644 --- a/sortix/initrd.cpp +++ b/sortix/initrd.cpp @@ -27,6 +27,7 @@ #include #include #include "syscall.h" +#include "memorymanagement.h" #include "log.h" // DEBUG @@ -82,9 +83,23 @@ namespace Sortix } } - void Init(byte* theinitrd, size_t size) + void Init(addr_t phys, size_t size) { - initrd = theinitrd; + // First up, map the initrd onto the kernel's address space. + addr_t virt = Memory::GetInitRD(); + size_t amount = 0; + while ( amount < size ) + { + if ( !Memory::MapKernel(phys + amount, virt + amount) ) + { + Panic("Unable to map the init ramdisk into virtual memory"); + } + amount += 0x1000UL; + } + + Memory::Flush(); + + initrd = (byte*) virt; initrdsize = size; if ( size < sizeof(Header) ) { PanicF("initrd.cpp: initrd is too small"); } Header* header = (Header*) initrd; diff --git a/sortix/initrd.h b/sortix/initrd.h index 771d87a5..a1ee26f1 100644 --- a/sortix/initrd.h +++ b/sortix/initrd.h @@ -55,7 +55,7 @@ namespace Sortix }; #ifdef SORTIX_KERNEL - void Init(byte* initrd, size_t size); + void Init(addr_t phys, size_t size); byte* Open(const char* filepath, size_t* size); const char* GetFilename(size_t index); size_t GetNumFiles(); diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 0ef97d24..ecee8f6f 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -184,7 +184,7 @@ namespace Sortix if ( BootInfo == NULL ) { Panic("kernel.cpp: The bootinfo structure was NULL. Are your bootloader multiboot compliant?"); } - uint8_t* initrd = NULL; + addr_t initrd = NULL; size_t initrdsize = 0; #ifndef JSSORTIX @@ -192,18 +192,20 @@ namespace Sortix for ( uint32_t I = 0; I < BootInfo->mods_count; I++ ) { initrdsize = modules[2*I+1] - modules[2*I+0]; - initrd = (uint8_t*) modules[2*I+0]; + initrd = (addr_t) modules[2*I+0]; break; } - if ( initrd == NULL ) { PanicF("No init ramdisk provided"); } + if ( !initrd ) { PanicF("No init ramdisk provided"); } #else // TODO: UGLY HACK because JSVM doesn't support multiboot yet! - initrd = (uint8_t*) 0x180000UL; + initrd = (addr_t) 0x180000UL; initrdsize = 0x280000; // 2 MiB 512 KiB #endif + Memory::RegisterInitRDSize(initrdsize); + #ifndef JSSORTIX // Search for PCI devices and load their drivers. PCI::Init(); diff --git a/sortix/memorymanagement.h b/sortix/memorymanagement.h index 86d0371c..0c185955 100644 --- a/sortix/memorymanagement.h +++ b/sortix/memorymanagement.h @@ -59,14 +59,13 @@ namespace Sortix addr_t UnmapKernel(addr_t mapto); addr_t UnmapUser(addr_t mapto); void Statistics(size_t* amountused, size_t* totalmem); - -#if defined(PLATFORM_X86) - const addr_t HEAPLOWER = 0x80000000UL; - const addr_t HEAPUPPER = 0xFF400000UL; -#elif defined(PLATFORM_X64) - const addr_t HEAPLOWER = 0xFFFF800000000000UL; - const addr_t HEAPUPPER = 0xFFFFFE8000000000UL; -#endif + addr_t GetKernelStack(); + size_t GetKernelStackSize(); + addr_t GetInitRD(); + size_t GetInitRDSize(); + void RegisterInitRDSize(size_t size); + addr_t GetHeapLower(); + addr_t GetHeapUpper(); } } diff --git a/sortix/scheduler.cpp b/sortix/scheduler.cpp index 14636ce6..089c6cb7 100644 --- a/sortix/scheduler.cpp +++ b/sortix/scheduler.cpp @@ -31,6 +31,7 @@ #include "memorymanagement.h" #include "syscall.h" #include "sound.h" // HACK FOR SIGINT +#include "descriptor_tables.h" namespace Sortix { @@ -39,7 +40,6 @@ namespace Sortix // Internal forward-declarations. namespace Scheduler { - void InitCPU(); Thread* PopNextThread(); void WakeSleeping(); void LogBeginContextSwitch(Thread* current, const CPU::InterruptRegisters* state); @@ -76,7 +76,16 @@ namespace Sortix Syscall::Register(SYSCALL_SLEEP, (void*) SysSleep); Syscall::Register(SYSCALL_USLEEP, (void*) SysUSleep); - InitCPU(); + addr_t stackstart = Memory::GetKernelStack(); + size_t stacksize = Memory::GetKernelStackSize(); + addr_t stackend = stackstart - stacksize; + if ( !Memory::MapRangeKernel(stackend, stacksize) ) + { + PanicF("could not create kernel stack (%zx to %zx)", + stackend, stackstart); + } + + GDT::SetKernelStack((size_t*) stackstart); } // The no operating thread is a thread stuck in an infinite loop that diff --git a/sortix/x64/memorymanagement.cpp b/sortix/x64/memorymanagement.cpp index bacd2050..74daa302 100644 --- a/sortix/x64/memorymanagement.cpp +++ b/sortix/x64/memorymanagement.cpp @@ -143,5 +143,47 @@ namespace Sortix PML* const BOOTPML4 = (PML* const) 0x01000UL; SwitchAddressSpace((addr_t) BOOTPML4); } + + const size_t KERNEL_STACK_SIZE = 256UL * 1024UL; + const addr_t KERNEL_STACK_END = 0xFFFF800000001000UL; + const addr_t KERNEL_STACK_START = KERNEL_STACK_END + KERNEL_STACK_SIZE; + addr_t INITRD = KERNEL_STACK_START; + size_t initrdsize = 0; + const addr_t HEAPUPPER = 0xFFFFFE8000000000UL; + + addr_t GetInitRD() + { + return INITRD; + } + + size_t GetInitRDSize() + { + return initrdsize; + } + + void RegisterInitRDSize(size_t size) + { + initrdsize = size; + } + + addr_t GetHeapLower() + { + return Page::AlignUp(INITRD + initrdsize); + } + + addr_t GetHeapUpper() + { + return HEAPUPPER; + } + + addr_t GetKernelStack() + { + return KERNEL_STACK_START; + } + + size_t GetKernelStackSize() + { + return KERNEL_STACK_SIZE; + } } } diff --git a/sortix/x64/scheduler.cpp b/sortix/x64/scheduler.cpp index 49b08b89..25dedf89 100644 --- a/sortix/x64/scheduler.cpp +++ b/sortix/x64/scheduler.cpp @@ -31,22 +31,8 @@ namespace Sortix { namespace Scheduler { - const size_t KERNEL_STACK_SIZE = 256UL * 1024UL; - const addr_t KERNEL_STACK_END = 0xFFFF800000001000UL; - const addr_t KERNEL_STACK_START = KERNEL_STACK_END + KERNEL_STACK_SIZE; - void InitCPU() { - // TODO: Prevent the kernel heap and other stuff from accidentally - // also allocating this virtual memory region! - - if ( !Memory::MapRangeKernel(KERNEL_STACK_END, KERNEL_STACK_SIZE) ) - { - PanicF("could not create kernel stack (%zx to %zx)", - KERNEL_STACK_END, KERNEL_STACK_START); - } - - GDT::SetKernelStack((size_t*) KERNEL_STACK_START); } } } diff --git a/sortix/x86-family/memorymanagement.cpp b/sortix/x86-family/memorymanagement.cpp index 0a694bb0..a998678d 100644 --- a/sortix/x86-family/memorymanagement.cpp +++ b/sortix/x86-family/memorymanagement.cpp @@ -35,7 +35,7 @@ using namespace Maxsi; namespace Sortix { - const addr_t KERNELEND = 0x400000UL; + const addr_t KERNELEND = 0x200000UL; namespace Page { @@ -98,17 +98,52 @@ namespace Sortix // Count the amount of usable RAM (even if reserved for kernel). Page::totalmem += length; - // Detect if this memory is completely covered by the kernel. - if ( base + length <= KERNELEND ) { continue; } - - // Detect if this memory is partially covered by the kernel. - if ( base <= KERNELEND && KERNELEND <= base + length ) + // Give all the physical memory to the physical memory allocator + // but make sure not to give it things we already use. + addr_t regionstart = mmap->addr; + addr_t regionend = mmap->addr + mmap->len; + addr_t processed = regionstart; + while ( processed < regionend ) { - length = (base + length) - KERNELEND; - base = KERNELEND; - } + addr_t lowest = processed; + addr_t highest = regionend; - Page::InitPushRegion(base, length); + // Don't allocate the kernel. + if ( lowest < KERNELEND ) { processed = KERNELEND; continue; } + + // Don't give any of our modules to the physical page + // allocator, we'll need them. + bool continuing = false; + uint32_t* modules = (uint32_t*) bootinfo->mods_addr; + for ( uint32_t i = 0; i < bootinfo->mods_count; i++ ) + { + size_t modsize = (size_t) (modules[2*i+1] - modules[2*i+0]); + addr_t modstart = (addr_t) modules[2*i+0]; + addr_t modend = modstart + modsize; + if ( modstart <= processed && processed < modend ) + { + processed = modend; + continuing = true; + break; + } + if ( lowest <= modstart && modstart < highest ) + { + highest = modstart; + } + } + + if ( continuing ) { continue; } + + if ( highest <= lowest ) { break; } + + // Now that we have a continious area not used by anything, + // let's forward it to the physical page allocator. + lowest = Page::AlignUp(lowest); + highest = Page::AlignUp(highest); + size_t size = highest - lowest; + Page::InitPushRegion(lowest, size); + processed = highest; + } } // If the physical allocator couldn't handle the vast amount of diff --git a/sortix/x86/memorymanagement.cpp b/sortix/x86/memorymanagement.cpp index 37fdddf9..6ec94507 100644 --- a/sortix/x86/memorymanagement.cpp +++ b/sortix/x86/memorymanagement.cpp @@ -153,5 +153,47 @@ namespace Sortix PML* const BOOTPML2 = (PML* const) 0x01000UL; SwitchAddressSpace((addr_t) BOOTPML2); } + + const size_t KERNEL_STACK_SIZE = 256UL * 1024UL; + const addr_t KERNEL_STACK_END = 0x80001000UL; + const addr_t KERNEL_STACK_START = KERNEL_STACK_END + KERNEL_STACK_SIZE; + addr_t INITRD = KERNEL_STACK_START; + size_t initrdsize = 0; + const addr_t HEAPUPPER = 0xFF400000UL; + + addr_t GetInitRD() + { + return INITRD; + } + + size_t GetInitRDSize() + { + return initrdsize; + } + + void RegisterInitRDSize(size_t size) + { + initrdsize = size; + } + + addr_t GetHeapLower() + { + return Page::AlignUp(INITRD + initrdsize); + } + + addr_t GetHeapUpper() + { + return HEAPUPPER; + } + + addr_t GetKernelStack() + { + return KERNEL_STACK_START; + } + + size_t GetKernelStackSize() + { + return KERNEL_STACK_SIZE; + } } } diff --git a/sortix/x86/scheduler.cpp b/sortix/x86/scheduler.cpp index ab4c4c9f..1525e47a 100644 --- a/sortix/x86/scheduler.cpp +++ b/sortix/x86/scheduler.cpp @@ -31,22 +31,5 @@ namespace Sortix { namespace Scheduler { - const size_t KERNEL_STACK_SIZE = 256UL * 1024UL; - const addr_t KERNEL_STACK_END = 0x80001000UL; - const addr_t KERNEL_STACK_START = KERNEL_STACK_END + KERNEL_STACK_SIZE; - - void InitCPU() - { - // TODO: Prevent the kernel heap and other stuff from accidentally - // also allocating this virtual memory region! - - if ( !Memory::MapRangeKernel(KERNEL_STACK_END, KERNEL_STACK_SIZE) ) - { - PanicF("could not create kernel stack (%zx to %zx)", - KERNEL_STACK_END, KERNEL_STACK_START); - } - - GDT::SetKernelStack((size_t*) KERNEL_STACK_START); - } } }