From 5fb55367caa61c14dbb3401522e53c45a2c008b5 Mon Sep 17 00:00:00 2001 From: Nigel Date: Sat, 6 Nov 2021 16:27:13 +0100 Subject: [PATCH] Implementation of simplistic physical memory manager --- Makefile | 6 +- src/kernel/bootcheck.h | 5 + src/kernel/kernel.cpp | 16 +-- src/kernel/kernel.h | 2 +- src/kernel/kstructures/bitmap.h | 40 +++++++ src/kernel/memory/PhysicalMemoryManager.cpp | 118 ++++++++++++++++++++ src/kernel/memory/PhysicalMemoryManager.h | 34 ++++++ src/libc/include/mem.h | 8 ++ 8 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 src/kernel/kstructures/bitmap.h create mode 100644 src/kernel/memory/PhysicalMemoryManager.cpp create mode 100644 src/kernel/memory/PhysicalMemoryManager.h create mode 100644 src/libc/include/mem.h diff --git a/Makefile b/Makefile index e3010f6..3c7ccbe 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CC = ${HOME}/opt/cross/bin/i686-elf-gcc CPP = ${HOME}/opt/cross/bin/i686-elf-g++ CFLAGS = -ffreestanding -O2 -Wall -Wextra -OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/PageFrameAllocator.o $(BUILD_DIR)/io.o $(BUILD_DIR)/PageDirectory.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/string.o +OFILES = $(BUILD_DIR)/boot.o $(BUILD_DIR)/kterm.o $(BUILD_DIR)/kernel.o $(BUILD_DIR)/PhysicalMemoryManager.o $(BUILD_DIR)/io.o $(BUILD_DIR)/PageDirectory.o $(BUILD_DIR)/idt.o $(BUILD_DIR)/pic.o $(BUILD_DIR)/string.o SRC_DIR = src BUILD_DIR = build @@ -83,5 +83,5 @@ $(BUILD_DIR)/pic.o: $(BUILD_DIR)/string.o: $(CC) -c $(SRC_DIR)/libc/include/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) -std=gnu99 -$(BUILD_DIR)/PageFrameAllocator.o: - $(CPP) -c $(SRC_DIR)/kernel/memory/PageFrameAllocator.cpp -o $(BUILD_DIR)/PageFrameAllocator.o $(CFLAGS) -fno-exceptions -fno-rtti +$(BUILD_DIR)/PhysicalMemoryManager.o: + $(CPP) -c $(SRC_DIR)/kernel/memory/PhysicalMemoryManager.cpp -o $(BUILD_DIR)/PhysicalMemoryManager.o $(CFLAGS) -fno-exceptions -fno-rtti diff --git a/src/kernel/bootcheck.h b/src/kernel/bootcheck.h index c7b7796..6fbe49b 100644 --- a/src/kernel/bootcheck.h +++ b/src/kernel/bootcheck.h @@ -67,5 +67,10 @@ void CheckMBT ( multiboot_info_t* mbt ){ } + /* Draw diagonal blue line */ + if (CHECK_FLAG (mbt->flags, 12)){ + printf("Can draw!"); + } + } \ No newline at end of file diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index f3658b2..2a80224 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -1,6 +1,6 @@ #include "kernel.h" -#include "memory/PageFrameAllocator.h" - +#define GB4 524288 +#define GB2 262144 extern "C" void early_main(unsigned long magic, unsigned long addr){ /** initialize terminal interface */ kterm_init(); @@ -16,14 +16,16 @@ /* Are mmap_* valid? */ if (CHECK_FLAG(mbt->flags, 6)){ - mapMultibootMemoryMap(mbt); + PhysicalMemoryManager_initialise( mbt->mmap_addr, GB2/* Seriously dangerous hardcoded memory value*/); + PhysicalMemoryManager_initialise_available_regions(mbt->mmap_addr, mbt->mmap_addr + mbt->mmap_length); + PhysicalMemoryManager_deinitialise_kernel(); + extern uint8_t* kernel_begin; + extern uint8_t* kernel_end; + printf("Kernel MemoryMap:\n"); + printf("kernel: 0x%x - 0x%x\n", &kernel_begin , &kernel_end); } - /* Draw diagonal blue line */ - if (CHECK_FLAG (mbt->flags, 12)){ - printf("Can draw!"); - } //setupGdt(); diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index bf2fdd9..2c61697 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -6,8 +6,8 @@ extern "C"{ #include "arch/i386/tty/kterm.h" #include "./bootloader/multiboot.h" - #include "bootcheck.h" +#include "memory/PhysicalMemoryManager.h" #include "arch/i386/gdt/gdtc.h" #include "arch/i386/idt/idt.h" diff --git a/src/kernel/kstructures/bitmap.h b/src/kernel/kstructures/bitmap.h new file mode 100644 index 0000000..e4487fe --- /dev/null +++ b/src/kernel/kstructures/bitmap.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include + + +inline void bitmap_set( uint32_t* map , int index ) +{ + map[index/32] |= (1 << (index % 32)); +} + +inline void bitmap_unset(uint32_t* map , int index) +{ + map[index/32] &= ~(1 << (index % 32)); +} + +inline int bitmap_first_unset( uint32_t* map , int size) +{ + uint32_t rem_bits = size % 32; + for(uint32_t i = 0; i < size/32; i++) + { + if(map[i] != 0xFFFFFFFF){ + for(int j = 0; j < 32; j++){ + if(!(map[i] & (1<< j))){ + return (i*32) + j; + } + } + } + } + + if(rem_bits){ + for(uint32_t j = 0; j < rem_bits; j++){ + if(!(map[size/32] & (1 << j ))){ + return size + j; // Original author divided size by 32 and then multiplied it by 32 which is a net zero calculation ?!? + } + } + } + + return -1; + +} diff --git a/src/kernel/memory/PhysicalMemoryManager.cpp b/src/kernel/memory/PhysicalMemoryManager.cpp new file mode 100644 index 0000000..8e894ba --- /dev/null +++ b/src/kernel/memory/PhysicalMemoryManager.cpp @@ -0,0 +1,118 @@ +#include "PhysicalMemoryManager.h" + +size_t mem_size = 0; +int used_blocks = 0; +size_t max_blocks = 0; +uint32_t* pmmap = 0; +size_t pmmap_size = 0; + + +void PhysicalMemoryManager_initialise(uint32_t physicalmemorymap_address, size_t size ) +{ + mem_size = size; + max_blocks = KB_TO_BLOCKS(mem_size); + + used_blocks = max_blocks; + + pmmap = (uint32_t*) physicalmemorymap_address; + + if(max_blocks % BLOCKS_PER_WORD) + pmmap_size++; + + memset(pmmap, 0xFF, pmmap_size); +} + +void PhysicalMemoryManager_region_initialise(uint32_t base, size_t size) +{ + size_t blocks = size /BLOCK_SIZE; + uint32_t align = base / BLOCK_SIZE; + + for(size_t i = 0 ; i < blocks; i ++) + { + bitmap_unset(pmmap, align++); + used_blocks--; + } + + bitmap_set(pmmap, 0); + +} + +void PhysicalMemoryManager_region_deinitialise(uint32_t base, size_t size ) +{ + size_t blocks = size / BLOCK_SIZE; + uint32_t align = base / BLOCK_SIZE; + + for(size_t i = 0 ; i < blocks; i++ ) + { + bitmap_set(pmmap, align++); + used_blocks++; + } + + +} + +void PhysicalMemoryManager_initialise_available_regions(uint32_t mmap_, uint32_t mmap_end_) +{ + multiboot_memory_map_t *mmap = (multiboot_memory_map_t*)mmap_; + multiboot_memory_map_t *mmap_end= (multiboot_memory_map_t*) mmap_end_; + + for(int i = 0; mmap < mmap_end ; mmap++, i++) + { + if(mmap->type == MULTIBOOT_MEMORY_AVAILABLE) + { + PhysicalMemoryManager_region_initialise((uint32_t) mmap->addr, (size_t) mmap->len); + } + } + +} + +void PhysicalMemoryManager_deinitialise_kernel() +{ + extern uint8_t kernel_begin; + extern uint8_t kernel_end; + + size_t kernel_size = (size_t) &kernel_end - (size_t) &kernel_begin; + + uint32_t pmmap_size_aligned = pmmap_size; + if(!IS_ALIGNED(pmmap_size_aligned, BLOCK_SIZE)) + { + pmmap_size_aligned = ALIGN(pmmap_size_aligned, BLOCK_SIZE); + } + + PhysicalMemoryManager_region_deinitialise((uint32_t) &kernel_begin, kernel_size); + PhysicalMemoryManager_region_deinitialise((uint32_t) &kernel_end, pmmap_size_aligned); + +} + +void* PhysicalMemoryManager_allocate_block() +{ + if(used_blocks - max_blocks <= 0) + { + return 0; + } + + int p_index = bitmap_first_unset(pmmap, p_index ); + + if(p_index == -1){ + return 0; + } + + bitmap_set(pmmap, p_index); + used_blocks++; + + return (void*) (BLOCK_SIZE * p_index); +} + +void PhysicalMemoryManager_free_block(void* p){ + if(p==0){ + return ; + } + + uint32_t p_addr = (uint32_t) p; + + int index = p_addr / BLOCK_SIZE; + bitmap_unset(pmmap, index); + + used_blocks--; + +} \ No newline at end of file diff --git a/src/kernel/memory/PhysicalMemoryManager.h b/src/kernel/memory/PhysicalMemoryManager.h new file mode 100644 index 0000000..3adc1eb --- /dev/null +++ b/src/kernel/memory/PhysicalMemoryManager.h @@ -0,0 +1,34 @@ +#pragma once + +#include "../bootloader/multiboot.h" +#include +#include +#include "../../libc/include/mem.h" +#include "../kstructures/bitmap.h" + + +#define BLOCK_SIZE 4092 +#define BLOCKS_PER_WORD 32 + +#define KB_TO_BLOCKS(x) (((x) * 1024 ) / BLOCK_SIZE) +#define IS_ALIGNED(addr, align) !((addr) & ~((align) - 1)) +#define ALIGN(addr, align) (((addr) & ~((align) - 1 )) + (align)) + + +extern void PhysicalMemoryManager_initialise(uint32_t, size_t); + +extern void PhysicalMemoryManager_region_initialise(uint32_t, size_t); +extern void PhysicalMemoryManager_region_deinitialise(uint32_t,size_t); + +extern void PhysicalMemoryManager_initialise_available_regions(uint32_t, uint32_t); +extern void PhysicalMemoryManager_deinitialise_kernel(); + +extern void* PhysicalMemoryManager_allocate_block(); +extern void PhysicalMemoryManager_free_block(void* p); + + +extern size_t mem_size; +extern int used_blocks; +extern size_t max_blocks; +extern uint32_t* pmmap; +extern size_t pmmap_size ; \ No newline at end of file diff --git a/src/libc/include/mem.h b/src/libc/include/mem.h new file mode 100644 index 0000000..62c4318 --- /dev/null +++ b/src/libc/include/mem.h @@ -0,0 +1,8 @@ +inline void* memset (void* ptr, int value, size_t num){ + for( int i = 0; i < num; i++ ) + { + int* data = (int*)ptr+ i; + *data = value; + } + return ptr; +}