Compare commits

...

37 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
7819b4a02d fix: same thing for alloc_frames 2025-11-28 11:14:04 +01:00
9b1a0f9f4f fix: multiboot using unmapped pd 2025-11-28 11:12:14 +01:00
c33f8fc05d wip: change memory to use recursive paging 2025-11-28 11:08:28 +01:00
c5f8599d90 wip: kernel and virt allocator 2025-11-13 12:09:36 +01:00
d30e1e4582 Update documentation/memory.md 2025-11-13 04:54:35 -05:00
9f142941c3 wip: separate allocators into a kernel one and a user one 2025-11-12 16:04:16 +01:00
a776a45f68 add: documentation on the pde 2025-11-12 16:29:19 +01:00
34aa0f0eb4 wip: fork() 2025-11-12 15:07:36 +01:00
02d196fab5 core: remove unused function 2025-11-12 15:07:14 +01:00
2945de2e29 fix: create process copy kernel heap 2025-11-11 18:56:12 +01:00
f9832ff151 wip: context switch when switching to another process 2025-11-11 17:31:08 +01:00
e4f5a377a3 fix: multitasking now works with correct timer 2025-11-11 14:00:30 +01:00
0d7db61fb1 fix: clock_handler use pass right esp to the scheduler 2025-11-11 14:41:08 +01:00
9059901f70 wip: better way of handling thread switch (iret in the switch) 2025-11-11 11:13:35 +01:00
bf993baa59 wip: uncrampt the stack thing in the irq 2025-11-07 16:58:11 +01:00
a3a226ad95 fix: thread switch gets back into the isr routine but iret does not return to the correct frame 2025-11-07 16:23:30 +01:00
42 changed files with 614 additions and 370 deletions

View File

@ -54,7 +54,7 @@ fast-run-iso: fast-iso
qemu-system-i386 -cdrom build/$(NAME).iso -vga std qemu-system-i386 -cdrom build/$(NAME).iso -vga std
debug: fast-iso 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 -M smm=off
clean: clean:
make -C libbozo clean make -C libbozo clean

View File

@ -8,3 +8,16 @@ To activate pagination you must put the physic [pd](./memory/page_directory.md)
Cause create all [pt](./memory/page_table.md) will cost 3MB (768 * 1024 * 4, 768: cause is our heap limite, 1024: cause each pt contains 1024 entry and 4: cause size of pte is 4byte) we decided to create it on the heap and dynamically. So the first pt of the pd (pd[0]) will contain a default_page_table (or heap_pt). Each page create by each the heap_pt will be a pt added to the pd. Cause create all [pt](./memory/page_table.md) will cost 3MB (768 * 1024 * 4, 768: cause is our heap limite, 1024: cause each pt contains 1024 entry and 4: cause size of pte is 4byte) we decided to create it on the heap and dynamically. So the first pt of the pd (pd[0]) will contain a default_page_table (or heap_pt). Each page create by each the heap_pt will be a pt added to the pd.
![](./assets/memory/heap_map.webp) ![](./assets/memory/heap_map.webp)
### Page Directory
|Name|Addresss|
|----|--------|
|0|left empty so read or write on NULL triggers an interrupt|
|1-767|user process allocations|
|768|kernel code and stack|
|769-1019|kernel allocations|
|1020|page for page allocations|
|1021|VBE screen|
|1022|frame allocator variables|
|1023|multiboot|

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

@ -12,17 +12,38 @@
#define ACCESSED (1 << 4) #define ACCESSED (1 << 4)
#define INIT_FLAGS (PRESENT | RW | SUPERVISOR) #define INIT_FLAGS (PRESENT | RW | SUPERVISOR)
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096
#define PT_SIZE 1024 #define PD ((uint32_t *)0xFFFFF000)
#define PD_SIZE 1024 #define VIRT_PT_BASE 0xFFC00000
#define VIRT_PD_BASE 0xFFFFF000
#define PAGE_MASK 0xFFFFF000 #define PAGE_MASK 0xFFFFF000
#define HEAP_END 0xC0000000 #define VIRT_OFFSET 0xC0000000
#define HEAP_START ((uint32_t)&_kernel_end - HEAP_END)
#define KERNEL_START ((uint32_t)&_kernel_start) #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 PT_START 256 #define KERNEL_PT_END 1020
#define KERNEL_PT_START 769
#define USER_PT_START 1
#define USER_PT_END 768
#define GET_PAGE_ADDR(pd_index, pt_index) \ #define PDE_VBE 1021
((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * 4096) #define PDE_FRAME_ZONES 1022
#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) \
((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 GET_FRAME(frame_table, i) (frame_table[i / 8] & (1 << (i % 8)))
#define SET_FRAME(frame_table, i, used) \ #define SET_FRAME(frame_table, i, used) \
@ -46,21 +67,15 @@ extern uint32_t _kernel_end;
extern uint32_t _kernel_start; extern uint32_t _kernel_start;
extern uint32_t boot_page_directory; extern uint32_t boot_page_directory;
extern uint32_t boot_page_table1; 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_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;
uint32_t *virt_to_phys(uint32_t *virt_addr); void init_multiboot(multiboot_info_t *mbd, uint32_t magic);
void init_memory(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);
int8_t add_single_page(void *frame); void *kalloc_pages(size_t nb_pages);
void *alloc_pages(size_t size, void **phys_addr); void *ualloc_pages(size_t nb_pages);
int free_pages(void *page_ptr, size_t size); int kfree_pages(void *page_ptr, size_t nb_pages);
void init_page_table(uint32_t page_table[1024], uint16_t start); int ufree_pages(void *page_ptr, size_t nb_pages);
int16_t add_page_table(uint16_t pd_index);
void switch_pd(uint32_t *pd, uint32_t *cr3);

View File

@ -1,25 +1,32 @@
#pragma once #pragma once
#include "list.h"
#include "signal.h" #include "signal.h"
#include "thread.h"
#include <stdint.h> #include <stdint.h>
extern struct pcb *current_pcb; extern struct pcb *current_pcb;
enum owner { OWNER_KERNEL, OWNER_USER }; enum owner { OWNER_KERNEL, OWNER_USER };
typedef uint16_t pid_t;
typedef uint8_t uid_t;
struct pcb { struct pcb {
void *cr3; void *cr3;
uint32_t *heap; uint32_t *heap;
uint16_t pid; pid_t pid;
uint8_t uid; uid_t uid;
tid_t tid;
struct signal_data signals; struct signal_data signals;
struct pcb *next; struct pcb *next;
struct pcb *prev; struct pcb *prev;
struct tcb *thread_list; struct pcb *daddy;
struct list *children;
struct list *thread_list;
}; };
void switch_process(struct pcb *next_pcb); void switch_process(struct pcb *next_pcb);
struct pcb *create_process(uint8_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

@ -1,3 +1,5 @@
#pragma once #pragma once
void scheduler(void); #include <stdint.h>
void scheduler(uint32_t *esp);

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "process.h"
#include <stdint.h> #include <stdint.h>
#define STACK_SIZE PAGE_SIZE * 4 #define STACK_SIZE PAGE_SIZE * 4
#define CURRENT_TCB ((struct tcb *)current_tcb->content)
typedef uint16_t tid_t;
typedef enum { typedef enum {
NEW, NEW,
@ -14,14 +15,13 @@ typedef enum {
} state_t; } state_t;
struct tcb { struct tcb {
uint8_t *esp; uint32_t *esp;
uint8_t *esp0; uint32_t *esp0;
uint16_t tid; tid_t tid;
state_t state; state_t state;
struct pcb *process; struct pcb *process;
struct tcb *next;
}; };
struct tcb *create_thread(struct pcb *process, void (*routine)(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(struct tcb *thread_to_switch); void switch_thread(struct tcb *thread_to_switch);

View File

@ -4,3 +4,6 @@ struct list {
void *content; void *content;
struct list *next; struct list *next;
}; };
struct list *lst_last(struct list *head);
void lst_add_back(struct list **head, struct list *e);

View File

@ -0,0 +1,10 @@
#include "list.h"
void lst_add_back(struct list **head, struct list *e)
{
struct list *last = lst_last(*head);
if (!last)
*head = e;
else
last->next = e;
}

View File

@ -0,0 +1,12 @@
#include "list.h"
#include <stddef.h>
struct list *lst_last(struct list *head)
{
if (!head)
return NULL;
struct list *it = head;
while (it->next)
it = it->next;
return it;
}

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

@ -38,11 +38,10 @@ void clock_init(struct registers *regs)
static void clock_handler(struct registers *regs) static void clock_handler(struct registers *regs)
{ {
(void)regs;
if (scheduler_counter % 10 == 0)
scheduler();
scheduler_counter++; scheduler_counter++;
sleep_counter--; sleep_counter--;
if (scheduler_counter % 30 == 0)
scheduler((uint32_t *)regs);
} }
void sleep(uint64_t delay) void sleep(uint64_t delay)

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

@ -31,6 +31,16 @@
#error "This tutorial needs to be compiled with a ix86-elf compiler" #error "This tutorial needs to be compiled with a ix86-elf compiler"
#endif #endif
static void uwu(void)
{
pid_t pid = fork();
kprintf("pid: %d\n", pid);
while (1) {
// sleep(1000);
// kprintf("%d\n", current_pcb->pid);
}
}
static void bozo(int int_code) static void bozo(int int_code)
{ {
(void)int_code; (void)int_code;
@ -42,11 +52,14 @@ 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_thread(current_pcb, uwu);
toris(); toris();
while (true); while (true)
;
} }

View File

@ -23,14 +23,17 @@ __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_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

@ -1,9 +1,9 @@
#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"
#include "utils.h"
Zone *kzones[3]; Zone *kzones[3];
@ -50,11 +50,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(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);
} }
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);

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

@ -0,0 +1,62 @@
#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 uint32_t *find_next_block(size_t nb_pages)
{
uint32_t count = 0;
for (uint32_t *pte = PTE2VA(1023, KERNEL_PT_START);
pte < PTE2VA(1023, KERNEL_PT_END); pte++) {
if (*pte) {
count = 0;
continue;
}
count++;
if (count == nb_pages)
return pte - (count - 1);
}
return NULL;
}
void *kalloc_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 kfree_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

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

@ -1,22 +1,14 @@
#include "memory.h" #include "memory.h"
#include "kpanic.h"
#include "string.h" #include "string.h"
#include "utils.h" #include "utils.h"
#include <stdint.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 frame_zones_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
uint32_t mem_size; uint32_t mem_size;
struct frame_zone *head; 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) static void lst_add_back(struct frame_zone **root, struct frame_zone *element)
{ {
if (!*root) { if (!*root) {
@ -31,7 +23,7 @@ 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;
/** /**
* # = kernel code * # = kernel code
@ -67,57 +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);
init_page_table(frame_zones_page_table, 0); PD[PDE_FRAME_ZONES] =
kernel_pd[1022] = ((uint32_t)frame_zones_page_table - HEAP_END) | 0x03; ((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 *)GET_PAGE_ADDR(1022, 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()
{ {
for (uint16_t i = 0; i < 0x300; i++)
kernel_pd[i] = 0x02;
init_page_table(page_table_default, 0);
kernel_pd[0] = ((uint32_t)page_table_default - HEAP_END) | 0x03;
current_pd = kernel_pd;
init_multiboot(mbd, magic);
init_frame_zones(); 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 | INIT_FLAGS;
bzero(PTE2VA(1023, i), PAGE_SIZE);
}
// kalash kalash kalash sur la mélodie chez nous pas de félonie ça vient
// de Sevran les R
} }

View File

@ -1,107 +0,0 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "assert.h"
#include "kprintf.h"
#include "memory.h"
#include "string.h"
#include "process.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 = 1; *pd_index_ptr < 768; (*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(0, *pd_index_ptr + PT_START);
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;
}
int8_t add_single_page(void *frame)
{
uint16_t pd_index;
uint32_t *page_table;
const int16_t i = find_next_block(1, &pd_index, &page_table);
if (i < 0) {
kprintf(KERN_CRIT "impossible to add page to page directory\n");
return -1;
}
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
return 0;
}
void *alloc_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;
}
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)
{
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,22 +0,0 @@
#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++)
page_table[i] = (i << 12) | 0x03;
}
int16_t add_page_table(uint16_t pd_index)
{
void *frame = alloc_frame();
if (!frame)
return -1;
page_table_default[PT_START + pd_index] =
((uint32_t)frame & PAGE_MASK) | 0x03;
uint32_t *page_table =
(uint32_t *)GET_PAGE_ADDR(0, PT_START + pd_index);
init_page_table(page_table, 0);
kernel_pd[pd_index] = ((uint32_t)frame & PAGE_MASK) | 0x03;
return 0;
}

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,8 @@
#include "kpanic.h" #include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "process.h" #include "string.h"
#include "utils.h"
Zone *vzones[3]; Zone *vzones[3];
@ -50,11 +51,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 = 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);
} }
memset(heap, 0, size);
Zone *zone = (Zone *)heap; Zone *zone = (Zone *)heap;
zone->type = type; zone->type = type;

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 = free_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,8 +1,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "commands.h"
#include "debug.h"
#include "kpanic.h" #include "kpanic.h"
#include "memory.h" #include "memory.h"
#include "multiboot.h" #include "multiboot.h"
@ -18,14 +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 = (multiboot_memory_map_t *)(GET_PAGE_ADDR(1023, *pt_index) + mmap_addr =
(uint32_t)mbd_virt->mmap_addr % (multiboot_memory_map_t *)((uint32_t)PTE2VA(PDE_MULTIBOOT, *pt_index) +
PAGE_SIZE); (mbd_virt->mmap_addr %
mmap_length = mbd_virt->mmap_length / sizeof(multiboot_memory_map_t); PAGE_SIZE));
mmap_length = mbd_virt->mmap_length;
*pt_index += i; *pt_index += i;
} }
@ -38,8 +37,9 @@ 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; uint32_t *pd = &boot_page_directory;
display.buff = (uint32_t *)GET_PAGE_ADDR(800, 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); (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;
@ -50,10 +50,10 @@ static void init_vbe(multiboot_info_t *mbd_virt)
void init_multiboot(multiboot_info_t *mbd, uint32_t magic) 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 good skill issue)"); kpanic("invalid magic number! (git gud skill issue)");
init_page_table(multiboot_page_table, 0); PD[PDE_MULTIBOOT] =
kernel_pd[1023] = ((uint32_t)multiboot_page_table - HEAP_END) | 0x03; ((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);
@ -62,7 +62,7 @@ void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
multiboot_page_table[i] = multiboot_page_table[i] =
(((uint32_t)mbd + PAGE_SIZE * i) & PAGE_MASK) | INIT_FLAGS; (((uint32_t)mbd + PAGE_SIZE * i) & PAGE_MASK) | INIT_FLAGS;
multiboot_info_t *mbd_virt = 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); (uint32_t)mbd % PAGE_SIZE);
init_mmap(mbd_virt, &pt_index); init_mmap(mbd_virt, &pt_index);
init_vbe(mbd_virt); init_vbe(mbd_virt);

107
src/multitasking/fork.c Normal file
View File

@ -0,0 +1,107 @@
#include "alloc.h"
#include "memory.h"
#include "process.h"
#include "string.h"
#include "thread.h"
static void free_pts(void)
{
for (size_t i = USER_PT_END / 2; PD[i]; i++) {
uint32_t *pt = PTE2VA(1023, i);
for (size_t j = 0; j < 1024; j++)
if (pt[j])
ufree_pages(PTE2VA(i, j), 1);
ufree_pages(pt, 1);
}
}
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)
{
struct pcb *new_pcb = create_process(current_pcb->uid);
if (!new_pcb)
return -1;
struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) {
remove_process(new_pcb);
return -1;
}
new_pcb->daddy = current_pcb;
lst_add_back(&current_pcb->children, new_node);
if (deep_copy(new_pcb) < 0) {
remove_process(new_pcb);
return -1;
}
return current_pcb == new_pcb ? 0 : new_pcb->pid;
}

View File

@ -5,47 +5,33 @@
#include "thread.h" #include "thread.h"
#include "string.h" #include "string.h"
#include <stdint.h>
// int8_t create_kernel_process(void) struct pcb *create_process(uid_t uid)
// {
// struct pcb *new_pcb = vmalloc(sizeof(struct pcb));
// if (!new_pcb)
// return -1;
// new_pcb->pid = 0;
// new_pcb->uid = 0;
// new_pcb->heap = kernel_pd;
// new_pcb->cr3 = (uint32_t *)((uint32_t)kernel_pd - HEAP_END);
// new_pcb->next = new_pcb;
// new_pcb->prev = new_pcb;
// struct tcb *kern_thread = vmalloc(sizeof(struct tcb));
// if (!kern_thread) {
// vfree(new_pcb);
// return -1;
// }
// kern_thread->esp = ;
// kern_thread->next = NULL;
// kern_thread->process = new_pcb;
// kern_thread->state = RUNNING;
// kern_thread->tid = 1;
// return 0;
// }
struct pcb *create_process(uint8_t uid)
{ {
static uint32_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->heap = alloc_pages(4096, &new_pcb->cr3); new_pcb->heap = kalloc_pages(4096);
if (!new_pcb->heap) { if (!new_pcb->heap) {
vfree(new_pcb); kfree(new_pcb);
return NULL; return NULL;
} }
memcpy(new_pcb->heap, current_pcb->heap, 4096); new_pcb->cr3 =
(void *)((uint32_t)*VA2PTE((uint32_t)new_pcb->heap) & PAGE_MASK);
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->children = NULL;
new_pcb->next = new_pcb;
new_pcb->prev = new_pcb;
if (current_pcb) { if (current_pcb) {
new_pcb->next = current_pcb->next; new_pcb->next = current_pcb->next;
@ -53,8 +39,7 @@ struct pcb *create_process(uint8_t uid)
current_pcb->next = new_pcb; current_pcb->next = new_pcb;
if (current_pcb->prev == current_pcb) if (current_pcb->prev == current_pcb)
current_pcb->prev = new_pcb; current_pcb->prev = new_pcb;
} } else {
else {
current_pcb = new_pcb; current_pcb = new_pcb;
} }
new_pcb->signals.pending = SIG_IGN; new_pcb->signals.pending = SIG_IGN;
@ -63,13 +48,13 @@ struct pcb *create_process(uint8_t uid)
return new_pcb; return new_pcb;
} }
void remove_pcb(struct pcb *pcb) 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

@ -9,21 +9,36 @@
#include <stddef.h> #include <stddef.h>
struct pcb *current_pcb; struct pcb *current_pcb;
struct tcb *current_tcb; struct list *current_tcb;
void scheduler(void) static struct list *get_thread_to_switch(void)
{ {
struct tcb *thread_to_switch; struct pcb *it_p;
if (!current_tcb) { struct list *it_t;
thread_to_switch = current_pcb->thread_list;
} else { it_p = current_pcb;
if (!current_tcb->next) { it_t = current_tcb == NULL ? NULL : current_tcb->next;
current_pcb = current_pcb->next; while (it_p) {
// TODO switch context while (it_t != NULL) {
thread_to_switch = current_pcb->thread_list; if (it_t != NULL &&
} else { ((struct tcb *)it_t->content)->state != WAITING)
thread_to_switch = current_tcb->next; return it_t;
it_t = it_t->next;
} }
it_p = it_p->next;
it_t = it_p->thread_list;
} }
return NULL;
}
void scheduler(uint32_t *esp)
{
struct list *list_node = get_thread_to_switch();
if (!list_node)
kpanic("No existing threads \n");
struct tcb *thread_to_switch = (struct tcb *)list_node->content;
if (current_tcb)
CURRENT_TCB->esp = esp;
current_tcb = list_node;
switch_thread(thread_to_switch); switch_thread(thread_to_switch);
} }

View File

@ -1,31 +1,33 @@
.intel_syntax noprefix .intel_syntax noprefix
.set CLEAR_ERRNO_INTNO, 0x08
.section .text .section .text
.global switch_thread .global switch_thread
switch_thread: switch_thread:
push ebx
push ebp
push edi
push esi
mov eax, [current_tcb] mov eax, [esp + 4]
mov esp, [eax]
// save the current stack pointer to the old stack mov edx, [eax + 16]
mov [eax+0], esp cmp [current_pcb], edx
je LABEL1
// stack pointer + the 4 regs pushed // change current_pcb
// and + 1 to get the argument (next thread) mov [current_pcb], edx
mov esi, [esp+(4+1)*4]
mov [current_tcb], esi
mov eax, [current_tcb] // reload cr3 with the new heap
mov edx, [edx]
mov cr3, edx
mov esp, [eax+0] // get esp LABEL1:
pop eax
mov ds, eax
pop esi popa
pop edi
pop ebp call pic_send_eoi
pop ebx
add esp, CLEAR_ERRNO_INTNO
iret iret

View File

@ -2,39 +2,70 @@
#include "alloc.h" #include "alloc.h"
#include "assert.h" #include "assert.h"
#include "interrupts.h" #include "interrupts.h"
#include "list.h"
#include "memory.h" #include "memory.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 (*routine)(void)) struct tcb *create_thread(struct pcb *process, void (*entry)(void))
{ {
static uint32_t tid = 1; struct tcb *new_tcb = kmalloc(sizeof(struct tcb));
struct tcb *new_tcb = vmalloc(sizeof(struct tcb));
if (!new_tcb) if (!new_tcb)
return NULL; return NULL;
new_tcb->tid = tid++; new_tcb->tid = process->tid++;
new_tcb->esp0 = alloc_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;
} }
// set esp to "skip" the 4 GPRs and eip later to be used as the context memcpy(process->heap, PD,
// of the thread (USER_PT_END - USER_PT_START) * sizeof(uint32_t));
new_tcb->esp = new_tcb->esp0 + STACK_SIZE - 5 * 4; uint32_t *stack = (uint32_t *)((uint8_t *)new_tcb->esp0 + STACK_SIZE);
memcpy(new_tcb->esp + 4, routine, 4); uint32_t *esp = stack;
// testing out some stuff
*(--stack) = 0x202; // EFLAGS
*(--stack) = 0x08; // CS = kernel code segment
*(--stack) = (uint32_t)entry;
// Error code and interrupt number (skipped by add $8, %esp)
*(--stack) = 0; // err_code
*(--stack) = 0; // int_no
// General purpose registers (for popa)
*(--stack) = 0; // EAX
*(--stack) = 0; // ECX
*(--stack) = 0; // EDX
*(--stack) = 0; // EBX
*(--stack) = (uint32_t)esp; // ESP (original - points to exit_process)
*(--stack) = 0; // EBP
*(--stack) = 0; // ESI
*(--stack) = 0; // EDI
*(--stack) = 0x10; // kernel DS
new_tcb->esp = stack;
new_tcb->process = process; new_tcb->process = process;
new_tcb->next = NULL;
new_tcb->state = NEW; new_tcb->state = NEW;
struct tcb *it = process->thread_list; struct list *new_node = kmalloc(sizeof(struct list));
if (it) { if (!new_node) {
while (it) kfree_pages(new_tcb->esp0, STACK_SIZE);
it = it->next; ufree(new_tcb);
it = new_tcb; return NULL;
} }
else { new_node->content = new_tcb;
process->thread_list = new_tcb; new_node->next = NULL;
if (process->thread_list == NULL) {
process->thread_list = new_node;
} else {
struct list *it = process->thread_list;
while (it->next)
it = it->next;
it->next = new_node;
} }
return new_tcb; return new_tcb;
@ -42,11 +73,13 @@ struct tcb *create_thread(struct pcb *process, void (*routine)(void))
void delete_thread(struct tcb *thread) void delete_thread(struct tcb *thread)
{ {
vfree(thread->esp0); kfree(thread->esp0);
struct tcb *it = thread->process->thread_list; struct list *it = thread->process->thread_list;
assert(it); assert(it);
while (it->next != thread) while (it->next && it->next->content != thread)
it = it->next; it = it->next;
struct list *to_free = it;
it->next = it->next->next; it->next = it->next->next;
vfree(thread); kfree(to_free);
kfree(thread);
} }

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();
} }