From 15523e7d716f016828413857202b831181515a60 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 14 Jun 2026 00:44:02 +0200 Subject: [PATCH] Fix AMD64 thread context setup --- xtoskrnl/ke/amd64/kthread.cc | 67 ++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/xtoskrnl/ke/amd64/kthread.cc b/xtoskrnl/ke/amd64/kthread.cc index 83820e759..67a40eccd 100644 --- a/xtoskrnl/ke/amd64/kthread.cc +++ b/xtoskrnl/ke/amd64/kthread.cc @@ -40,6 +40,7 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, IN PCONTEXT ContextRecord) { PKTHREAD_INIT_FRAME ThreadFrame; + CONTEXT ContextFrame; /* Set initial thread frame */ ThreadFrame = ((PKTHREAD_INIT_FRAME)Thread->InitialStack) - 1; @@ -50,45 +51,60 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, /* Check if context provided for this thread */ if(ContextRecord) { - /* User mode thread needs further initialization, this is not completed */ - UNIMPLEMENTED; + /* Make a local copy of the context to avoid mutating caller's memory */ + RTL::Memory::CopyMemory(&ContextFrame, ContextRecord, sizeof(CONTEXT)); + + /* Disable debug registers and enable context registers */ + ContextFrame.ContextFlags |= CONTEXT_CONTROL; + ContextFrame.ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; + + /* Align the stack and reserve space for 4 parameters and return value */ + ContextFrame.Rsp = (ContextFrame.Rsp & ~15) - 40; + + /* Set CS and SS segments for user mode */ + ContextFrame.SegCs = KGDT_R3_CODE | RPL_MASK; + ContextFrame.SegSs = KGDT_R3_DATA | RPL_MASK; /* Fill exception and trap frames with zeroes */ RTL::Memory::ZeroMemory(&ThreadFrame->ExceptionFrame, sizeof(KEXCEPTION_FRAME)); RTL::Memory::ZeroMemory(&ThreadFrame->TrapFrame, sizeof(KTRAP_FRAME)); - /* Disable debug registers and enable context registers */ - ContextRecord->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; - - /* Align the stack and reserve space for 4 parameters and return value */ - ContextRecord->Rsp = (ContextRecord->Rsp & ~15) - 40; - - /* Set CS and SS segments for user mode */ - ContextRecord->SegCs = KGDT_R3_CODE | RPL_MASK; - ContextRecord->SegSs = KGDT_R3_DATA | RPL_MASK; + /* Translate Context frame to Trap frame */ + KE::Processor::RestoreProcessorContext(&ThreadFrame->TrapFrame, &ThreadFrame->ExceptionFrame, + &ContextFrame, ContextFrame.ContextFlags); /* This is user mode thread */ Thread->PreviousMode = UserMode; + ThreadFrame->TrapFrame.PreviousMode = UserMode; /* Enable floating point state */ Thread->NpxState = NPX_STATE_SCRUB; /* Set initial floating point state */ ThreadFrame->NpxFrame.ControlWord = 0x27F; + ThreadFrame->NpxFrame.DataOffset = 0; + ThreadFrame->NpxFrame.DataSelector = 0; + ThreadFrame->NpxFrame.ErrorOffset = 0; + ThreadFrame->NpxFrame.ErrorOpcode = 0; + ThreadFrame->NpxFrame.ErrorSelector = 0; + ThreadFrame->NpxFrame.StatusWord = 0; ThreadFrame->NpxFrame.TagWord = 0xFFFF; + /* Set initial MXCSR register value */ + ThreadFrame->TrapFrame.MxCsr = INITIAL_MXCSR; + /* Clear DR6 and DR7 registers */ ThreadFrame->TrapFrame.Dr6 = 0; ThreadFrame->TrapFrame.Dr7 = 0; - /* Set initial MXCSR register value */ - ThreadFrame->TrapFrame.MxCsr = INITIAL_MXCSR; + /* Terminate the Exception Handler List */ + ThreadFrame->TrapFrame.ExceptionFrame = (ULONGLONG)NULLPTR; /* Initialize exception frame */ - ThreadFrame->ExceptionFrame.P1Home = (ULONG64)StartContext; - ThreadFrame->ExceptionFrame.P2Home = (ULONG64)StartRoutine; - ThreadFrame->ExceptionFrame.P3Home = (ULONG64)SystemRoutine; - ThreadFrame->ExceptionFrame.P4Home = (ULONG64)SystemRoutine; + ThreadFrame->ExceptionFrame.P1Home = (ULONGLONG)StartContext; + ThreadFrame->ExceptionFrame.P2Home = (ULONGLONG)StartRoutine; + ThreadFrame->ExceptionFrame.P3Home = (ULONGLONG)SystemRoutine; + ThreadFrame->ExceptionFrame.P4Home = (ULONGLONG)SystemRoutine; } else { @@ -97,22 +113,21 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, /* Disable floating point state */ Thread->NpxState = NPX_STATE_UNUSED; - - /* Set thread start address */ - ThreadFrame->StartFrame.Return = (ULONG64)NULLPTR; } /* Initialize thread startup information */ - ThreadFrame->StartFrame.P1Home = (ULONG64)StartContext; - ThreadFrame->StartFrame.P2Home = (ULONG64)StartRoutine; - ThreadFrame->StartFrame.P3Home = (ULONG64)SystemRoutine; - ThreadFrame->StartFrame.P4Home = (ULONG64)SystemRoutine; + ThreadFrame->StartFrame.P1Home = (ULONGLONG)StartContext; + ThreadFrame->StartFrame.P2Home = (ULONGLONG)StartRoutine; + ThreadFrame->StartFrame.P3Home = (ULONGLONG)SystemRoutine; + ThreadFrame->StartFrame.P4Home = (ULONGLONG)SystemRoutine; /* Initialize switch frame */ ThreadFrame->SwitchFrame.ApcBypass = APC_LEVEL; ThreadFrame->SwitchFrame.MxCsr = INITIAL_MXCSR; - ThreadFrame->SwitchFrame.Rbp = (ULONG64)&ThreadFrame->TrapFrame; + ThreadFrame->SwitchFrame.Rbp = (ULONGLONG)&ThreadFrame->TrapFrame; + ThreadFrame->SwitchFrame.Return = (ULONGLONG)RunThread; - /* Set thread stack */ + /* Set thread stack boundaries */ + Thread->InitialStack = (PVOID)&ThreadFrame->NpxFrame; Thread->KernelStack = &ThreadFrame->SwitchFrame; }