From a5e7fdd07e9cd4a625c331c0ad3cbcf2eae90351 Mon Sep 17 00:00:00 2001 From: Nigel Date: Thu, 1 Sep 2022 16:11:35 +0200 Subject: [PATCH] KERNEL: Physical Page Frame allocation Rewriting the setup to allow for physical memory allocation again to work. --- source/kernel/Boot/boot.s | 3 +- source/kernel/Memory/GDT/gdtc.cpp | 2 +- .../kernel/Memory/PhysicalMemoryManager.cpp | 82 +++++++++++++------ source/kernel/Memory/PhysicalMemoryManager.h | 12 +-- source/kernel/PreKernel/bootstructure.h | 12 +-- source/kernel/PreKernel/prekernel.cpp | 20 +++-- source/kernel/kernel.cpp | 60 ++++++-------- 7 files changed, 107 insertions(+), 84 deletions(-) diff --git a/source/kernel/Boot/boot.s b/source/kernel/Boot/boot.s index b32fdaa..f8eb7f6 100644 --- a/source/kernel/Boot/boot.s +++ b/source/kernel/Boot/boot.s @@ -35,7 +35,7 @@ _start: /* push the magic value */ pushl %eax - call testLauncher + call prekernelSetup # Get physical address of the boot_page_table movl $(boot_page_table - 0xC0000000), %edi @@ -60,7 +60,6 @@ _start: 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 diff --git a/source/kernel/Memory/GDT/gdtc.cpp b/source/kernel/Memory/GDT/gdtc.cpp index e78b509..bd10a08 100644 --- a/source/kernel/Memory/GDT/gdtc.cpp +++ b/source/kernel/Memory/GDT/gdtc.cpp @@ -51,7 +51,7 @@ void initGDT(){ gdtDescriptor.limit = ((sizeof(SegmentDescriptor ) * 5 ) - 1); gdtDescriptor.base = (unsigned int) &GlobalDescriptorTable; - + printf("GDT at address 0x%x, with an size of 0x%x bytes\n" , (unsigned int)GlobalDescriptorTable, sizeof(GlobalDescriptorTable)); LoadGlobalDescriptorTable(); diff --git a/source/kernel/Memory/PhysicalMemoryManager.cpp b/source/kernel/Memory/PhysicalMemoryManager.cpp index dd8bd5c..7551f91 100644 --- a/source/kernel/Memory/PhysicalMemoryManager.cpp +++ b/source/kernel/Memory/PhysicalMemoryManager.cpp @@ -2,32 +2,61 @@ PhysicalMemoryManagerInfoBlock* PMMInfoBlock; +const uint32_t KERNEL_OFFSET = 0xC0000000; +void SetupPhysicalMemoryManager( BootInfoBlock* Bootinfo) { -void initPMM( MemoryInfo* memory) { - - // NOTE: Lets for now puts the Physical memoryManagerBlock at a random address - // We'll think of a more proper solution a bit later - PMMInfoBlock = (PhysicalMemoryManagerInfoBlock*) 0xCC900000; - + PMMInfoBlock = (PhysicalMemoryManagerInfoBlock*) ((uint32_t)MemoryMapHeap_pptr + Bootinfo->map_size + 0xC0000000); + /* + Every byte contains 8 pages + A page is 4096 kib + Every block (1 bit) represent an page + */ // calculate the maximum number of blocks - PMMInfoBlock->max_blocks = KB_TO_BLOCKS(memory->TotalMemory); + PMMInfoBlock->max_blocks =Bootinfo->MemorySize / BLOCK_SIZE / 8; PMMInfoBlock->used_blocks = 0; - PMMInfoBlock->memoryBitMap = (uint32_t*) 0xCCA00000; - printf("Maximum Number of blocks: 0x%x, Number of bytes for memMap: 0x%x\n", PMMInfoBlock->max_blocks , (PMMInfoBlock->max_blocks/8)); + // put the map after the gdt + PMMInfoBlock->memoryBitMap = (uint32_t*) ( 0xC010b100) ; + + // // Page in the address space please + // uint32_t PDEI = 0xC020a000 >> 22; + // uint32_t PTEI = (0xC020a000 >> 12) & 0x1FFF; + // printf("PDEI: %d, PTEI: %d\n", PDEI, PTEI); - //Size of memory map - uint32_t memMap_size = (PMMInfoBlock->max_blocks / 8 ) ; - printf("Memory Map size: 0x%x\n", memMap_size ); - printf("size of int in bytes: 0x%x \n" , sizeof(int)); - + printf("Maximum num blocks: %d \n",PMMInfoBlock->max_blocks); + //Size of memory map + uint32_t memMap_size = PMMInfoBlock->max_blocks / 8; + printf("Memory map size: %d\n", memMap_size); + printf("Address of memory map 0x%x\n", PMMInfoBlock->memoryBitMap); // Set all places in memory as free - memset(PMMInfoBlock->memoryBitMap, 0xFF, memMap_size ); + memset(PMMInfoBlock->memoryBitMap, 0xFF, memMap_size ); + + // Loop over memory map and allocate physical locations + // that are already in use + MemoryInfoBlock* currentBlock = (MemoryInfoBlock*) ((uint32_t)Bootinfo->MemoryMap + KERNEL_OFFSET) ; + printf("Starting address: 0x%x\n", currentBlock); + while( (uint32_t) currentBlock->next != 0x0) + { + if(IS_AVAILABLE_MEM(currentBlock->type)){ + printf("skip!\n"); + } else { + printf("allocate region 0x%x of size 0x%x\n" , currentBlock->Base_addr, currentBlock->Memory_Size); + allocate_region((uint32_t) currentBlock->Base_addr, currentBlock->Memory_Size); + } + + currentBlock = (MemoryInfoBlock*) ((uint32_t)currentBlock->next + KERNEL_OFFSET ); + } + + uint32_t kernel_size = ((uint32_t)&kernel_end - (uint32_t)&kernel_begin ) - KERNEL_OFFSET; + + printf("kernel size in memory: 0x%x\n", kernel_size); + allocate_region((uint32_t)&kernel_begin, kernel_size); } -// NOTE: this can only give blocks of 4kb at a time! +// NOTE: This can only give blocks of 4kb at a time! +// We might at some point want to allocate multiple blocks at once. void* allocate_block() { uint8_t blocks_available = PMMInfoBlock->max_blocks - PMMInfoBlock->used_blocks; // Are there any blocks available? @@ -38,10 +67,8 @@ void* allocate_block() { } // Find 1 free block somewhere - int free_block_index = bitmap_first_unset(PMMInfoBlock->memoryBitMap, (PMMInfoBlock->max_blocks /8) /*memMap Size*/ ); + int free_block_index = bitmap_first_unset(PMMInfoBlock->memoryBitMap, PMMInfoBlock->max_blocks / 8 ); - - if(free_block_index == -1) { printf("Could not find a good block!\n"); @@ -83,20 +110,27 @@ void allocate_region(uint32_t startAddress, uint32_t size) { int NumberOfBlocksToAllocate = ( size / 1024) / 4 / 8 + 1; int startBlock = (startAddress / 1024) / 4 / 8 ; - // printf("NumberOfBlocksToAllocate: 0x%x\n", NumberOfBlocksToAllocate); - //printf( "start block: 0x%x\n" , startBlock); + for( int i = 0; i < NumberOfBlocksToAllocate; i++) { - - //printf("ALLOCATE BLOCK: 0x%x\n" , startBlock + i ); bitmap_unset(PMMInfoBlock->memoryBitMap, startBlock+ i); PMMInfoBlock->used_blocks++; } } + void deallocate_region(uint32_t StartAddress , uint32_t size ) { - // NOT IMPLEMENTED YET + // reverse of what happened in allocate_region + + int NumberOfBlocks = (size / 1024) / 4 / 8 + 1; + int startBlock = (StartAddress / 1024) / 4 / 8; + + for(int i = 0; i < NumberOfBlocks; i++) + { + bitmap_set(PMMInfoBlock->memoryBitMap, startBlock + i); + PMMInfoBlock->used_blocks --; + } } diff --git a/source/kernel/Memory/PhysicalMemoryManager.h b/source/kernel/Memory/PhysicalMemoryManager.h index 649c922..1122b25 100644 --- a/source/kernel/Memory/PhysicalMemoryManager.h +++ b/source/kernel/Memory/PhysicalMemoryManager.h @@ -1,17 +1,13 @@ #pragma once #include -#include "memoryinfo.h" - +#include "../PreKernel/bootstructure.h" #include "../Terminal/kterm.h" #include "../Lib/mem.h" #include "../bitmap.h" -// Asumming 32 bit x86 for now! -#define BLOCK_SIZE 4092 -#define WORD_SIZE 2 -#define BLOCKS_PER_WORD 32 +// Asumming i386 for now! +#define BLOCK_SIZE 4092 -#define KB_TO_BLOCKS(x) (x / BLOCK_SIZE) #define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) #define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) @@ -23,7 +19,7 @@ struct PhysicalMemoryManagerInfoBlock int used_blocks; }; -void initPMM(MemoryInfo* memory); +void SetupPhysicalMemoryManager(BootInfoBlock* memory); void free_block(void* ptr); void* allocate_block(); void allocate_region(uint32_t, uint32_t); diff --git a/source/kernel/PreKernel/bootstructure.h b/source/kernel/PreKernel/bootstructure.h index 70f9abf..78f4580 100644 --- a/source/kernel/PreKernel/bootstructure.h +++ b/source/kernel/PreKernel/bootstructure.h @@ -2,17 +2,12 @@ #include #include - extern "C" const uint32_t kernel_begin; extern "C" const uint32_t kernel_end; -// Put the BootInfoBlock 1MB above the kernel. -const uint32_t BootInfoBlock_pptr = (uint32_t)&kernel_end - 0xC0000000 + 0x1; -const uint32_t MemoryMapHeap_pptr = BootInfoBlock_pptr + 0x1; - #define IS_AVAILABLE_MEM(MEM_TYPE) MEM_TYPE & 0x1 #define IS_ACPI_MEM(MEM_TYPE) MEM_TYPE & 0x2 -#define IS_RESERVED_MEM(MEM_TYPE) MEM_TYPE & 0x3 +#define IS_RESERVED_MEM(MEM_TYPE) MEM_TYPE & 0x4 #define IS_NVS_MEMORY(MEM_TYPE) MEM_TYPE & 0x8 #define IS_BADRAM_MEMORY(MEM_TYPE) MEM_TYPE & 0x10 @@ -40,6 +35,11 @@ struct BootInfoBlock { bool PhysicalMemoryMapAvailable; MemoryInfoBlock* MemoryMap; + uint32_t map_size; + uint32_t MemorySize ; }; +// TODO Put the BootInfoBlock 1MB above the kernel. +const uint32_t BootInfoBlock_pptr = (uint32_t)&kernel_end - 0xC0000000 + 0x1; +const uint32_t MemoryMapHeap_pptr = BootInfoBlock_pptr + sizeof(BootInfoBlock); diff --git a/source/kernel/PreKernel/prekernel.cpp b/source/kernel/PreKernel/prekernel.cpp index 48ab238..479af04 100644 --- a/source/kernel/PreKernel/prekernel.cpp +++ b/source/kernel/PreKernel/prekernel.cpp @@ -5,7 +5,7 @@ #define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit))) -extern "C" void testLauncher ( unsigned long magic, multiboot_info_t* mbi) { +extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi) { // Create the bootInfoBlock at its location BootInfoBlock* BIB = (BootInfoBlock*) BootInfoBlock_pptr; @@ -74,23 +74,25 @@ if (CHECK_FLAG(mbi->flags, 6)) auto CurrentInfoBlock = BIB->MemoryMap; - - while((unsigned long) mmap < MemoryMapEnd){ + uint32_t RAM_size = 0; + while((unsigned long) mmap < MemoryMapEnd){ + BIB->map_size += sizeof(MemoryInfoBlock); CurrentInfoBlock->Base_addr = mmap->addr; CurrentInfoBlock->Memory_Size = mmap->len; if(mmap->type == MULTIBOOT_MEMORY_AVAILABLE) - CurrentInfoBlock->type &= 0x1; + CurrentInfoBlock->type |= 0x1; + RAM_size += mmap->len; if(mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) - CurrentInfoBlock->type &= 0x2; + CurrentInfoBlock->type |= 0x2; if(mmap->type == MULTIBOOT_MEMORY_RESERVED) - CurrentInfoBlock->type &= 0x4; + CurrentInfoBlock->type |= 0x4; if(mmap->type == MULTIBOOT_MEMORY_NVS) - CurrentInfoBlock->type &= 0x8; + CurrentInfoBlock->type |= 0x8; if(mmap->type == MULTIBOOT_MEMORY_BADRAM) - CurrentInfoBlock->type &= 0x10; + CurrentInfoBlock->type |= 0x10; // continue to the next block @@ -102,7 +104,7 @@ if (CHECK_FLAG(mbi->flags, 6)) } CurrentInfoBlock->next = (MemoryInfoBlock*) 0x0; - + BIB->MemorySize = RAM_size; } else { BIB->PhysicalMemoryMapAvailable = false; diff --git a/source/kernel/kernel.cpp b/source/kernel/kernel.cpp index c9b8aff..d2f1018 100644 --- a/source/kernel/kernel.cpp +++ b/source/kernel/kernel.cpp @@ -4,9 +4,11 @@ extern "C" void early_main() /* * Initialize terminal interface */ - initGDT(); + kterm_init(); + initGDT(); + init_serial(); print_serial("Hello Higher half kernel!\n"); @@ -21,7 +23,7 @@ extern "C" void early_main() printf("|=== BarinkOS ===|\n"); printf("Kernel End Addr: 0x%x\n" , &kernel_end + KERNEL_BASE_ADDR); - uint32_t PageDirectoryEntryIndex = ((uint32_t)&kernel_end + KERNEL_BASE_ADDR ) >> 2 ; + uint32_t PageDirectoryEntryIndex = ((uint32_t)&kernel_end + KERNEL_BASE_ADDR ) >> 22 ; uint32_t PageTableEntryIndex = (((uint32_t)&kernel_end + KERNEL_BASE_ADDR) >> 12) & 0x1FFF; @@ -38,6 +40,8 @@ extern "C" void early_main() BootInfoBlock* BootInfo = (BootInfoBlock*) ( BootInfoBlock_pptr + 0xC0000000 ); + + printf("Size of BootInfoBlock: %d bytes\n", sizeof(BootInfoBlock)); printf("Bootloader information:\n"); if( BootInfo->ValidELFHeader ) { @@ -57,71 +61,58 @@ extern "C" void early_main() if(BootInfo->PhysicalMemoryMapAvailable) { printf("- Physical Memory Map available!\n"); - + printf("MemoryInfoheap size : %d bytes\n", BootInfo->map_size); // Print the memory regions MemoryInfoBlock* currentBlock = (MemoryInfoBlock*) ((uint32_t)BootInfo->MemoryMap + KERNEL_BASE_ADDR) ; - kterm_setcolor(VGA_COLOR_RED); - printf("size of MemoryInfoBlock: 0x%x\n", sizeof(MemoryInfoBlock)); - kterm_setcolor(VGA_COLOR_CYAN); - printf("Kernel End is at address: 0x%x\n", &kernel_end); - printf("BootInfo is at address: 0x%x\n", BootInfo); - printf("map is at address: 0x%x\n", currentBlock + KERNEL_BASE_ADDR); - kterm_setcolor(VGA_COLOR_WHITE); + printf( "Starting address: 0x%x\n", currentBlock); while( (uint32_t)currentBlock->next != 0x0 ) { - kterm_setcolor(VGA_COLOR_CYAN); - printf("map is at address: 0x%x\n", ( (uint32_t)currentBlock )); - kterm_setcolor(VGA_COLOR_WHITE); - - /* - uint32_t pageDirectoryIndex = ((uint32_t)¤tBlock ) >> 22; - printf("pageDirectoryIndex: %d\n", pageDirectoryIndex); - - uint32_t pageTableIndex = ((uint32_t)¤tBlock >> 12) & 0x1FFF; - printf("PagTableIndex: %d\n", pageTableIndex); - */ - - //printf("boot_page_directory addr: 0x%x\n", &boot_page_directory); - //printf("boot_page_table addr: 0x%x\n", &multiboot_page_table); - printf("Memory Region: \n"); - if(IS_AVAILABLE_MEM(currentBlock->type)){ //printf("AVAILABLE RAM\n"); } else if(IS_ACPI_MEM(currentBlock->type)){ - printf("ACPI MEMORY\n"); + //printf("ACPI MEMORY\n"); } else if(IS_RESERVED_MEM(currentBlock->type)){ - printf("RESERVED MEMORY\n"); + // printf("RESERVED MEMORY\n"); } else if(IS_NVS_MEMORY(currentBlock->type)){ - printf("NVS MEMORY \n"); + // printf("NVS MEMORY \n"); } else if(IS_BADRAM_MEMORY(currentBlock->type)){ - printf("BADRAM MEMORY \n"); + // printf("BADRAM MEMORY \n"); } else { // printf("(TYPE 0x%x )TYPE NOT SPECIFIED\n", currentBlock->type); } - - // printf("Base address: 0x%x, Memory size: 0x%x\n", currentBlock->Base_addr, currentBlock->Memory_Size); currentBlock = (MemoryInfoBlock*) ((uint32_t)currentBlock->next + KERNEL_BASE_ADDR ); } - + // Setup PhysicalMemoryManagement + SetupPhysicalMemoryManager(BootInfo); + // Small test! + void* block = allocate_block(); + void* block2 = allocate_block(); + printf("Allocated addresss 1: 0x%x 2: 0x%x\n", (uint32_t)block ,(uint32_t)block2); + free_block(block); + free_block(block2); + void* block3 = allocate_block(); + printf("Allocated addresss 3: 0x%x\n", (uint32_t)block3); + free_block(block3); } asm volatile("mov %cr0, %eax "); asm volatile("or $1, %eax"); - asm volatile("mov %eax, %cr0"); + asm volatile("mov %eax, %cr0"); // re-enable protected mode ? kernel_main(); } + void map_multiboot_info_structure(unsigned long addr){ // map the multiboot structure into virtual memory // so we can gather the necessary data from it. @@ -150,6 +141,7 @@ void map_multiboot_info_structure(unsigned long addr){ } void PhysicalMemoryAllocatorTest(){ + #ifdef UNIT_TESTS // test alloc_block uint8_t* memory = (uint8_t*) memAlloc.allocate_block();