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);
int free_frame(void *frame_ptr);
int8_t add_single_page(void *frame);
void *alloc_pages(size_t size, void **phys_addr);
int free_pages(void *page_ptr, size_t size);
void *kalloc_pages(size_t size, void **phys_addr);
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);
int16_t add_page_table(uint16_t pd_index);
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;
while (i < ARRAY_SIZE(faults)) {
if (i == 6)
reboot();
if (i == regs->int_no)
kpanic("interrupt: %s\n", faults[i]);
i++;

View File

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

View File

@ -1,9 +1,8 @@
#include "alloc.h"
#include "assert.h"
#include "kpanic.h"
#include "kprintf.h"
#include "memory.h"
#include "process.h"
#include "string.h"
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)
{
// assert(current_task->pid);
void *heap = alloc_frame();
void *heap = kalloc_pages(size, NULL);
if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_frame failed\n");
return (-1);
}
memset(heap, 0, size);
Zone *zone = (Zone *)heap;
zone->type = type;

View File

@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
if (right)
right->prev = left;
unmap:
err = free_pages((void *)zone, zone->size);
err = kfree_pages((void *)zone, zone->size);
if (err)
kprintf(KERN_ERR "error: munmap failed\n");
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
.text
.section .text
.global load_page_directory
load_page_directory:
push ebp
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)
{
for (uint16_t i = 0; i < 0x300; i++)
for (uint16_t i = 769; i < 1021; i++)
kernel_pd[i] = 0x02;
init_page_table(page_table_default, 0);
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"
void init_page_table(uint32_t page_table[1024], uint16_t start)
{
for (uint16_t i = start; i < 1024; i++)

View File

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

View File

@ -3,7 +3,7 @@
#include "kpanic.h"
#include "kprintf.h"
#include "memory.h"
#include "process.h"
#include "string.h"
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)
{
// assert(current_task->pid);
void *heap = alloc_pages(size, NULL);
void *heap = valloc_pages(size, NULL);
if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_pages failed\n");
return (-1);
}
memset(heap, 0, size);
Zone *zone = (Zone *)heap;
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;
}
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);
uint16_t pd_index;
@ -56,11 +56,10 @@ void *alloc_pages(size_t size, void **phys_addr)
*phys_addr = frame;
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);
}
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 nb_pages = CEIL(size, PAGE_SIZE);

View File

@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
if (right)
right->prev = left;
unmap:
err = free_pages((void *)zone, zone->size);
err = vfree_pages((void *)zone, zone->size);
if (err)
kprintf(KERN_ERR "error: munmap failed\n");
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) |
INIT_FLAGS;
}
kernel_pd[800] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03;
display.buff = (uint32_t *)GET_PAGE_ADDR(800, 0) +
kernel_pd[1021] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03;
display.buff = (uint32_t *)GET_PAGE_ADDR(1021, 0) +
(mbd_virt->framebuffer_addr % PAGE_SIZE);
display.height = mbd_virt->framebuffer_height;
display.width = mbd_virt->framebuffer_width;

View File

@ -10,7 +10,7 @@ static struct tcb *thread_clone(struct tcb *thread)
if (!new_tcb)
return NULL;
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) {
delete_thread(new_tcb);
return NULL;

View File

@ -9,16 +9,16 @@
struct pcb *create_process(uid_t uid)
{
static pid_t pid = 1;
struct pcb *new_pcb = vmalloc(sizeof(struct pcb));
struct pcb *new_pcb = kmalloc(sizeof(struct pcb));
if (!new_pcb)
return NULL;
new_pcb->uid = uid;
new_pcb->pid = pid++;
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) {
vfree(new_pcb);
kfree(new_pcb);
return NULL;
}
memcpy(new_pcb->heap, current_pd, 4096);
@ -48,8 +48,8 @@ void remove_process(struct pcb *pcb)
struct pcb *left = pcb->prev;
struct pcb *right = pcb->next;
if (pcb->heap)
free_pages(pcb->heap, 4096);
kfree_pages(pcb->heap, 4096);
left->next = right;
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 *new_tcb = vmalloc(sizeof(struct tcb));
struct tcb *new_tcb = kmalloc(sizeof(struct tcb));
if (!new_tcb)
return NULL;
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) {
vfree(new_tcb);
return NULL;
@ -46,9 +46,9 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
new_tcb->process = process;
new_tcb->state = NEW;
struct list *new_node = vmalloc(sizeof(struct list));
struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) {
free_pages(new_tcb->esp0, STACK_SIZE);
kfree_pages(new_tcb->esp0, STACK_SIZE);
vfree(new_tcb);
return NULL;
}
@ -68,13 +68,13 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
void delete_thread(struct tcb *thread)
{
vfree(thread->esp0);
kfree(thread->esp0);
struct list *it = thread->process->thread_list;
assert(it);
while (it->next && it->next->content != thread)
it = it->next;
struct list *to_free = it;
it->next = it->next->next;
vfree(to_free);
vfree(thread);
kfree(to_free);
kfree(thread);
}