From 656ca0baa82c7be3e0d16d136fe53caa88273050 Mon Sep 17 00:00:00 2001 From: Nigel Date: Sat, 3 Sep 2022 01:00:17 +0200 Subject: [PATCH] KERNEL: Pre-kernel sets up the physical memory manager. * BUG: allocated blocks is possibly incorrect! * prekernel no longer gets compiled as being in physical memory --- source/kernel/bitmap.h | 2 - source/kernel/boot/boot.s | 19 +- source/kernel/kernel.cpp | 37 +-- source/kernel/linker.ld | 6 +- .../kernel/memory/PhysicalMemoryManager.cpp | 98 +++---- source/kernel/memory/PhysicalMemoryManager.h | 22 +- source/kernel/memory/VirtualMemoryManager.cpp | 2 +- source/kernel/prekernel/bootstructure.h | 5 - source/kernel/prekernel/prekernel.cpp | 239 ++++++++++-------- 9 files changed, 193 insertions(+), 237 deletions(-) diff --git a/source/kernel/bitmap.h b/source/kernel/bitmap.h index 165266c..fd80075 100644 --- a/source/kernel/bitmap.h +++ b/source/kernel/bitmap.h @@ -2,7 +2,6 @@ #include #include - inline void bitmap_set( uint32_t* map , int index ) { map[index/32] |= (1 << (index % 32)); @@ -24,7 +23,6 @@ inline uint32_t bitmap_first_unset( uint32_t* map , int map_size) for(int j = 0 ; j < 32 ; j++){ if ( (map[i] & (0x00000001 << j)) > 0) { - printf("Found bit: byte 0x%x , bit 0x%x\n", i , j); return (i*32)+j; } } diff --git a/source/kernel/boot/boot.s b/source/kernel/boot/boot.s index 5469538..cbfb2ce 100644 --- a/source/kernel/boot/boot.s +++ b/source/kernel/boot/boot.s @@ -27,17 +27,10 @@ multiboot_page_table: # Entry point .section .multiboot.text, "a" -.global _start +.globl _start .type _start, @function _start: - /* push the pointer to the Multiboot information structure*/ - pushl %ebx - - /* push the magic value */ - pushl %eax - call prekernelSetup - # Get physical address of the boot_page_table movl $(boot_page_table - 0xC0000000), %edi # Map address 0 @@ -82,8 +75,15 @@ _start: 4: # At this point, paging is fully set up and enabled isPaging: + /* push the pointer to the Multiboot information structure*/ + pushl %ebx + + /* push the magic value */ + pushl %eax + call prekernelSetup + # Unmap the identity mapping as it is now unnecessary - //movl $0, boot_page_directory + 0 + movl $0, boot_page_directory + 0 # Reload cr3 to force tlb flush movl %cr3, %ecx @@ -97,6 +97,7 @@ isPaging: pushl $0 popf + call early_main cli diff --git a/source/kernel/kernel.cpp b/source/kernel/kernel.cpp index 073223e..6f932a1 100644 --- a/source/kernel/kernel.cpp +++ b/source/kernel/kernel.cpp @@ -39,13 +39,17 @@ extern "C" void early_main() { init_serial(); print_serial("Hello Higher half kernel!\n"); + kterm_init(); + + printf("Allocated blocks: %d \n", GetUsedBlocks()); + initGDT(); init_idt(); + // Enable interrupts asm volatile("STI"); - ProcessBootInfo(); initHeap(); @@ -75,33 +79,4 @@ extern "C" void early_main() kernel_main(); -} - -void ProcessBootInfo(){ - uint32_t BootInfoStruct = BootInfoBlock_pptr + 0xC0000000; - BootInfoBlock* BootInfo = (BootInfoBlock*) ( BootInfoBlock_pptr + 0xC0000000 ); - - if( BootInfo->ValidELFHeader ) - { - // NOTE: Do something with it.. (Store it , process it etc...) - } - - if(BootInfo->EnabledVBE) - { - // NOTE: Do something with it.. (Store it , process it etc...) - } - - if(BootInfo->ValidSymbolTable) - { - // NOTE: Do something with it.. (Store it , process it etc...) - // printf("- Valid Symbol Table available at 0x%x.\n Tab Size: %d, str Size: %d\n", BootInfo->SymbolTableAddr, BootInfo->SymbolTabSize, BootInfo->SymbolStrSize); - } - - if(BootInfo->PhysicalMemoryMapAvailable) - { - - - SetupPhysicalMemoryManager(BootInfo); - } - -} +} \ No newline at end of file diff --git a/source/kernel/linker.ld b/source/kernel/linker.ld index ef2b6a1..f15ca57 100644 --- a/source/kernel/linker.ld +++ b/source/kernel/linker.ld @@ -8,20 +8,16 @@ SECTIONS _kernel_start = .; kernel_begin = .; /* For legacy reasons */ - - + .multiboot.data : { *(.multiboot.data) } .multiboot.text : { *(multiboot.text) - *prekernel.o(.text) } . += 0xC0000000; /* Addresses in the following code need to be above the 3Gb mark */ - - .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000) { *(.text) diff --git a/source/kernel/memory/PhysicalMemoryManager.cpp b/source/kernel/memory/PhysicalMemoryManager.cpp index c16d33e..33dde1e 100644 --- a/source/kernel/memory/PhysicalMemoryManager.cpp +++ b/source/kernel/memory/PhysicalMemoryManager.cpp @@ -1,66 +1,46 @@ #include "./PhysicalMemoryManager.h" +#define BLOCK_SIZE 4092 +#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) +#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) const uint32_t KERNEL_OFFSET = 0xC0000000; -extern uint32_t* boot_page_directory; -extern uint32_t* boot_page_table; -extern uint32_t* multiboot_page_table; -PhysicalMemoryManagerInfoBlock* PMMInfoBlock; +uint32_t* memoryBitMap; +uint32_t pmmap_size; +uint32_t max_blocks; +int used_blocks; -void SetupPhysicalMemoryManager( BootInfoBlock* Bootinfo) + +void SetupPhysicalMemoryManager(uint32_t mapAddress, uint32_t memorySize ) { - - // NOTE: We should move our bitmap to just after the end of our kernel instead - PMMInfoBlock = (PhysicalMemoryManagerInfoBlock*) ( ((uint32_t)MemoryMapHeap_pptr + 80 ) + KERNEL_OFFSET ); - /* + /* Every byte contains 8 pages A page is 4096 kib Every block (1 bit) represent an page */ - // Calculate the maximum number of blocks - int maximum_blocks = (uint32_t)Bootinfo->MemorySize / BLOCK_SIZE / 8; - PMMInfoBlock->max_blocks = maximum_blocks; - PMMInfoBlock->used_blocks = 0; + // Set the maximum number of blocks + max_blocks = (uint32_t)memorySize / BLOCK_SIZE ; + printf("Max Blocks: %d\n", max_blocks); - // put the map after the gdt - PMMInfoBlock->memoryBitMap = (uint32_t*) ( 0xC010b100) ; + // Set size of the bitmap + uint32_t bitmap_size = max_blocks / 32; + printf("Bitmap size: %d bytes\n",bitmap_size); + + // Set blocks used to zero + used_blocks = 0; - //Size of memory map - uint32_t memMap_size = PMMInfoBlock->max_blocks / 8; + // set the address of the memory bitmap + memoryBitMap = (uint32_t*) mapAddress; + // Set all places in memory as free - memset(PMMInfoBlock->memoryBitMap, 0xFF, memMap_size ); - MemoryInfoBlock* currentBlock = (MemoryInfoBlock*) ((uint32_t)Bootinfo->MemoryMap + 0xC0000000) ; - - 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 %d bytes\n", currentBlock->Base_addr, currentBlock->Memory_Size); - // allocate_region( currentBlock->Base_addr, currentBlock->Memory_Size); // allocate region causes #PF Exception - } - - currentBlock = (MemoryInfoBlock*) ((uint32_t)currentBlock->next + 0xC0000000 ); - - } - - 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); - - printf("allocate BIOS region\n"); - allocate_region (0x0000000, 0x00100000); + memset(memoryBitMap, 0xFFFFFFFF, max_blocks / 32 ); } // 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; + uint8_t blocks_available = max_blocks - used_blocks; // Are there any blocks available? if( blocks_available <= 0) { @@ -69,7 +49,7 @@ void* allocate_block() { } // Find 1 free block somewhere - int free_block_index = bitmap_first_unset(PMMInfoBlock->memoryBitMap, PMMInfoBlock->max_blocks / 8 ); + int free_block_index = bitmap_first_unset(memoryBitMap, max_blocks / 8 ); if(free_block_index == -1) { @@ -82,10 +62,10 @@ void* allocate_block() { printf("Somethings wrong!!!\n"); // Set the block to be used! - bitmap_unset(PMMInfoBlock->memoryBitMap, free_block_index); + bitmap_unset(memoryBitMap, free_block_index); // Increase the used_block count! - PMMInfoBlock->used_blocks++; - printf("used blocks: 0x%x\n", PMMInfoBlock->used_blocks); + used_blocks++; + printf("used blocks: 0x%x\n", used_blocks); // return the pointer to the physical address return (void*) (BLOCK_SIZE * free_block_index); } @@ -99,9 +79,9 @@ void free_block(void* p) { int index = ((uint32_t) p) / BLOCK_SIZE; // set the block to be free - bitmap_set(PMMInfoBlock->memoryBitMap, index); - PMMInfoBlock->used_blocks--; - printf("used blocks: 0x%x, after free\n", PMMInfoBlock->used_blocks); + bitmap_set(memoryBitMap, index); + used_blocks--; + printf("used blocks: 0x%x, after free\n", used_blocks); } @@ -111,28 +91,26 @@ void allocate_region(uint32_t startAddress, uint32_t size) { int NumberOfBlocksToAllocate = ( size / 1024) / 4 / 8 + 1; int startBlock = (startAddress / 1024) / 4 / 8 ; - for( int i = 0; i < NumberOfBlocksToAllocate; i++) { - bitmap_unset(PMMInfoBlock->memoryBitMap, startBlock+ i); - PMMInfoBlock->used_blocks++; + bitmap_unset(memoryBitMap, startBlock + i);// allocate region causes #PF Exception + used_blocks++; } - - } void deallocate_region(uint32_t StartAddress , uint32_t size ) { // 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 --; + bitmap_set(memoryBitMap, startBlock + i); + used_blocks --; } } - +int GetUsedBlocks (){ + return used_blocks; +} diff --git a/source/kernel/memory/PhysicalMemoryManager.h b/source/kernel/memory/PhysicalMemoryManager.h index f51c329..87d3a8c 100644 --- a/source/kernel/memory/PhysicalMemoryManager.h +++ b/source/kernel/memory/PhysicalMemoryManager.h @@ -5,22 +5,14 @@ #include "../lib/mem.h" #include "../bitmap.h" -// Asumming i386 for now! -#define BLOCK_SIZE 4092 -#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) -#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) -struct PhysicalMemoryManagerInfoBlock -{ - uint32_t* memoryBitMap; - uint32_t pmmap_size; - uint32_t max_blocks; - int used_blocks; -}; +void SetupPhysicalMemoryManager(uint32_t mapAddress, uint32_t memorySize); -void SetupPhysicalMemoryManager(BootInfoBlock* memory); -void free_block(void* ptr); void* allocate_block(); -void allocate_region(uint32_t, uint32_t); -void deallocate_region(uint32_t , uint32_t ); +void free_block(void* ptr); + +void allocate_region(uint32_t address, uint32_t size); +void deallocate_region(uint32_t address, uint32_t size); + +int GetUsedBlocks(); \ No newline at end of file diff --git a/source/kernel/memory/VirtualMemoryManager.cpp b/source/kernel/memory/VirtualMemoryManager.cpp index 813d52b..bc535ee 100644 --- a/source/kernel/memory/VirtualMemoryManager.cpp +++ b/source/kernel/memory/VirtualMemoryManager.cpp @@ -1,5 +1,5 @@ #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]; diff --git a/source/kernel/prekernel/bootstructure.h b/source/kernel/prekernel/bootstructure.h index 51f8ce0..63e95f6 100644 --- a/source/kernel/prekernel/bootstructure.h +++ b/source/kernel/prekernel/bootstructure.h @@ -39,8 +39,3 @@ struct BootInfoBlock { uint32_t MemorySize ; }; - - -const uint32_t pke = ((uint32_t)&kernel_end) - 0xC0000000; -const uint32_t BootInfoBlock_pptr = pke + 1000 - sizeof(BootInfoBlock); -const uint32_t MemoryMapHeap_pptr = pke + 0x1; diff --git a/source/kernel/prekernel/prekernel.cpp b/source/kernel/prekernel/prekernel.cpp index 156201c..53c34d3 100644 --- a/source/kernel/prekernel/prekernel.cpp +++ b/source/kernel/prekernel/prekernel.cpp @@ -1,119 +1,140 @@ #include #include #include "multiboot.h" -#include "bootstructure.h" +#include "../memory/PhysicalMemoryManager.h" + #define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit))) +#define VADDR_TO_PADDR(vaddr) (vaddr - 0xC0000000) +#define PADDR_TO_VADDR(paddr) (paddr + 0xC0000000) -extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi) { - - // Create the bootInfoBlock at its location - BootInfoBlock* BIB = (BootInfoBlock*) BootInfoBlock_pptr; +extern "C" void prekernelSetup ( unsigned long magic, multiboot_info_t* mbi) +{ - /* - * Check Multiboot magic number - */ - if (magic != MULTIBOOT_BOOTLOADER_MAGIC) - { - BIB->MapIsInvalid = true; - // crash - return; - } else{ - BIB->MapIsInvalid = false; - } - - /* is boot device valid ? */ - if (CHECK_FLAG (mbi->flags, 1)) - { - BIB->bootDeviceID = mbi->boot_device; - } else{ - BIB->bootDeviceID = 0x11111111; - } - - /* Are mods_* valid? */ - if(CHECK_FLAG ( mbi->flags, 3)){ - multiboot_module_t *mod; - uint32_t i; - - BIB->GrubModuleCount = mbi->mods_count; - - - for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){ - - } - } - - /* Is the symbol table of a.out valid? */ - if (CHECK_FLAG(mbi->flags, 4)) - { - BIB->ValidSymbolTable = true; - multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym); - - } else{ - BIB->ValidSymbolTable = false; - } - - /* Is the section header table of ELF valid? */ - if (CHECK_FLAG(mbi->flags, 5)) - { - BIB->ValidELFHeader = true; - multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec); - - }else{ - BIB->ValidELFHeader = false; - } -/* -If we got a memory map from our bootloader we -should be parsing it to find out the memory regions available. -*/ -if (CHECK_FLAG(mbi->flags, 6)) -{ - BIB->PhysicalMemoryMapAvailable = true; - BIB->MemoryMap = (MemoryInfoBlock*) MemoryMapHeap_pptr; - multiboot_memory_map_t *mmap = (multiboot_memory_map_t*) (mbi->mmap_addr) ; - auto MemoryMapEnd = mbi->mmap_addr + mbi->mmap_length; - - auto CurrentInfoBlock = BIB->MemoryMap; - - 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; - RAM_size += mmap->len; - if(mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) - CurrentInfoBlock->type |= 0x2; - if(mmap->type == MULTIBOOT_MEMORY_RESERVED) - CurrentInfoBlock->type |= 0x4; - if(mmap->type == MULTIBOOT_MEMORY_NVS) - CurrentInfoBlock->type |= 0x8; - if(mmap->type == MULTIBOOT_MEMORY_BADRAM) - CurrentInfoBlock->type |= 0x10; - - - // continue to the next block - mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + mmap->size + sizeof(mmap->size)); - - CurrentInfoBlock->next = (MemoryInfoBlock*) CurrentInfoBlock + 16; - CurrentInfoBlock = CurrentInfoBlock->next; + /* + * Check Multiboot magic number + */ + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) + { + // PANIC!! + return; } - CurrentInfoBlock->next = (MemoryInfoBlock*) 0x0; - BIB->MemorySize = RAM_size; -} else -{ - BIB->PhysicalMemoryMapAvailable = false; -} - - /* Draw diagonal blue line */ - if (CHECK_FLAG (mbi->flags, 12)){ - BIB->EnabledVBE = true; - } else{ - BIB->EnabledVBE; - } + mbi = PADDR_TO_VADDR(mbi); + + + // Setup the physical memory manager immmediatly + // Doing so saves the complications of doing it later when + // paging is enabled + + /* + If we got a memory map from our bootloader we + should be parsing it to find out the memory regions available. + */ + if (CHECK_FLAG(mbi->flags, 6)) + { + + // Calculate total memory size + uint32_t RAM_size = 0; + for( + multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mbi->mmap_addr; + (unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length; + mmap += mmap->size +sizeof(mmap->size) + ){ + RAM_size += mmap->len; + } + + // Call SetupPhysicalMemoryManager at its physical address + SetupPhysicalMemoryManager ( (uint32_t)VADDR_TO_PADDR(&kernel_end), RAM_size); + + for( + multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mbi->mmap_addr; + (unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length; + mmap += mmap->size +sizeof(mmap->size) + ){ + + if(mmap->type == MULTIBOOT_MEMORY_AVAILABLE) + deallocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) + allocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_RESERVED) + allocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_NVS) + allocate_region(mmap->addr, mmap->len); + if(mmap->type == MULTIBOOT_MEMORY_BADRAM) + allocate_region(mmap->addr, mmap->len); + + } + + + // Allocate the kernel + allocate_region( (uint32_t)&kernel_begin, ( (uint32_t)&kernel_end - (uint32_t)&kernel_begin)- 0xC0000000 ); + + // Allocate the memory region below 1MB + allocate_region(0x0000000, 0x00100000); + + } + else + { + // We didn't get a memory map from our bootloader. + // PANIC!!!! + return; + } + + // allocate a full block for the other boot info! + BootInfoBlock* BIB = (BootInfoBlock*) allocate_block(); + + + /* is boot device valid ? */ + if (CHECK_FLAG (mbi->flags, 1)) + { + BIB->bootDeviceID = mbi->boot_device; + } else{ + BIB->bootDeviceID = 0x11111111; + } + + /* Are mods_* valid? */ + if(CHECK_FLAG ( mbi->flags, 3)){ + multiboot_module_t *mod; + uint32_t i; + + BIB->GrubModuleCount = mbi->mods_count; + + + for(i = 0, mod = (multiboot_module_t *) mbi->mods_addr; i < mbi->mods_count; i++ , mod++){ + + } + } + + /* Is the symbol table of a.out valid? */ + if (CHECK_FLAG(mbi->flags, 4)) + { + // NOTE: Do something with it.. (Store it , process it etc...) + // printf("- Valid Symbol Table available at 0x%x.\n Tab Size: %d, str Size: %d\n", BootInfo->SymbolTableAddr, BootInfo->SymbolTabSize, BootInfo->SymbolStrSize); + BIB->ValidSymbolTable = true; + multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym); + + } else{ + BIB->ValidSymbolTable = false; + } + + /* Is the section header table of ELF valid? */ + if (CHECK_FLAG(mbi->flags, 5)) + { + // NOTE: Do something with it.. (Store it , process it etc...) + BIB->ValidELFHeader = true; + multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec); + + }else{ + BIB->ValidELFHeader = false; + } + + /* Draw diagonal blue line */ + if (CHECK_FLAG (mbi->flags, 12)){ + BIB->EnabledVBE = true; + + // NOTE: Do something with it.. (Store it , process it etc...) + } else{ + BIB->EnabledVBE; + } }