diff options
author | Marvin Borner | 2020-01-26 18:38:36 +0100 |
---|---|---|
committer | Marvin Borner | 2020-01-26 18:38:36 +0100 |
commit | bb2a6b4d93512e8afc1b1999eb58f1f506cc27ae (patch) | |
tree | ea30b53ac6043faddd1cdb2fdea17f37178b1cc7 /src/kernel/tasks | |
parent | b8630d78a15a69f50dac747e41e84b143dd99b08 (diff) |
Magic commit
Some things work, others don't.
Diffstat (limited to 'src/kernel/tasks')
-rw-r--r-- | src/kernel/tasks/process.asm | 48 | ||||
-rw-r--r-- | src/kernel/tasks/task.c | 168 | ||||
-rw-r--r-- | src/kernel/tasks/task.h | 30 |
3 files changed, 246 insertions, 0 deletions
diff --git a/src/kernel/tasks/process.asm b/src/kernel/tasks/process.asm new file mode 100644 index 0000000..a46ac3d --- /dev/null +++ b/src/kernel/tasks/process.asm @@ -0,0 +1,48 @@ +[GLOBAL read_eip] +read_eip: + pop eax + jmp eax + +[GLOBAL copy_page_physical] +copy_page_physical: + push ebx + pushf + + cli + + mov ebx, [esp+12] + mov ecx, [esp+16] + + mov edx, cr0 + and edx, 0x7fffffff + mov cr0, edx + + mov edx, 1024 + +.loop: + mov eax, [ebx] + mov [ecx], eax + add ebx, 4 + add ecx, 4 + dec edx + jnz .loop + + mov edx, cr0 + or edx, 0x80000000 + mov cr0, edx + + popf + pop ebx + ret + +[GLOBAL perform_task_switch] +perform_task_switch: + cli + mov ecx, [esp+4] + mov eax, [esp+8] + mov ebp, [esp+12] + mov esp, [esp+16] + mov cr3, eax + mov eax, 0x12345 + sti + jmp ecx
\ No newline at end of file diff --git a/src/kernel/tasks/task.c b/src/kernel/tasks/task.c new file mode 100644 index 0000000..e6caf9a --- /dev/null +++ b/src/kernel/tasks/task.c @@ -0,0 +1,168 @@ +#include <kernel/memory/paging.h> +#include <kernel/tasks/task.h> +#include <kernel/memory/kheap.h> +#include <kernel/lib/lib.h> +#include <kernel/gdt/gdt.h> +#include <kernel/system.h> + +volatile task_t *current_task; +volatile task_t *ready_queue; + +extern page_directory_t *kernel_directory; +extern page_directory_t *current_directory; + +extern uint32_t read_eip(); + +uint32_t next_pid = 1; + +void tasking_install() +{ + asm ("cli"); + move_stack((void *) 0xE0000000, 0x2000); + + current_task = ready_queue = (task_t *) kmalloc(sizeof(task_t)); + current_task->id = (int) next_pid++; + current_task->esp = current_task->ebp = 0; + current_task->eip = 0; + current_task->page_directory = current_directory; + current_task->next = 0; + current_task->kernel_stack = kmalloc_a(KERNEL_STACK_SIZE); + + vga_log("Installed Tasking"); + asm ("sti"); +} + +void move_stack(void *new_stack_start, uint32_t size) +{ + for (uint32_t i = (uint32_t) new_stack_start; + i >= ((uint32_t) new_stack_start - size); + i -= 0x1000) { + paging_alloc_frame(paging_get_page(i, 1, current_directory), 0, 1); + } + + uint32_t pd_addr; + asm volatile ("mov %%cr3, %0" : "=r" (pd_addr)); + asm volatile ("mov %0, %%cr3" : : "r" (pd_addr)); + + uint32_t old_stack_pointer; asm volatile ("mov %%esp, %0" : "=r" (old_stack_pointer)); + uint32_t old_base_pointer; asm volatile ("mov %%ebp, %0" : "=r" (old_base_pointer)); + + uint32_t offset = (uint32_t) new_stack_start - initial_esp; + + uint32_t new_stack_pointer = old_stack_pointer + offset; + uint32_t new_base_pointer = old_base_pointer + offset; + + memcpy((void *) new_stack_pointer, (void *) old_stack_pointer, initial_esp - old_stack_pointer); + + for (uint32_t i = (uint32_t) new_stack_start; i > (uint32_t) new_stack_start - size; i -= 4) { + uint32_t tmp = *(uint32_t *) i; + if ((old_stack_pointer < tmp) && (tmp < initial_esp)) { + tmp = tmp + offset; + uint32_t *tmp2 = (uint32_t *) i; + *tmp2 = tmp; + } + } + + asm volatile ("mov %0, %%esp" : : "r" (new_stack_pointer)); + asm volatile ("mov %0, %%ebp" : : "r" (new_base_pointer)); +} + +extern void perform_task_switch(uint32_t, uint32_t, uint32_t, uint32_t); + +void switch_task() +{ + if (!current_task) + return; + + uint32_t esp, ebp, eip; + asm volatile ("mov %%esp, %0" : "=r"(esp)); + asm volatile ("mov %%ebp, %0" : "=r"(ebp)); + + eip = read_eip(); + + if (eip == 0x12345) + return; + + current_task->eip = eip; + current_task->esp = esp; + current_task->ebp = ebp; + + current_task = current_task->next; + if (!current_task) current_task = ready_queue; + + eip = current_task->eip; + esp = current_task->esp; + ebp = current_task->ebp; + + current_directory = current_task->page_directory; + + set_kernel_stack(current_task->kernel_stack + KERNEL_STACK_SIZE); + + perform_task_switch(eip, current_directory->physicalAddr, ebp, esp); +} + +int fork() +{ + asm ("cli"); + + task_t *parent_task = (task_t *) current_task; + + page_directory_t *directory = paging_clone_directory(current_directory); + + task_t *new_task = (task_t *) kmalloc(sizeof(task_t)); + new_task->id = (int) next_pid++; + new_task->esp = new_task->ebp = 0; + new_task->eip = 0; + new_task->page_directory = directory; + current_task->kernel_stack = kmalloc_a(KERNEL_STACK_SIZE); + new_task->next = 0; + + task_t *tmp_task = (task_t *) ready_queue; + while (tmp_task->next) + tmp_task = tmp_task->next; + tmp_task->next = new_task; + + uint32_t eip = read_eip(); + + if (current_task == parent_task) { + uint32_t esp; asm volatile ("mov %%esp, %0" : "=r"(esp)); + uint32_t ebp; asm volatile ("mov %%ebp, %0" : "=r"(ebp)); + new_task->esp = esp; + new_task->ebp = ebp; + new_task->eip = eip; + asm volatile ("sti"); + + return new_task->id; + } else { + return 0; + } +} + +int getpid() +{ + return current_task->id; +} + +void switch_to_usermode(uint32_t binary) +{ + set_kernel_stack(current_task->kernel_stack + KERNEL_STACK_SIZE); + + info("Switching to user mode..."); + + asm volatile ("\ + cli; \ + mov $0x23, %%ax; \ + mov %%ax, %%ds; \ + mov %%ax, %%es; \ + mov %%ax, %%fs; \ + mov %%ax, %%gs; \ + mov %%esp, %%eax; \ + pushl $0x23; \ + pushl %%esp; \ + pushf; \ + pushl $0x1B; \ + push %0; \ + iret; \ + 1: \ + " : : "r" (binary)); +}
\ No newline at end of file diff --git a/src/kernel/tasks/task.h b/src/kernel/tasks/task.h new file mode 100644 index 0000000..97aeb15 --- /dev/null +++ b/src/kernel/tasks/task.h @@ -0,0 +1,30 @@ +#ifndef MELVIX_TASK_H +#define MELVIX_TASK_H + +#include <stdint.h> +#include <kernel/memory/paging.h> + +#define KERNEL_STACK_SIZE 2048 + +typedef struct task { + int id; + uint32_t esp, ebp; + uint32_t eip; + page_directory_t *page_directory; + uint32_t kernel_stack; + struct task *next; +} task_t; + +void tasking_install(); + +void switch_task(); + +int fork(); + +void move_stack(void *new_stack_start, uint32_t size); + +int getpid(); + +void switch_to_usermode(uint32_t); + +#endif |