virtual page allocation
This commit is contained in:
@@ -26,8 +26,7 @@ void x86_64_main(u32 magic, multiboot_info_t* info)
|
|||||||
enable_interrupts();
|
enable_interrupts();
|
||||||
|
|
||||||
pmm_init(info);
|
pmm_init(info);
|
||||||
void* mem = vmm_alloc(1);
|
vmm_init();
|
||||||
vmm_free(mem, 1);
|
|
||||||
|
|
||||||
kernel_main();
|
kernel_main();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ static size_t num_regions = 0;
|
|||||||
|
|
||||||
static u8 page_bitmap[BITMAP_SIZE];
|
static u8 page_bitmap[BITMAP_SIZE];
|
||||||
static u64 total_pages = 0;
|
static u64 total_pages = 0;
|
||||||
static u64 free_pages = 0;
|
|
||||||
|
|
||||||
void pmm_init(multiboot_info_t* info)
|
void pmm_init(multiboot_info_t* info)
|
||||||
{
|
{
|
||||||
@@ -72,7 +71,6 @@ void pmm_init(multiboot_info_t* info)
|
|||||||
if (page < BITMAP_SIZE * 8)
|
if (page < BITMAP_SIZE * 8)
|
||||||
{
|
{
|
||||||
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
||||||
free_pages++;
|
|
||||||
total_pages++;
|
total_pages++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -92,7 +90,6 @@ void pmm_init(multiboot_info_t* info)
|
|||||||
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
|
if (!(page_bitmap[page / 8] & (1 << (page % 8))))
|
||||||
{
|
{
|
||||||
page_bitmap[page / 8] |= (1 << (page % 8));
|
page_bitmap[page / 8] |= (1 << (page % 8));
|
||||||
free_pages--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -113,7 +110,6 @@ u64 pmm_alloc()
|
|||||||
if (!(page_bitmap[i] & (1 << bit)))
|
if (!(page_bitmap[i] & (1 << bit)))
|
||||||
{
|
{
|
||||||
page_bitmap[i] |= (1 << bit);
|
page_bitmap[i] |= (1 << bit);
|
||||||
free_pages--;
|
|
||||||
return ((i * 8 + bit) * PAGE_SIZE);
|
return ((i * 8 + bit) * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,12 +127,11 @@ void pmm_free(u64 physical_address)
|
|||||||
if (page_bitmap[page / 8] & (1 << (page % 8)))
|
if (page_bitmap[page / 8] & (1 << (page % 8)))
|
||||||
{
|
{
|
||||||
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
page_bitmap[page / 8] &= ~(1 << (page % 8));
|
||||||
free_pages++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("pmm_free: Physical address %x is already free", physical_address);
|
printf("Physical address %x is already free", physical_address);
|
||||||
panic("pmm_free: Failed to free");
|
panic("Failed to free physical address");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,8 +13,74 @@
|
|||||||
#define PTE_USER (1ULL << 2)
|
#define PTE_USER (1ULL << 2)
|
||||||
#define PTE_PS (1ULL << 7)
|
#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[];
|
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)
|
static u64 create_2mb_pte(u64 physical_address, u32 flags)
|
||||||
{
|
{
|
||||||
if (physical_address & (PAGE_SIZE - 1))
|
if (physical_address & (PAGE_SIZE - 1))
|
||||||
@@ -97,16 +163,6 @@ u64 vmm_unmap(u64 virtual_address)
|
|||||||
return physical_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)
|
void* vmm_alloc(size_t page_count)
|
||||||
{
|
{
|
||||||
u64 virtual_address = vmm_alloc_address(page_count);
|
u64 virtual_address = vmm_alloc_address(page_count);
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
#include "std.h"
|
#include "std.h"
|
||||||
|
|
||||||
// Low level function to map a virtual address to a physical address
|
#define ADDRES_SPACE_SIZE GiB(64)
|
||||||
void vmm_map(u64 physical_address, u64 virtual_address, u32 flags);
|
|
||||||
// Low level function to unmap a virtual address from a physical address
|
void vmm_init();
|
||||||
u64 vmm_unmap(u64 virtual_address);
|
|
||||||
|
|
||||||
// Allocates a free page aligned block of virtual addresses
|
// Allocates a free page aligned block of virtual addresses
|
||||||
u64 vmm_alloc_address(size_t page_count);
|
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`
|
// Only use this function for pages mapped via `vmm_alloc_address`
|
||||||
u64 vmm_free_address(u64 virtual_address, size_t page_count);
|
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
|
// Allocates and maps `page_count` continuous pages and returns the virtual address of the first page
|
||||||
void* vmm_alloc(size_t page_count);
|
void* vmm_alloc(size_t page_count);
|
||||||
// Frees the pages allocated via `vmm_alloc` at the specified virtual address
|
// Frees the pages allocated via `vmm_alloc` at the specified virtual address
|
||||||
|
|||||||
Reference in New Issue
Block a user