Finalise mvoe to Ring 3, add separate kernel stacks for each process, correctly switch between those kernel stacks within context_switch, etc

This commit is contained in:
Xnoe 2021-12-07 22:04:53 +00:00
parent cd56b924e1
commit 02e0bcd70e
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
10 changed files with 51 additions and 11 deletions

View File

@ -102,4 +102,5 @@ void init_gdt() {
"mov %%eax, %%ds;" "mov %%eax, %%ds;"
"mov $0x28, %%ax;" "mov $0x28, %%ax;"
"ltr %%ax" : : "m" (descr)); "ltr %%ax" : : "m" (descr));
Global::tss = &tss;
} }

View File

@ -2,6 +2,7 @@
#define GDT_H #define GDT_H
#include "types.h" #include "types.h"
#include "global.h"
struct __attribute__((packed)) tss_struct { struct __attribute__((packed)) tss_struct {
uint16_t link; uint16_t link;

View File

@ -4,6 +4,7 @@ namespace Global {
Allocator* allocator = 0; Allocator* allocator = 0;
Kernel* kernel = 0; Kernel* kernel = 0;
Process* currentProc = 0; Process* currentProc = 0;
tss_struct* tss = 0;
} }
void* operator new (uint32_t size) { void* operator new (uint32_t size) {

View File

@ -6,11 +6,13 @@
class Kernel; class Kernel;
class Allocator; class Allocator;
class Process; class Process;
struct tss_struct;
namespace Global { namespace Global {
extern Allocator* allocator; extern Allocator* allocator;
extern Kernel* kernel; extern Kernel* kernel;
extern Process* currentProc; extern Process* currentProc;
extern tss_struct* tss;
} }
void* operator new (uint32_t size); void* operator new (uint32_t size);

View File

@ -39,12 +39,29 @@ __attribute__((interrupt)) void gpf(interrupt_frame* frame, uint32_t err_code) {
} }
__attribute__((interrupt)) void context_switch(interrupt_frame* frame) { __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 ("cli"); // Disable interrupts whilst handling the context switch.
asm ("pusha"); // Push registers to the stack asm ("pusha"); // Push registers to the stack
//asm ("pushf"); // Push flags to the stack //asm ("pushf"); // Push flags to the stack
Process* currentProc = Global::currentProc; Process* currentProc = Global::currentProc;
Process* nextProc = 0; Process* nextProc = 0;
// Write current esp to currentProc->kernelStackPtr
asm ("mov %%esp, %0" : "=a" (currentProc->kernelStackPtr):);
if (currentProc) { if (currentProc) {
xnoe::linkedlist<Process*>* processes = &Global::kernel->processes; xnoe::linkedlist<Process*>* processes = &Global::kernel->processes;
@ -84,16 +101,22 @@ __attribute__((interrupt)) void context_switch(interrupt_frame* frame) {
Global::currentProc = nextProc; Global::currentProc = nextProc;
uint32_t cESP; //uint32_t cESP;
asm volatile ("mov %%esp, %0" : "=a" (cESP) :); //asm volatile ("mov %%esp, %0" : "=a" (cESP) :);
currentProc->esp = cESP; // Store the current ESP of the current process process. //currentProc->esp = cESP; // Store the current ESP of the current process process.
outb(0x20, 0x20); outb(0x20, 0x20);
// Select the next processes page directory // Select the next processes page directory
asm volatile ("mov %0, %%cr3" : : "r" (nextProc->PD->phys_addr)); asm volatile ("mov %0, %%cr3" : : "r" (nextProc->PD->phys_addr));
// Restore ESP of the new process. // Restore kernelStackPtr of the new process.
asm volatile ("mov %0, %%esp" : : "m" (Global::kernel->processes.start->elem->esp)); 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 ("popf"); // Pop flags
asm ("popa"); // Restore registers 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. // Clear the garbage that was on the stack from previous switch_context call.
asm ("mov %ebp, %esp"); asm ("mov %ebp, %esp");
asm ("pop %ebp"); // Pop EBP asm ("pop %ebp"); // Pop EBP
asm ("iret"); // Manually perform iret. asm ("iret"); // Manually perform iret.
} }
} }

View File

@ -5,6 +5,7 @@
#include "screenstuff.h" #include "screenstuff.h"
#include "global.h" #include "global.h"
#include "kernel.h" #include "kernel.h"
#include "gdt.h"
struct interrupt_frame { struct interrupt_frame {
uint32_t eip; uint32_t eip;

View File

@ -47,6 +47,9 @@ int main() {
Global::currentProc = &kernel; Global::currentProc = &kernel;
Process* p1 = kernel.createProcess("WORLD BIN"); Process* p1 = kernel.createProcess("WORLD BIN");
Process* p2 = kernel.createProcess("HELLO BIN");
Process* p3 = kernel.createProcess("HELLO BIN");
init_keyboard(); init_keyboard();

View File

@ -28,6 +28,7 @@ Process::Process(uint32_t PID)
this->page_remaining = 0; this->page_remaining = 0;
this->last_page_pointer = 0; this->last_page_pointer = 0;
this->stack = this->allocate(0x8000); this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0x1000;
} }
Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename) 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->PD->page_directory[index] = inherit->page_directory[index];
this->stack = this->allocate(0x8000); this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0xffc;
this->kernelStackPtrDefault = this->kernelStackPtr;
uint32_t pCR3; uint32_t pCR3;
asm ("mov %%cr3, %0" : "=a" (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; uint8_t* program_data = this->allocate(file_size(filename) + 12) + 12;
// We also need to initialise ESP and the stack // 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--;
*stack32 = 0x23; *stack32 = 0x23; // SS
stack32--; stack32--;
*stack32 = ((uint32_t)this->stack + 0x8000); *stack32 = ((uint32_t)this->stack + 0x8000); // ESP
stack32--; stack32--;
*stack32 = 0x200; // EFLAGS *stack32 = 0x200; // EFLAGS
stack32--; stack32--;
*stack32 = 27; // CS 0x08 *stack32 = 27; // CS 0x08
stack32--; stack32--;
*stack32 = (uint32_t)program_data; *stack32 = (uint32_t)program_data; // EIP
stack32--; stack32--;
*stack32 = ((uint32_t)this->stack + 0x8000); // EBP *stack32 = ((uint32_t)this->stack + 0x8000); // EBP
@ -84,7 +87,7 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha
stack32--; stack32--;
*stack32 = 0; // EDI *stack32 = 0; // EDI
this->esp = stack32; this->kernelStackPtr = stack32;
load_file(filename, program_data); load_file(filename, program_data);
@ -102,6 +105,7 @@ Process::~Process() {
this->deallocate(active->elem.page_base+1); this->deallocate(active->elem.page_base+1);
} }
this->deallocate(stack); this->deallocate(stack);
delete kernelStackPtr;
} }
void* Process::allocate(uint32_t size) { void* Process::allocate(uint32_t size) {

View File

@ -34,6 +34,9 @@ public:
uint32_t PID; uint32_t PID;
uint32_t esp; 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, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
Process(uint32_t PID); Process(uint32_t PID);
Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename); Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename);

View File

@ -2,6 +2,6 @@
int main() { int main() {
while (1) { while (1) {
print("Hello"); // print("Hello");
} }
} }