[task] Holy crap, tasking. That took forever and it's still broken.

This commit is contained in:
Kevin Lange 2011-03-01 17:48:39 -06:00
parent 937f1dd547
commit ee04a7271d
8 changed files with 302 additions and 14 deletions

View File

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

View File

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

View File

@ -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
View 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));
}

View File

@ -20,6 +20,7 @@ timer_handler(
++timer_ticks;
if (timer_ticks % 18 == 0) {
++ticker;
switch_task();
}
}

View File

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

View File

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

View File

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