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

@ -6,23 +6,44 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define PRESENT (1 << 0) #define PRESENT (1 << 0)
#define RW (1 << 1) #define RW (1 << 1)
#define SUPERVISOR (0 << 2) #define SUPERVISOR (0 << 2)
#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 PAGE_MASK 0xFFFFF000 #define VIRT_PD_BASE 0xFFFFF000
#define HEAP_END 0xC0000000 #define PAGE_MASK 0xFFFFF000
#define HEAP_START ((uint32_t)&_kernel_end - HEAP_END) #define VIRT_OFFSET 0xC0000000
#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,12 +1,13 @@
.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
mov eax, [esp + 8] mov eax, [esp + 8]
mov cr3, eax mov cr3, eax
mov esp, ebp mov esp, ebp
pop ebp pop ebp
ret ret

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,13 +1,14 @@
.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
mov eax, cr0 mov eax, cr0
or eax, 0x80000000 or eax, 0x80000000
mov cr0, eax mov cr0, eax
mov esp, ebp mov esp, ebp
pop ebp pop ebp
ret ret

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