From e035666f7a829946b2d142feae33a191f27ce829 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 14 Jun 2026 00:53:34 +0200 Subject: [PATCH] Fix i686 thread context setup --- xtoskrnl/ke/i686/kthread.cc | 38 +++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/xtoskrnl/ke/i686/kthread.cc b/xtoskrnl/ke/i686/kthread.cc index 6a619a612..ca3e1f234 100644 --- a/xtoskrnl/ke/i686/kthread.cc +++ b/xtoskrnl/ke/i686/kthread.cc @@ -41,6 +41,7 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, { PKTHREAD_INIT_FRAME ThreadFrame; PFX_SAVE_FORMAT FxSaveFormat; + CONTEXT ContextFrame; /* Set initial thread frame */ ThreadFrame = ((PKTHREAD_INIT_FRAME)Thread->InitialStack) - 1; @@ -51,18 +52,24 @@ 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 control and extended registers */ + ContextFrame.ContextFlags |= (CONTEXT_CONTROL | CONTEXT_EXTENDED_REGISTERS); + ContextFrame.ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; /* Fill trap frame with zeroes */ RTL::Memory::ZeroMemory(&ThreadFrame->TrapFrame, sizeof(KTRAP_FRAME)); - /* Disable debug registers and enable context registers */ - ContextRecord->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; + /* Translate Context frame to Trap frame */ + KE::Processor::RestoreProcessorContext(&ThreadFrame->TrapFrame, NULLPTR, + &ContextFrame, ContextFrame.ContextFlags); /* This is user mode thread */ - ThreadFrame->StartFrame.UserMode = TRUE; Thread->PreviousMode = UserMode; + ThreadFrame->StartFrame.UserMode = TRUE; + ThreadFrame->TrapFrame.PreviousMode = UserMode; /* Disable coprocessor floating point state */ Thread->NpxState = NPX_STATE_UNLOADED; @@ -71,11 +78,19 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, /* Set initial floating point state */ FxSaveFormat = (PFX_SAVE_FORMAT)ContextRecord->ExtendedRegisters; FxSaveFormat->ControlWord = 0x27F; - FxSaveFormat->MxCsr = 0x1F80; - ContextRecord->FloatSave.Cr0NpxState = 0; + FxSaveFormat->DataOffset = 0; + FxSaveFormat->DataSelector = 0; + FxSaveFormat->ErrorOffset = 0; + FxSaveFormat->ErrorSelector = 0; + FxSaveFormat->StatusWord = 0; + FxSaveFormat->TagWord = 0; + ContextFrame.FloatSave.Cr0NpxState = 0; ThreadFrame->NpxFrame.Cr0NpxState = 0; ThreadFrame->NpxFrame.NpxSavedCpu = 0; + /* Set initial MXCSR register value */ + FxSaveFormat->MxCsr = 0x1F80; + /* Clear DR6 and DR7 registers */ ThreadFrame->TrapFrame.Dr6 = 0; ThreadFrame->TrapFrame.Dr7 = 0; @@ -84,15 +99,12 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, ThreadFrame->TrapFrame.SegDs |= RPL_MASK; ThreadFrame->TrapFrame.SegEs |= RPL_MASK; ThreadFrame->TrapFrame.SegSs |= RPL_MASK; - - /* Set user mode thread in the trap frame */ - ThreadFrame->TrapFrame.PreviousMode = UserMode; } else { /* This is kernel mode thread */ - ThreadFrame->StartFrame.UserMode = FALSE; Thread->PreviousMode = KernelMode; + ThreadFrame->StartFrame.UserMode = FALSE; /* Disable coprocessor floating point state */ Thread->NpxState = NPX_STATE_UNLOADED; @@ -110,7 +122,9 @@ KE::KThread::InitializeThreadContext(IN PKTHREAD Thread, /* Initialize switch frame */ ThreadFrame->SwitchFrame.ApcBypassDisabled = TRUE; ThreadFrame->SwitchFrame.ExceptionList = (PEXCEPTION_REGISTRATION_RECORD) - 1; + ThreadFrame->SwitchFrame.Return = (PVOID)(ULONG)RunThread; - /* Set thread stack */ + /* Set thread stack boundaries */ + Thread->InitialStack = (PVOID)&ThreadFrame->NpxFrame; Thread->KernelStack = &ThreadFrame->SwitchFrame; }