Update files

This commit is contained in:
Alex 2022-10-23 02:18:29 +03:00
parent 84b9f6bdf0
commit 8308506ace
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
8 changed files with 324 additions and 115 deletions

View File

@ -1,6 +1,7 @@
#include "apic.hpp"
#include <memory.hpp>
#include <uart.hpp>
#include <cpu.hpp>
#include <smp.hpp>
#include <io.h>
@ -49,7 +50,10 @@ namespace APIC
void APIC::Write(uint32_t Register, uint32_t Value)
{
if (Register != APIC_EOI)
if (Register != APIC_EOI &&
Register != APIC_TDCR &&
Register != APIC_TIMER &&
Register != APIC_TICR)
debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
if (x2APICSupported)
{
@ -209,6 +213,9 @@ namespace APIC
void Timer::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
// fixme("APIC IRQ0 INTERRUPT RECEIVED ON CPU %d", CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE));
// UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('\n');
// UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('H');
// UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('\n');
}
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
@ -231,9 +238,9 @@ namespace APIC
IOIn = (IOIn & 0xFD) | 1;
outb(0x61, IOIn);
outb(0x43, 178);
outb(0x42, Ticks & 0xff);
outb(0x40, Ticks & 0xff);
inb(0x60);
outb(0x42, Ticks >> 8);
outb(0x40, Ticks >> 8);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);

View File

@ -47,7 +47,8 @@ extern "C" void StartCPU()
CPU::Interrupts(CPU::Enable);
KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
CPUEnabled = true;
CPU::Stop(); // Stop and surpress interrupts.
while (1)
CPU::Halt();
}
namespace SMP
@ -100,7 +101,7 @@ namespace SMP
((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x600 | ((uint32_t)TRAMPOLINE_START / PAGE_SIZE));
while (!CPUEnabled)
;
CPU::Pause();
trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId);
KernelAllocator.FreePages((void *)*reinterpret_cast<long *>(STACK), TO_PAGES(STACK_SIZE));

View File

@ -118,6 +118,7 @@ namespace Interrupts
if (apic[Core])
{
((APIC::APIC *)Interrupts::apic[Core])->EOI();
// apic->IPI(CurrentCPU->ID, SchedulerInterrupt); ??????
return;
}
// TODO: PIC

View File

@ -6,7 +6,8 @@ void KernelMainThread()
{
KPrint("Kernel main thread started!");
// asm("int $0x1");
CPU::Stop();
while (1)
CPU::Halt();
}
void KernelShutdownThread(bool Reboot)

View File

@ -57,11 +57,11 @@ EXTERNC void Entry(BootInfo *Info)
KPrint("CPU: \e8822AA%s \e8888FF%s (\e058C19%s\e8888FF)", CPU::Vendor(), CPU::Name(), CPU::Hypervisor());
KPrint("Initializing GDT and IDT");
Interrupts::Initialize(0);
KPrint("Initializing CPU features");
KPrint("Initializing CPU Features");
CPU::InitializeFeatures();
KPrint("Loading kernel symbols");
KPrint("Loading Kernel Symbols");
KernelSymbolTable = new SymbolResolver::Symbols((uint64_t)Info->Kernel.FileBase);
KPrint("Reading kernel parameters");
KPrint("Reading Kernel Parameters");
Config = ParseConfig((char *)bInfo->Kernel.CommandLine);
KPrint("Initializing Power Manager");
PowerManager = new Power::Power;
@ -76,14 +76,14 @@ EXTERNC void Entry(BootInfo *Info)
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass),
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
}
KPrint("Enabling interrupts");
KPrint("Enabling Interrupts on Bootstrap Processor");
Interrupts::Enable(0);
KPrint("Initializing timer");
KPrint("Initializing Bootstrap Processor Timer");
Interrupts::InitializeTimer(0);
KPrint("Initializing SMP");
SMP::Initialize(PowerManager->GetMADT());
CPU::Interrupts(CPU::Enable);
TaskManager = new Tasking::Task((Tasking::IP)KernelMainThread);
KPrint("\e058C19######## \eE85230END \e058C19########");
CPU::Stop();
while (1)
CPU::Halt();
}

View File

@ -13,7 +13,7 @@
#elif defined(__aarch64__)
#endif
#define DEBUG_SCHEDULER 1
// #define DEBUG_SCHEDULER 1
#ifdef DEBUG_SCHEDULER
#define schedbg(m, ...) debug(m, ##__VA_ARGS__)
@ -50,15 +50,266 @@ namespace Tasking
#endif
}
Vector<PCB *> ListProcess;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
#if defined(__amd64__)
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
fixme("unimplemented");
OneShot(500); // test
SmartCriticalSection(TaskingLock);
CPUData *CurrentCPU = GetCurrentCPU();
debug("Scheduler called on CPU %d.", CurrentCPU->ID);
schedbg("Status: 0-ukn | 1-rdy | 2-run | 3-wait | 4-term");
schedbg("Technical Informations on regs %#lx", Frame->InterruptNumber);
schedbg("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, Frame->ds);
schedbg("R8=%#lx R9=%#lx R10=%#lx R11=%#lx",
Frame->r8, Frame->r9, Frame->r10, Frame->r11);
schedbg("R12=%#lx R13=%#lx R14=%#lx R15=%#lx",
Frame->r12, Frame->r13, Frame->r14, Frame->r15);
schedbg("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx",
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
schedbg("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx",
Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx",
Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode);
// Null or invalid process/thread? Let's find a new one to execute.
if (InvalidPCB(CurrentCPU->CurrentProcess) || InvalidTCB(CurrentCPU->CurrentThread))
{
schedbg("%d processes", ListProcess.size());
#ifdef DEBUG_SCHEDULER
foreach (auto var in ListProcess)
{
schedbg("Process %d %s", var->ID, var->Name);
}
#endif
// Find a new process to execute.
foreach (PCB *pcb in ListProcess)
{
if (InvalidPCB(pcb))
continue;
// Check process status.
switch (pcb->Status)
{
case TaskStatus::Ready:
schedbg("Ready process (%s)%d", pcb->Name, pcb->ID);
break;
default:
schedbg("Process %s(%d) status %d", pcb->Name, pcb->ID, pcb->Status);
// RemoveProcess(pcb); // ignore for now
continue;
}
// Get first available thread from the list.
foreach (TCB *tcb in pcb->Threads)
{
if (InvalidTCB(tcb))
continue;
if (tcb->Status != TaskStatus::Ready)
continue;
// Set process and thread as the current one's.
CurrentCPU->CurrentProcess = pcb;
CurrentCPU->CurrentThread = tcb;
// Success!
goto Success;
}
}
schedbg("No process to run.");
// No process found. Idling...
goto Idle;
}
else
{
// Save current process and thread registries, gs, fs, fpu, etc...
CurrentCPU->CurrentThread->Registers = *Frame;
// _fxsave(CurrentCPU->CurrentThread->FXRegion);
// Set the process & thread as ready if it's running.
if (CurrentCPU->CurrentProcess->Status == TaskStatus::Running)
CurrentCPU->CurrentProcess->Status = TaskStatus::Ready;
if (CurrentCPU->CurrentThread->Status == TaskStatus::Running)
CurrentCPU->CurrentThread->Status = TaskStatus::Ready;
// Get next available thread from the list.
for (uint64_t i = 0; i < CurrentCPU->CurrentProcess->Threads.size(); i++)
{
// Loop until we find the current thread from the process thread list.
if (CurrentCPU->CurrentProcess->Threads[i] == CurrentCPU->CurrentThread)
{
// Check if the next thread is valid. If not, we search until we find, but if we reach the end of the list, we go to the next process.
uint64_t tmpidx = i;
RetryAnotherThread:
TCB *thread = CurrentCPU->CurrentProcess->Threads[tmpidx + 1];
if (InvalidTCB(thread))
{
if (tmpidx > CurrentCPU->CurrentProcess->Threads.size())
break;
tmpidx++;
goto RetryAnotherThread;
}
schedbg("%s(%d) and next thread is %s(%d)", CurrentCPU->CurrentProcess->Threads[i]->Name, CurrentCPU->CurrentProcess->Threads[i]->ID, thread->Name, thread->ID);
// Check if the thread is ready to be executed.
if (thread->Status != TaskStatus::Ready)
{
schedbg("Thread %d is not ready", thread->ID);
goto RetryAnotherThread;
}
// Everything is fine, we can set the new thread as the current one.
CurrentCPU->CurrentThread = thread;
schedbg("[thd 0 -> end] Scheduling thread %d parent of %s->%d Procs %d", thread->ID, thread->Parent->Name, CurrentCPU->CurrentProcess->Threads.size(), ListProcess.size());
// Yay! We found a new thread to execute.
goto Success;
}
}
// If the last process didn't find a thread to execute, we search for a new process.
for (uint64_t i = 0; i < ListProcess.size(); i++)
{
// Loop until we find the current process from the process list.
if (ListProcess[i] == CurrentCPU->CurrentProcess)
{
// Check if the next process is valid. If not, we search until we find.
uint64_t tmpidx = i;
RetryAnotherProcess:
PCB *pcb = ListProcess[tmpidx + 1];
if (InvalidPCB(pcb))
{
if (tmpidx > ListProcess.size())
break;
tmpidx++;
goto RetryAnotherProcess;
}
if (pcb->Status != TaskStatus::Ready)
goto RetryAnotherProcess;
// Everything good, now search for a thread.
for (uint64_t j = 0; j < pcb->Threads.size(); j++)
{
TCB *tcb = pcb->Threads[j];
if (InvalidTCB(tcb))
continue;
if (tcb->Status != TaskStatus::Ready)
continue;
// Success! We set as the current one and restore the stuff.
CurrentCPU->CurrentProcess = pcb;
CurrentCPU->CurrentThread = tcb;
schedbg("[cur proc+1 -> first thd] Scheduling thread %d %s->%d (Total Procs %d)", tcb->ID, tcb->Name, pcb->Threads.size(), ListProcess.size());
goto Success;
}
}
}
// Before checking from the beginning, we remove everything that is terminated.
foreach (PCB *pcb in ListProcess)
{
if (InvalidPCB(pcb))
continue;
// RemoveProcess(pcb); // comment this until i will find a way to handle properly vectors, the memory need to be 0ed after removing.
}
// If we didn't find anything, we check from the start of the list. This is the last chance to find something or we go to idle.
foreach (PCB *pcb in ListProcess)
{
if (InvalidPCB(pcb))
continue;
if (pcb->Status != TaskStatus::Ready)
continue;
// Now do the thread search!
foreach (TCB *tcb in pcb->Threads)
{
if (InvalidTCB(tcb))
continue;
if (tcb->Status != TaskStatus::Ready)
continue;
// \o/ We found a new thread to execute.
CurrentCPU->CurrentProcess = pcb;
CurrentCPU->CurrentThread = tcb;
schedbg("[proc 0 -> end -> first thd] Scheduling thread %d parent of %s->%d (Procs %d)", tcb->ID, tcb->Parent->Name, pcb->Threads.size(), ListProcess.size());
goto Success;
}
}
}
Idle:
{
// I should remove processes that are no longer having any threads? remove only from userspace?
if (IdleProcess == nullptr)
{
schedbg("Idle process created");
IdleProcess = CreateProcess(nullptr, (char *)"idle", TaskTrustLevel::Idle);
IdleThread = CreateThread(IdleProcess, reinterpret_cast<uint64_t>(IdleProcessLoop), 0);
}
CurrentCPU->CurrentProcess = IdleProcess;
CurrentCPU->CurrentThread = IdleThread;
*Frame = CurrentCPU->CurrentThread->Registers;
// UpdatePageTable(CurrentCPU->CurrentProcess->PageTable); // kernel one
// _fxrstor(CurrentCPU->CurrentThread->FXRegion);
goto End;
}
Success:
{
schedbg("Success Prc:%s(%d) Thd:%s(%d)->RIP:%#lx-RSP:%#lx(STACK: %#lx)",
CurrentCPU->CurrentProcess->Name, CurrentCPU->CurrentProcess->ID,
CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID,
CurrentCPU->CurrentThread->Registers.rip, CurrentCPU->CurrentThread->Registers.rsp, CurrentCPU->CurrentThread->Stack);
CurrentCPU->CurrentProcess->Status = TaskStatus::Running;
CurrentCPU->CurrentThread->Status = TaskStatus::Running;
*Frame = CurrentCPU->CurrentThread->Registers;
// UpdatePageTable(CurrentCPU->CurrentProcess->PageTable);
switch (CurrentCPU->CurrentProcess->Security.TrustLevel)
{
case TaskTrustLevel::System:
case TaskTrustLevel::Idle:
case TaskTrustLevel::Kernel:
// wrmsr(MSR_SHADOW_GS_BASE, (uint64_t)CurrentCPU->CurrentThread);
break;
case TaskTrustLevel::User:
// wrmsr(MSR_SHADOW_GS_BASE, CurrentCPU->CurrentThread->gs);
break;
default:
error("Unknown trust level %d.", CurrentCPU->CurrentProcess->Security.TrustLevel);
break;
}
// _fxrstor(CurrentCPU->CurrentThread->FXRegion);
}
End:
{
// UpdateTimeUsed(&CurrentCPU->CurrentProcess->Info);
// UpdateTimeUsed(&CurrentCPU->CurrentThread->Info);
// UpdateCPUUsage(&CurrentCPU->CurrentProcess->Info);
// UpdateCPUUsage(&CurrentCPU->CurrentThread->Info);
OneShot(CurrentCPU->CurrentThread->Info.Priority);
schedbg("Scheduler end");
}
schedbg("Technical Informations on Thread %s[%ld]:", CurrentCPU->CurrentThread->Name, CurrentCPU->CurrentThread->ID);
schedbg("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx",
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
Frame->ss, Frame->cs, Frame->ds);
schedbg("R8=%#lx R9=%#lx R10=%#lx R11=%#lx",
Frame->r8, Frame->r9, Frame->r10, Frame->r11);
schedbg("R12=%#lx R13=%#lx R14=%#lx R15=%#lx",
Frame->r12, Frame->r13, Frame->r14, Frame->r15);
schedbg("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx",
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
schedbg("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx",
Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
schedbg("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx",
Frame->rip, Frame->rflags, Frame->InterruptNumber, Frame->ErrorCode);
schedbg("SCHEDULER FUNCTION END");
}
#elif defined(__i386__)
__attribute__((no_stack_protector)) void Task::OnInterruptReceived(void *Frame)
@ -112,7 +363,12 @@ namespace Tasking
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
#if defined(__amd64__)
memset(&Thread->Registers, 0, sizeof(CPU::x64::TrapFrame)); // Just in case
Thread->Registers.rip = (EntryPoint + Offset);
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
switch (Parent->Security.TrustLevel)
{
case TaskTrustLevel::System:
@ -265,6 +521,7 @@ namespace Tasking
Process->Info.Priority = 0;
Parent->Children.push_back(Process);
ListProcess.push_back(Process);
return Process;
}
@ -290,12 +547,21 @@ namespace Tasking
kthrd->Rename("Main Thread");
debug("Created Kernel Process: %s and Thread: %s", kproc->Name, kthrd->Name);
TaskingLock.Lock();
#if defined(__amd64__) || defined(__i386__)
uint32_t rax, rbx, rcx, rdx;
CPU::x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
if (rcx & CPU::x64::CPUID_FEAT_RCX_MONITOR)
{
trace("CPU has MONITOR/MWAIT support.");
}
for (int i = 0; i < SMP::CPUCores; i++)
{
/* do stuff i guess */
((APIC::Timer *)Interrupts::apicTimer[i])->OneShot(CPU::x64::IRQ16, 100);
((APIC::Timer *)Interrupts::apicTimer[i])->OneShot(CPU::x64::IRQ16, 1000);
}
// ((APIC::Timer *)Interrupts::apicTimer[0])->OneShot(CPU::x64::IRQ16, 100);
#endif
debug("Tasking Started");
}

View File

@ -136,7 +136,7 @@ namespace CPU
/**
* @brief Pause the CPU
*/
static inline void Pause()
__attribute__((no_stack_protector)) static inline void Pause()
{
#if defined(__amd64__) || defined(__i386__)
asmv("pause");
@ -148,7 +148,7 @@ namespace CPU
/**
* @brief Stop the CPU (infinite loop)
*/
static inline void Stop()
__attribute__((no_stack_protector)) static inline void Stop()
{
while (1)
{
@ -158,11 +158,8 @@ namespace CPU
"hlt\n"
"jmp CPUStopLoop");
#elif defined(__aarch64__)
while (1)
{
asmv("msr daifset, #2");
asmv("wfe");
}
#endif
}
}
@ -170,7 +167,7 @@ namespace CPU
/**
* @brief Halt the CPU
*/
static inline void Halt()
__attribute__((no_stack_protector)) static inline void Halt()
{
#if defined(__amd64__) || defined(__i386__)
asmv("hlt");

View File

@ -15,90 +15,6 @@ namespace Tasking
typedef unsigned long UTID;
typedef unsigned long Token;
struct ThreadFrame
{
#if defined(__amd64__)
// uint64_t gs; // General-purpose Segment
// uint64_t fs; // General-purpose Segment
// uint64_t es; // Extra Segment (used for string operations)
uint64_t ds; // Data Segment
uint64_t r15; // General purpose
uint64_t r14; // General purpose
uint64_t r13; // General purpose
uint64_t r12; // General purpose
uint64_t r11; // General purpose
uint64_t r10; // General purpose
uint64_t r9; // General purpose
uint64_t r8; // General purpose
uint64_t rbp; // Base Pointer (meant for stack frames)
uint64_t rdi; // First Argument
uint64_t rsi; // Second Argument
uint64_t rdx; // Data (commonly extends the A register)
uint64_t rcx; // Counter
uint64_t rbx; // Base
uint64_t rax; // Accumulator
uint64_t int_num; // Interrupt Number
uint64_t error_code; // Error code
uint64_t rip; // Instruction Pointer
uint64_t cs; // Code Segment
union
{
struct
{
/** @brief Carry Flag */
uint64_t CF : 1;
/** @brief Reserved */
uint64_t AlwaysOne : 1;
/** @brief Parity Flag */
uint64_t PF : 1;
/** @brief Reserved */
uint64_t Reserved0 : 1;
/** @brief Auxiliary Carry Flag */
uint64_t AF : 1;
/** @brief Reserved */
uint64_t Reserved1 : 1;
/** @brief Zero Flag */
uint64_t ZF : 1;
/** @brief Sign Flag */
uint64_t SF : 1;
/** @brief Trap Flag */
uint64_t TF : 1;
/** @brief Interrupt Enable Flag */
uint64_t IF : 1;
/** @brief Direction Flag */
uint64_t DF : 1;
/** @brief Overflow Flag */
uint64_t OF : 1;
/** @brief I/O Privilege Level */
uint64_t IOPL : 2;
/** @brief Nested Task */
uint64_t NT : 1;
/** @brief Reserved */
uint64_t Reserved2 : 1;
/** @brief Resume Flag */
uint64_t RF : 1;
/** @brief Virtual 8086 Mode */
uint64_t VM : 1;
/** @brief Alignment Check */
uint64_t AC : 1;
/** @brief Virtual Interrupt Flag */
uint64_t VIF : 1;
/** @brief Virtual Interrupt Pending */
uint64_t VIP : 1;
/** @brief ID Flag */
uint64_t ID : 1;
/** @brief Reserved */
uint64_t Reserved3 : 10;
};
uint64_t raw;
} rflags; // Register Flags
uint64_t rsp; // Stack Pointer
uint64_t ss; // Stack Segment / Data Segment
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
};
enum TaskArchitecture
{
UnknownArchitecture,
@ -164,7 +80,13 @@ namespace Tasking
int ExitCode;
void *Stack;
TaskStatus Status;
ThreadFrame Registers;
#if defined(__amd64__)
CPU::x64::TrapFrame Registers;
#elif defined(__i386__)
uint32_t Registers; // TODO
#elif defined(__aarch64__)
uint64_t Registers; // TODO
#endif
TaskSecurity Security;
TaskInfo Info;
@ -220,6 +142,20 @@ namespace Tasking
UPID NextPID = 0;
UTID NextTID = 0;
Vector<PCB *> ListProcess;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
bool InvalidPCB(PCB *pcb)
{
return false;
}
bool InvalidTCB(TCB *tcb)
{
return false;
}
#if defined(__amd64__)
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
#elif defined(__i386__)