From a47879f404e5d7ea268247a56cc535f86014869c Mon Sep 17 00:00:00 2001 From: Nigel Date: Sat, 3 Sep 2022 17:27:29 +0200 Subject: [PATCH] KERNEL: First Kernel heap implementation --- source/kernel/kernel.cpp | 15 ++++--- source/kernel/memory/KernelHeap.cpp | 43 +++++++++++++++++-- .../kernel/memory/PhysicalMemoryManager.cpp | 3 +- source/kernel/memory/PhysicalMemoryManager.h | 1 + source/kernel/memory/VirtualMemoryManager.cpp | 32 ++++++++++---- source/kernel/memory/VirtualMemoryManager.h | 12 ++++-- source/kernel/prekernel/bootstructure.h | 11 ----- source/kernel/serial.h | 17 -------- 8 files changed, 83 insertions(+), 51 deletions(-) diff --git a/source/kernel/kernel.cpp b/source/kernel/kernel.cpp index 6f932a1..8049eb5 100644 --- a/source/kernel/kernel.cpp +++ b/source/kernel/kernel.cpp @@ -38,11 +38,9 @@ extern "C" void kernel_main () extern "C" void early_main() { init_serial(); - print_serial("Hello Higher half kernel!\n"); kterm_init(); - - printf("Allocated blocks: %d \n", GetUsedBlocks()); + printf("Allocated blocks: 0x%x \n", GetUsedBlocks()); initGDT(); init_idt(); @@ -53,8 +51,12 @@ extern "C" void early_main() initHeap(); + printf("TRY ALLOCATING 4 BYTES\n"); + uint32_t* MyVariable = (uint32_t*) malloc(4); // allocate 4 bytes using my heap + free(MyVariable); + // test heap allocation - /* + struct KernelInfo { int bar; bool foo; @@ -64,9 +66,10 @@ extern "C" void early_main() MyInfo->bar = 6; MyInfo->foo = false; - + printf("bar contains %d\n", MyInfo->bar); free(MyInfo); - */ + + printf("Enable Protected mode and jump to kernel main\n"); diff --git a/source/kernel/memory/KernelHeap.cpp b/source/kernel/memory/KernelHeap.cpp index 0aff6d3..a17ccf6 100644 --- a/source/kernel/memory/KernelHeap.cpp +++ b/source/kernel/memory/KernelHeap.cpp @@ -1,4 +1,5 @@ #include "KernelHeap.h" +#include "VirtualMemoryManager.h" // Size of heap meta data is 5 bytes struct heap_block{ @@ -11,7 +12,7 @@ heap_block* start ; void* malloc(size_t size) { - printf("Received request for %d bytes of memory", size); + printf("Received request for %d bytes of memory\n", size); heap_block* current = start; // look for a free block @@ -20,8 +21,21 @@ void* malloc(size_t size) if(current->Size >= size && current->Used == false ) { // We found a spot + printf("Block found!\n"); + // Set the spot to in-use - current->Used = false; + current->Used = true; + + + // split the block + printf("Split block.\n"); + uint32_t oldSize = current->Size; + current->Size = size; + + heap_block* new_block = current + sizeof(heap_block) + current->Size; + new_block->Size = oldSize - ( sizeof(heap_block) + size); + new_block->Used = false; + // return the free address // NOTE: added an offset from the initial address to accomodate for // meta-data. @@ -36,6 +50,7 @@ void* malloc(size_t size) // probably ask the VMM for more // TODO: ask for more memory | Extend kernel heap + printf("ERROR: OUT OF HEAP MEMORY CONDITION IS NOT IMPLEMENTED. HEAP NEEDS TO BE EXTENDED!\n"); } void free(void* addr) @@ -48,6 +63,26 @@ void free(void* addr) void initHeap() { - // NOTE: What to do now?? - + // put the start of our kernel heap 1 page after the kernel_end address + // Lets calculate the address + printf("FIND SUITABLE HEAP_ADDRESS\n"); + uint32_t alligned_k_end = (uint32_t) &kernel_end + ((uint32_t)&kernel_end % BLOCK_SIZE == 0 ? 4096 : 0); + uint32_t HEAP_ADDRESS = (uint32_t) alligned_k_end + 4096; + printf("HEAP_ADDRESS: 0x%x\n", HEAP_ADDRESS); + + // NOTE: we can't check if the mapping has failed or not here! + AllocatePage(HEAP_ADDRESS); + start = (heap_block*) HEAP_ADDRESS; + heap_size = 4096; + + printf("Clear heap\n"); + // Clear the heap + printf("set at 0x%x %d bytes to zero\n", start , heap_size); + memset((void*)start, 0x00, heap_size /4); + + printf("Init first heap block\n"); + // initialzie + start->Size = heap_size - sizeof(heap_block); + start->Used = false; + } \ No newline at end of file diff --git a/source/kernel/memory/PhysicalMemoryManager.cpp b/source/kernel/memory/PhysicalMemoryManager.cpp index 33dde1e..3d78798 100644 --- a/source/kernel/memory/PhysicalMemoryManager.cpp +++ b/source/kernel/memory/PhysicalMemoryManager.cpp @@ -1,5 +1,4 @@ #include "./PhysicalMemoryManager.h" -#define BLOCK_SIZE 4092 #define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) #define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) @@ -28,7 +27,7 @@ void SetupPhysicalMemoryManager(uint32_t mapAddress, uint32_t memorySize ) printf("Bitmap size: %d bytes\n",bitmap_size); // Set blocks used to zero - used_blocks = 0; + used_blocks = max_blocks; // set the address of the memory bitmap memoryBitMap = (uint32_t*) mapAddress; diff --git a/source/kernel/memory/PhysicalMemoryManager.h b/source/kernel/memory/PhysicalMemoryManager.h index 87d3a8c..e68b33d 100644 --- a/source/kernel/memory/PhysicalMemoryManager.h +++ b/source/kernel/memory/PhysicalMemoryManager.h @@ -5,6 +5,7 @@ #include "../lib/mem.h" #include "../bitmap.h" +#define BLOCK_SIZE 4092 void SetupPhysicalMemoryManager(uint32_t mapAddress, uint32_t memorySize); diff --git a/source/kernel/memory/VirtualMemoryManager.cpp b/source/kernel/memory/VirtualMemoryManager.cpp index bc535ee..3ce9260 100644 --- a/source/kernel/memory/VirtualMemoryManager.cpp +++ b/source/kernel/memory/VirtualMemoryManager.cpp @@ -1,9 +1,16 @@ #include "VirtualMemoryManager.h" #define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) + extern uint32_t boot_page_directory[1024] ; extern uint32_t boot_page_table[1024]; +void flush_cr3(){ + asm volatile("movl %cr3, %ecx;" + "movl %ecx, %cr3"); +} + + void AllocatePage(uint32_t vaddr) { uint32_t page_aligned_address = ALIGN(vaddr, 4096); @@ -15,23 +22,31 @@ void AllocatePage(uint32_t vaddr) printf("Allocation happening at PDE: %d PTE: %d\n", PageDirectoryEntryIndex, PageTableEntryIndex); // check if the page directory entry is marked as present - if (boot_page_directory[PageDirectoryEntryIndex] & 0x1 ) { - - uint32_t* page_table = (uint32_t*)((boot_page_directory[PageDirectoryEntryIndex]) & 0xFFFFE000 + 0xC0000000); + if (boot_page_directory[PageDirectoryEntryIndex] & 0x1 ) + { + printf("Directory entry is marked as present\n"); + uint32_t* page_table = (uint32_t*)((boot_page_directory[PageDirectoryEntryIndex]) & 0xFFFFE000) ; + page_table = (uint32_t*) ((uint32_t)page_table + 0xC0000000); // Add kernel offset + printf("Page table address: 0x%x\n", (uint32_t)page_table); // check if the page table entry is marked as present if ( page_table[PageTableEntryIndex] & 0x1 ) { + printf("page already present!\n"); + return; + } else{ + printf("Mapping a physical page.\n"); // Map the entry to a physical page page_table[PageTableEntryIndex] = (uint32_t)(allocate_block() + 0x3); - } else{ - // mark page as present - page_table[PageTableEntryIndex] = 0x3; + flush_cr3(); } } else { + printf("Mapping a new page directory entry with a page table\n"); // mark the page table as present and allocate a physical block for it boot_page_directory[PageDirectoryEntryIndex] = (uint32_t)(allocate_block() + 0x3); + flush_cr3(); + } @@ -56,7 +71,8 @@ void FreePage(uint32_t vaddr ) } -void Map ( uint32_t vaddr, uint32_t paddr) + +void Immediate_Map ( uint32_t vaddr, uint32_t paddr) { uint32_t page_aligned_address = ALIGN(vaddr, 4096); @@ -66,7 +82,7 @@ void Map ( uint32_t vaddr, uint32_t paddr) } -void Unmap(uint32_t vaddr) +void Immediate_Unmap(uint32_t vaddr) { // NOTE: I will implement lazy unmapping for now uint32_t page_aligned_address = ALIGN(vaddr, 4096); diff --git a/source/kernel/memory/VirtualMemoryManager.h b/source/kernel/memory/VirtualMemoryManager.h index e54e3ed..ef80ffe 100644 --- a/source/kernel/memory/VirtualMemoryManager.h +++ b/source/kernel/memory/VirtualMemoryManager.h @@ -1,10 +1,16 @@ #pragma once -#include "PhysicalMemoryManager.h" #include "../terminal/kterm.h" #include "../cpu.h" +#include "PhysicalMemoryManager.h" + + +void SetupVMM(); void AllocatePage(uint32_t v_addr ); void FreePage(uint32_t v_addr); -void Map(uint32_t p_addr, uint32_t v_addr); -void Unmap (uint32_t v_addr); +void Immediate_Map(uint32_t p_addr, uint32_t v_addr); +void Immediate_Unmap (uint32_t v_addr); + +// void Demand_map(uint32_t p_addr, uint32_t v_addr); +// void Demand_Unmap (uint32_t v_addr); diff --git a/source/kernel/prekernel/bootstructure.h b/source/kernel/prekernel/bootstructure.h index 63e95f6..48fd40d 100644 --- a/source/kernel/prekernel/bootstructure.h +++ b/source/kernel/prekernel/bootstructure.h @@ -11,13 +11,7 @@ extern "C" const uint32_t kernel_end; #define IS_NVS_MEMORY(MEM_TYPE) MEM_TYPE & 0x8 #define IS_BADRAM_MEMORY(MEM_TYPE) MEM_TYPE & 0x10 -struct MemoryInfoBlock { - uint32_t Base_addr ; - uint32_t Memory_Size; - MemoryInfoBlock* next; - uint8_t type; -}; struct BootInfoBlock { bool MapIsInvalid; uint32_t bootDeviceID ; @@ -33,9 +27,4 @@ struct BootInfoBlock { bool EnabledVBE; - bool PhysicalMemoryMapAvailable; - MemoryInfoBlock* MemoryMap; - uint32_t map_size; - uint32_t MemorySize ; - }; diff --git a/source/kernel/serial.h b/source/kernel/serial.h index b17afd8..6494a36 100644 --- a/source/kernel/serial.h +++ b/source/kernel/serial.h @@ -56,20 +56,3 @@ void print_serial(const char* string ){ } } -void test_serial(){ - /** Serial test **/ - kterm_writestring("Writing to COM1 serial port:"); - init_serial(); - write_serial('A'); - write_serial('B'); - write_serial('C'); - write_serial('D'); - write_serial('E'); - - char Character_received = read_serial(); - kterm_writestring("\n"); - kterm_writestring("received from COM 1: \n"); - kterm_put(Character_received); - - kterm_writestring("\n"); -}