wip: change memory to use recursive paging

This commit is contained in:
0x35c
2025-11-28 11:08:28 +01:00
parent c5f8599d90
commit c33f8fc05d
10 changed files with 95 additions and 149 deletions

View File

@ -54,7 +54,7 @@ fast-run-iso: fast-iso
qemu-system-i386 -cdrom build/$(NAME).iso -vga std
debug: fast-iso
qemu-system-i386 -s -S -cdrom build/$(NAME).iso -vga std -D qemu.log -d in_asm,int -M smm=off
qemu-system-i386 -s -S -cdrom build/$(NAME).iso -vga std -d in_asm,int -M smm=off
clean:
make -C libbozo clean

View File

@ -12,18 +12,31 @@
#define ACCESSED (1 << 4)
#define INIT_FLAGS (PRESENT | RW | SUPERVISOR)
#define PAGE_SIZE 4096
#define PT_SIZE 1024
#define PD_SIZE 1024
#define PD ((uint32_t *)0xFFFFF000)
#define VIRT_PT_BASE 0xFFC00000
#define VIRT_PD_BASE 0xFFFFF000
#define PAGE_MASK 0xFFFFF000
#define HEAP_END 0xC0000000
#define HEAP_START ((uint32_t)&_kernel_end - HEAP_END)
#define VIRT_OFFSET 0xC0000000
#define KERNEL_START ((uint32_t)&_kernel_start)
#define KERNEL_END ((uint32_t)&_kernel_end - HEAP_END)
#define KERNEL_END ((uint32_t)&_kernel_end - VIRT_OFFSET)
#define KERNEL_PT_END 1020
#define KERNEL_PT_START 769
#define GET_PAGE_ADDR(pd_index, pt_index) \
((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * 4096)
#define PDE_VBE 1021
#define PDE_FRAME_ZONES 1022
#define PDE_MULTIBOOT 1023
#define PTE2VA(pd_index, pt_index) \
((uint32_t *)((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * \
4096))
static inline uint32_t *VA2PTE(uint32_t va)
{
uint32_t pde = va >> 22;
uint32_t pte = (va >> 12) & 0x3FF;
uint32_t *pt = (uint32_t *)(VIRT_PT_BASE + (pde * 0x1000));
return &pt[pte];
}
#define GET_FRAME(frame_table, i) (frame_table[i / 8] & (1 << (i % 8)))
#define SET_FRAME(frame_table, i, used) \
@ -47,23 +60,14 @@ extern uint32_t _kernel_end;
extern uint32_t _kernel_start;
extern uint32_t boot_page_directory;
extern uint32_t boot_page_table1;
extern uint32_t *kernel_pd;
extern uint32_t *current_pd;
extern uint32_t page_table_default[1024];
extern uint32_t mem_size;
extern multiboot_memory_map_t *mmap_addr;
extern multiboot_uint32_t mmap_length;
extern struct frame_zone *head;
uint32_t *virt_to_phys(uint32_t *virt_addr);
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 *kalloc_pages(size_t size, void **phys_addr);
void *kalloc_pages(size_t nb_pages);
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, uint16_t pt_start);
void switch_pd(uint32_t *pd, uint32_t *cr3);

View File

@ -49,7 +49,7 @@ 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 = kalloc_pages(size, NULL);
void *heap = kalloc_pages(size);
if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_frame failed\n");
return (-1);

View File

@ -9,86 +9,51 @@
#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)
static uint32_t *find_next_block(size_t nb_pages)
{
for (*pd_index_ptr = KERNEL_PT_START; *pd_index_ptr < KERNEL_PT_END;
(*pd_index_ptr)++) {
if (current_pd[(*pd_index_ptr)] == 0x02) {
if (add_page_table(*pd_index_ptr, KERNEL_PT_START) < 0)
return -2;
uint32_t count = 0;
for (uint32_t *pte = PTE2VA(1023, 0); pte < PTE2VA(1023, 1023); pte++) {
if (!*pte) {
count = 0;
continue;
}
*page_table_ptr =
(uint32_t *)GET_PAGE_ADDR(KERNEL_PT_START, *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;
count++;
if (count == nb_pages)
return pte - count;
}
}
return -1;
return NULL;
}
void *kalloc_pages(size_t size, void **phys_addr)
void *kalloc_pages(size_t nb_pages)
{
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++) {
uint32_t *start = find_next_block(nb_pages);
for (uint32_t i = 0; i < 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));
for (uint32_t j = 0; j < i; j++)
free_frame((void *)(((uint32_t)(start + j)) &
PAGE_MASK));
return NULL;
}
if (phys_addr)
*phys_addr = frame;
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
assert(!((uint32_t)frame & PAGE_MASK));
start[i] = (uint32_t)frame | INIT_FLAGS;
}
return (void *)GET_PAGE_ADDR(pd_index, index);
uint32_t page_index = start - PTE2VA(1023, 0);
return PTE2VA(page_index / 1024, page_index % 1024);
}
int kfree_pages(void *page_ptr, size_t size)
int kfree_pages(void *page_ptr, size_t nb_pages)
{
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 < KERNEL_PT_START || pd_index > KERNEL_PT_END) {
kprintf(KERN_WARNING "Address out of range\n");
return -1;
} else if (page_addr % PAGE_SIZE) {
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(KERNEL_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;
}
for (uint32_t *pte = VA2PTE(page_addr);
pte < VA2PTE(page_addr) + nb_pages; pte++) {
free_frame((void *)(*pte & PAGE_MASK));
*pte = 0;
}
return 0;
}

View File

@ -1,22 +1,14 @@
#include "memory.h"
#include "kpanic.h"
#include "string.h"
#include "utils.h"
#include <stdint.h>
uint32_t *kernel_pd = &boot_page_directory;
uint32_t *current_pd;
uint32_t page_table_default[1024] __attribute__((aligned(PAGE_SIZE)));
uint32_t frame_zones_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
uint32_t mem_size;
struct frame_zone *head;
void switch_pd(uint32_t *pd, uint32_t *cr3)
{
current_pd = pd;
asm volatile("mov %0, %%cr3" ::"r"(cr3));
}
static void lst_add_back(struct frame_zone **root, struct frame_zone *element)
{
if (!*root) {
@ -38,9 +30,9 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
* - = blank
*/
uint64_t start_addr = mmmt->addr;
uint64_t end_addr = mmmt->addr + mmmt->len;
uint64_t len = mmmt->len;
uint32_t start_addr = mmmt->addr;
uint32_t end_addr = mmmt->addr + mmmt->len;
uint32_t len = mmmt->len;
/** Kernel code cover all the block
* this situation:
@ -67,13 +59,13 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
}
end_addr = ROUND_CEIL(start_addr + len, PAGE_SIZE);
init_page_table(frame_zones_page_table, 0);
kernel_pd[1022] = ((uint32_t)frame_zones_page_table - HEAP_END) | 0x03;
PD[PDE_FRAME_ZONES] =
((uint32_t)frame_zones_page_table - VIRT_OFFSET) | INIT_FLAGS;
frame_zones_page_table[index] =
((uint32_t)start_addr & PAGE_MASK) | INIT_FLAGS;
struct frame_zone *current =
(struct frame_zone *)GET_PAGE_ADDR(1022, index++);
(struct frame_zone *)PTE2VA(PDE_FRAME_ZONES, index++);
current->frame_table = (uint8_t *)current + sizeof(struct frame_zone);
@ -96,7 +88,7 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
frame_zones_page_table[index + i] =
((uint32_t)(start_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS;
current->addr = (void *)start_addr + i * PAGE_SIZE;
current->addr = (void *)(start_addr + i * PAGE_SIZE);
index += i - 1;
lst_add_back(&head, current);
}
@ -113,11 +105,16 @@ static void init_frame_zones(void)
void init_memory(multiboot_info_t *mbd, uint32_t magic)
{
for (uint16_t i = KERNEL_PT_START; i < 1020; i++)
kernel_pd[i] = 0x02;
init_page_table(page_table_default, 0);
kernel_pd[1020] = ((uint32_t)page_table_default - HEAP_END) | 0x03;
current_pd = kernel_pd;
init_multiboot(mbd, magic);
init_frame_zones();
// initialize all the PTs
for (uint16_t i = KERNEL_PT_START; i < KERNEL_PT_END; i++) {
uint32_t frame = (uint32_t)alloc_frame();
if (!frame)
kpanic("Couldn't initialize kernel PTs\n");
PD[i] = frame | RW;
}
PD[1023] = ((uint32_t)&boot_page_directory - VIRT_OFFSET) | INIT_FLAGS;
// kalash kalash kalash sur la mélodie chez nous pas de félonie ça vient
// de Sevran les R
}

View File

@ -1,19 +0,0 @@
#include "memory.h"
void init_page_table(uint32_t page_table[1024], uint16_t start)
{
for (uint16_t i = start; i < 1024; i++)
page_table[i] = (i << 12) | 0x03;
}
int16_t add_page_table(uint16_t pd_index, uint16_t pt_start)
{
void *frame = alloc_frame();
if (!frame)
return -1;
page_table_default[pd_index] = ((uint32_t)frame & PAGE_MASK) | 0x03;
uint32_t *page_table = (uint32_t *)GET_PAGE_ADDR(pt_start, pd_index);
init_page_table(page_table, 0);
kernel_pd[pd_index] = ((uint32_t)frame & PAGE_MASK) | 0x03;
return 0;
}

View File

@ -13,12 +13,12 @@ static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
uint32_t **page_table_ptr)
{
for (*pd_index_ptr = 2; *pd_index_ptr < 768; (*pd_index_ptr)++) {
if (current_pd[(*pd_index_ptr)] == 0x02) {
if (add_page_table(*pd_index_ptr, 1) < 0)
return -2;
}
*page_table_ptr = (uint32_t *)GET_PAGE_ADDR(1, *pd_index_ptr);
for (uint16_t i = 0; i + nb_pages - 1 < PT_SIZE; i++) {
// if (current_pd[(*pd_index_ptr)] == 0x02) {
// if (add_page_table(*pd_index_ptr, 1) < 0)
// return -2;
// }
*page_table_ptr = (uint32_t *)PTE2VA(1, *pd_index_ptr);
for (uint16_t i = 0; i + nb_pages - 1 < 1024; i++) {
uint16_t j;
for (j = 0; (*page_table_ptr)[i + j] >> 12 == i + j &&
j < nb_pages;
@ -41,7 +41,7 @@ void *valloc_pages(size_t size, void **phys_addr)
if (index < 0) {
kprintf(KERN_CRIT "%d: Not enough pages (max: %d)\n", index,
PT_SIZE);
1024);
return NULL;
}
for (size_t i = index; i - (size_t)index < nb_pages; i++) {
@ -55,7 +55,7 @@ void *valloc_pages(size_t size, void **phys_addr)
*phys_addr = frame;
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
}
return (void *)GET_PAGE_ADDR(pd_index, index);
return (void *)PTE2VA(pd_index, index);
}
int vfree_pages(void *page_ptr, size_t size)
@ -63,8 +63,8 @@ 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);
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;
const uint32_t pd_index = page_index / 1024;
const uint32_t pt_index = page_index % 1024;
if ((uint32_t)pd_index > 0x300) {
kprintf(KERN_WARNING "Address out of range\n");
@ -72,11 +72,11 @@ int vfree_pages(void *page_ptr, size_t size)
} else if (page_addr % PAGE_SIZE) {
kprintf(KERN_WARNING "Invalid address\n");
return -1;
} else if (pt_index + nb_pages > PT_SIZE) {
} else if (pt_index + nb_pages > 1024) {
kprintf(KERN_WARNING "Invalid number of frames\n");
return -1;
}
uint32_t *page_table = (uint32_t *)GET_PAGE_ADDR(1, pd_index);
uint32_t *page_table = (uint32_t *)PTE2VA(1, 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 freed\n");

View File

@ -1,8 +1,6 @@
#include <stddef.h>
#include <stdint.h>
#include "commands.h"
#include "debug.h"
#include "kpanic.h"
#include "memory.h"
#include "multiboot.h"
@ -22,7 +20,8 @@ static void init_mmap(multiboot_info_t *mbd_virt, size_t *pt_index)
multiboot_page_table[i + *pt_index] =
((mbd_virt->mmap_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS;
mmap_addr = (multiboot_memory_map_t *)(GET_PAGE_ADDR(1023, *pt_index) +
mmap_addr =
(multiboot_memory_map_t *)(PTE2VA(PDE_MULTIBOOT, *pt_index) +
(uint32_t)mbd_virt->mmap_addr %
PAGE_SIZE);
mmap_length = mbd_virt->mmap_length / sizeof(multiboot_memory_map_t);
@ -38,8 +37,8 @@ static void init_vbe(multiboot_info_t *mbd_virt)
((mbd_virt->framebuffer_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS;
}
kernel_pd[1021] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03;
display.buff = (uint32_t *)GET_PAGE_ADDR(1021, 0) +
PD[PDE_VBE] = ((uint32_t)vbe_page_table - VIRT_OFFSET) | INIT_FLAGS;
display.buff = (uint32_t *)PTE2VA(PDE_VBE, 0) +
(mbd_virt->framebuffer_addr % PAGE_SIZE);
display.height = mbd_virt->framebuffer_height;
display.width = mbd_virt->framebuffer_width;
@ -50,10 +49,10 @@ static void init_vbe(multiboot_info_t *mbd_virt)
void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
{
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
kpanic("invalid magic number! (git good skill issue)");
kpanic("invalid magic number! (git gud skill issue)");
init_page_table(multiboot_page_table, 0);
kernel_pd[1023] = ((uint32_t)multiboot_page_table - HEAP_END) | 0x03;
PD[PDE_MULTIBOOT] =
((uint32_t)multiboot_page_table - VIRT_OFFSET) | INIT_FLAGS;
size_t pt_index = CEIL(
(uint32_t)mbd % PAGE_SIZE + sizeof(multiboot_info_t), PAGE_SIZE);
@ -62,7 +61,7 @@ void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
multiboot_page_table[i] =
(((uint32_t)mbd + PAGE_SIZE * i) & PAGE_MASK) | INIT_FLAGS;
multiboot_info_t *mbd_virt =
(multiboot_info_t *)(GET_PAGE_ADDR(1023, 0) +
(multiboot_info_t *)(PTE2VA(PDE_MULTIBOOT, 0) +
(uint32_t)mbd % PAGE_SIZE);
init_mmap(mbd_virt, &pt_index);
init_vbe(mbd_virt);

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 = kalloc_pages(STACK_SIZE, NULL);
new_tcb->esp0 = kalloc_pages(STACK_SIZE);
if (!new_tcb->esp0) {
delete_thread(new_tcb);
return NULL;
@ -31,10 +31,8 @@ pid_t fork(void)
}
new_pcb->daddy = current_pcb;
lst_add_back(&new_pcb->children, new_node);
current_pd = new_pcb->cr3;
// loop on threads clone
thread_clone(current_pcb->thread_list->content);
current_pd = current_pcb->cr3;
return new_pcb->pid;
}

View File

@ -16,12 +16,14 @@ struct pcb *create_process(uid_t uid)
new_pcb->pid = pid++;
new_pcb->tid = 1;
new_pcb->heap = kalloc_pages(4096, &new_pcb->cr3);
new_pcb->heap = kalloc_pages(4096);
if (!new_pcb->heap) {
kfree(new_pcb);
return NULL;
}
memcpy(new_pcb->heap, current_pd, 4096);
new_pcb->cr3 =
(void *)((uint32_t)VA2PTE((uint32_t)new_pcb->heap) & PAGE_MASK);
memcpy(new_pcb->heap, PD, 4096);
new_pcb->daddy = NULL;
new_pcb->children = NULL;