Untitled_Kernel/src/physmem.c
lordtet 6261af8e3a Some changes to names and a convenience ASM function
asm.h now can nuke the TLB by refreshing the PD.
also changed some symbols to more accurately represent what they are
for, such as the kernelspace page tables or the global PD.
2025-07-15 23:14:33 -04:00

88 lines
3 KiB
C

#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;
}