virtual page allocation
This commit is contained in:
@@ -26,8 +26,7 @@ void x86_64_main(u32 magic, multiboot_info_t* info)
|
||||
enable_interrupts();
|
||||
|
||||
pmm_init(info);
|
||||
void* mem = vmm_alloc(1);
|
||||
vmm_free(mem, 1);
|
||||
vmm_init();
|
||||
|
||||
kernel_main();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ static size_t num_regions = 0;
|
||||
|
||||
static u8 page_bitmap[BITMAP_SIZE];
|
||||
static u64 total_pages = 0;
|
||||
static u64 free_pages = 0;
|
||||
|
||||
void pmm_init(multiboot_info_t* info)
|
||||
{
|
||||
@@ -72,7 +71,6 @@ void pmm_init(multiboot_info_t* info)
|
||||
if (page < BITMAP_SIZE * 8)
|
||||
{
|
||||
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
||||
free_pages++;
|
||||
total_pages++;
|
||||
}
|
||||
else
|
||||
@@ -92,7 +90,6 @@ void pmm_init(multiboot_info_t* info)
|
||||
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
|
||||
{
|
||||
page_bitmap[page / 8] |= (1 << (page % 8));
|
||||
free_pages--;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -113,7 +110,6 @@ u64 pmm_alloc()
|
||||
if (!(page_bitmap[i] & (1 << bit)))
|
||||
{
|
||||
page_bitmap[i] |= (1 << bit);
|
||||
free_pages--;
|
||||
return ((i * 8 + bit) * PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -131,12 +127,11 @@ void pmm_free(u64 physical_address)
|
||||
if (page_bitmap[page / 8] & (1 << (page % 8)))
|
||||
{
|
||||
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
||||
free_pages++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("pmm_free: Physical address %x is already free", physical_address);
|
||||
panic("pmm_free: Failed to free");
|
||||
printf("Physical address %x is already free", physical_address);
|
||||
panic("Failed to free physical address");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,74 @@
|
||||
#define PTE_USER (1ULL << 2)
|
||||
#define PTE_PS (1ULL << 7)
|
||||
|
||||
#define BITMAP_PAGE_COUNT (ADDRES_SPACE_SIZE / PAGE_SIZE)
|
||||
#define BITMAP_SIZE (BITMAP_PAGE_COUNT / 8)
|
||||
|
||||
static u8 page_bitmap[BITMAP_SIZE];
|
||||
static u64 total_pages = 0;
|
||||
static u64 free_pages = 0;
|
||||
|
||||
extern u64 pml4[];
|
||||
|
||||
void vmm_init()
|
||||
{
|
||||
// Mark first 32 pages (64mb) as unusable since it is reserved by the bootloader
|
||||
// todo(nub31): This should be revisited. Maybe do a higher half kernel?
|
||||
for (u64 page = 0; page < 32; page++)
|
||||
{
|
||||
if (page < BITMAP_PAGE_COUNT)
|
||||
{
|
||||
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
|
||||
{
|
||||
page_bitmap[page / 8] |= (1 << (page % 8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
panic("Bitmap is not large enough to hold the bootloader reserved memory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64 vmm_alloc_address(size_t page_count)
|
||||
{
|
||||
for (size_t i = 0; i < BITMAP_SIZE; i++)
|
||||
{
|
||||
if (page_bitmap[i] != 0xFF)
|
||||
{
|
||||
for (int bit = 0; bit < 8; bit++)
|
||||
{
|
||||
if (!(page_bitmap[i] & (1 << bit)))
|
||||
{
|
||||
page_bitmap[i] |= (1 << bit);
|
||||
free_pages--;
|
||||
return ((i * 8 + bit) * PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 vmm_free_address(u64 virtual_address, size_t page_count)
|
||||
{
|
||||
u64 page = virtual_address / PAGE_SIZE;
|
||||
if (page < BITMAP_SIZE * 8)
|
||||
{
|
||||
if (page_bitmap[page / 8] & (1 << (page % 8)))
|
||||
{
|
||||
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
||||
free_pages++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Virtual address %x is already free", virtual_address);
|
||||
panic("Failed to free virtual address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u64 create_2mb_pte(u64 physical_address, u32 flags)
|
||||
{
|
||||
if (physical_address & (PAGE_SIZE - 1))
|
||||
@@ -97,16 +163,6 @@ u64 vmm_unmap(u64 virtual_address)
|
||||
return physical_address;
|
||||
}
|
||||
|
||||
u64 vmm_alloc_address(size_t page_count)
|
||||
{
|
||||
panic("not implemented");
|
||||
}
|
||||
|
||||
u64 vmm_free_address(u64 virtual_address, size_t page_count)
|
||||
{
|
||||
panic("not implemented");
|
||||
}
|
||||
|
||||
void* vmm_alloc(size_t page_count)
|
||||
{
|
||||
u64 virtual_address = vmm_alloc_address(page_count);
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
#include "std.h"
|
||||
|
||||
// Low level function to map a virtual address to a physical address
|
||||
void vmm_map(u64 physical_address, u64 virtual_address, u32 flags);
|
||||
// Low level function to unmap a virtual address from a physical address
|
||||
u64 vmm_unmap(u64 virtual_address);
|
||||
#define ADDRES_SPACE_SIZE GiB(64)
|
||||
|
||||
void vmm_init();
|
||||
|
||||
// Allocates a free page aligned block of virtual addresses
|
||||
u64 vmm_alloc_address(size_t page_count);
|
||||
@@ -13,6 +12,11 @@ u64 vmm_alloc_address(size_t page_count);
|
||||
// Only use this function for pages mapped via `vmm_alloc_address`
|
||||
u64 vmm_free_address(u64 virtual_address, size_t page_count);
|
||||
|
||||
// Low level function to map a virtual address to a physical address
|
||||
void vmm_map(u64 physical_address, u64 virtual_address, u32 flags);
|
||||
// Low level function to unmap a virtual address from a physical address
|
||||
u64 vmm_unmap(u64 virtual_address);
|
||||
|
||||
// Allocates and maps `page_count` continuous pages and returns the virtual address of the first page
|
||||
void* vmm_alloc(size_t page_count);
|
||||
// Frees the pages allocated via `vmm_alloc` at the specified virtual address
|
||||
|
||||
Reference in New Issue
Block a user