Untitled_Kernel/src/physmem.c

93 lines
3 KiB
C
Raw Normal View History

#include "physmem.h"
#include <stdint.h>
#include <io.h>
uint8_t* pmem_bitmap;
uint32_t bitmap_size;
void free_page(void* addr) {
//Available. Calculate the offset of the bit on the bitmap based on the page address
unsigned int pagenumber = (unsigned int)addr / PAGE_SIZE;
uint8_t* bitmap_byte = pmem_bitmap + (pagenumber / 8);
int bitmap_bit = pagenumber % 8;
//ok now set the bit to unused
*bitmap_byte &= ~(0x80 >> bitmap_bit);
}
unsigned int build_bitmap(mb_mmap_entry_t* mmap, int mmap_size) {
//rather important global pointer to the bitmap
pmem_bitmap = &_kernel_end;
//some variables
int mmap_end = (uint32_t)mmap + mmap_size;
unsigned int pages_allocated = 0;
uint32_t max_memory = 0;
//How much memory do we even have? Find the highest usable mmap region, and that'll be our bitmap size.
for(mb_mmap_entry_t* mmap_walk = mmap;
(int)mmap_walk < mmap_end;
mmap_walk = (mb_mmap_entry_t*)((int)mmap_walk + mmap_walk->entry_size + sizeof(mmap_walk->entry_size))) {
if(mmap_walk->type != 1)
//lol lmao
continue;
uint32_t section_upper = (uint32_t)mmap_walk->addr + (uint32_t)mmap_walk->mem_size;
if(section_upper > max_memory) {
max_memory = section_upper;
}
}
//Now that we know the bitmap size, we can define it a bit
bitmap_size = max_memory / (PAGE_SIZE*8);
uint32_t bitmap_end = (uint32_t)pmem_bitmap + bitmap_size;
//Now we'll Fill out our bitmap with 1s.
for(unsigned int i = 0; i < bitmap_size; i++) {
*(pmem_bitmap + i) = 0xFF;
}
//Time to actually fill it out. Iterate the memory map, and for every VALID memory region, set their bits to 0.
for(;
(int)mmap < mmap_end;
mmap = (mb_mmap_entry_t*)((int)mmap + mmap->entry_size + sizeof(mmap->entry_size))) {
//The bottom of our memory, rounded up to the nearest page boundary.
uint8_t* mem_bottom =(uint8_t*) (((uint32_t)mmap->addr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
//Is it usable mem?
if(mmap->type != 1) {
//nah...
continue;
}
//Top of our memory, rounded UP this time.
uint8_t* mem_top = (uint8_t*) (((uint32_t)mmap->addr + (uint32_t)mmap->mem_size) & ~(PAGE_SIZE - 1));
//Iterating through our pages in the memory region. Free the ones that meet our criteria.
int page_count = (mem_top - mem_bottom) / PAGE_SIZE;
for(int i = 0; i < page_count; i++){
//OK which page is this
uint8_t* page_addr = mem_bottom + (PAGE_SIZE * i);
//Is it in an invalid region? skip this page if so.
if((uint32_t)page_addr < bitmap_end) {
continue;
}
//Looks good! Go ahead and free it.
free_page((void*)page_addr);
pages_allocated++;
}
}
return pages_allocated;
}