[task] Holy crap, tasking. That took forever and it's still broken.
This commit is contained in:
parent
937f1dd547
commit
ee04a7271d
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
#CC = gcc
|
||||
CC = clang
|
||||
GCC = gcc
|
||||
CFLAGS = -Wall -Wextra -pedantic -m32 -O0 -std=c99 -finline-functions -fno-stack-protector -nostdinc -ffreestanding -Wno-unused-function -Wno-unused-parameter
|
||||
CFLAGS = -Wall -Wextra -pedantic -m32 -O0 -std=c99 -finline-functions -fno-stack-protector -nostdinc -ffreestanding -Wno-unused-function -Wno-unused-parameter -g
|
||||
LD = ld -m elf_i386
|
||||
YASM = yasm
|
||||
ECHO = `which echo` -e
|
||||
|
@ -696,7 +696,6 @@ static void klfree(void *ptr) {
|
||||
/*
|
||||
* Well howdy-do, it was.
|
||||
*/
|
||||
kprintf("Attempted to free herpaderpaderpa.\n");
|
||||
ptr = (void *)((uintptr_t)ptr - 1);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
extern uintptr_t end;
|
||||
uintptr_t placement_pointer = (uintptr_t)&end;
|
||||
uintptr_t heap_end = (uintptr_t)NULL;
|
||||
|
||||
void
|
||||
kmalloc_startat(
|
||||
@ -25,7 +26,20 @@ kmalloc_real(
|
||||
int align,
|
||||
uintptr_t * phys
|
||||
) {
|
||||
|
||||
if (heap_end) {
|
||||
void * address;
|
||||
if (align) {
|
||||
address = valloc(size);
|
||||
} else {
|
||||
address = malloc(size);
|
||||
}
|
||||
if (phys) {
|
||||
page_t *page = get_page((uintptr_t)address, 0, kernel_directory);
|
||||
*phys = page->frame * 0x1000 + ((uintptr_t)address & 0xFFF);
|
||||
}
|
||||
return (uintptr_t)address;
|
||||
}
|
||||
|
||||
if (align && (placement_pointer & 0xFFFFF000)) {
|
||||
placement_pointer &= 0xFFFFF000;
|
||||
}
|
||||
@ -34,7 +48,7 @@ kmalloc_real(
|
||||
}
|
||||
uintptr_t address = placement_pointer;
|
||||
placement_pointer += size;
|
||||
return address;
|
||||
return (uintptr_t)address;
|
||||
}
|
||||
/*
|
||||
* Normal
|
||||
@ -138,6 +152,8 @@ alloc_frame(
|
||||
int is_writeable
|
||||
) {
|
||||
if (page->frame) {
|
||||
page->rw = (is_writeable == 1) ? 1 : 0;
|
||||
page->user = (is_kernel == 1) ? 0 : 1;
|
||||
return;
|
||||
} else {
|
||||
uint32_t index = first_frame();
|
||||
@ -146,8 +162,8 @@ alloc_frame(
|
||||
}
|
||||
set_frame(index * 0x1000);
|
||||
page->present = 1;
|
||||
page->rw = (is_writeable) ? 1 : 0;
|
||||
page->user = (is_kernel) ? 0 : 1;
|
||||
page->rw = (is_writeable == 1) ? 1 : 0;
|
||||
page->user = (is_kernel == 1) ? 0 : 1;
|
||||
page->frame = index;
|
||||
}
|
||||
}
|
||||
@ -170,16 +186,23 @@ paging_install(uint32_t memsize) {
|
||||
nframes = memsize / 4;
|
||||
frames = (uint32_t *)kmalloc(INDEX_FROM_BIT(nframes));
|
||||
memset(frames, 0, INDEX_FROM_BIT(nframes));
|
||||
kernel_directory = (page_directory_t *)kvmalloc(sizeof(page_directory_t));
|
||||
|
||||
uintptr_t phys;
|
||||
kernel_directory = (page_directory_t *)kvmalloc_p(sizeof(page_directory_t),&phys);
|
||||
memset(kernel_directory, 0, sizeof(page_directory_t));
|
||||
current_directory = kernel_directory;
|
||||
|
||||
kprintf("0x%x\n", phys);
|
||||
|
||||
uint32_t i = 0;
|
||||
while (i < placement_pointer) {
|
||||
while (i < placement_pointer + 0x1000) {
|
||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||
i += 0x1000;
|
||||
}
|
||||
isrs_install_handler(14, page_fault);
|
||||
kernel_directory->physical_address = (uintptr_t)kernel_directory->physical_tables;
|
||||
|
||||
|
||||
current_directory = clone_directory(kernel_directory);
|
||||
switch_page_directory(kernel_directory);
|
||||
}
|
||||
|
||||
@ -188,7 +211,7 @@ switch_page_directory(
|
||||
page_directory_t * dir
|
||||
) {
|
||||
current_directory = dir;
|
||||
__asm__ __volatile__ ("mov %0, %%cr3":: "r"(&dir->physical_tables));
|
||||
__asm__ __volatile__ ("mov %0, %%cr3":: "r"(dir->physical_address));
|
||||
uint32_t cr0;
|
||||
__asm__ __volatile__ ("mov %%cr0, %0": "=r"(cr0));
|
||||
cr0 |= 0x80000000;
|
||||
@ -240,11 +263,10 @@ page_fault(
|
||||
* who feel the need to screw up.
|
||||
*/
|
||||
|
||||
uintptr_t heap_end = (uintptr_t)NULL;
|
||||
|
||||
void
|
||||
heap_install() {
|
||||
heap_end = placement_pointer;
|
||||
heap_end = (placement_pointer + 0x1000) & ~0xFFF;
|
||||
placement_pointer = 0;
|
||||
}
|
||||
|
||||
@ -253,12 +275,13 @@ sbrk(
|
||||
uintptr_t increment
|
||||
) {
|
||||
ASSERT(increment % 0x1000 == 0);
|
||||
ASSERT(heap_end % 0x1000 == 0);
|
||||
uintptr_t address = heap_end;
|
||||
heap_end += increment;
|
||||
uintptr_t i;
|
||||
for (i = address; i < heap_end; i += 0x1000) {
|
||||
get_page(i, 1, kernel_directory);
|
||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 1);
|
||||
}
|
||||
return (void *)address;
|
||||
}
|
||||
|
185
kernel/core/task.c
Normal file
185
kernel/core/task.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* vim:tabstop=4
|
||||
* vim:noexpandtab
|
||||
*/
|
||||
#include <system.h>
|
||||
|
||||
__volatile__ task_t * current_task;
|
||||
__volatile__ task_t * ready_queue;
|
||||
|
||||
uint32_t next_pid = 1;
|
||||
|
||||
page_directory_t *
|
||||
clone_directory(
|
||||
page_directory_t * src
|
||||
) {
|
||||
uintptr_t phys;
|
||||
page_directory_t * dir = (page_directory_t *)kvmalloc_p(sizeof(page_directory_t), &phys);
|
||||
memset(dir, 0, sizeof(page_directory_t));
|
||||
uintptr_t offset = (uintptr_t)dir->physical_tables - (uintptr_t)dir;
|
||||
dir->physical_address = phys + offset;
|
||||
uint32_t i;
|
||||
for (i = 0; i < 1024; ++i) {
|
||||
if (!src->tables[i]) {
|
||||
continue;
|
||||
}
|
||||
if (kernel_directory->tables[i] == src->tables[i]) {
|
||||
dir->tables[i] = src->tables[i];
|
||||
dir->physical_tables[i] = src->physical_tables[i];
|
||||
} else {
|
||||
uintptr_t phys;
|
||||
dir->tables[i] = clone_table(src->tables[i], &phys);
|
||||
dir->physical_tables[i] = phys | 0x07;
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
page_table_t *
|
||||
clone_table(
|
||||
page_table_t * src,
|
||||
uintptr_t * physAddr
|
||||
) {
|
||||
page_table_t * table = (page_table_t *)kvmalloc_p(sizeof(page_table_t), physAddr);
|
||||
memset(table, 0, sizeof(page_directory_t));
|
||||
uint32_t i;
|
||||
for (i = 0; i < 1024; ++i) {
|
||||
if (!src->pages[i].frame) {
|
||||
continue;
|
||||
}
|
||||
alloc_frame(&table->pages[i], 0, 0);
|
||||
if (src->pages[i].present) table->pages[i].present = 1;
|
||||
if (src->pages[i].rw) table->pages[i].rw = 1;
|
||||
if (src->pages[i].user) table->pages[i].user = 1;
|
||||
if (src->pages[i].accessed) table->pages[i].accessed = 1;
|
||||
if (src->pages[i].dirty) table->pages[i].dirty = 1;
|
||||
copy_page_physical(src->pages[i].frame * 0x1000, table->pages[i].frame * 0x1000);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
void
|
||||
move_stack(
|
||||
void *new_stack_start,
|
||||
size_t size
|
||||
) {
|
||||
uintptr_t i;
|
||||
for ( i = (uintptr_t)new_stack_start;
|
||||
i >= ((uintptr_t)new_stack_start - size);
|
||||
i -= 0x1000) {
|
||||
kprintf("Allocating a page for 0x%x\n", i);
|
||||
alloc_frame(get_page(i, 1, current_directory), 0 /* user */, 1 /* writable */);
|
||||
}
|
||||
puts("Herping the derp.\n");
|
||||
uintptr_t pd_addr;
|
||||
__asm__ __volatile__ ("mov %%cr3, %0" : "=r" (pd_addr));
|
||||
__asm__ __volatile__ ("mov %0, %%cr3" : : "r" (pd_addr));
|
||||
uintptr_t old_stack_pointer;
|
||||
__asm__ __volatile__ ("mov %%esp, %0" : "=r" (old_stack_pointer));
|
||||
uintptr_t old_base_pointer;
|
||||
__asm__ __volatile__ ("mov %%ebp, %0" : "=r" (old_base_pointer));
|
||||
uintptr_t offset = (uintptr_t)new_stack_start - initial_esp;
|
||||
uintptr_t new_stack_pointer = old_stack_pointer + offset;
|
||||
uintptr_t new_base_pointer = old_base_pointer + offset;
|
||||
kprintf("0x%x 0x%x\n", new_stack_pointer, old_stack_pointer);
|
||||
memcpy((void *)new_stack_pointer, (void *)old_stack_pointer, initial_esp - old_stack_pointer);
|
||||
for (i = (uintptr_t)new_stack_start; i > (uintptr_t)new_stack_start - size; i -= 4) {
|
||||
uintptr_t temp = *(uintptr_t*)i;
|
||||
if ((old_stack_pointer < temp) && (temp < initial_esp)) {
|
||||
temp = temp + offset;
|
||||
uintptr_t *temp2 = (uintptr_t *)i;
|
||||
*temp2 = temp;
|
||||
}
|
||||
}
|
||||
__asm__ __volatile__ ("mov %0, %%esp" : : "r" (new_stack_pointer));
|
||||
__asm__ __volatile__ ("mov %0, %%ebp" : : "r" (new_base_pointer));
|
||||
}
|
||||
|
||||
void
|
||||
tasking_install() {
|
||||
__asm__ __volatile__ ("cli");
|
||||
move_stack((void *)0xE000000, 0x2000);
|
||||
|
||||
current_task = (task_t *)kmalloc(sizeof(task_t));
|
||||
ready_queue = current_task;
|
||||
current_task->id = next_pid++;
|
||||
current_task->esp = 0;
|
||||
current_task->ebp = 0;
|
||||
current_task->eip = 0;
|
||||
current_task->page_directory = current_directory;
|
||||
current_task->next = 0;
|
||||
|
||||
__asm__ __volatile__ ("sti");
|
||||
}
|
||||
|
||||
uint32_t
|
||||
fork() {
|
||||
__asm__ __volatile__ ("cli");
|
||||
task_t * parent = (task_t *)current_task;
|
||||
page_directory_t * directory = clone_directory(current_directory);
|
||||
task_t * new_task = (task_t *)kmalloc(sizeof(task_t));
|
||||
new_task->id = next_pid++;
|
||||
new_task->esp = 0;
|
||||
new_task->ebp = 0;
|
||||
new_task->eip = 0;
|
||||
new_task->page_directory = directory;
|
||||
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;
|
||||
uintptr_t eip = read_eip();
|
||||
if (current_task == parent) {
|
||||
uintptr_t esp;
|
||||
uintptr_t ebp;
|
||||
__asm__ __volatile__ ("mov %%esp, %0" : "=r" (esp));
|
||||
__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;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
getpid() {
|
||||
return current_task->id;
|
||||
}
|
||||
|
||||
void
|
||||
switch_task() {
|
||||
if (!current_task) {
|
||||
return;
|
||||
}
|
||||
uintptr_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;
|
||||
__asm__ __volatile__ (
|
||||
"cli\n"
|
||||
"mov %0, %%ecx\n"
|
||||
"mov %1, %%esp\n"
|
||||
"mov %2, %%ebp\n"
|
||||
"mov %3, %%cr3\n"
|
||||
"mov $0x12345, %%eax\n"
|
||||
"sti\n"
|
||||
"jmp *%%ecx"
|
||||
: : "r" (eip), "r" (esp), "r" (ebp), "r" (current_directory->physical_address));
|
||||
}
|
@ -20,6 +20,7 @@ timer_handler(
|
||||
++timer_ticks;
|
||||
if (timer_ticks % 18 == 0) {
|
||||
++ticker;
|
||||
switch_task();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,6 +125,8 @@ extern void page_fault(struct regs *r);
|
||||
|
||||
void heap_install();
|
||||
|
||||
void alloc_frame(page_t *page, int is_kernel, int is_writeable);
|
||||
|
||||
/* klmalloc */
|
||||
void * __attribute__ ((malloc)) malloc(size_t size);
|
||||
void * __attribute__ ((malloc)) realloc(void *ptr, size_t size);
|
||||
@ -140,5 +142,27 @@ extern void serial_install();
|
||||
extern char serial_recv();
|
||||
extern void serial_send(char out);
|
||||
|
||||
/* Tasks */
|
||||
extern uintptr_t read_eip();
|
||||
extern void copy_page_physical(uint32_t, uint32_t);
|
||||
extern page_directory_t * clone_directory(page_directory_t * src);
|
||||
extern page_table_t * clone_table(page_table_t * src, uintptr_t * physAddr);
|
||||
extern void move_stack(void *new_stack_start, size_t size);
|
||||
|
||||
typedef struct task {
|
||||
uint32_t id;
|
||||
uintptr_t esp;
|
||||
uintptr_t ebp;
|
||||
uintptr_t eip;
|
||||
page_directory_t * page_directory;
|
||||
struct task *next;
|
||||
} task_t;
|
||||
|
||||
extern void tasking_install();
|
||||
extern void switch_task();
|
||||
extern uint32_t fork();
|
||||
extern uint32_t getpid();
|
||||
|
||||
uintptr_t initial_esp;
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
* vim:tabstop=4
|
||||
* vim:noexpandtab
|
||||
* Copyright (c) 2011 Kevin Lange. All rights reserved.
|
||||
*
|
||||
* Developed by: ToAruOS Kernel Development Team
|
||||
@ -54,8 +56,9 @@
|
||||
* multiboot data from the bootloader. It will then proceed to print
|
||||
* out the contents of the initial ramdisk image.
|
||||
*/
|
||||
int main(struct multiboot *mboot_ptr, uint32_t mboot_mag)
|
||||
int main(struct multiboot *mboot_ptr, uint32_t mboot_mag, uintptr_t esp)
|
||||
{
|
||||
initial_esp = esp;
|
||||
enum BOOTMODE boot_mode = unknown; /* Boot Mode */
|
||||
char * ramdisk = NULL;
|
||||
if (mboot_mag == MULTIBOOT_EAX_MAGIC) {
|
||||
@ -92,12 +95,17 @@ int main(struct multiboot *mboot_ptr, uint32_t mboot_mag)
|
||||
|
||||
/* Memory management */
|
||||
paging_install(mboot_ptr->mem_upper);
|
||||
kprintf("herp\n");
|
||||
heap_install();
|
||||
tasking_install();
|
||||
kprintf("derp\n");
|
||||
|
||||
/* Kernel Version */
|
||||
settextcolor(12, 0);
|
||||
kprintf("[%s %s]\n", KERNEL_UNAME, KERNEL_VERSION_STRING);
|
||||
|
||||
|
||||
__asm__ __volatile__ ("cli");
|
||||
if (boot_mode == multiboot) {
|
||||
/* Print multiboot information */
|
||||
dump_multiboot(mboot_ptr);
|
||||
@ -108,8 +116,26 @@ int main(struct multiboot *mboot_ptr, uint32_t mboot_mag)
|
||||
}
|
||||
}
|
||||
}
|
||||
__asm__ __volatile__ ("sti");
|
||||
|
||||
start_shell();
|
||||
|
||||
/*
|
||||
* Aw man...
|
||||
*/
|
||||
|
||||
uint32_t child = fork();
|
||||
|
||||
uint32_t i = getpid();
|
||||
while (1) {
|
||||
__asm__ __volatile__ ("cli");
|
||||
if (i == 1) {
|
||||
putch('A');
|
||||
} else {
|
||||
putch('B');
|
||||
}
|
||||
__asm__ __volatile__ ("sti");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ global start
|
||||
start:
|
||||
; Set up stack pointer.
|
||||
mov esp, 0x7FFFF
|
||||
push esp
|
||||
; Push the incoming mulitboot headers
|
||||
push eax ; Header magic
|
||||
push ebx ; Header pointer
|
||||
@ -195,6 +196,35 @@ irq_common_stub:
|
||||
add esp, 8
|
||||
iret
|
||||
|
||||
global read_eip
|
||||
read_eip: ; Clever girl
|
||||
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, 0x400
|
||||
.page_loop:
|
||||
mov eax, [ebx]
|
||||
mov [ecx], eax
|
||||
add ebx, 4
|
||||
add ecx, 4
|
||||
dec edx
|
||||
jnz .page_loop
|
||||
mov edx, cr0
|
||||
or edx, 0x80000000
|
||||
mov cr0, edx
|
||||
popf
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
; BSS Section
|
||||
SECTION .bss
|
||||
|
Loading…
Reference in New Issue
Block a user