wip: separate allocators into a kernel one and a user one

This commit is contained in:
0x35c
2025-11-12 16:02:52 +01:00
parent a776a45f68
commit 9f142941c3
22 changed files with 149 additions and 56 deletions

View File

@ -59,8 +59,10 @@ void init_memory(multiboot_info_t *mbd, uint32_t magic);
void *alloc_frame(void); void *alloc_frame(void);
int free_frame(void *frame_ptr); int free_frame(void *frame_ptr);
int8_t add_single_page(void *frame); int8_t add_single_page(void *frame);
void *alloc_pages(size_t size, void **phys_addr); void *kalloc_pages(size_t size, void **phys_addr);
int free_pages(void *page_ptr, size_t size); void *valloc_pages(size_t size, void **phys_addr);
int kfree_pages(void *page_ptr, size_t size);
int vfree_pages(void *page_ptr, size_t size);
void init_page_table(uint32_t page_table[1024], uint16_t start); void init_page_table(uint32_t page_table[1024], uint16_t start);
int16_t add_page_table(uint16_t pd_index); int16_t add_page_table(uint16_t pd_index);
void switch_pd(uint32_t *pd, uint32_t *cr3); void switch_pd(uint32_t *pd, uint32_t *cr3);

View File

@ -36,8 +36,6 @@ void isr_handler(struct registers *regs)
{ {
uint8_t i = 0; uint8_t i = 0;
while (i < ARRAY_SIZE(faults)) { while (i < ARRAY_SIZE(faults)) {
if (i == 6)
reboot();
if (i == regs->int_no) if (i == regs->int_no)
kpanic("interrupt: %s\n", faults[i]); kpanic("interrupt: %s\n", faults[i]);
i++; i++;

View File

@ -23,10 +23,10 @@ __attribute__((noreturn)) void kpanic(const char *format, ...)
va_end(va); va_end(va);
uint32_t faulting_address; uint32_t faulting_address;
// __asm__ __volatile__("mov %%cr2, %0" : "=r"(faulting_address)); __asm__ __volatile__("mov %%cr2, %0" : "=r"(faulting_address));
// kprintf("fault at address: %p\n", faulting_address); kprintf("fault at address: %p\n", faulting_address);
/* for (int i = 16; i < 32; i++) */ // for (int i = 16; i < 32; i++)
/* kprintf("%p\n", page_table1[i]); */ // kprintf("%p\n", page_table1[i]);
// show_valloc_mem(); // show_valloc_mem();
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */
/* print_stack(); */ /* print_stack(); */

View File

@ -1,9 +1,8 @@
#include "alloc.h" #include "alloc.h"
#include "assert.h" #include "assert.h"
#include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "process.h" #include "string.h"
Zone *kzones[3]; Zone *kzones[3];
@ -50,11 +49,12 @@ static void new_block(Zone *zone, uint32_t zone_size)
int new_kzone(block_type_t type, uint32_t size) int new_kzone(block_type_t type, uint32_t size)
{ {
// assert(current_task->pid); // assert(current_task->pid);
void *heap = alloc_frame(); void *heap = kalloc_pages(size, NULL);
if (heap == NULL) { if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_frame failed\n"); kprintf(KERN_ERR "error: alloc_frame failed\n");
return (-1); return (-1);
} }
memset(heap, 0, size);
Zone *zone = (Zone *)heap; Zone *zone = (Zone *)heap;
zone->type = type; zone->type = type;

View File

@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
if (right) if (right)
right->prev = left; right->prev = left;
unmap: unmap:
err = free_pages((void *)zone, zone->size); err = kfree_pages((void *)zone, zone->size);
if (err) if (err)
kprintf(KERN_ERR "error: munmap failed\n"); kprintf(KERN_ERR "error: munmap failed\n");
return (err); return (err);

92
src/memory/kern/page.c Normal file
View File

@ -0,0 +1,92 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "assert.h"
#include "kprintf.h"
#include "memory.h"
#include "process.h"
#include "string.h"
#include "utils.h"
static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
uint32_t **page_table_ptr)
{
for (*pd_index_ptr = 769; *pd_index_ptr < 1021; (*pd_index_ptr)++) {
if (current_pd[(*pd_index_ptr)] == 0x02) {
if (add_page_table(*pd_index_ptr) < 0)
return -2;
}
*page_table_ptr = (uint32_t *)GET_PAGE_ADDR(769, *pd_index_ptr);
for (uint16_t i = 0; i + nb_pages - 1 < PT_SIZE; i++) {
uint16_t j;
for (j = 0; (*page_table_ptr)[i + j] >> 12 == i + j &&
j < nb_pages;
j++)
;
if (j == nb_pages)
return i;
i += j;
}
}
return -1;
}
void *kalloc_pages(size_t size, void **phys_addr)
{
const uint32_t nb_pages = CEIL(size, PAGE_SIZE);
uint16_t pd_index;
uint32_t *page_table;
const int16_t index = find_next_block(nb_pages, &pd_index, &page_table);
if (index < 0) {
kprintf(KERN_CRIT "%d: Not enough pages (max: %d)\n", index,
PT_SIZE);
return NULL;
}
for (size_t i = index; i - (size_t)index < nb_pages; i++) {
void *frame = alloc_frame();
if (!frame) {
for (size_t j = index; j < i; j++)
free_frame((void *)(page_table[j] & PAGE_MASK));
return NULL;
}
if (phys_addr)
*phys_addr = frame;
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
}
return (void *)GET_PAGE_ADDR(pd_index, index);
}
int kfree_pages(void *page_ptr, size_t size)
{
const uint32_t page_addr = (uint32_t)page_ptr;
const uint32_t nb_pages = CEIL(size, PAGE_SIZE);
const uint32_t page_index = page_addr / PAGE_SIZE;
const uint32_t pd_index = page_index / PD_SIZE;
const uint32_t pt_index = page_index % PD_SIZE;
if ((uint32_t)pd_index > 0x300) {
kprintf(KERN_WARNING "Address out of range\n");
return -1;
} else if (page_addr % PAGE_SIZE) {
kprintf(KERN_WARNING "Invalid address\n");
return -1;
} else if (pt_index + nb_pages > PT_SIZE) {
kprintf(KERN_WARNING "Invalid number of frames\n");
return -1;
}
uint32_t *page_table =
(uint32_t *)GET_PAGE_ADDR(0, PT_START + pd_index);
for (uint16_t i = pt_index; i < pt_index + nb_pages; i++) {
if (page_table[i] >> 12 == i) {
kprintf(KERN_WARNING "Page already free\n");
return -2;
}
free_frame((void *)(page_table[i] & PAGE_MASK));
page_table[i] = i << 12;
}
return 0;
}

View File

@ -1,7 +1,8 @@
.intel_syntax noprefix .intel_syntax noprefix
.text .section .text
.global load_page_directory .global load_page_directory
load_page_directory: load_page_directory:
push ebp push ebp
mov ebp, esp mov ebp, esp

View File

@ -113,7 +113,7 @@ static void init_frame_zones(void)
void init_memory(multiboot_info_t *mbd, uint32_t magic) void init_memory(multiboot_info_t *mbd, uint32_t magic)
{ {
for (uint16_t i = 0; i < 0x300; i++) for (uint16_t i = 769; i < 1021; i++)
kernel_pd[i] = 0x02; kernel_pd[i] = 0x02;
init_page_table(page_table_default, 0); init_page_table(page_table_default, 0);
kernel_pd[0] = ((uint32_t)page_table_default - HEAP_END) | 0x03; kernel_pd[0] = ((uint32_t)page_table_default - HEAP_END) | 0x03;

View File

@ -1,6 +1,5 @@
#include "assert.h"
#include "kprintf.h"
#include "memory.h" #include "memory.h"
void init_page_table(uint32_t page_table[1024], uint16_t start) void init_page_table(uint32_t page_table[1024], uint16_t start)
{ {
for (uint16_t i = start; i < 1024; i++) for (uint16_t i = start; i < 1024; i++)

View File

@ -1,7 +1,8 @@
.intel_syntax noprefix .intel_syntax noprefix
.text .section .text
.global enable_paging .global enable_paging
enable_paging: enable_paging:
push ebp push ebp
mov ebp, esp mov ebp, esp

View File

@ -3,7 +3,7 @@
#include "kpanic.h" #include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "process.h" #include "string.h"
Zone *vzones[3]; Zone *vzones[3];
@ -50,11 +50,12 @@ static void new_block(Zone *zone, uint32_t zone_size)
int new_vzone(block_type_t type, uint32_t size) int new_vzone(block_type_t type, uint32_t size)
{ {
// assert(current_task->pid); // assert(current_task->pid);
void *heap = alloc_pages(size, NULL); void *heap = valloc_pages(size, NULL);
if (heap == NULL) { if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_pages failed\n"); kprintf(KERN_ERR "error: alloc_pages failed\n");
return (-1); return (-1);
} }
memset(heap, 0, size);
Zone *zone = (Zone *)heap; Zone *zone = (Zone *)heap;
zone->type = type; zone->type = type;

View File

@ -33,7 +33,7 @@ static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
return -1; return -1;
} }
void *alloc_pages(size_t size, void **phys_addr) void *valloc_pages(size_t size, void **phys_addr)
{ {
const uint32_t nb_pages = CEIL(size, PAGE_SIZE); const uint32_t nb_pages = CEIL(size, PAGE_SIZE);
uint16_t pd_index; uint16_t pd_index;
@ -56,11 +56,10 @@ void *alloc_pages(size_t size, void **phys_addr)
*phys_addr = frame; *phys_addr = frame;
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS; page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
} }
memset((void *)GET_PAGE_ADDR(pd_index, index), 0, nb_pages * PAGE_SIZE);
return (void *)GET_PAGE_ADDR(pd_index, index); return (void *)GET_PAGE_ADDR(pd_index, index);
} }
int free_pages(void *page_ptr, size_t size) int vfree_pages(void *page_ptr, size_t size)
{ {
const uint32_t page_addr = (uint32_t)page_ptr; const uint32_t page_addr = (uint32_t)page_ptr;
const uint32_t nb_pages = CEIL(size, PAGE_SIZE); const uint32_t nb_pages = CEIL(size, PAGE_SIZE);

View File

@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
if (right) if (right)
right->prev = left; right->prev = left;
unmap: unmap:
err = free_pages((void *)zone, zone->size); err = vfree_pages((void *)zone, zone->size);
if (err) if (err)
kprintf(KERN_ERR "error: munmap failed\n"); kprintf(KERN_ERR "error: munmap failed\n");
return (err); return (err);

View File

@ -38,8 +38,8 @@ static void init_vbe(multiboot_info_t *mbd_virt)
((mbd_virt->framebuffer_addr + i * PAGE_SIZE) & PAGE_MASK) | ((mbd_virt->framebuffer_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS; INIT_FLAGS;
} }
kernel_pd[800] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03; kernel_pd[1021] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03;
display.buff = (uint32_t *)GET_PAGE_ADDR(800, 0) + display.buff = (uint32_t *)GET_PAGE_ADDR(1021, 0) +
(mbd_virt->framebuffer_addr % PAGE_SIZE); (mbd_virt->framebuffer_addr % PAGE_SIZE);
display.height = mbd_virt->framebuffer_height; display.height = mbd_virt->framebuffer_height;
display.width = mbd_virt->framebuffer_width; display.width = mbd_virt->framebuffer_width;

View File

@ -10,7 +10,7 @@ static struct tcb *thread_clone(struct tcb *thread)
if (!new_tcb) if (!new_tcb)
return NULL; return NULL;
new_tcb->tid = thread->tid; new_tcb->tid = thread->tid;
new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL); new_tcb->esp0 = kalloc_pages(STACK_SIZE, NULL);
if (!new_tcb->esp0) { if (!new_tcb->esp0) {
delete_thread(new_tcb); delete_thread(new_tcb);
return NULL; return NULL;

View File

@ -9,16 +9,16 @@
struct pcb *create_process(uid_t uid) struct pcb *create_process(uid_t uid)
{ {
static pid_t pid = 1; static pid_t pid = 1;
struct pcb *new_pcb = vmalloc(sizeof(struct pcb)); struct pcb *new_pcb = kmalloc(sizeof(struct pcb));
if (!new_pcb) if (!new_pcb)
return NULL; return NULL;
new_pcb->uid = uid; new_pcb->uid = uid;
new_pcb->pid = pid++; new_pcb->pid = pid++;
new_pcb->tid = 1; new_pcb->tid = 1;
new_pcb->heap = alloc_pages(4096, &new_pcb->cr3); new_pcb->heap = kalloc_pages(4096, &new_pcb->cr3);
if (!new_pcb->heap) { if (!new_pcb->heap) {
vfree(new_pcb); kfree(new_pcb);
return NULL; return NULL;
} }
memcpy(new_pcb->heap, current_pd, 4096); memcpy(new_pcb->heap, current_pd, 4096);
@ -48,8 +48,8 @@ void remove_process(struct pcb *pcb)
struct pcb *left = pcb->prev; struct pcb *left = pcb->prev;
struct pcb *right = pcb->next; struct pcb *right = pcb->next;
if (pcb->heap) if (pcb->heap)
free_pages(pcb->heap, 4096); kfree_pages(pcb->heap, 4096);
left->next = right; left->next = right;
right->prev = left; right->prev = left;
vfree(pcb); kfree(pcb);
} }

View File

@ -10,12 +10,12 @@
struct tcb *create_thread(struct pcb *process, void (*entry)(void)) struct tcb *create_thread(struct pcb *process, void (*entry)(void))
{ {
struct tcb *new_tcb = vmalloc(sizeof(struct tcb)); struct tcb *new_tcb = kmalloc(sizeof(struct tcb));
if (!new_tcb) if (!new_tcb)
return NULL; return NULL;
new_tcb->tid = process->tid++; new_tcb->tid = process->tid++;
new_tcb->esp0 = alloc_pages(STACK_SIZE, NULL); new_tcb->esp0 = kalloc_pages(STACK_SIZE, NULL);
if (!new_tcb->esp0) { if (!new_tcb->esp0) {
vfree(new_tcb); vfree(new_tcb);
return NULL; return NULL;
@ -46,9 +46,9 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
new_tcb->process = process; new_tcb->process = process;
new_tcb->state = NEW; new_tcb->state = NEW;
struct list *new_node = vmalloc(sizeof(struct list)); struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) { if (!new_node) {
free_pages(new_tcb->esp0, STACK_SIZE); kfree_pages(new_tcb->esp0, STACK_SIZE);
vfree(new_tcb); vfree(new_tcb);
return NULL; return NULL;
} }
@ -68,13 +68,13 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
void delete_thread(struct tcb *thread) void delete_thread(struct tcb *thread)
{ {
vfree(thread->esp0); kfree(thread->esp0);
struct list *it = thread->process->thread_list; struct list *it = thread->process->thread_list;
assert(it); assert(it);
while (it->next && it->next->content != thread) while (it->next && it->next->content != thread)
it = it->next; it = it->next;
struct list *to_free = it; struct list *to_free = it;
it->next = it->next->next; it->next = it->next->next;
vfree(to_free); kfree(to_free);
vfree(thread); kfree(thread);
} }