Compare commits
3 Commits
cb41953354
...
d3024211a7
Author | SHA1 | Date |
---|---|---|
|
d3024211a7 | |
|
7a3b4d2d42 | |
|
0d275c72a1 |
zion
|
@ -38,6 +38,30 @@ InterruptDescriptor CreateDescriptor(void isr(void)) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InterruptFrame {
|
||||||
|
uint64_t rax;
|
||||||
|
uint64_t rbx;
|
||||||
|
uint64_t rcx;
|
||||||
|
uint64_t rdx;
|
||||||
|
uint64_t rsi;
|
||||||
|
uint64_t rdi;
|
||||||
|
uint64_t r8;
|
||||||
|
uint64_t r9;
|
||||||
|
uint64_t r10;
|
||||||
|
uint64_t r11;
|
||||||
|
uint64_t r12;
|
||||||
|
uint64_t r13;
|
||||||
|
uint64_t r14;
|
||||||
|
uint64_t r15;
|
||||||
|
uint64_t rbp;
|
||||||
|
uint64_t error_code;
|
||||||
|
uint64_t rip;
|
||||||
|
uint64_t cs;
|
||||||
|
uint64_t eflags;
|
||||||
|
uint64_t rsp;
|
||||||
|
uint64_t ss;
|
||||||
|
};
|
||||||
|
|
||||||
extern "C" void isr_divide_by_zero();
|
extern "C" void isr_divide_by_zero();
|
||||||
extern "C" void interrupt_divide_by_zero(void* frame) { panic("DIV0"); }
|
extern "C" void interrupt_divide_by_zero(void* frame) { panic("DIV0"); }
|
||||||
|
|
||||||
|
@ -45,7 +69,31 @@ extern "C" void isr_protection_fault();
|
||||||
extern "C" void interrupt_protection_fault(void* frame) { panic("GP"); }
|
extern "C" void interrupt_protection_fault(void* frame) { panic("GP"); }
|
||||||
|
|
||||||
extern "C" void isr_page_fault();
|
extern "C" void isr_page_fault();
|
||||||
extern "C" void interrupt_page_fault(void* frame) { panic("PF"); }
|
extern "C" void interrupt_page_fault(InterruptFrame* frame) {
|
||||||
|
dbgln("Page Fault:");
|
||||||
|
uint64_t err = frame->error_code;
|
||||||
|
if (err & 0x1) {
|
||||||
|
dbgln("Page Protection");
|
||||||
|
} else {
|
||||||
|
dbgln("Page Not Present");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err & 0x2) {
|
||||||
|
dbgln("Write");
|
||||||
|
} else {
|
||||||
|
dbgln("Read");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err & 0x8) {
|
||||||
|
dbgln("Instruction Fetch");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t cr2;
|
||||||
|
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||||
|
dbgln("rip: %m", frame->rip);
|
||||||
|
dbgln("addr: %m", cr2);
|
||||||
|
panic("PF");
|
||||||
|
}
|
||||||
|
|
||||||
void InitIdt() {
|
void InitIdt() {
|
||||||
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
|
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
|
||||||
|
|
|
@ -98,20 +98,37 @@ void MapPage(uint64_t virt, uint64_t phys) {
|
||||||
*PageTableEntry(virt) = PageAlign(phys) | PRESENT_BIT | READ_WRITE_BIT;
|
*PageTableEntry(virt) = PageAlign(phys) | PRESENT_BIT | READ_WRITE_BIT;
|
||||||
ZeroOutPage(reinterpret_cast<uint64_t*>(virt));
|
ZeroOutPage(reinterpret_cast<uint64_t*>(virt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Pml4Index(uint64_t addr) { return (addr >> PML_OFFSET) & 0x1FF; }
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void InitPaging() {
|
void InitPaging() {
|
||||||
uint64_t pml4_addr = 0;
|
uint64_t pml4_addr = 0;
|
||||||
asm volatile("mov %%cr3, %0;" : "=r"(pml4_addr));
|
asm volatile("mov %%cr3, %0;" : "=r"(pml4_addr));
|
||||||
InitializePml4(pml4_addr);
|
uint64_t* pml4_virtual =
|
||||||
|
reinterpret_cast<uint64_t*>(boot::GetHigherHalfDirectMap() + pml4_addr);
|
||||||
|
|
||||||
|
uint64_t recursive_entry = pml4_addr | PRESENT_BIT | READ_WRITE_BIT;
|
||||||
|
pml4_virtual[0x1FE] = recursive_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializePml4(uint64_t pml4_physical_addr) {
|
void InitializePml4(uint64_t pml4_physical_addr) {
|
||||||
uint64_t* pml4_virtual = reinterpret_cast<uint64_t*>(
|
uint64_t* pml4_virtual = reinterpret_cast<uint64_t*>(
|
||||||
boot::GetHigherHalfDirectMap() + pml4_physical_addr);
|
boot::GetHigherHalfDirectMap() + pml4_physical_addr);
|
||||||
|
|
||||||
|
// Map the recursive entry.
|
||||||
uint64_t recursive_entry = pml4_physical_addr | PRESENT_BIT | READ_WRITE_BIT;
|
uint64_t recursive_entry = pml4_physical_addr | PRESENT_BIT | READ_WRITE_BIT;
|
||||||
pml4_virtual[0x1FE] = recursive_entry;
|
pml4_virtual[0x1FE] = recursive_entry;
|
||||||
|
|
||||||
|
// Map the kernel entry.
|
||||||
|
// This should contain the heap at 0xFFFFFFFF'40000000
|
||||||
|
uint64_t kernel_addr = 0xFFFFFFFF'80000000;
|
||||||
|
pml4_virtual[Pml4Index(kernel_addr)] = *Pml4Entry(kernel_addr);
|
||||||
|
|
||||||
|
// Map the HHDM.
|
||||||
|
// This is necessary to access values off of the kernel stack.
|
||||||
|
uint64_t hhdm = boot::GetHigherHalfDirectMap();
|
||||||
|
pml4_virtual[Pml4Index(hhdm)] = *Pml4Entry(hhdm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AllocatePage(uint64_t addr) {
|
void AllocatePage(uint64_t addr) {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "scheduler/process.h"
|
#include "scheduler/process.h"
|
||||||
|
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
#include "memory/paging_util.h"
|
||||||
|
#include "memory/physical_memory.h"
|
||||||
|
#include "scheduler/scheduler.h"
|
||||||
#include "scheduler/thread.h"
|
#include "scheduler/thread.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -22,18 +25,29 @@ Process* Process::RootProcess() {
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* Process::CreateThread() {
|
Process::Process() : id_(gNextId++) {
|
||||||
Thread* thread = new Thread(this, next_thread_id_++);
|
cr3_ = phys_mem::AllocatePage();
|
||||||
|
InitializePml4(cr3_);
|
||||||
|
CreateThread();
|
||||||
|
}
|
||||||
|
|
||||||
ThreadEntry* entry = thread_list_front_;
|
void Process::CreateThread() {
|
||||||
while (entry->next != nullptr) {
|
Thread* thread = new Thread(this, next_thread_id_++);
|
||||||
entry = entry->next;
|
ThreadEntry* tentry = new ThreadEntry{
|
||||||
}
|
|
||||||
entry->next = new ThreadEntry{
|
|
||||||
.thread = thread,
|
.thread = thread,
|
||||||
.next = nullptr,
|
.next = nullptr,
|
||||||
};
|
};
|
||||||
return thread;
|
|
||||||
|
if (thread_list_front_ == nullptr) {
|
||||||
|
thread_list_front_ = tentry;
|
||||||
|
} else {
|
||||||
|
ThreadEntry* entry = thread_list_front_;
|
||||||
|
while (entry->next != nullptr) {
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
entry->next = tentry;
|
||||||
|
}
|
||||||
|
sched::EnqueueThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* Process::GetThread(uint64_t tid) {
|
Thread* Process::GetThread(uint64_t tid) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Process {
|
||||||
uint64_t id() { return id_; }
|
uint64_t id() { return id_; }
|
||||||
uint64_t cr3() { return cr3_; }
|
uint64_t cr3() { return cr3_; }
|
||||||
|
|
||||||
Thread* CreateThread();
|
void CreateThread();
|
||||||
Thread* GetThread(uint64_t tid);
|
Thread* GetThread(uint64_t tid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -49,8 +49,6 @@ class Scheduler {
|
||||||
Process* root = Process::RootProcess();
|
Process* root = Process::RootProcess();
|
||||||
current_thread_ = root->GetThread(0);
|
current_thread_ = root->GetThread(0);
|
||||||
proc_list_.InsertProcess(Process::RootProcess());
|
proc_list_.InsertProcess(Process::RootProcess());
|
||||||
// FIXME: Don't enqueue threads here.
|
|
||||||
Enqueue(root->CreateThread());
|
|
||||||
}
|
}
|
||||||
void Enable() { enabled_ = true; }
|
void Enable() { enabled_ = true; }
|
||||||
|
|
||||||
|
@ -79,7 +77,9 @@ class Scheduler {
|
||||||
Thread* prev = current_thread_;
|
Thread* prev = current_thread_;
|
||||||
current_thread_ = current_thread_->next_thread_;
|
current_thread_ = current_thread_->next_thread_;
|
||||||
prev->next_thread_ = nullptr;
|
prev->next_thread_ = nullptr;
|
||||||
Enqueue(prev);
|
if (prev->pid() != 0) {
|
||||||
|
Enqueue(prev);
|
||||||
|
}
|
||||||
context_switch(prev->Rsp0Ptr(), current_thread_->Rsp0Ptr());
|
context_switch(prev->Rsp0Ptr(), current_thread_->Rsp0Ptr());
|
||||||
|
|
||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
|
@ -108,6 +108,8 @@ void EnableScheduler() { GetScheduler().Enable(); }
|
||||||
|
|
||||||
void Yield() { GetScheduler().Yield(); }
|
void Yield() { GetScheduler().Yield(); }
|
||||||
|
|
||||||
|
void EnqueueThread(Thread* thread) { GetScheduler().Enqueue(thread); }
|
||||||
|
|
||||||
Process& CurrentProcess() { return GetScheduler().CurrentProcess(); }
|
Process& CurrentProcess() { return GetScheduler().CurrentProcess(); }
|
||||||
Thread& CurrentThread() { return GetScheduler().CurrentThread(); }
|
Thread& CurrentThread() { return GetScheduler().CurrentThread(); }
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,8 @@ namespace {
|
||||||
|
|
||||||
extern "C" void thread_init() {
|
extern "C" void thread_init() {
|
||||||
asm("sti");
|
asm("sti");
|
||||||
dbgln("New Thread!");
|
sched::CurrentThread().Init();
|
||||||
sched::Yield();
|
panic("Reached end of thread.");
|
||||||
panic("End of thread.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -32,3 +31,10 @@ Thread::Thread(Process* proc, uint64_t tid) : process_(proc), id_(tid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Thread::pid() { return process_->id(); }
|
uint64_t Thread::pid() { return process_->id(); }
|
||||||
|
|
||||||
|
void Thread::Init() {
|
||||||
|
while (true) {
|
||||||
|
dbgln("[%u.%u]", pid(), id_);
|
||||||
|
sched::Yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ class Thread {
|
||||||
|
|
||||||
uint64_t* Rsp0Ptr() { return &rsp0_; }
|
uint64_t* Rsp0Ptr() { return &rsp0_; }
|
||||||
|
|
||||||
|
// Called the first time the thread starts up.
|
||||||
|
void Init();
|
||||||
|
|
||||||
// FIXME: Probably make this private.
|
// FIXME: Probably make this private.
|
||||||
Thread* next_thread_;
|
Thread* next_thread_;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ extern "C" void zion() {
|
||||||
phys_mem::InitPhysicalMemoryManager();
|
phys_mem::InitPhysicalMemoryManager();
|
||||||
|
|
||||||
sched::InitScheduler();
|
sched::InitScheduler();
|
||||||
|
Process p1;
|
||||||
|
p1.CreateThread();
|
||||||
|
Process p2;
|
||||||
|
p2.CreateThread();
|
||||||
sched::EnableScheduler();
|
sched::EnableScheduler();
|
||||||
sched::Yield();
|
sched::Yield();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue