Compare commits
40 Commits
359484b2e4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d828c8067 | |||
| 274113a401 | |||
| 896a0a04f9 | |||
| 5b25422f8d | |||
| afe83d5059 | |||
| dbfa2febec | |||
| cde3702132 | |||
| 6ff044c07a | |||
| 700864cbf2 | |||
| f9cb7a6a8a | |||
| 24dce6e737 | |||
| d46fe337c1 | |||
| 1992d7f79b | |||
| 2308ef509c | |||
| 3df6011d7a | |||
| c6a5bf25c2 | |||
| 9c91830007 | |||
| 3c2c9b0a10 | |||
| 674509a79e | |||
| 99ee5b8cec | |||
| 5591120deb | |||
| 7819b4a02d | |||
| 9b1a0f9f4f | |||
| c33f8fc05d | |||
| c5f8599d90 | |||
| d30e1e4582 | |||
| 9f142941c3 | |||
| a776a45f68 | |||
| 34aa0f0eb4 | |||
| 02d196fab5 | |||
| 2945de2e29 | |||
| f9832ff151 | |||
| e4f5a377a3 | |||
| 0d7db61fb1 | |||
| 9059901f70 | |||
| bf993baa59 | |||
| a3a226ad95 | |||
| d1364f5c1f | |||
| 4bc9dfa589 | |||
| d12371d4a2 |
2
Makefile
2
Makefile
@ -54,7 +54,7 @@ fast-run-iso: fast-iso
|
||||
qemu-system-i386 -cdrom build/$(NAME).iso -vga std
|
||||
|
||||
debug: fast-iso
|
||||
qemu-system-i386 -s -S -cdrom build/$(NAME).iso -vga std -D qemu.log -d in_asm,int -M smm=off
|
||||
qemu-system-i386 -s -S -cdrom build/$(NAME).iso -vga std -M smm=off
|
||||
|
||||
clean:
|
||||
make -C libbozo clean
|
||||
|
||||
@ -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.
|
||||

|
||||
|
||||
### 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|
|
||||
@ -75,10 +75,10 @@ int new_vzone(block_type_t type, size_t size);
|
||||
int new_kzone(block_type_t type, size_t size);
|
||||
/*----------------------------*/
|
||||
|
||||
void *vmalloc(size_t size);
|
||||
void vfree(void *ptr);
|
||||
void *umalloc(size_t size);
|
||||
void ufree(void *ptr);
|
||||
void *vrealloc(void *ptr, size_t size);
|
||||
void show_valloc_mem(void);
|
||||
void show_ualloc_mem(void);
|
||||
size_t vsize(void *virt_addr);
|
||||
void *kmalloc(size_t size);
|
||||
void kfree(void *ptr);
|
||||
|
||||
@ -12,17 +12,38 @@
|
||||
#define ACCESSED (1 << 4)
|
||||
#define INIT_FLAGS (PRESENT | RW | SUPERVISOR)
|
||||
#define PAGE_SIZE 4096
|
||||
#define PT_SIZE 1024
|
||||
#define PD_SIZE 1024
|
||||
#define PD ((uint32_t *)0xFFFFF000)
|
||||
#define VIRT_PT_BASE 0xFFC00000
|
||||
#define VIRT_PD_BASE 0xFFFFF000
|
||||
#define PAGE_MASK 0xFFFFF000
|
||||
#define HEAP_END 0xC0000000
|
||||
#define HEAP_START ((uint32_t)&_kernel_end - HEAP_END)
|
||||
#define VIRT_OFFSET 0xC0000000
|
||||
#define KERNEL_START ((uint32_t)&_kernel_start)
|
||||
#define KERNEL_END ((uint32_t)&_kernel_end - HEAP_END)
|
||||
#define PT_START 256
|
||||
#define KERNEL_END ((uint32_t)&_kernel_end - VIRT_OFFSET)
|
||||
#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) \
|
||||
((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * 4096)
|
||||
#define PDE_VBE 1021
|
||||
#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 SET_FRAME(frame_table, i, used) \
|
||||
@ -46,21 +67,15 @@ extern uint32_t _kernel_end;
|
||||
extern uint32_t _kernel_start;
|
||||
extern uint32_t boot_page_directory;
|
||||
extern uint32_t boot_page_table1;
|
||||
extern uint32_t *kernel_pd;
|
||||
extern uint32_t *current_pd;
|
||||
extern uint32_t page_table_default[1024];
|
||||
extern uint32_t mem_size;
|
||||
extern multiboot_memory_map_t *mmap_addr;
|
||||
extern multiboot_uint32_t mmap_length;
|
||||
extern struct frame_zone *head;
|
||||
|
||||
uint32_t *virt_to_phys(uint32_t *virt_addr);
|
||||
void init_memory(multiboot_info_t *mbd, uint32_t magic);
|
||||
void init_multiboot(multiboot_info_t *mbd, uint32_t magic);
|
||||
void init_memory(void);
|
||||
void *alloc_frame(void);
|
||||
int free_frame(void *frame_ptr);
|
||||
int8_t add_single_page(void *frame);
|
||||
void *alloc_pages(size_t size, void **phys_addr);
|
||||
int free_pages(void *page_ptr, size_t size);
|
||||
void init_page_table(uint32_t page_table[1024], uint16_t start);
|
||||
int16_t add_page_table(uint16_t pd_index);
|
||||
void switch_pd(uint32_t *pd, uint32_t *cr3);
|
||||
void *kalloc_pages(size_t nb_pages);
|
||||
void *ualloc_pages(size_t nb_pages);
|
||||
int kfree_pages(void *page_ptr, size_t nb_pages);
|
||||
int ufree_pages(void *page_ptr, size_t nb_pages);
|
||||
|
||||
@ -1,25 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "list.h"
|
||||
#include "signal.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern struct pcb *current_pcb;
|
||||
|
||||
enum owner { OWNER_KERNEL, OWNER_USER };
|
||||
typedef uint16_t pid_t;
|
||||
typedef uint8_t uid_t;
|
||||
|
||||
struct pcb {
|
||||
void *cr3;
|
||||
uint32_t *heap;
|
||||
uint16_t pid;
|
||||
uint8_t uid;
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
tid_t tid;
|
||||
struct signal_data signals;
|
||||
struct pcb *next;
|
||||
struct pcb *prev;
|
||||
struct tcb *thread_list;
|
||||
struct pcb *daddy;
|
||||
struct list *children;
|
||||
struct list *thread_list;
|
||||
};
|
||||
|
||||
void switch_process(struct pcb *next_pcb);
|
||||
struct pcb *create_process(uint8_t uid);
|
||||
// int8_t create_kernel_process(void);
|
||||
struct pcb *create_process(uid_t uid);
|
||||
void remove_process(struct pcb *pcb);
|
||||
pid_t fork(void);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
void scheduler(void);
|
||||
#include <stdint.h>
|
||||
|
||||
void scheduler(uint32_t *esp);
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "process.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define STACK_SIZE PAGE_SIZE * 4
|
||||
#define CURRENT_TCB ((struct tcb *)current_tcb->content)
|
||||
|
||||
typedef uint16_t tid_t;
|
||||
|
||||
typedef enum {
|
||||
NEW,
|
||||
@ -14,14 +15,13 @@ typedef enum {
|
||||
} state_t;
|
||||
|
||||
struct tcb {
|
||||
uint8_t *esp;
|
||||
uint8_t *esp0;
|
||||
uint16_t tid;
|
||||
uint32_t *esp;
|
||||
uint32_t *esp0;
|
||||
tid_t tid;
|
||||
state_t state;
|
||||
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 switch_thread(struct tcb *thread_to_switch);
|
||||
|
||||
@ -4,3 +4,6 @@ struct list {
|
||||
void *content;
|
||||
struct list *next;
|
||||
};
|
||||
|
||||
struct list *lst_last(struct list *head);
|
||||
void lst_add_back(struct list **head, struct list *e);
|
||||
|
||||
10
libbozo/src/list/lst_add_back.c
Normal file
10
libbozo/src/list/lst_add_back.c
Normal 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;
|
||||
}
|
||||
12
libbozo/src/list/lst_last.c
Normal file
12
libbozo/src/list/lst_last.c
Normal 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;
|
||||
}
|
||||
@ -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 + 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.
|
||||
movl $(boot_page_directory - 0xC0000000), %ecx
|
||||
movl %ecx, %cr3
|
||||
|
||||
@ -38,11 +38,10 @@ void clock_init(struct registers *regs)
|
||||
|
||||
static void clock_handler(struct registers *regs)
|
||||
{
|
||||
(void)regs;
|
||||
if (scheduler_counter % 10 == 0)
|
||||
scheduler();
|
||||
scheduler_counter++;
|
||||
sleep_counter--;
|
||||
if (scheduler_counter % 30 == 0)
|
||||
scheduler((uint32_t *)regs);
|
||||
}
|
||||
|
||||
void sleep(uint64_t delay)
|
||||
|
||||
@ -36,8 +36,6 @@ void isr_handler(struct registers *regs)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
while (i < ARRAY_SIZE(faults)) {
|
||||
if (i == 6)
|
||||
reboot();
|
||||
if (i == regs->int_no)
|
||||
kpanic("interrupt: %s\n", faults[i]);
|
||||
i++;
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
#include "apic.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "interrupts.h"
|
||||
#include "sys/io.h"
|
||||
#include "kprintf.h"
|
||||
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
@ -44,5 +46,5 @@ void init_idt(void)
|
||||
for (uint8_t j = 0; j < 16; j++)
|
||||
idt_set_descriptor(i + j, irq_stub_table[j], 0x8E);
|
||||
load_idt(&idtr);
|
||||
__asm__ volatile("sti");
|
||||
// toris();
|
||||
}
|
||||
|
||||
18
src/kernel.c
18
src/kernel.c
@ -31,6 +31,16 @@
|
||||
#error "This tutorial needs to be compiled with a ix86-elf compiler"
|
||||
#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)
|
||||
{
|
||||
(void)int_code;
|
||||
@ -42,10 +52,14 @@ void kernel_main(multiboot_info_t *mbd, uint32_t magic)
|
||||
cli();
|
||||
init_gdt();
|
||||
init_idt();
|
||||
init_memory(mbd, magic);
|
||||
init_multiboot(mbd, magic);
|
||||
init_memory();
|
||||
load_drivers();
|
||||
terminal_initialize();
|
||||
create_process(1);
|
||||
create_thread(current_pcb, shell_init);
|
||||
// create_thread(current_pcb, shell_init);
|
||||
create_thread(current_pcb, uwu);
|
||||
toris();
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
|
||||
17
src/kpanic.c
17
src/kpanic.c
@ -23,14 +23,17 @@ __attribute__((noreturn)) void kpanic(const char *format, ...)
|
||||
va_end(va);
|
||||
|
||||
uint32_t faulting_address;
|
||||
// __asm__ __volatile__("mov %%cr2, %0" : "=r"(faulting_address));
|
||||
// kprintf("fault at address: %p\n", faulting_address);
|
||||
/* for (int i = 16; i < 32; i++) */
|
||||
/* kprintf("%p\n", page_table1[i]); */
|
||||
// show_valloc_mem();
|
||||
__asm__ __volatile__("mov %%cr2, %0" : "=r"(faulting_address));
|
||||
kprintf("fault at address: %p\n", faulting_address);
|
||||
// for (int i = 16; i < 32; i++)
|
||||
// kprintf("%p\n", page_table1[i]);
|
||||
// show_ualloc_mem();
|
||||
/* kprintf("\n\n"); */
|
||||
/* print_stack(); */
|
||||
/* kprintf("\n\n"); */
|
||||
/* kprintf("PRESS SPACE TO REBOOT"); */
|
||||
__asm__ __volatile__("jmp panic");
|
||||
kprintf("PRESS SPACE TO REBOOT");
|
||||
while (terminal_getkey().c != ' ')
|
||||
;
|
||||
reboot();
|
||||
// __asm__ __volatile__("jmp panic");
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
#include "alloc.h"
|
||||
#include "assert.h"
|
||||
#include "kpanic.h"
|
||||
#include "kprintf.h"
|
||||
#include "memory.h"
|
||||
#include "process.h"
|
||||
#include "string.h"
|
||||
#include "utils.h"
|
||||
|
||||
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)
|
||||
{
|
||||
// assert(current_task->pid);
|
||||
void *heap = alloc_frame();
|
||||
void *heap = kalloc_pages(CEIL(size, PAGE_SIZE));
|
||||
if (heap == NULL) {
|
||||
kprintf(KERN_ERR "error: alloc_frame failed\n");
|
||||
return (-1);
|
||||
}
|
||||
memset(heap, 0, size);
|
||||
|
||||
Zone *zone = (Zone *)heap;
|
||||
zone->type = type;
|
||||
@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
|
||||
if (right)
|
||||
right->prev = left;
|
||||
unmap:
|
||||
err = free_pages((void *)zone, zone->size);
|
||||
err = kfree_pages((void *)zone, zone->size);
|
||||
if (err)
|
||||
kprintf(KERN_ERR "error: munmap failed\n");
|
||||
return (err);
|
||||
62
src/memory/kern/page.c
Normal file
62
src/memory/kern/page.c
Normal 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;
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.text
|
||||
.section .text
|
||||
.global load_page_directory
|
||||
|
||||
load_page_directory:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
@ -1,22 +1,14 @@
|
||||
#include "memory.h"
|
||||
#include "kpanic.h"
|
||||
#include "string.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t *kernel_pd = &boot_page_directory;
|
||||
uint32_t *current_pd;
|
||||
uint32_t page_table_default[1024] __attribute__((aligned(PAGE_SIZE)));
|
||||
uint32_t frame_zones_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
|
||||
uint32_t mem_size;
|
||||
struct frame_zone *head;
|
||||
|
||||
void switch_pd(uint32_t *pd, uint32_t *cr3)
|
||||
{
|
||||
current_pd = pd;
|
||||
asm volatile("mov %0, %%cr3" ::"r"(cr3));
|
||||
}
|
||||
|
||||
static void lst_add_back(struct frame_zone **root, struct frame_zone *element)
|
||||
{
|
||||
if (!*root) {
|
||||
@ -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 uint32_t index;
|
||||
static uint32_t index = 0;
|
||||
|
||||
/**
|
||||
* # = 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);
|
||||
|
||||
init_page_table(frame_zones_page_table, 0);
|
||||
kernel_pd[1022] = ((uint32_t)frame_zones_page_table - HEAP_END) | 0x03;
|
||||
frame_zones_page_table[index] =
|
||||
((uint32_t)start_addr & PAGE_MASK) | INIT_FLAGS;
|
||||
PD[PDE_FRAME_ZONES] =
|
||||
((uint32_t)frame_zones_page_table - VIRT_OFFSET) | 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 *)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->next = NULL;
|
||||
current->remaining_frames = nb_frame;
|
||||
current->total_frames = nb_frame;
|
||||
current->addr = (void *)(uint32_t)start_addr + page_needed * PAGE_SIZE;
|
||||
|
||||
memset(current->frame_table, 0,
|
||||
nb_frame * sizeof(*current->frame_table));
|
||||
bzero(current->frame_table, frame_table_size);
|
||||
|
||||
uint32_t i = 1;
|
||||
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;
|
||||
index += i;
|
||||
lst_add_back(&head, current);
|
||||
}
|
||||
|
||||
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 *)mmap_addr + i;
|
||||
(multiboot_memory_map_t *)((uint32_t)mmap_addr + i);
|
||||
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE)
|
||||
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();
|
||||
// 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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
.intel_syntax noprefix
|
||||
|
||||
.text
|
||||
.section .text
|
||||
.global enable_paging
|
||||
|
||||
enable_paging:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
#include "kpanic.h"
|
||||
#include "kprintf.h"
|
||||
#include "memory.h"
|
||||
#include "process.h"
|
||||
#include "string.h"
|
||||
#include "utils.h"
|
||||
|
||||
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)
|
||||
{
|
||||
// assert(current_task->pid);
|
||||
void *heap = alloc_pages(size, NULL);
|
||||
void *heap = ualloc_pages(CEIL(size, PAGE_SIZE));
|
||||
if (heap == NULL) {
|
||||
kprintf(KERN_ERR "error: alloc_pages failed\n");
|
||||
return (-1);
|
||||
}
|
||||
memset(heap, 0, size);
|
||||
|
||||
Zone *zone = (Zone *)heap;
|
||||
zone->type = type;
|
||||
@ -5,7 +5,7 @@
|
||||
// FULL_INFO is to display (or not) both used and unused blocks
|
||||
#define FULL_INFO 1
|
||||
|
||||
void show_valloc_mem(void)
|
||||
void show_ualloc_mem(void)
|
||||
{
|
||||
char *const zones_name[3] = {"TINY", "SMALL", "LARGE"};
|
||||
uint32_t total_size = 0;
|
||||
77
src/memory/user/page.c
Normal file
77
src/memory/user/page.c
Normal 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;
|
||||
}
|
||||
@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
|
||||
if (right)
|
||||
right->prev = left;
|
||||
unmap:
|
||||
err = free_pages((void *)zone, zone->size);
|
||||
err = ufree_pages((void *)zone, zone->size);
|
||||
if (err)
|
||||
kprintf(KERN_ERR "error: munmap failed\n");
|
||||
return (err);
|
||||
@ -94,7 +94,7 @@ static int add_available(Block *available, Block *merged)
|
||||
* newly merged block
|
||||
* Finally, we add the block to the list of available blocks
|
||||
*/
|
||||
void vfree(void *ptr)
|
||||
void ufree(void *ptr)
|
||||
{
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
@ -33,7 +33,7 @@ static Block *find_block(Zone *head, uint32_t size)
|
||||
* After the allocation, this will become
|
||||
* ... -> [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:
|
||||
* ... -> [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)
|
||||
*/
|
||||
void *vmalloc(uint32_t size)
|
||||
void *umalloc(uint32_t size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
|
||||
if (size == 0) {
|
||||
kprintf(KERN_WARNING "vmalloc: can't vmalloc(0)\n");
|
||||
kprintf(KERN_WARNING "umalloc: can't umalloc(0)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Prototype for kfree and vmalloc
|
||||
// Prototype for kfree and umalloc
|
||||
void kfree(void *ptr);
|
||||
void *vmalloc(uint32_t size);
|
||||
void *umalloc(uint32_t size);
|
||||
|
||||
/*
|
||||
* ptr: block to resize (undefined behavior if invalid)
|
||||
@ -28,10 +28,10 @@ void *vrealloc(void *ptr, uint32_t size)
|
||||
block->sub_size = size;
|
||||
return (ptr);
|
||||
}
|
||||
new_ptr = vmalloc(size);
|
||||
new_ptr = umalloc(size);
|
||||
if (new_ptr == NULL)
|
||||
return NULL;
|
||||
memmove(new_ptr, ptr, block->size);
|
||||
vfree(ptr);
|
||||
ufree(ptr);
|
||||
return (new_ptr);
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "debug.h"
|
||||
#include "kpanic.h"
|
||||
#include "memory.h"
|
||||
#include "multiboot.h"
|
||||
@ -18,14 +16,15 @@ static void init_mmap(multiboot_info_t *mbd_virt, size_t *pt_index)
|
||||
{
|
||||
// Index mbd->mmap_addr pointers
|
||||
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] =
|
||||
((mbd_virt->mmap_addr + i * PAGE_SIZE) & PAGE_MASK) |
|
||||
INIT_FLAGS;
|
||||
mmap_addr = (multiboot_memory_map_t *)(GET_PAGE_ADDR(1023, *pt_index) +
|
||||
(uint32_t)mbd_virt->mmap_addr %
|
||||
PAGE_SIZE);
|
||||
mmap_length = mbd_virt->mmap_length / sizeof(multiboot_memory_map_t);
|
||||
mmap_addr =
|
||||
(multiboot_memory_map_t *)((uint32_t)PTE2VA(PDE_MULTIBOOT, *pt_index) +
|
||||
(mbd_virt->mmap_addr %
|
||||
PAGE_SIZE));
|
||||
mmap_length = mbd_virt->mmap_length;
|
||||
*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) |
|
||||
INIT_FLAGS;
|
||||
}
|
||||
kernel_pd[800] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03;
|
||||
display.buff = (uint32_t *)GET_PAGE_ADDR(800, 0) +
|
||||
uint32_t *pd = &boot_page_directory;
|
||||
pd[PDE_VBE] = ((uint32_t)vbe_page_table - VIRT_OFFSET) | INIT_FLAGS;
|
||||
display.buff = (uint32_t *)PTE2VA(PDE_VBE, 0) +
|
||||
(mbd_virt->framebuffer_addr % PAGE_SIZE);
|
||||
display.height = mbd_virt->framebuffer_height;
|
||||
display.width = mbd_virt->framebuffer_width;
|
||||
@ -50,10 +50,10 @@ static void init_vbe(multiboot_info_t *mbd_virt)
|
||||
void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
|
||||
{
|
||||
if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
|
||||
kpanic("invalid magic number! (git good skill issue)");
|
||||
kpanic("invalid magic number! (git gud skill issue)");
|
||||
|
||||
init_page_table(multiboot_page_table, 0);
|
||||
kernel_pd[1023] = ((uint32_t)multiboot_page_table - HEAP_END) | 0x03;
|
||||
PD[PDE_MULTIBOOT] =
|
||||
((uint32_t)multiboot_page_table - VIRT_OFFSET) | INIT_FLAGS;
|
||||
size_t pt_index = CEIL(
|
||||
(uint32_t)mbd % PAGE_SIZE + sizeof(multiboot_info_t), PAGE_SIZE);
|
||||
|
||||
@ -62,7 +62,7 @@ void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
|
||||
multiboot_page_table[i] =
|
||||
(((uint32_t)mbd + PAGE_SIZE * i) & PAGE_MASK) | INIT_FLAGS;
|
||||
multiboot_info_t *mbd_virt =
|
||||
(multiboot_info_t *)(GET_PAGE_ADDR(1023, 0) +
|
||||
(multiboot_info_t *)(PTE2VA(PDE_MULTIBOOT, 0) +
|
||||
(uint32_t)mbd % PAGE_SIZE);
|
||||
init_mmap(mbd_virt, &pt_index);
|
||||
init_vbe(mbd_virt);
|
||||
|
||||
107
src/multitasking/fork.c
Normal file
107
src/multitasking/fork.c
Normal 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(¤t_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;
|
||||
}
|
||||
@ -5,65 +5,56 @@
|
||||
#include "thread.h"
|
||||
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// int8_t create_kernel_process(void)
|
||||
// {
|
||||
// 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)
|
||||
struct pcb *create_process(uid_t uid)
|
||||
{
|
||||
static uint32_t pid = 1;
|
||||
struct pcb *new_pcb = vmalloc(sizeof(struct pcb));
|
||||
static pid_t pid = 1;
|
||||
struct pcb *new_pcb = kmalloc(sizeof(struct pcb));
|
||||
if (!new_pcb)
|
||||
return NULL;
|
||||
new_pcb->uid = uid;
|
||||
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) {
|
||||
vfree(new_pcb);
|
||||
kfree(new_pcb);
|
||||
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) {
|
||||
new_pcb->next = current_pcb->next;
|
||||
new_pcb->prev = current_pcb;
|
||||
current_pcb->next = new_pcb;
|
||||
if (current_pcb->prev == current_pcb)
|
||||
current_pcb->prev = new_pcb;
|
||||
|
||||
} else {
|
||||
current_pcb = new_pcb;
|
||||
}
|
||||
new_pcb->signals.pending = SIG_IGN;
|
||||
new_pcb->thread_list = NULL;
|
||||
|
||||
return new_pcb;
|
||||
}
|
||||
|
||||
void remove_pcb(struct pcb *pcb)
|
||||
void remove_process(struct pcb *pcb)
|
||||
{
|
||||
struct pcb *left = pcb->prev;
|
||||
struct pcb *right = pcb->next;
|
||||
if (pcb->heap)
|
||||
free_pages(pcb->heap, 4096);
|
||||
kfree_pages(pcb->heap, 4096);
|
||||
left->next = right;
|
||||
right->prev = left;
|
||||
vfree(pcb);
|
||||
kfree(pcb);
|
||||
}
|
||||
|
||||
@ -9,21 +9,36 @@
|
||||
#include <stddef.h>
|
||||
|
||||
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;
|
||||
if (!current_tcb) {
|
||||
thread_to_switch = current_pcb->thread_list;
|
||||
} else {
|
||||
if (!current_tcb->next) {
|
||||
current_pcb = current_pcb->next;
|
||||
// TODO switch context
|
||||
thread_to_switch = current_pcb->thread_list;
|
||||
} else {
|
||||
thread_to_switch = current_tcb->next;
|
||||
struct pcb *it_p;
|
||||
struct list *it_t;
|
||||
|
||||
it_p = current_pcb;
|
||||
it_t = current_tcb == NULL ? NULL : current_tcb->next;
|
||||
while (it_p) {
|
||||
while (it_t != NULL) {
|
||||
if (it_t != NULL &&
|
||||
((struct tcb *)it_t->content)->state != WAITING)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1,31 +1,33 @@
|
||||
.intel_syntax noprefix
|
||||
.set CLEAR_ERRNO_INTNO, 0x08
|
||||
|
||||
.section .text
|
||||
.global 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 [eax+0], esp
|
||||
mov edx, [eax + 16]
|
||||
cmp [current_pcb], edx
|
||||
je LABEL1
|
||||
|
||||
// stack pointer + the 4 regs pushed
|
||||
// and + 1 to get the argument (next thread)
|
||||
mov esi, [esp+(4+1)*4]
|
||||
mov [current_tcb], esi
|
||||
// change current_pcb
|
||||
mov [current_pcb], edx
|
||||
|
||||
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
|
||||
pop edi
|
||||
pop ebp
|
||||
pop ebx
|
||||
popa
|
||||
|
||||
call pic_send_eoi
|
||||
|
||||
add esp, CLEAR_ERRNO_INTNO
|
||||
|
||||
iret
|
||||
|
||||
@ -2,46 +2,84 @@
|
||||
#include "alloc.h"
|
||||
#include "assert.h"
|
||||
#include "interrupts.h"
|
||||
#include "list.h"
|
||||
#include "memory.h"
|
||||
#include "process.h"
|
||||
#include "string.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 = vmalloc(sizeof(struct tcb));
|
||||
struct tcb *new_tcb = kmalloc(sizeof(struct tcb));
|
||||
if (!new_tcb)
|
||||
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) {
|
||||
vfree(new_tcb);
|
||||
ufree(new_tcb);
|
||||
return NULL;
|
||||
}
|
||||
// set esp to "skip" the 4 GPRs and eip later to be used as the context
|
||||
// of the thread
|
||||
new_tcb->esp = new_tcb->esp0 + STACK_SIZE - 5 * 4;
|
||||
memcpy(new_tcb->esp + 4, routine, 4);
|
||||
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 *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->next = NULL;
|
||||
new_tcb->state = NEW;
|
||||
|
||||
struct tcb *it = process->thread_list;
|
||||
while (it)
|
||||
struct list *new_node = kmalloc(sizeof(struct list));
|
||||
if (!new_node) {
|
||||
kfree_pages(new_tcb->esp0, STACK_SIZE);
|
||||
ufree(new_tcb);
|
||||
return NULL;
|
||||
}
|
||||
new_node->content = 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 = new_tcb;
|
||||
it->next = new_node;
|
||||
}
|
||||
|
||||
return new_tcb;
|
||||
}
|
||||
|
||||
void delete_thread(struct tcb *thread)
|
||||
{
|
||||
vfree(thread->esp0);
|
||||
struct tcb *it = thread->process->thread_list;
|
||||
kfree(thread->esp0);
|
||||
struct list *it = thread->process->thread_list;
|
||||
assert(it);
|
||||
while (it->next != thread)
|
||||
while (it->next && it->next->content != thread)
|
||||
it = it->next;
|
||||
struct list *to_free = it;
|
||||
it->next = it->next->next;
|
||||
vfree(thread);
|
||||
kfree(to_free);
|
||||
kfree(thread);
|
||||
}
|
||||
|
||||
@ -5,5 +5,5 @@
|
||||
void heap_cmd(char *arg)
|
||||
{
|
||||
(void)arg;
|
||||
show_valloc_mem();
|
||||
show_ualloc_mem();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user