Compare commits

..

19 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
26 changed files with 280 additions and 200 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

@ -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

@ -21,7 +21,6 @@ static void lst_add_back(struct frame_zone **root, struct frame_zone *element)
it->next = element; it->next = 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 = 0; static uint32_t index = 0;
@ -64,27 +63,34 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
((uint32_t)frame_zones_page_table - VIRT_OFFSET) | INIT_FLAGS; ((uint32_t)frame_zones_page_table - VIRT_OFFSET) | INIT_FLAGS;
/** We need to determine how many frames are available /** We need to determine how many frames are available
to save how many frame the blocks contain etc we need some meta data to save how many frame the blocks contain etc we need some meta
1 struct frame_zone and a frame_table, the size of the frame_table is 1 bit per frame data 1 struct frame_zone and a frame_table, the size of the
the frame_table is a uint8_t so 8 bit, so its size must be CEIL(max_frames, 8) frame_table is 1 bit per frame the frame_table is a uint8_t so 8 bit,
But we don't have max_frames. 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) We can determine max_frame = (block_len - sizeof(struct
Because we don't use float we can't have 1 / 8 frame_zone)) / (PAGE_SIZE + 1 / 8) (1 / 8 because size is in byte but
So we will multiplicate every members of this equation by 8 to have only complet number we only need one bit) Because we don't use float we can't have 1 / 8
So... max_frame = (block_len - sizeof(struct frame_zone)) * 8 / (PAGE_SIZE * 8 + 1) 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 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)); 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 page_needed =
CEIL(frame_table_size + sizeof(struct frame_zone), PAGE_SIZE);
uint32_t i = 0; uint32_t i = 0;
for (; i < page_needed; i++) for (; i < page_needed; i++)
frame_zones_page_table[index + i] = (((uint32_t)start_addr + i * PAGE_SIZE) & PAGE_MASK) | INIT_FLAGS; 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*) ((uint32_t) current + sizeof(struct frame_zone)); current->frame_table =
(uint8_t *)((uint32_t)current + sizeof(struct frame_zone));
current->first_free_frame = 0; current->first_free_frame = 0;
current->next = NULL; current->next = NULL;
@ -98,15 +104,12 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
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; for (uint32_t i = 0; i < mmap_length;
i += sizeof(multiboot_memory_map_t)) i += sizeof(multiboot_memory_map_t)) {
{
multiboot_memory_map_t *mmmt = multiboot_memory_map_t *mmmt =
(multiboot_memory_map_t *)((uint32_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);
} }
@ -120,7 +123,8 @@ void init_memory()
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);
} }
// 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();
} }