Allocating Pages

This commit is contained in:
vanten-s 2025-07-01 12:48:05 +02:00
parent 5d9a3055b7
commit 582f4b720f
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
6 changed files with 194 additions and 40 deletions

View file

@ -7,39 +7,13 @@
#include <debugging.h>
#include <kernel/heap.h>
struct x86_Page_Directory {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disable: 1;
bool accesed: 1;
bool available_2: 1;
bool page_size: 1;
uint8_t available_1 : 4;
uintptr_t address : 20; // Multiply by 0x1000
} __attribute__((packed));
struct x86_Page_Table {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disable: 1;
bool accesed: 1;
bool dirty: 1;
bool page_attribute_table: 1;
bool global: 1;
uint8_t available_1 : 3;
uintptr_t address : 20; // Multiply by 0x1000
} __attribute__((packed));
extern struct x86_Page_Directory boot_page_directory[1024] __attribute__((aligned(4096)));
static struct x86_Page_Table user_code_table __attribute__((aligned(4096)));
static struct x86_Page_Table user_code_table[1024] __attribute__((aligned(4096)));
static uint8_t user_code[4096] __attribute__((aligned(4096)));
static struct x86_Page_Table user_data_table __attribute__((aligned(4096)));
static struct x86_Page_Table user_data_table[1024] __attribute__((aligned(4096)));
static uint8_t user_data[4096] __attribute__((aligned(4096)));
static struct x86_Page_Table* get_table(uint16_t index) {
@ -54,13 +28,25 @@ movl %ecx, %cr3; \
");
}
static void set_page_directory_entry(uintptr_t address, struct x86_Page_Table* table) {
void set_page_directory_entry(uintptr_t address, struct x86_Page_Table* table)
{
boot_page_directory[address >> 22].address = ((uintptr_t)(table) - 0xC0000000) >> 12;
boot_page_directory[address >> 22].present = true;
boot_page_directory[address >> 22].read_write = true;
boot_page_directory[address >> 22].user_supervisor = true;
}
void set_page_table_entry(size_t address, void* ptr)
{
struct x86_Page_Table* table = (struct x86_Page_Table*)((boot_page_directory[address >> 22].address << 12) + 0xC0000000);
table[(address >> 12) & 0x3FF].address = (size_t)(ptr - 0xC0000000) >> 12;
table[(address >> 12) & 0x3FF].present = true;
table[(address >> 12) & 0x3FF].read_write = true;
table[(address >> 12) & 0x3FF].user_supervisor = true;
}
struct x86_Page_Table create_table;
void setup_paging() {
struct x86_Page_Table* kernel = get_table(768);
@ -81,19 +67,21 @@ void setup_paging() {
set_page_directory_entry(0, &user_code_table);
/*
user_code_table.address = ((uintptr_t)user_code - 0xC0000000) >> 12;
user_code_table.present = true;
user_code_table.read_write = true;
user_code_table.user_supervisor = true;
*/
set_page_directory_entry(0x00400000, &user_data_table);
/*
user_data_table.address = ((uintptr_t)user_data - 0xC0000000) >> 12;
user_data_table.present = true;
user_data_table.read_write = true;
user_data_table.user_supervisor = true;
user_data[0] = 'B';
*/
reload_pages();
}

View file

@ -18,4 +18,6 @@ struct Heap_Block {
void heap_init();
void* malloc(size_t size);
void* alloc_page(size_t num_pages, struct Heap_Block** ptr);
void free(void *ptr);
void free_page(struct Heap_Block *ptr);

View file

@ -1,4 +1,6 @@
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
struct PageDirectory {
size_t page_table;
@ -8,4 +10,33 @@ struct PageTable {
};
struct x86_Page_Directory {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disable: 1;
bool accesed: 1;
bool available_2: 1;
bool page_size: 1;
uint8_t available_1 : 4;
uintptr_t address : 20; // Multiply by 0x1000
} __attribute__((packed));
struct x86_Page_Table {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disable: 1;
bool accesed: 1;
bool dirty: 1;
bool page_attribute_table: 1;
bool global: 1;
uint8_t available_1 : 3;
uintptr_t address : 20; // Multiply by 0x1000
} __attribute__((packed));
void setup_paging();
void set_page_table_entry(size_t address, void* ptr);
void set_page_directory_entry(uintptr_t address, struct x86_Page_Table* table);

View file

@ -16,7 +16,8 @@ static void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t s
void run_program(uint8_t* code, size_t code_length, uint8_t* data, size_t data_length)
{
uint8_t* userland_code = (uint8_t*) 0x00000010;
// TODO: Replace following lines with malloc calls and paging calls
uint8_t* userland_code = (uint8_t*) 0x00000000;
uint8_t* userland_data = (uint8_t*) 0x00400000;
memcpy(userland_code, code, code_length);

View file

@ -1,12 +1,50 @@
#include <stdint.h>
#include <kernel/heap.h>
#include <kernel/tty.h>
#include <debugging.h>
#define HEAP_SIZE (1 << 12)
#define HEAP_SIZE (1 << 16)
#define NUM_PAGES (128)
uint8_t global_heap_data[HEAP_SIZE + sizeof(struct Heap_Block)];
uint8_t pages_heap_data[NUM_PAGES * 4096 + sizeof(struct Heap_Block)] __attribute__((aligned(4096)));
struct Heap_Block pages_heap_blocks[NUM_PAGES];
uint8_t* global_heap_data[HEAP_SIZE + sizeof(struct Heap_Block)];
struct Heap_Metadata global_heap;
struct Heap_Metadata pages_heap;
void* nearest_aligned(void* ptr, size_t alignment)
{
// TODO: Fix this solution up, it's *extremely* inneficient for numbers that aren't powers of 2
size_t address = (size_t)ptr;
if (address % alignment == 0) {
return (void*) address;
}
if ((alignment & (alignment - 1)) == 0) {
address = address & ~(alignment - 1);
address += alignment;
return (void*) address;
}
while (address % alignment != 0) {
address++;
}
return (void*) address;
}
size_t sizeof_block(struct Heap_Block* block, size_t alignment)
{
size_t start = (size_t)nearest_aligned(block->data, alignment);
size_t end = (size_t)block->next;
return end - start;
}
void heap_init()
{
@ -18,6 +56,16 @@ void heap_init()
start->used = false;
start->data = start + 1;
start->next = 0;
struct Heap_Block* page_start = pages_heap_blocks;
pages_heap.size = NUM_PAGES;
pages_heap.start = (struct Heap_Block*) page_start;
page_start->size = NUM_PAGES;
page_start->used = false;
page_start->data = pages_heap_data;
page_start->next = 0;
}
void* malloc(size_t size)
@ -31,6 +79,7 @@ void* malloc(size_t size)
}
if (current == 0) {
terminal_writestring("WARNING: Heap Full\n");
return 0;
}
@ -48,6 +97,43 @@ void* malloc(size_t size)
}
}
void* alloc_page(size_t num_pages, struct Heap_Block** ptr)
{
struct Heap_Block* current = pages_heap.start;
while (true) {
if (current->used || current->size < num_pages) {
current = current->next;
continue;
}
if (current == 0) {
terminal_writestring("WARNING: Heap Full\n");
return 0;
}
if ((size_t)current->data % 4096 != 0) {
terminal_writestring("ERROR: Pages are unaligned");
}
size_t current_index = ((size_t)current->data - (size_t)pages_heap_data) / 4096;
struct Heap_Block* next = pages_heap_blocks + (current_index + num_pages);
next->data = current->data + 4096 * num_pages;
next->next = current->next;
next->size = current->size - num_pages;
current->next = next;
current->size = num_pages;
current->used = true;
*ptr = current;
return current->data;
}
}
void free(void *ptr)
{
struct Heap_Block* current = global_heap.start;
@ -83,6 +169,43 @@ void free(void *ptr)
}
start->next = current;
start->size = (uint32_t)start->next - (uint32_t)start->data;
start->size = (size_t)start->next - (size_t)start->data;
}
void free_page(struct Heap_Block *ptr)
{
struct Heap_Block* current = pages_heap.start;
struct Heap_Block* first_unused;
bool found_unused = false;
while (current != ptr) {
if (!current->used && !found_unused) {
first_unused = current;
found_unused = true;
} else {
found_unused = false;
}
current = current->next;
}
if (!found_unused) {
first_unused = current;
}
current->used = false;
if (current->next == 0) {
return;
}
struct Heap_Block* start = first_unused;
current = start;
while (current->used == false && current->next != 0) {
current = current->next;
}
start->next = current;
start->size = ((size_t)start->next - (size_t)start->data) / 4096;
}

View file

@ -23,8 +23,6 @@ uint8_t data[] = "Hello From Userspace\n";
uint8_t kernel_data[] = "Hello From Kernelspace\n";
// uint8_t data[] = {};
void irq0();
void kernel_main(void)
{
/* Initialize terminal interface */
@ -40,7 +38,18 @@ void kernel_main(void)
terminal_writestring("Woaw\n");
asm("cli");
struct Heap_Block* block;
void* code_page = alloc_page(1, &block);
void* data_page = alloc_page(1, &block);
set_page_table_entry(0, code_page);
set_page_table_entry(0x00400000, data_page);
*(int*)0 = 1;
while (true) { }
/* asm("cli");
run_program(program, sizeof(program), data, sizeof(data));
@ -56,5 +65,5 @@ void kernel_main(void)
asm("int $0x80");
i = 0;
}
}
} */
}