Compare commits

..

21 Commits

Author SHA1 Message Date
0d828c8067 wip: switch current_pcb and cr3 in switch_thread 2025-11-30 14:54:17 +01:00
274113a401 core: refactor fork function 2025-11-30 14:30:04 +01:00
896a0a04f9 fix: set content to the new thread_list node
fix: copy child to the current_pcb
2025-11-30 14:24:33 +01:00
5b25422f8d fix: memcpy not in the right order 2025-11-30 14:14:03 +01:00
afe83d5059 add: parentheses around param in PTE2VA 2025-11-30 15:10:51 +01:00
dbfa2febec fix: new_pt in deep_copy (still not working tho) 2025-11-30 13:45:12 +01:00
cde3702132 feature: fork() (to be tested) 2025-11-30 13:32:24 +01:00
6ff044c07a fix: get pd phys addr 2025-11-28 20:22:19 +01:00
700864cbf2 wip: allocate user process stack on the right PD 2025-11-28 19:16:54 +01:00
f9cb7a6a8a fix: use right var to prevent crash 2025-11-28 20:13:04 +01:00
24dce6e737 fix: setup recursive paging in process 2025-11-28 20:06:27 +01:00
d46fe337c1 fix: GET_PTE cast type 2025-11-28 19:25:16 +01:00
1992d7f79b fix: bzero page tables before use it, alloc return the right index 2025-11-28 19:24:40 +01:00
2308ef509c fix: GET_PTE uses the right value 2025-11-28 17:39:10 +01:00
3df6011d7a wip: user allocator 2025-11-28 17:36:10 +01:00
c6a5bf25c2 feature: reboot on space with kpanic 2025-11-28 16:35:40 +01:00
9c91830007 core: change multiboot pde 2025-11-28 16:22:55 +01:00
3c2c9b0a10 core: init_multiboot in main 2025-11-28 16:22:30 +01:00
674509a79e fix: init_mmap: use right addr 2025-11-28 16:22:03 +01:00
99ee5b8cec fix: add_frame_node: map enough page to write frame metadata 2025-11-28 16:21:28 +01:00
5591120deb core: setup recusive paging in boot.s 2025-11-28 16:20:31 +01:00
27 changed files with 298 additions and 208 deletions

View File

@ -75,10 +75,10 @@ int new_vzone(block_type_t type, size_t size);
int new_kzone(block_type_t type, size_t size); int new_kzone(block_type_t type, size_t size);
/*----------------------------*/ /*----------------------------*/
void *vmalloc(size_t size); void *umalloc(size_t size);
void vfree(void *ptr); void ufree(void *ptr);
void *vrealloc(void *ptr, size_t size); void *vrealloc(void *ptr, size_t size);
void show_valloc_mem(void); void show_ualloc_mem(void);
size_t vsize(void *virt_addr); size_t vsize(void *virt_addr);
void *kmalloc(size_t size); void *kmalloc(size_t size);
void kfree(void *ptr); void kfree(void *ptr);

View File

@ -21,14 +21,21 @@
#define KERNEL_END ((uint32_t)&_kernel_end - VIRT_OFFSET) #define KERNEL_END ((uint32_t)&_kernel_end - VIRT_OFFSET)
#define KERNEL_PT_END 1020 #define KERNEL_PT_END 1020
#define KERNEL_PT_START 769 #define KERNEL_PT_START 769
#define USER_PT_START 1
#define USER_PT_END 768
#define PDE_VBE 1021 #define PDE_VBE 1021
#define PDE_FRAME_ZONES 1022 #define PDE_FRAME_ZONES 1022
#define PDE_MULTIBOOT 1023 #define PDE_MULTIBOOT 1020
#define GET_PTE(pd_index, pt_index) \
((uint32_t *)(VIRT_PT_BASE + ((uint32_t)pd_index) * 4096 + \
((uint32_t)pt_index) * 4))
#define PTE2VA(pd_index, pt_index) \ #define PTE2VA(pd_index, pt_index) \
((uint32_t *)((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * \ ((uint32_t *)(( \
4096)) ((((uint32_t)pd_index) * 1024) + ((uint32_t)pt_index)) * 4096)))
static inline uint32_t *VA2PTE(uint32_t va) static inline uint32_t *VA2PTE(uint32_t va)
{ {
uint32_t pde = va >> 22; uint32_t pde = va >> 22;
@ -64,10 +71,11 @@ extern multiboot_memory_map_t *mmap_addr;
extern multiboot_uint32_t mmap_length; extern multiboot_uint32_t mmap_length;
extern struct frame_zone *head; extern struct frame_zone *head;
void init_memory(multiboot_info_t *mbd, uint32_t magic); void init_multiboot(multiboot_info_t *mbd, uint32_t magic);
void init_memory(void);
void *alloc_frame(void); void *alloc_frame(void);
int free_frame(void *frame_ptr); int free_frame(void *frame_ptr);
void *kalloc_pages(size_t nb_pages); void *kalloc_pages(size_t nb_pages);
void *valloc_pages(size_t size, void **phys_addr); void *ualloc_pages(size_t nb_pages);
int kfree_pages(void *page_ptr, size_t size); int kfree_pages(void *page_ptr, size_t nb_pages);
int vfree_pages(void *page_ptr, size_t size); int ufree_pages(void *page_ptr, size_t nb_pages);

View File

@ -28,5 +28,5 @@ struct pcb {
void switch_process(struct pcb *next_pcb); void switch_process(struct pcb *next_pcb);
struct pcb *create_process(uid_t uid); struct pcb *create_process(uid_t uid);
// int8_t create_kernel_process(void);
void remove_process(struct pcb *pcb); void remove_process(struct pcb *pcb);
pid_t fork(void);

View File

@ -24,4 +24,4 @@ struct tcb {
struct tcb *create_thread(struct pcb *process, void (*entry)(void)); struct tcb *create_thread(struct pcb *process, void (*entry)(void));
void delete_thread(struct tcb *thread); void delete_thread(struct tcb *thread);
void switch_thread(uint32_t *esp); void switch_thread(struct tcb *thread_to_switch);

View File

@ -93,6 +93,10 @@ _start:
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0 movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4 movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
# Map the recusive paging
movl $(boot_page_directory - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 1023 * 4
# Set cr3 to the address of the boot_page_directory. # Set cr3 to the address of the boot_page_directory.
movl $(boot_page_directory - 0xC0000000), %ecx movl $(boot_page_directory - 0xC0000000), %ecx
movl %ecx, %cr3 movl %ecx, %cr3

View File

@ -40,7 +40,7 @@ static void clock_handler(struct registers *regs)
{ {
scheduler_counter++; scheduler_counter++;
sleep_counter--; sleep_counter--;
if (scheduler_counter % 100 == 0) if (scheduler_counter % 30 == 0)
scheduler((uint32_t *)regs); scheduler((uint32_t *)regs);
} }

View File

@ -33,9 +33,11 @@
static void uwu(void) static void uwu(void)
{ {
pid_t pid = fork();
kprintf("pid: %d\n", pid);
while (1) { while (1) {
// sleep(1000); // sleep(1000);
kprintf("uwu\n"); // kprintf("%d\n", current_pcb->pid);
} }
} }
@ -50,13 +52,13 @@ void kernel_main(multiboot_info_t *mbd, uint32_t magic)
cli(); cli();
init_gdt(); init_gdt();
init_idt(); init_idt();
init_memory(mbd, magic); init_multiboot(mbd, magic);
init_memory();
load_drivers(); load_drivers();
terminal_initialize(); terminal_initialize();
create_process(1); create_process(1);
create_thread(current_pcb, shell_init); // create_thread(current_pcb, shell_init);
create_process(2); create_thread(current_pcb, uwu);
create_thread(current_pcb->next, uwu);
toris(); toris();
while (true) while (true)
; ;

View File

@ -27,10 +27,13 @@ __attribute__((noreturn)) void kpanic(const char *format, ...)
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_ualloc_mem();
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */
/* print_stack(); */ /* print_stack(); */
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */
/* kprintf("PRESS SPACE TO REBOOT"); */ kprintf("PRESS SPACE TO REBOOT");
__asm__ __volatile__("jmp panic"); while (terminal_getkey().c != ' ')
;
reboot();
// __asm__ __volatile__("jmp panic");
} }

View File

@ -3,6 +3,7 @@
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "string.h" #include "string.h"
#include "utils.h"
Zone *kzones[3]; Zone *kzones[3];
@ -49,7 +50,7 @@ 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 = kalloc_pages(size); void *heap = kalloc_pages(CEIL(size, PAGE_SIZE));
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);

View File

@ -12,14 +12,15 @@
static uint32_t *find_next_block(size_t nb_pages) static uint32_t *find_next_block(size_t nb_pages)
{ {
uint32_t count = 0; uint32_t count = 0;
for (uint32_t *pte = PTE2VA(1023, 0); pte < PTE2VA(1023, 1023); pte++) { for (uint32_t *pte = PTE2VA(1023, KERNEL_PT_START);
if (!*pte) { pte < PTE2VA(1023, KERNEL_PT_END); pte++) {
if (*pte) {
count = 0; count = 0;
continue; continue;
} }
count++; count++;
if (count == nb_pages) if (count == nb_pages)
return pte - count; return pte - (count - 1);
} }
return NULL; return NULL;
} }
@ -27,6 +28,8 @@ static uint32_t *find_next_block(size_t nb_pages)
void *kalloc_pages(size_t nb_pages) void *kalloc_pages(size_t nb_pages)
{ {
uint32_t *start = find_next_block(nb_pages); uint32_t *start = find_next_block(nb_pages);
if (!start)
return NULL;
for (uint32_t i = 0; i < nb_pages; i++) { for (uint32_t i = 0; i < nb_pages; i++) {
void *frame = alloc_frame(); void *frame = alloc_frame();
if (!frame) { if (!frame) {
@ -35,7 +38,7 @@ void *kalloc_pages(size_t nb_pages)
PAGE_MASK)); PAGE_MASK));
return NULL; return NULL;
} }
assert(!((uint32_t)frame & PAGE_MASK)); assert((uint32_t)frame & PAGE_MASK);
start[i] = (uint32_t)frame | INIT_FLAGS; start[i] = (uint32_t)frame | INIT_FLAGS;
} }
uint32_t page_index = start - PTE2VA(1023, 0); uint32_t page_index = start - PTE2VA(1023, 0);

View File

@ -23,17 +23,16 @@ static void lst_add_back(struct frame_zone **root, struct frame_zone *element)
static void add_frame_node(multiboot_memory_map_t *mmmt) static void add_frame_node(multiboot_memory_map_t *mmmt)
{ {
static uint32_t index; static uint32_t index = 0;
uint32_t *pd = &boot_page_directory;
/** /**
* # = kernel code * # = kernel code
* - = blank * - = blank
*/ */
uint32_t start_addr = mmmt->addr; uint64_t start_addr = mmmt->addr;
uint32_t end_addr = mmmt->addr + mmmt->len; uint64_t end_addr = mmmt->addr + mmmt->len;
uint32_t len = mmmt->len; uint64_t len = mmmt->len;
/** Kernel code cover all the block /** Kernel code cover all the block
* this situation: * this situation:
@ -60,62 +59,73 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
} }
end_addr = ROUND_CEIL(start_addr + len, PAGE_SIZE); end_addr = ROUND_CEIL(start_addr + len, PAGE_SIZE);
pd[PDE_FRAME_ZONES] = PD[PDE_FRAME_ZONES] =
((uint32_t)frame_zones_page_table - VIRT_OFFSET) | INIT_FLAGS; ((uint32_t)frame_zones_page_table - VIRT_OFFSET) | INIT_FLAGS;
frame_zones_page_table[index] =
((uint32_t)start_addr & PAGE_MASK) | INIT_FLAGS; /** We need to determine how many frames are available
to save how many frame the blocks contain etc we need some meta
data 1 struct frame_zone and a frame_table, the size of the
frame_table is 1 bit per frame the frame_table is a uint8_t so 8 bit,
so its size must be CEIL(max_frames, 8) But we don't have max_frames.
We can determine max_frame = (block_len - sizeof(struct
frame_zone)) / (PAGE_SIZE + 1 / 8) (1 / 8 because size is in byte but
we only need one bit) Because we don't use float we can't have 1 / 8
So we will multiplicate every members of this equation by 8 to
have only complet number So... max_frame = (block_len - sizeof(struct
frame_zone)) * 8 / (PAGE_SIZE * 8 + 1)
*/
const uint32_t nb_frame =
(len - sizeof(struct frame_zone)) * 8 / (PAGE_SIZE * 8 + 1);
const uint32_t frame_table_size = CEIL(nb_frame, (sizeof(uint8_t) * 8));
uint32_t page_needed =
CEIL(frame_table_size + sizeof(struct frame_zone), PAGE_SIZE);
uint32_t i = 0;
for (; i < page_needed; i++)
frame_zones_page_table[index + i] =
(((uint32_t)start_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS;
struct frame_zone *current = struct frame_zone *current =
(struct frame_zone *)PTE2VA(PDE_FRAME_ZONES, index++); (struct frame_zone *)PTE2VA(PDE_FRAME_ZONES, index);
current->frame_table = (uint8_t *)current + sizeof(struct frame_zone); current->frame_table =
(uint8_t *)((uint32_t)current + sizeof(struct frame_zone));
/** 8 is cause we are using uint8_t
nb_frame = size / (PAGE_SIZE + 1 / 8)
cause we are using non decimal number
nb_frame = ((size * 8) / (PAGE_SIZE * 8 + 1))
*/
const uint32_t nb_frame = ((len * 8) / (PAGE_SIZE * 8 + 1));
current->first_free_frame = 0; current->first_free_frame = 0;
current->next = NULL; current->next = NULL;
current->remaining_frames = nb_frame; current->remaining_frames = nb_frame;
current->total_frames = nb_frame; current->total_frames = nb_frame;
current->addr = (void *)(uint32_t)start_addr + page_needed * PAGE_SIZE;
memset(current->frame_table, 0, bzero(current->frame_table, frame_table_size);
nb_frame * sizeof(*current->frame_table));
uint32_t i = 1; index += i;
for (; i < CEIL(nb_frame, PAGE_SIZE); i++)
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);
index += i - 1;
lst_add_back(&head, current); lst_add_back(&head, current);
} }
static void init_frame_zones(void) static void init_frame_zones(void)
{ {
for (uint32_t i = 0; i < mmap_length; i++) { for (uint32_t i = 0; i < mmap_length;
i += sizeof(multiboot_memory_map_t)) {
multiboot_memory_map_t *mmmt = multiboot_memory_map_t *mmmt =
(multiboot_memory_map_t *)mmap_addr + i; (multiboot_memory_map_t *)((uint32_t)mmap_addr + i);
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE) if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE)
add_frame_node(mmmt); add_frame_node(mmmt);
} }
} }
void init_memory(multiboot_info_t *mbd, uint32_t magic) void init_memory()
{ {
init_multiboot(mbd, magic);
init_frame_zones(); init_frame_zones();
// initialize all the PTs // initialize all the PTs
for (uint16_t i = KERNEL_PT_START; i < KERNEL_PT_END; i++) { for (uint16_t i = KERNEL_PT_START; i < KERNEL_PT_END; i++) {
uint32_t frame = (uint32_t)alloc_frame(); uint32_t frame = (uint32_t)alloc_frame();
if (!frame) if (!frame)
kpanic("Couldn't initialize kernel PTs\n"); kpanic("Couldn't initialize kernel PTs\n");
PD[i] = frame | RW; PD[i] = frame | INIT_FLAGS;
bzero(PTE2VA(1023, i), PAGE_SIZE);
} }
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 // kalash kalash kalash sur la mélodie chez nous pas de félonie ça vient
// de Sevran les R // de Sevran les R
} }

View File

@ -4,6 +4,7 @@
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "string.h" #include "string.h"
#include "utils.h"
Zone *vzones[3]; Zone *vzones[3];
@ -50,7 +51,7 @@ 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 = valloc_pages(size, NULL); void *heap = ualloc_pages(CEIL(size, PAGE_SIZE));
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);

View File

@ -5,7 +5,7 @@
// FULL_INFO is to display (or not) both used and unused blocks // FULL_INFO is to display (or not) both used and unused blocks
#define FULL_INFO 1 #define FULL_INFO 1
void show_valloc_mem(void) void show_ualloc_mem(void)
{ {
char *const zones_name[3] = {"TINY", "SMALL", "LARGE"}; char *const zones_name[3] = {"TINY", "SMALL", "LARGE"};
uint32_t total_size = 0; uint32_t total_size = 0;

77
src/memory/user/page.c Normal file
View File

@ -0,0 +1,77 @@
#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 int8_t alloc_pagetable(uint16_t pd_index)
{
uint32_t *pt = alloc_frame();
if (!pt)
return -1;
PD[pd_index] = (uint32_t)pt | INIT_FLAGS;
bzero(PTE2VA(1023, pd_index), PAGE_SIZE);
return 0;
}
static uint32_t *find_next_block(size_t nb_pages)
{
size_t count = 0;
for (size_t i = USER_PT_START; i < USER_PT_END; i++) {
if (!PD[i])
if (alloc_pagetable(i) < 0)
return NULL;
for (size_t j = 0; j < 1024; j++) {
if (*GET_PTE(i, j)) {
count = 0;
continue;
}
count++;
if (count == nb_pages) {
return GET_PTE(i, j) - (count - 1);
}
}
}
return NULL;
}
void *ualloc_pages(size_t nb_pages)
{
uint32_t *start = find_next_block(nb_pages);
if (!start)
return NULL;
for (uint32_t i = 0; i < nb_pages; i++) {
void *frame = alloc_frame();
if (!frame) {
for (uint32_t j = 0; j < i; j++)
free_frame((void *)(((uint32_t)(start + j)) &
PAGE_MASK));
return NULL;
}
assert((uint32_t)frame & PAGE_MASK);
start[i] = (uint32_t)frame | INIT_FLAGS;
}
uint32_t page_index = start - PTE2VA(1023, 0);
return PTE2VA(page_index / 1024, page_index % 1024);
}
int ufree_pages(void *page_ptr, size_t nb_pages)
{
const uint32_t page_addr = (uint32_t)page_ptr;
if (page_addr % PAGE_SIZE) {
kprintf(KERN_WARNING "Invalid address\n");
return -1;
}
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

@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
if (right) if (right)
right->prev = left; right->prev = left;
unmap: unmap:
err = vfree_pages((void *)zone, zone->size); err = ufree_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);
@ -94,7 +94,7 @@ static int add_available(Block *available, Block *merged)
* newly merged block * newly merged block
* Finally, we add the block to the list of available blocks * Finally, we add the block to the list of available blocks
*/ */
void vfree(void *ptr) void ufree(void *ptr)
{ {
if (ptr == NULL) if (ptr == NULL)
return; return;

View File

@ -33,7 +33,7 @@ static Block *find_block(Zone *head, uint32_t size)
* After the allocation, this will become * After the allocation, this will become
* ... -> [5] -> [new] -> [6] -> ... * ... -> [5] -> [new] -> [6] -> ...
* *
* For an example of [5].size = 32 and requiring a vmalloc of 10 * For an example of [5].size = 32 and requiring a umalloc of 10
* Let's say the metadata takes a size of 2: * Let's say the metadata takes a size of 2:
* ... -> [metadata][data][remaining size] -> [6] * ... -> [metadata][data][remaining size] -> [6]
* ^ ^ ^ * ^ ^ ^
@ -126,12 +126,12 @@ static void save_block(Zone *head, Block *block, Zone *zone)
* *
* ptr: returns the aligned pointer of the block (after the metadata) * ptr: returns the aligned pointer of the block (after the metadata)
*/ */
void *vmalloc(uint32_t size) void *umalloc(uint32_t size)
{ {
void *ptr = NULL; void *ptr = NULL;
if (size == 0) { if (size == 0) {
kprintf(KERN_WARNING "vmalloc: can't vmalloc(0)\n"); kprintf(KERN_WARNING "umalloc: can't umalloc(0)\n");
return NULL; return NULL;
} }

View File

@ -2,9 +2,9 @@
#include "string.h" #include "string.h"
#include <stdint.h> #include <stdint.h>
// Prototype for kfree and vmalloc // Prototype for kfree and umalloc
void kfree(void *ptr); void kfree(void *ptr);
void *vmalloc(uint32_t size); void *umalloc(uint32_t size);
/* /*
* ptr: block to resize (undefined behavior if invalid) * ptr: block to resize (undefined behavior if invalid)
@ -28,10 +28,10 @@ void *vrealloc(void *ptr, uint32_t size)
block->sub_size = size; block->sub_size = size;
return (ptr); return (ptr);
} }
new_ptr = vmalloc(size); new_ptr = umalloc(size);
if (new_ptr == NULL) if (new_ptr == NULL)
return NULL; return NULL;
memmove(new_ptr, ptr, block->size); memmove(new_ptr, ptr, block->size);
vfree(ptr); ufree(ptr);
return (new_ptr); return (new_ptr);
} }

View File

@ -1,90 +0,0 @@
#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 = 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 *)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;
j++)
;
if (j == nb_pages)
return i;
i += j;
}
}
return -1;
}
void *valloc_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,
1024);
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 *)PTE2VA(pd_index, index);
}
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 / 1024;
const uint32_t pt_index = page_index % 1024;
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 > 1024) {
kprintf(KERN_WARNING "Invalid number of frames\n");
return -1;
}
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");
return -2;
}
free_frame((void *)(page_table[i] & PAGE_MASK));
page_table[i] = i << 12;
}
return 0;
}

View File

@ -16,15 +16,15 @@ static void init_mmap(multiboot_info_t *mbd_virt, size_t *pt_index)
{ {
// Index mbd->mmap_addr pointers // Index mbd->mmap_addr pointers
uint32_t i = 0; uint32_t i = 0;
for (; i < mbd_virt->mmap_length; i++) for (; i < CEIL(mbd_virt->mmap_length, PAGE_SIZE); i++)
multiboot_page_table[i + *pt_index] = multiboot_page_table[i + *pt_index] =
((mbd_virt->mmap_addr + i * PAGE_SIZE) & PAGE_MASK) | ((mbd_virt->mmap_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS; INIT_FLAGS;
mmap_addr = mmap_addr =
(multiboot_memory_map_t *)(PTE2VA(PDE_MULTIBOOT, *pt_index) + (multiboot_memory_map_t *)((uint32_t)PTE2VA(PDE_MULTIBOOT, *pt_index) +
(uint32_t)mbd_virt->mmap_addr % (mbd_virt->mmap_addr %
PAGE_SIZE); PAGE_SIZE));
mmap_length = mbd_virt->mmap_length / sizeof(multiboot_memory_map_t); mmap_length = mbd_virt->mmap_length;
*pt_index += i; *pt_index += i;
} }
@ -52,8 +52,7 @@ void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
if (magic != MULTIBOOT_BOOTLOADER_MAGIC) if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
kpanic("invalid magic number! (git gud skill issue)"); kpanic("invalid magic number! (git gud skill issue)");
uint32_t *pd = &boot_page_directory; PD[PDE_MULTIBOOT] =
pd[PDE_MULTIBOOT] =
((uint32_t)multiboot_page_table - VIRT_OFFSET) | INIT_FLAGS; ((uint32_t)multiboot_page_table - VIRT_OFFSET) | INIT_FLAGS;
size_t pt_index = CEIL( size_t pt_index = CEIL(
(uint32_t)mbd % PAGE_SIZE + sizeof(multiboot_info_t), PAGE_SIZE); (uint32_t)mbd % PAGE_SIZE + sizeof(multiboot_info_t), PAGE_SIZE);

View File

@ -4,19 +4,85 @@
#include "string.h" #include "string.h"
#include "thread.h" #include "thread.h"
static struct tcb *thread_clone(struct tcb *thread) static void free_pts(void)
{ {
struct tcb *new_tcb = vmalloc(sizeof(struct tcb)); for (size_t i = USER_PT_END / 2; PD[i]; i++) {
if (!new_tcb) uint32_t *pt = PTE2VA(1023, i);
return NULL; for (size_t j = 0; j < 1024; j++)
new_tcb->tid = thread->tid; if (pt[j])
new_tcb->esp0 = kalloc_pages(STACK_SIZE); ufree_pages(PTE2VA(i, j), 1);
if (!new_tcb->esp0) { ufree_pages(pt, 1);
delete_thread(new_tcb);
return NULL;
} }
memcpy(new_tcb->esp0, thread->esp0, STACK_SIZE); }
return new_tcb;
static int copy_pt(uint32_t *pt_src, uint32_t *pt_dest, size_t pd_index)
{
for (size_t i = 0; i < 1024; i++) {
if (pt_src[i]) {
pt_dest[i] = (uint32_t)alloc_frame() | INIT_FLAGS;
if (pt_dest[i] == INIT_FLAGS) {
for (size_t j = 0; j < i; j++)
free_frame(
(void *)(pt_dest[j] & PAGE_MASK));
return -1;
}
void *src_page = PTE2VA(pd_index, i);
void *dest_page = PTE2VA(pd_index + USER_PT_END / 2, i);
memcpy(dest_page, src_page, PAGE_SIZE);
}
}
return 0;
}
static int copy_thread_list(struct pcb *new_pcb)
{
struct list *e;
struct list *prev = NULL;
for (struct list *it = current_pcb->thread_list; it; it = it->next) {
e = kmalloc(sizeof(struct list));
if (!e)
return -1;
if (prev)
prev->next = e;
else
new_pcb->thread_list = e;
struct tcb *new_content = kmalloc(sizeof(struct tcb));
if (!new_content) {
kfree(e);
return -1;
}
memcpy(new_content, it->content, sizeof(struct tcb));
new_content->process = new_pcb;
e->next = NULL;
e->content = new_content;
prev = e;
}
return 0;
}
static int deep_copy(struct pcb *new_pcb)
{
if (PD[USER_PT_END / 2])
return -2;
size_t i;
for (i = USER_PT_START; PD[i]; i++) {
void *new_pt = alloc_frame();
if (!new_pt) {
free_pts();
return -1;
}
PD[i + USER_PT_END / 2] = (uint32_t)new_pt | INIT_FLAGS;
if (copy_pt(PTE2VA(1023, i), PTE2VA(1023, i + USER_PT_END / 2),
i) < 0) {
free_pts();
return -1;
}
new_pcb->heap[i] = (uint32_t)new_pt | INIT_FLAGS;
}
bzero(PD + USER_PT_END / 2, i * sizeof(uint32_t));
if (copy_thread_list(new_pcb) < 0)
return -1;
return 0;
} }
pid_t fork(void) pid_t fork(void)
@ -24,15 +90,18 @@ pid_t fork(void)
struct pcb *new_pcb = create_process(current_pcb->uid); struct pcb *new_pcb = create_process(current_pcb->uid);
if (!new_pcb) if (!new_pcb)
return -1; return -1;
struct list *new_node = vmalloc(sizeof(struct list)); struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) { if (!new_node) {
remove_process(new_pcb); remove_process(new_pcb);
return -1; return -1;
} }
new_pcb->daddy = current_pcb; new_pcb->daddy = current_pcb;
lst_add_back(&new_pcb->children, new_node); lst_add_back(&current_pcb->children, new_node);
// loop on threads clone
thread_clone(current_pcb->thread_list->content);
return new_pcb->pid; if (deep_copy(new_pcb) < 0) {
remove_process(new_pcb);
return -1;
}
return current_pcb == new_pcb ? 0 : new_pcb->pid;
} }

View File

@ -5,6 +5,7 @@
#include "thread.h" #include "thread.h"
#include "string.h" #include "string.h"
#include <stdint.h>
struct pcb *create_process(uid_t uid) struct pcb *create_process(uid_t uid)
{ {
@ -22,8 +23,10 @@ struct pcb *create_process(uid_t uid)
return NULL; return NULL;
} }
new_pcb->cr3 = new_pcb->cr3 =
(void *)((uint32_t)VA2PTE((uint32_t)new_pcb->heap) & PAGE_MASK); (void *)((uint32_t)*VA2PTE((uint32_t)new_pcb->heap) & PAGE_MASK);
memcpy(new_pcb->heap, PD, 4096); memcpy(new_pcb->heap, PD,
4096); // TODO optimize to copy only used bytes
new_pcb->heap[1023] = (uint32_t)new_pcb->cr3 | INIT_FLAGS;
new_pcb->daddy = NULL; new_pcb->daddy = NULL;
new_pcb->children = NULL; new_pcb->children = NULL;

View File

@ -20,7 +20,8 @@ static struct list *get_thread_to_switch(void)
it_t = current_tcb == NULL ? NULL : current_tcb->next; it_t = current_tcb == NULL ? NULL : current_tcb->next;
while (it_p) { while (it_p) {
while (it_t != NULL) { while (it_t != NULL) {
if (it_t != NULL && CURRENT_TCB->state != WAITING) if (it_t != NULL &&
((struct tcb *)it_t->content)->state != WAITING)
return it_t; return it_t;
it_t = it_t->next; it_t = it_t->next;
} }
@ -38,8 +39,6 @@ void scheduler(uint32_t *esp)
struct tcb *thread_to_switch = (struct tcb *)list_node->content; struct tcb *thread_to_switch = (struct tcb *)list_node->content;
if (current_tcb) if (current_tcb)
CURRENT_TCB->esp = esp; CURRENT_TCB->esp = esp;
if (thread_to_switch->process != current_pcb)
switch_process(thread_to_switch->process);
current_tcb = list_node; current_tcb = list_node;
switch_thread(thread_to_switch->esp); switch_thread(thread_to_switch);
} }

View File

@ -1,16 +0,0 @@
.intel_syntax noprefix
.extern current_pcb
.section .text
.global switch_process
switch_process:
// change current_pcb global
mov eax, [esp + 4]
mov [current_pcb], eax
// reload cr3 with the new heap
mov edx, [eax + 0]
mov cr3, edx
ret

View File

@ -7,8 +7,20 @@
switch_thread: switch_thread:
mov eax, [esp + 4] mov eax, [esp + 4]
mov esp, eax mov esp, [eax]
mov edx, [eax + 16]
cmp [current_pcb], edx
je LABEL1
// change current_pcb
mov [current_pcb], edx
// reload cr3 with the new heap
mov edx, [edx]
mov cr3, edx
LABEL1:
pop eax pop eax
mov ds, eax mov ds, eax

View File

@ -7,6 +7,7 @@
#include "process.h" #include "process.h"
#include "string.h" #include "string.h"
#include "thread.h" #include "thread.h"
#include "utils.h"
struct tcb *create_thread(struct pcb *process, void (*entry)(void)) struct tcb *create_thread(struct pcb *process, void (*entry)(void))
{ {
@ -15,11 +16,15 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
return NULL; return NULL;
new_tcb->tid = process->tid++; new_tcb->tid = process->tid++;
new_tcb->esp0 = valloc_pages(STACK_SIZE, NULL); memcpy(PD, process->heap,
(USER_PT_END - USER_PT_START) * sizeof(uint32_t));
new_tcb->esp0 = ualloc_pages(CEIL(STACK_SIZE, PAGE_SIZE));
if (!new_tcb->esp0) { if (!new_tcb->esp0) {
vfree(new_tcb); ufree(new_tcb);
return NULL; return NULL;
} }
memcpy(process->heap, PD,
(USER_PT_END - USER_PT_START) * sizeof(uint32_t));
uint32_t *stack = (uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE); uint32_t *stack = (uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE);
uint32_t *esp = stack; uint32_t *esp = stack;
@ -49,7 +54,7 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
struct list *new_node = kmalloc(sizeof(struct list)); struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) { if (!new_node) {
kfree_pages(new_tcb->esp0, STACK_SIZE); kfree_pages(new_tcb->esp0, STACK_SIZE);
vfree(new_tcb); ufree(new_tcb);
return NULL; return NULL;
} }
new_node->content = new_tcb; new_node->content = new_tcb;

View File

@ -5,5 +5,5 @@
void heap_cmd(char *arg) void heap_cmd(char *arg)
{ {
(void)arg; (void)arg;
show_valloc_mem(); show_ualloc_mem();
} }