From 582f4b720fc623d9347c1f2cba5e1cd6e210359a Mon Sep 17 00:00:00 2001 From: vanten-s Date: Tue, 1 Jul 2025 12:48:05 +0200 Subject: [PATCH] Allocating Pages --- arch/i686/paging.c | 52 +++++++--------- include/kernel/heap.h | 2 + include/kernel/paging.h | 31 ++++++++++ kernel/elf.c | 3 +- kernel/heap.c | 129 +++++++++++++++++++++++++++++++++++++++- kernel/kernel.c | 17 ++++-- 6 files changed, 194 insertions(+), 40 deletions(-) diff --git a/arch/i686/paging.c b/arch/i686/paging.c index e410133..ce551bd 100644 --- a/arch/i686/paging.c +++ b/arch/i686/paging.c @@ -7,39 +7,13 @@ #include #include -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(); } diff --git a/include/kernel/heap.h b/include/kernel/heap.h index f13ffec..ad2a659 100644 --- a/include/kernel/heap.h +++ b/include/kernel/heap.h @@ -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); diff --git a/include/kernel/paging.h b/include/kernel/paging.h index 85a1475..216983e 100644 --- a/include/kernel/paging.h +++ b/include/kernel/paging.h @@ -1,4 +1,6 @@ #include +#include +#include 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); diff --git a/kernel/elf.c b/kernel/elf.c index d45348d..111481f 100644 --- a/kernel/elf.c +++ b/kernel/elf.c @@ -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); diff --git a/kernel/heap.c b/kernel/heap.c index 9b52f27..f058c2c 100644 --- a/kernel/heap.c +++ b/kernel/heap.c @@ -1,12 +1,50 @@ #include #include +#include #include -#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; +} diff --git a/kernel/kernel.c b/kernel/kernel.c index 2a7edeb..124f5a0 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -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; } - } + } */ }