Espresso 0.0.2a
This commit is contained in:
98
lib/mm/pmm.c
98
lib/mm/pmm.c
@ -1,80 +1,76 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <mm/pmm.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define BITMAP_SIZE (1024 * 1024) /* Supports up to 4GB RAM (1 bit per page) */
|
||||
|
||||
static uint8_t bitmap[BITMAP_SIZE / 8];
|
||||
static uint32_t total_pages;
|
||||
static uint32_t used_pages = 0;
|
||||
#define MAX_PAGES (1024 * 1024) /* 4GB / 4KB */
|
||||
static uint8_t bitmap[MAX_PAGES / 8] __attribute__((section(".pmm_bitmap")));
|
||||
static size_t total_pages;
|
||||
|
||||
static inline void set_bit(uint32_t idx)
|
||||
#define BITMAP_SET(i) (bitmap[(i) / 8] |= (1 << ((i) % 8)))
|
||||
#define BITMAP_CLEAR(i) (bitmap[(i) / 8] &= ~(1 << ((i) % 8)))
|
||||
#define BITMAP_TEST(i) (bitmap[(i) / 8] & (1 << ((i) % 8)))
|
||||
|
||||
void pmm_init(multiboot_info_t* mb)
|
||||
{
|
||||
bitmap[idx / 8] |= (1 << (idx % 8));
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
printf("[ PMM ] Initializing physical memory manager...\n");
|
||||
#endif
|
||||
|
||||
static inline void clear_bit(uint32_t idx)
|
||||
{
|
||||
bitmap[idx / 8] &= ~(1 << (idx % 8));
|
||||
}
|
||||
|
||||
static inline int test_bit(uint32_t idx)
|
||||
{
|
||||
return (bitmap[idx / 8] >> (idx % 8)) & 1;
|
||||
}
|
||||
|
||||
void pmm_init(multiboot_info_t* mb_info)
|
||||
{
|
||||
total_pages = 0x100000; /* 4GB / 4KB = 1M pages */
|
||||
for (uint32_t i = 0; i < total_pages / 8; i++)
|
||||
total_pages = MAX_PAGES;
|
||||
|
||||
for (uint32_t i = 0; i < (total_pages / 8); i++)
|
||||
{
|
||||
bitmap[i] = 0xFF; /* Mark all as used */
|
||||
bitmap[i] = 0xFF;
|
||||
}
|
||||
|
||||
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*) mb_info->mmap_addr;
|
||||
while ((uint32_t)mmap < mb_info->mmap_addr + mb_info->mmap_length)
|
||||
multiboot_memory_map_t* mmap = (void*)(uintptr_t)mb->mmap_addr;
|
||||
size_t entries = mb->mmap_length / sizeof(multiboot_memory_map_t);
|
||||
|
||||
for (size_t i = 0; i < entries; i++)
|
||||
{
|
||||
if (mmap->type == 1) /* Usable */
|
||||
if (mmap[i].type == 1) /* usable */
|
||||
{
|
||||
uint64_t base = mmap->addr;
|
||||
uint64_t len = mmap->len;
|
||||
for (uint64_t addr = base; addr < base + len; addr += PAGE_SIZE)
|
||||
uint64_t start = mmap[i].addr;
|
||||
uint64_t end = start + mmap[i].len;
|
||||
for (uint64_t addr = start; addr < end; addr += 0x1000)
|
||||
{
|
||||
if (addr >= 0x210000) /* Skip first 2.1MB, or ≈ 2.06MiB */
|
||||
if (addr >= 0x100000) /* skip below 1MB */
|
||||
{
|
||||
uint32_t idx = addr / PAGE_SIZE;
|
||||
|
||||
if (idx >= total_pages)
|
||||
{
|
||||
continue; /* skip entries above 4GB */
|
||||
}
|
||||
|
||||
clear_bit(idx);
|
||||
used_pages--;
|
||||
size_t idx = addr / 0x1000;
|
||||
BITMAP_CLEAR(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
mmap = (multiboot_memory_map_t*)((uint32_t)mmap + mmap->size + sizeof(mmap->size));
|
||||
}
|
||||
total_pages = MAX_PAGES;
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("[ PMM ] Physical memory manager initialized\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void* alloc_page(void) {
|
||||
for (uint32_t i = 0; i < total_pages; i++)
|
||||
void* pmm_alloc_page(void)
|
||||
{
|
||||
for (uint32_t i = 0; i < total_pages; ++i)
|
||||
{
|
||||
if (!test_bit(i))
|
||||
if (!BITMAP_TEST(i))
|
||||
{
|
||||
set_bit(i);
|
||||
used_pages++;
|
||||
return (void*)(i * PAGE_SIZE);
|
||||
BITMAP_SET(i);
|
||||
return (void*)(i * 4096);
|
||||
}
|
||||
}
|
||||
return NULL; /* Out of memory */
|
||||
|
||||
printf("pmm_alloc_page(): No free page found!\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_page(void* ptr)
|
||||
|
||||
void pmm_free_page(void* addr)
|
||||
{
|
||||
uint32_t idx = (uint32_t)ptr / PAGE_SIZE;
|
||||
clear_bit(idx);
|
||||
size_t idx = (uintptr_t)addr / 0x1000;
|
||||
BITMAP_CLEAR(idx);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user