diff --git a/src/kernel/gdt.cpp b/src/kernel/gdt.cpp index c387c3c..8664685 100644 --- a/src/kernel/gdt.cpp +++ b/src/kernel/gdt.cpp @@ -102,4 +102,5 @@ void init_gdt() { "mov %%eax, %%ds;" "mov $0x28, %%ax;" "ltr %%ax" : : "m" (descr)); + Global::tss = &tss; } \ No newline at end of file diff --git a/src/kernel/gdt.h b/src/kernel/gdt.h index b1b4a3c..cac9f3a 100644 --- a/src/kernel/gdt.h +++ b/src/kernel/gdt.h @@ -2,6 +2,7 @@ #define GDT_H #include "types.h" +#include "global.h" struct __attribute__((packed)) tss_struct { uint16_t link; diff --git a/src/kernel/global.cpp b/src/kernel/global.cpp index 5679b50..42304ab 100644 --- a/src/kernel/global.cpp +++ b/src/kernel/global.cpp @@ -4,6 +4,7 @@ namespace Global { Allocator* allocator = 0; Kernel* kernel = 0; Process* currentProc = 0; + tss_struct* tss = 0; } void* operator new (uint32_t size) { diff --git a/src/kernel/global.h b/src/kernel/global.h index 2a2f9c7..c1bba8c 100644 --- a/src/kernel/global.h +++ b/src/kernel/global.h @@ -6,11 +6,13 @@ class Kernel; class Allocator; class Process; +struct tss_struct; namespace Global { extern Allocator* allocator; extern Kernel* kernel; extern Process* currentProc; + extern tss_struct* tss; } void* operator new (uint32_t size); diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index 8ce6d08..31f2b09 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -39,12 +39,29 @@ __attribute__((interrupt)) void gpf(interrupt_frame* frame, uint32_t err_code) { } __attribute__((interrupt)) void context_switch(interrupt_frame* frame) { + // When any interrupt occurs (including context_switch), SS:ESP is set to + // the values of SS0:ESP0 in Global::tss + // + // This means that processes need to track a kernel stack pointer + // Which is the location of their indivudual kernel stacks. + // + // Context switch needs to do two things. + // #1 update currentProc's kernel stack pointer to be the correct value after + // data has been pushed on to the stack + // + // #2 load the kernelStackPtr in to esp before popping data and falling through + // to iret + asm ("cli"); // Disable interrupts whilst handling the context switch. asm ("pusha"); // Push registers to the stack //asm ("pushf"); // Push flags to the stack Process* currentProc = Global::currentProc; Process* nextProc = 0; + + // Write current esp to currentProc->kernelStackPtr + asm ("mov %%esp, %0" : "=a" (currentProc->kernelStackPtr):); + if (currentProc) { xnoe::linkedlist* processes = &Global::kernel->processes; @@ -84,16 +101,22 @@ __attribute__((interrupt)) void context_switch(interrupt_frame* frame) { Global::currentProc = nextProc; - uint32_t cESP; - asm volatile ("mov %%esp, %0" : "=a" (cESP) :); - currentProc->esp = cESP; // Store the current ESP of the current process process. + //uint32_t cESP; + //asm volatile ("mov %%esp, %0" : "=a" (cESP) :); + //currentProc->esp = cESP; // Store the current ESP of the current process process. outb(0x20, 0x20); // Select the next processes page directory asm volatile ("mov %0, %%cr3" : : "r" (nextProc->PD->phys_addr)); - // Restore ESP of the new process. - asm volatile ("mov %0, %%esp" : : "m" (Global::kernel->processes.start->elem->esp)); + // Restore kernelStackPtr of the new process. + asm volatile ("mov %0, %%esp" : : "m" (Global::kernel->processes.start->elem->kernelStackPtr)); + + // At this point interrupts are disabled till iret so we can safely set + // Global::tss->esp0 + // to the new Process's kernelStackPtrDefault + + Global::tss->esp0 = Global::kernel->processes.start->elem->kernelStackPtrDefault; //asm ("popf"); // Pop flags asm ("popa"); // Restore registers @@ -101,6 +124,7 @@ __attribute__((interrupt)) void context_switch(interrupt_frame* frame) { // Clear the garbage that was on the stack from previous switch_context call. asm ("mov %ebp, %esp"); asm ("pop %ebp"); // Pop EBP + asm ("iret"); // Manually perform iret. } } diff --git a/src/kernel/idt.h b/src/kernel/idt.h index 11a6004..3f3ea5e 100644 --- a/src/kernel/idt.h +++ b/src/kernel/idt.h @@ -5,6 +5,7 @@ #include "screenstuff.h" #include "global.h" #include "kernel.h" +#include "gdt.h" struct interrupt_frame { uint32_t eip; diff --git a/src/kernel/kmain.cpp b/src/kernel/kmain.cpp index 23f29f2..9f3089e 100644 --- a/src/kernel/kmain.cpp +++ b/src/kernel/kmain.cpp @@ -47,6 +47,9 @@ int main() { Global::currentProc = &kernel; Process* p1 = kernel.createProcess("WORLD BIN"); + Process* p2 = kernel.createProcess("HELLO BIN"); + Process* p3 = kernel.createProcess("HELLO BIN"); + init_keyboard(); diff --git a/src/kernel/process.cpp b/src/kernel/process.cpp index 615da5f..797b4d3 100644 --- a/src/kernel/process.cpp +++ b/src/kernel/process.cpp @@ -28,6 +28,7 @@ Process::Process(uint32_t PID) this->page_remaining = 0; this->last_page_pointer = 0; this->stack = this->allocate(0x8000); + this->kernelStackPtr = (new uint8_t[0x1000]) + 0x1000; } Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename) @@ -40,6 +41,8 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha this->PD->page_directory[index] = inherit->page_directory[index]; this->stack = this->allocate(0x8000); + this->kernelStackPtr = (new uint8_t[0x1000]) + 0xffc; + this->kernelStackPtrDefault = this->kernelStackPtr; uint32_t pCR3; asm ("mov %%cr3, %0" : "=a" (pCR3) :); @@ -48,17 +51,17 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha uint8_t* program_data = this->allocate(file_size(filename) + 12) + 12; // We also need to initialise ESP and the stack - uint32_t* stack32 = ((uint32_t)this->stack + 0x8000); + uint32_t* stack32 = ((uint32_t)this->kernelStackPtr); stack32--; - *stack32 = 0x23; + *stack32 = 0x23; // SS stack32--; - *stack32 = ((uint32_t)this->stack + 0x8000); + *stack32 = ((uint32_t)this->stack + 0x8000); // ESP stack32--; *stack32 = 0x200; // EFLAGS stack32--; *stack32 = 27; // CS 0x08 stack32--; - *stack32 = (uint32_t)program_data; + *stack32 = (uint32_t)program_data; // EIP stack32--; *stack32 = ((uint32_t)this->stack + 0x8000); // EBP @@ -84,7 +87,7 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha stack32--; *stack32 = 0; // EDI - this->esp = stack32; + this->kernelStackPtr = stack32; load_file(filename, program_data); @@ -102,6 +105,7 @@ Process::~Process() { this->deallocate(active->elem.page_base+1); } this->deallocate(stack); + delete kernelStackPtr; } void* Process::allocate(uint32_t size) { diff --git a/src/kernel/process.h b/src/kernel/process.h index bbd2165..8a686dc 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -34,6 +34,9 @@ public: uint32_t PID; uint32_t esp; + void* kernelStackPtr; + void* kernelStackPtrDefault; + Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base); Process(uint32_t PID); Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename); diff --git a/src/program/hello.c b/src/program/hello.c index 659d50e..3dbaccb 100644 --- a/src/program/hello.c +++ b/src/program/hello.c @@ -2,6 +2,6 @@ int main() { while (1) { - print("Hello"); + // print("Hello"); } } \ No newline at end of file