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:
parent
cd56b924e1
commit
02e0bcd70e
@ -102,4 +102,5 @@ void init_gdt() {
|
||||
"mov %%eax, %%ds;"
|
||||
"mov $0x28, %%ax;"
|
||||
"ltr %%ax" : : "m" (descr));
|
||||
Global::tss = &tss;
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#define GDT_H
|
||||
|
||||
#include "types.h"
|
||||
#include "global.h"
|
||||
|
||||
struct __attribute__((packed)) tss_struct {
|
||||
uint16_t link;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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<Process*>* 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.
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "screenstuff.h"
|
||||
#include "global.h"
|
||||
#include "kernel.h"
|
||||
#include "gdt.h"
|
||||
|
||||
struct interrupt_frame {
|
||||
uint32_t eip;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
int main() {
|
||||
while (1) {
|
||||
print("Hello");
|
||||
// print("Hello");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user