scheduler: Fix page table switch for scheduler

The userspace process may map pages where the kernel has allocated data and cause a crash.

This patch fixes this issue by having a separate IRQ handler which sets the kernel page table at the start of SchedulerInterruptHandler() and restores it in SchedulerHandlerStub() function.
This commit is contained in:
EnderIce2
2024-11-17 03:11:20 +02:00
parent 079055082a
commit 86a119ea51
9 changed files with 161 additions and 21 deletions

View File

@ -556,7 +556,7 @@ namespace Tasking::Scheduler
}
}
nsa NIF void Custom::Schedule(CPU::TrapFrame *Frame)
nsa NIF void Custom::Schedule(CPU::SchedulerFrame *Frame)
{
if (unlikely(StopScheduler))
{
@ -564,9 +564,6 @@ namespace Tasking::Scheduler
return;
}
bool ProcessNotChanged = false;
/* Restore kernel page table for safety reasons. */
if (!SchedulerUpdateTrapFrame)
KernelPageTable->Update();
uint64_t SchedTmpTicks = TimeManager->GetCounter();
this->LastTaskTicks.store(size_t(SchedTmpTicks - this->SchedulerTicks.load()));
CPUData *CurrentCPU = GetCurrentCPU();
@ -671,6 +668,13 @@ namespace Tasking::Scheduler
CurrentCPU->CurrentProcess->State.store(TaskState::Running);
CurrentCPU->CurrentThread->State.store(TaskState::Running);
if (CurrentCPU->CurrentThread->Registers.cs != GDT_KERNEL_CODE)
CurrentCPU->CurrentThread->Registers.ppt = (uint64_t)(void *)CurrentCPU->CurrentProcess->PageTable;
else
CurrentCPU->CurrentThread->Registers.ppt = (uint64_t)(void *)KernelPageTable;
// if (!SchedulerUpdateTrapFrame) {} // TODO
*Frame = CurrentCPU->CurrentThread->Registers;
#ifdef a64
@ -713,11 +717,9 @@ namespace Tasking::Scheduler
}
this->SchedulerTicks.store(size_t(TimeManager->GetCounter() - SchedTmpTicks));
if (CurrentCPU->CurrentThread->Registers.cs != GDT_KERNEL_CODE)
CurrentCPU->CurrentProcess->PageTable->Update();
}
nsa NIF void Custom::OnInterruptReceived(CPU::TrapFrame *Frame)
nsa NIF void Custom::OnInterruptReceived(CPU::SchedulerFrame *Frame)
{
SmartCriticalSection(SchedulerLock);
this->Schedule(Frame);