diff --git a/include/kernel.h b/include/kernel.h index 0d1054e..ed7761e 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -40,6 +40,12 @@ struct message_t uint32_t param1, param2, param3; }; +struct address_space_t +{ + physaddr_t top_table; + int counter; +}; + struct process_t { size_t priority; @@ -70,10 +76,14 @@ int active_process(); int add_process(void *program_entry, int priority, physaddr_t address_space); -struct process_context_t *next_process(struct process_context_t *prev_state); +struct process_context_t *next_process(); int terminate_process(size_t process_id); +int store_active_context(struct process_context_t *context, size_t size); + +struct process_context_t *get_active_context(); + /* int accept_message(size_t process_id, struct message_t *message); diff --git a/include/platform/context.h b/include/platform/context.h index f3fd65d..dbf5b94 100644 --- a/include/platform/context.h +++ b/include/platform/context.h @@ -1,9 +1,11 @@ #pragma once +struct process_context_t; + void *initialize_context(void *task_entry); void destroy_context(void *ctx); -void save_context(struct process_context_t *context, void *ptr); +void save_context(struct process_context_t *context); void load_context(struct process_context_t *context); diff --git a/src/Makefile.am b/src/Makefile.am index bdbd1e8..47a930e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ quark_kernel_SOURCES += x86/paging.c \ x86/isr.c \ x86/msr.c \ x86/context.c \ - x86/contextswitch.S \ + x86/load_context.S \ x86/preempt.S \ x86/quark_x86.c \ x86/entry.S diff --git a/src/kernel.c b/src/kernel.c index 9c510c2..df99c06 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -57,7 +57,7 @@ void kernel_initialize(struct boot_info_t *boot_info) asm("hlt");*/ irq_enable(); - load_context(next_process(NULL)); + load_context(next_process()); } int set_syscall(int id, int arg_count, int pid, void *func_ptr) @@ -219,13 +219,8 @@ int add_process(void *program_entry, int priority, physaddr_t address_space) return new_process->resource_id; } -struct process_context_t *next_process(struct process_context_t *prev_state) +struct process_context_t *next_process() { - if(prev_state != NULL) - { - kernel.active_process->state = prev_state; - queue_insert(&kernel.priority_queue, kernel.active_process, kernel.active_process->priority); - } kernel.active_process = extract_min(&kernel.priority_queue); if(kernel.active_process != NULL) { @@ -254,6 +249,19 @@ int terminate_process(size_t process_id) return S_OK; } +int store_active_context(struct process_context_t *context, size_t size) +{ + if(kernel.active_process != NULL && kernel.active_process->state != NULL) + { + memcpy(kernel.active_process->state, context, size); + return S_OK; + } + else + { + return S_DOESNT_EXIST; + } +} + /* int accept_message(size_t process_id, struct message_t *message) { diff --git a/src/x86/context.c b/src/x86/context.c index 2387392..bcb6f7f 100644 --- a/src/x86/context.c +++ b/src/x86/context.c @@ -1,35 +1,45 @@ #include "platform/context.h" +#include "kernel.h" #include "mmgr.h" +#include "heap.h" #include "string.h" +#include "system.h" #include "x86/processstate.h" void *initialize_context(void *task_entry) { - /* - * TODO: this implementation is a goddamn mess. - * Stack pointer is hardcoded, and the stack isn't resizable. - * PCB pointer is just a constant. - */ - map_page(NULL, reserve_page(), PAGE_RW); - map_page((void*)0xFF3FF000, reserve_page(), PAGE_RW | PAGE_USERMODE); - unmap_page((void*)0xFF3FE000); - uint32_t flags; - asm("pushf; " - "mov (%%esp), %0; " - "popf; " - : "=r"(flags)); - struct process_context_t *state = (struct process_context_t*)PCB_LOCATION; - memset(NULL, 0, page_size); - state->cs = 0x1B; - state->eip = (uint32_t)task_entry; - state->flags = (flags & ~0xFD) | 0x200; - state->ss = 0x23; - state->esp = 0xFF400000; - state->ebp = 0xFF400000; - return (void*)state; + physaddr_t stack_frame = reserve_page(); + if(stack_frame % page_size != 0) + { + return NULL; + } + map_page((void*)&_kernel_start - page_size, stack_frame, PAGE_RW | PAGE_USERMODE); + unmap_page((void*)&_kernel_start - (2 * page_size)); + struct process_context_t *context = kmalloc(sizeof(struct process_context_t)); + if(context != NULL) + { + memset(context, 0, sizeof(struct process_context_t)); + uint32_t flags; + asm("pushf; " + "mov (%%esp), %0; " + "popf; " + : "=r"(flags)); + context->cs = 0x1B; + context->eip = (uint32_t)task_entry; + context->flags = (flags & ~0xFD) | 0x200; + context->ss = 0x23; + context->esp = &_kernel_start; + context->ebp = &_kernel_start; + } + return (void*)context; } void destroy_context(void *ctx) { - // Nothing to do... + kfree(ctx); +} + +void save_context(struct process_context_t *context) +{ + store_active_context(context, sizeof(*context)); } \ No newline at end of file diff --git a/src/x86/contextswitch.S b/src/x86/contextswitch.S deleted file mode 100644 index 79c48ba..0000000 --- a/src/x86/contextswitch.S +++ /dev/null @@ -1,67 +0,0 @@ -.section .text - -/* - * save_context(struct process_state_t *context, struct interrupt_frame_t *frame) - */ - .global save_context - .type save_context, @function -save_context: - push %edi - push %esi - push %eax - mov $0x10, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov 16(%esp), %eax - mov %ebx, 0x04(%eax) - mov %ecx, 0x08(%eax) - mov %edx, 0x0C(%eax) - mov %edi, 0x10(%eax) - mov %esi, 0x14(%eax) - mov %ebp, 0x18(%eax) - mov %eax, %edi - pop %eax - mov %eax, 0x00(%edi) - mov 16(%esp), %esi - mov 0x10(%esi), %eax - mov %eax, 0x1C(%edi) - mov 0x0C(%esi), %eax - mov %eax, 0x20(%edi) - mov 0x08(%esi), %eax - mov %eax, 0x2C(%edi) - mov 0x04(%esi), %eax - mov %eax, 0x24(%edi) - mov 0x00(%esi), %eax - mov %eax, 0x28(%edi) - pop %esi - pop %edi - ret - -/* - * load_context(struct process_state_t *context) - */ -.global load_context -.type load_context, @function -load_context: - mov 4(%esp), %eax - push 0x1C(%eax) - push 0x20(%eax) - push 0x2C(%eax) - push 0x24(%eax) - push 0x28(%eax) - push 0x00(%eax) - mov 0x04(%eax), %ebx - mov 0x08(%eax), %ecx - mov 0x0C(%eax), %edx - mov 0x10(%eax), %edi - mov 0x14(%eax), %esi - mov 0x18(%eax), %ebp - mov 0x1C(%eax), %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - pop %eax - iret \ No newline at end of file diff --git a/src/x86/load_context.S b/src/x86/load_context.S new file mode 100644 index 0000000..4550674 --- /dev/null +++ b/src/x86/load_context.S @@ -0,0 +1,28 @@ +.section .text + +/* + * load_context(struct process_state_t *context) + */ +.global load_context +.type load_context, @function +load_context: + mov 4(%esp), %eax + push 0x1C(%eax) + push 0x20(%eax) + push 0x2C(%eax) + push 0x24(%eax) + push 0x28(%eax) + push 0x00(%eax) + mov 0x04(%eax), %ebx + mov 0x08(%eax), %ecx + mov 0x0C(%eax), %edx + mov 0x10(%eax), %edi + mov 0x14(%eax), %esi + mov 0x18(%eax), %ebp + mov 0x1C(%eax), %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + pop %eax + iret \ No newline at end of file diff --git a/src/x86/preempt.S b/src/x86/preempt.S index ededc1c..d341100 100644 --- a/src/x86/preempt.S +++ b/src/x86/preempt.S @@ -25,14 +25,63 @@ isr_syscall: .global isr_preempt .type isr_preempt, @function isr_preempt: + + // Disable interrupts for now cli + + // Save process's base pointer + push %ebp + + // Save base pointer; it points to the interrupt stack frame + mov %esp, %ebp + sub $4, %ebp + + // Save EAX on stack so it can be used as a buffer + push %eax + + // Load EFLAGS, then push it onto stack + mov 8(%ebp), %eax + push %eax + + // Load EIP, then push it onto stack + mov 16(%ebp), %eax + push %eax + + // Load CS, then push it onto stack + mov 12(%ebp), %eax + push %eax + + // Load ESP, then push it onto stack + mov 4(%ebp), %eax + push %eax + + // Load SS, then push it onto stack + mov (%ebp), %eax + push %eax + + // Load EBP, then push it onto stack + mov -4(%ebp), %eax + push %eax + + // Push GP registers onto stack + push %esi + push %edi + push %edx + push %ecx + push %ebx + + // Restore saved value of EAX, then push it onto stack + mov -8(%ebp), %eax + push %eax + + // Push pointer to the process context saved on the stack push %esp - push $0x800 + call save_context - add $8, %esp - push $0x800 + mov %ebp, %esp + call next_process - add $8, %esp + push %eax call load_context \ No newline at end of file