diff --git a/Makefile b/Makefile index 8edbf60e..d3968162 100644 --- a/Makefile +++ b/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 diff --git a/kernel/core/alloc.c b/kernel/core/alloc.c index 871b5ef6..392e7c6f 100644 --- a/kernel/core/alloc.c +++ b/kernel/core/alloc.c @@ -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); } diff --git a/kernel/core/mem.c b/kernel/core/mem.c index fd095ee4..66239691 100644 --- a/kernel/core/mem.c +++ b/kernel/core/mem.c @@ -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; } diff --git a/kernel/core/task.c b/kernel/core/task.c new file mode 100644 index 00000000..0c8e2005 --- /dev/null +++ b/kernel/core/task.c @@ -0,0 +1,185 @@ +/* + * vim:tabstop=4 + * vim:noexpandtab + */ +#include + +__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)); +} diff --git a/kernel/core/timer.c b/kernel/core/timer.c index d683acf7..d663fbef 100644 --- a/kernel/core/timer.c +++ b/kernel/core/timer.c @@ -20,6 +20,7 @@ timer_handler( ++timer_ticks; if (timer_ticks % 18 == 0) { ++ticker; + switch_task(); } } diff --git a/kernel/include/system.h b/kernel/include/system.h index 503f3a0b..4db88287 100644 --- a/kernel/include/system.h +++ b/kernel/include/system.h @@ -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 diff --git a/kernel/main.c b/kernel/main.c index 0810b6ca..f4cc49db 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -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; } diff --git a/kernel/start.s b/kernel/start.s index f5413527..89a72fa5 100644 --- a/kernel/start.s +++ b/kernel/start.s @@ -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