#define FOOLOS_MODULE_NAME "mem" #include #include "config.h" #include "multiboot.h" #include "lib/logger/log.h" #define PMMNGR_BLOCKS_PER_BYTE 8 #define PMMNGR_BLOCK_SIZE 4096 #define PMMNGR_MAX_BLOCKS 1048576 #define PMMNGR_MAP_SIZE PMMNGR_MAX_BLOCKS/PMMNGR_BLOCKS_PER_BYTE/4 // defined in linker.ld and multiboot.s extern uint32_t kernel_start[]; extern uint32_t kernel_end[]; extern uint32_t stack_top[]; extern uint32_t stack_bottom[]; //memory map bit array. Each bit represents a 4KB memory block, //so uint32_t represents 8*4 blocks static uint32_t _mmngr_memory_map[PMMNGR_MAP_SIZE]; static uint32_t mem_free_blocks; //number of free blocks static uint32_t mem_max_block; //index of highest usable block static uint32_t mem_min_block; //index of lowset block available to userspace char *memmap_type_to_string[]= { "Usable", "Reserved", "ACPI reclaimable", "ACPI NVS", "Bad Memory" }; uint32_t mem_get_free_blocks_count() { return mem_free_blocks; } // bit funcs! void mmap_set(int bit) { _mmngr_memory_map[bit / 32] |= (1 << (bit % 32)); } void mmap_unset(int bit) { _mmngr_memory_map[bit / 32] &= ~ (1 << (bit % 32)); } int mmap_test(int bit) { return _mmngr_memory_map[bit / 32] & (1 << (bit % 32)); } // // By default, Set all of memory is in use void pmmngr_init () { mem_free_blocks=0; for(int i=0;i0; blocks--) { mmap_unset (align++); mem_free_blocks++; } } void pmmngr_deinit_region (uint32_t base, uint32_t size) { uint32_t align = base / PMMNGR_BLOCK_SIZE; uint32_t blocks = size / PMMNGR_BLOCK_SIZE; if(size%PMMNGR_BLOCK_SIZE)blocks++; for (; blocks>0; blocks--) { mmap_set (align++); mem_free_blocks--; } } void* pmmngr_alloc_block () { int frame = mmap_first_free (); if (frame == -1) { panic(FOOLOS_MODULE_NAME,"OUT OF MEMORY (alloc_block)"); return 0; //out of memory } mmap_set (frame); mem_free_blocks--; uint32_t addr = frame * PMMNGR_BLOCK_SIZE; log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"alloc block (%d) 0x%08X)",frame,addr); return (void*)addr; } void pmmngr_free_block (void* p) { uint32_t addr = (uint32_t*)p; int frame = addr / PMMNGR_BLOCK_SIZE; if(mmap_test(frame)) { mmap_unset (frame); mem_free_blocks++; } else { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_ERROR,"free block (%d) 0x%08X)",frame,addr); panic(FOOLOS_MODULE_NAME,"trying to free, free physical mem!"); } log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"free block (%d) 0x%08X)",frame,addr); } void mem_init(multiboot_information *info) { if(info->flags&&1<<6) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"memory map of length %d provided by bootloader",info->mmap_length); } else panic(FOOLOS_MODULE_NAME,"Unable to continue without memory map, sorry!"); pmmngr_init (); //clear memmap uint64_t memmap=info->mmap_addr; uint64_t length=info->mmap_length; log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"kernel loaded at: 0x%08X- 0x%08X",kernel_start,kernel_end); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"initial stack at: 0x%08X- 0x%08X",stack_top,stack_bottom); // count available mem and track high_end of usable memory uint32_t total_mem=0, highest_end; // iterate : print memory map, calc blocks, deinit for(uint32_t mmap_addr=memmap;mmap_addrbase_addr; uint64_t mem_end=mmap->base_addr+mmap->length; #ifdef MEM_PRINT_MEMORYMAP log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"%08X - %08X / type: %s, (size: %d)", (uint32_t)mem_start, (uint32_t)mem_end, memmap_type_to_string[mmap->type-1], mmap->size); #endif uint32_t mem=mmap->length; //reclaimable OR usable if(mmap->type==1||mmap->type==3) { total_mem+=mem; highest_end=mmap->base_addr+mmap->length-1; pmmngr_init_region(mmap->base_addr,mmap->length); } //next mmap_addr+=mmap->size+4; } uint32_t blocks=highest_end/4096+1; mem_max_block=blocks/32+1; // deinit modules memory if(info->flags&&1<<3) { multiboot_mod *mod=info->mods_addr; for(int i=0;imods_count;i++) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"mod 0x%08X-0x%08X : %s", mod->mod_start,mod->mod_end, mod->string); mem_min_block=mod->mod_end/PMMNGR_BLOCK_SIZE+1; pmmngr_deinit_region(mod->mod_start,((uint32_t)mod->mod_end-(uint32_t)mod->mod_start)+1); mod++; } } // deinitialize kernel pmmngr_deinit_region(kernel_start,((uint32_t)kernel_end-(uint32_t)kernel_start)+1); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Usable ~%d / %d MB ",mem_free_blocks*4096/1024/1024,total_mem/1024/1024); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO, "Free 4K blocks: %d (first free: %d)",mem_free_blocks,mem_min_block); }