Updated tasking

This commit is contained in:
Alex
2022-10-22 04:56:57 +03:00
parent 11e6080fe1
commit 4f94d4cc6d
8 changed files with 335 additions and 127 deletions

View File

@ -1,6 +1,5 @@
#include <task.hpp>
#include <interrupts.hpp>
#include <lock.hpp>
#include <debug.h>
#include <smp.hpp>
@ -14,6 +13,14 @@
#elif defined(__aarch64__)
#endif
#define DEBUG_SCHEDULER 1
#ifdef DEBUG_SCHEDULER
#define schedbg(m, ...) debug(m, ##__VA_ARGS__)
#else
#define schedbg(m, ...)
#endif
NewLock(TaskingLock);
namespace Tasking
@ -27,7 +34,7 @@ namespace Tasking
#endif
}
extern "C" __attribute__((naked, used, no_stack_protector)) void IdleProcessLoop()
__attribute__((naked, used, no_stack_protector)) void IdleProcessLoop()
{
#if defined(__amd64__) || defined(__i386__)
asmv("IdleLoop:\n"
@ -41,61 +48,36 @@ namespace Tasking
#endif
}
/** @brief Called by the IDT (IRQ16 for x64 and x32) */
extern "C" __attribute__((naked, used, no_stack_protector)) void SchedulerInterruptStub()
{
#if defined(__amd64__)
asm("cld\n"
"pushq %rax\n"
"pushq %rbx\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"pushq %rbp\n"
"pushq %r8\n"
"pushq %r9\n"
"pushq %r10\n"
"pushq %r11\n"
"pushq %r12\n"
"pushq %r13\n"
"pushq %r14\n"
"pushq %r15\n"
"movq %ds, %rax\n"
"pushq %rax\n"
"movq %rsp, %rdi\n"
"call SchedulerInterruptHandler\n"
"popq %rax\n" // Pop the DS register
"popq %r15\n"
"popq %r14\n"
"popq %r13\n"
"popq %r12\n"
"popq %r11\n"
"popq %r10\n"
"popq %r9\n"
"popq %r8\n"
"popq %rbp\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"popq %rbx\n"
"popq %rax\n"
"addq $16, %rsp\n"
"iretq");
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
}
Vector<PCB *> ListProcess;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
extern "C" __attribute__((no_stack_protector)) void SchedulerInterruptHandler(ThreadFrame *Frame)
{
fixme("SchedulerInterruptHandler: %d", GetCurrentCPU()->ID);
#if defined(__amd64__)
((APIC::APIC *)Interrupts::apic[GetCurrentCPU()->ID])->EOI();
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
fixme("unimplemented");
}
#elif defined(__i386__)
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
{
fixme("unimplemented");
}
#elif defined(__aarch64__)
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
{
fixme("unimplemented");
}
#endif
void ThreadDoExit(int Code)
{
SmartCriticalSection(TaskingLock);
CPUData *CPUData = GetCurrentCPU();
CPUData->CurrentThread->Status = TaskStatus::Terminated;
CPUData->CurrentThread->ExitCode = Code;
debug("parent:%s tid:%d, code:%016p", CPUData->CurrentProcess->Name, CPUData->CurrentThread->ID, Code);
trace("Exiting thread %d(%s)...", CPUData->CurrentThread->ID, CPUData->CurrentThread->Name);
CPU::Stop();
}
PCB *Task::GetCurrentProcess()
@ -110,46 +92,208 @@ namespace Tasking
return GetCurrentCPU()->CurrentThread;
}
PCB *Task::CreateProcess(PCB *Parent,
const char *Name,
TaskElevation Elevation)
{
SmartCriticalSection(TaskingLock);
PCB *Process = new PCB;
#if defined(__amd64__)
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
return Process;
}
TCB *Task::CreateThread(PCB *Parent,
IP EntryPoint)
IP EntryPoint,
IPOffset Offset,
TaskArchitecture Architecture,
TaskCompatibility Compatibility)
{
SmartCriticalSection(TaskingLock);
TCB *Thread = new TCB;
Thread->ID = this->NextTID++;
strcpy(Thread->Name, Parent->Name);
Thread->Parent = Parent;
Thread->EntryPoint = EntryPoint;
Thread->Offset = Offset;
Thread->ExitCode = 0xdeadbeef;
Thread->Stack = (void *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
Thread->Status = TaskStatus::Ready;
memset(&Thread->Registers, 0, sizeof(ThreadFrame)); // Just in case
switch (Parent->Security.TrustLevel)
{
case TaskTrustLevel::System:
warn("Trust level not supported.");
[[fallthrough]];
case TaskTrustLevel::Idle:
case TaskTrustLevel::Kernel:
{
#if defined(__amd64__)
SecurityManager.TrustToken(Thread->Security.UniqueToken, TokenTrustLevel::TrustedByKernel);
Thread->Registers.cs = GDT_KERNEL_CODE;
Thread->Registers.ds = GDT_KERNEL_DATA;
Thread->Registers.ss = GDT_KERNEL_DATA;
Thread->Registers.rflags.AlwaysOne = 1;
Thread->Registers.rflags.IF = 1;
Thread->Registers.rflags.ID = 1;
Thread->Registers.rsp = (uint64_t)Thread->Stack;
POKE(uint64_t, Thread->Registers.rsp) = (uint64_t)ThreadDoExit;
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
break;
}
case TaskTrustLevel::User:
{
#if defined(__amd64__)
SecurityManager.TrustToken(Thread->Security.UniqueToken, TokenTrustLevel::Untrusted);
Thread->Registers.cs = GDT_USER_CODE;
Thread->Registers.ds = GDT_USER_DATA;
Thread->Registers.ss = GDT_USER_DATA;
Thread->Registers.rflags.AlwaysOne = 1;
Thread->Registers.rflags.IF = 1;
Thread->Registers.rflags.ID = 1;
Thread->Registers.rsp = (uint64_t)Thread->Stack;
/* We need to leave the libc's crt to make a syscall when the Thread is exited or we are going to get GPF or PF exception. */
for (uint64_t i = 0; i < TO_PAGES(STACK_SIZE); i++)
Memory::Virtual().Map((void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)),
(void *)((uint64_t)Thread->Stack + (i * PAGE_SIZE)),
Memory::PTFlag::US);
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
break;
}
default:
{
error("Unknown elevation.");
KernelAllocator.FreePages((void *)((uint64_t)Thread->Stack - STACK_SIZE), TO_PAGES(STACK_SIZE));
delete Thread;
return nullptr;
}
}
Thread->Security.TrustLevel = Parent->Security.TrustLevel;
Thread->Security.UniqueToken = SecurityManager.CreateToken();
Thread->Info.SpawnTime = 0;
Thread->Info.UsedTime = 0;
Thread->Info.OldUsedTime = 0;
Thread->Info.OldSystemTime = 0;
Thread->Info.CurrentSystemTime = 0;
Thread->Info.Year = 0;
Thread->Info.Month = 0;
Thread->Info.Day = 0;
Thread->Info.Hour = 0;
Thread->Info.Minute = 0;
Thread->Info.Second = 0;
for (int i = 0; i < MAX_CPU; i++)
{
Thread->Info.Usage[i] = 0;
Thread->Info.Affinity[i] = 0;
}
Thread->Info.Priority = 0;
Thread->Info.Architecture = Architecture;
Thread->Info.Compatibility = Compatibility;
Parent->Threads.push_back(Thread);
return Thread;
}
Task::Task(const IP EntryPoint)
PCB *Task::CreateProcess(PCB *Parent,
const char *Name,
TaskTrustLevel TrustLevel)
{
SmartCriticalSection(TaskingLock);
PCB *Process = new PCB;
Process->ID = this->NextPID++;
strcpy(Process->Name, Name);
Process->Parent = Parent;
Process->ExitCode = 0xdeadbeef;
Process->Status = TaskStatus::Ready;
Process->Security.TrustLevel = TrustLevel;
Process->Security.UniqueToken = SecurityManager.CreateToken();
switch (TrustLevel)
{
case TaskTrustLevel::System:
warn("Trust level not supported.");
[[fallthrough]];
case TaskTrustLevel::Idle:
case TaskTrustLevel::Kernel:
{
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::TrustedByKernel);
#if defined(__amd64__)
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(Process->PageTable, 0, PAGE_SIZE);
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
memcpy(Process->PageTable, (void *)cr3.raw, PAGE_SIZE);
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
break;
}
case TaskTrustLevel::User:
{
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::Untrusted);
#if defined(__amd64__)
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
// TODO: Do mapping for page table
fixme("User process page table mapping not implemented.");
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
break;
}
default:
{
error("Unknown elevation.");
delete Process;
return nullptr;
}
}
Process->Info.SpawnTime = 0;
Process->Info.UsedTime = 0;
Process->Info.OldUsedTime = 0;
Process->Info.OldSystemTime = 0;
Process->Info.CurrentSystemTime = 0;
Process->Info.Year = 0;
Process->Info.Month = 0;
Process->Info.Day = 0;
Process->Info.Hour = 0;
Process->Info.Minute = 0;
Process->Info.Second = 0;
for (int i = 0; i < MAX_CPU; i++)
{
Process->Info.Usage[i] = 0;
Process->Info.Affinity[i] = 0;
}
Process->Info.Priority = 0;
Parent->Children.push_back(Process);
return Process;
}
Task::Task(const IP EntryPoint) : Interrupts::Handler(CPU::x64::IRQ16)
{
SmartCriticalSection(TaskingLock);
KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint));
#if defined(__amd64__) || defined(__i386__)
for (int i = 0; i < SMP::CPUCores; i++)
((APIC::APIC *)Interrupts::apic[i])->RedirectIRQ(i, CPU::x64::IRQ16 - CPU::x64::IRQ0, 1);
KPrint("Starting Tasking With Instruction Pointer: %p (\e666666%s\eCCCCCC)", EntryPoint, KernelSymbolTable->GetSymbolFromAddress(EntryPoint));
TaskingLock.Unlock();
#if defined(__amd64__)
TaskArchitecture Arch = TaskArchitecture::x64;
#elif defined(__i386__)
TaskArchitecture Arch = TaskArchitecture::x32;
#elif defined(__aarch64__)
TaskArchitecture Arch = TaskArchitecture::ARM64;
#endif
TaskingLock.Unlock();
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskElevation::Kernel);
TCB *kthrd = CreateThread(kproc, EntryPoint);
PCB *kproc = CreateProcess(nullptr, "Kernel", TaskTrustLevel::Kernel);
TCB *kthrd = CreateThread(kproc, EntryPoint, 0, Arch);
kthrd->Rename("Main Thread");
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
TaskingLock.Lock();
OneShot(100);
#if defined(__amd64__) || defined(__i386__)
for (int i = 0; i < SMP::CPUCores; i++)
{
/* do stuff i guess */
((APIC::Timer *)Interrupts::apicTimer[i])->OneShot(CPU::x64::IRQ16, 100);
}
#endif
debug("Tasking Started");
}