diff --git a/xtoskrnl/includes/ke/proc.hh b/xtoskrnl/includes/ke/proc.hh index e588dee..8e5eafc 100644 --- a/xtoskrnl/includes/ke/proc.hh +++ b/xtoskrnl/includes/ke/proc.hh @@ -32,7 +32,19 @@ namespace KE STATIC XTAPI VOID RegisterHardwareId(IN ULONG HardwareId); STATIC XTAPI VOID RegisterProcessorBlock(ULONG CpuNumber, PKPROCESSOR_BLOCK ProcessorBlock); + STATIC XTAPI VOID RestoreProcessorContext(IN OUT PKTRAP_FRAME TrapFrame, + IN OUT PKEXCEPTION_FRAME ExceptionFrame, + IN PCONTEXT ContextFrame, + IN ULONG ContextFlags); + STATIC XTAPI VOID RestoreProcessorControlState(IN PKPROCESSOR_STATE CpuState); + STATIC XTAPI VOID RestoreProcessorState(OUT PKTRAP_FRAME TrapFrame, + OUT PKEXCEPTION_FRAME ExceptionFrame); + STATIC XTAPI VOID SaveProcessorContext(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN OUT PCONTEXT ContextRecord); STATIC XTAPI VOID SaveProcessorControlState(OUT PKPROCESSOR_STATE CpuState); + STATIC XTAPI VOID SaveProcessorState(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame); }; } diff --git a/xtoskrnl/ke/amd64/proc.cc b/xtoskrnl/ke/amd64/proc.cc index d49b82e..fcf0e49 100644 --- a/xtoskrnl/ke/amd64/proc.cc +++ b/xtoskrnl/ke/amd64/proc.cc @@ -193,10 +193,233 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber, } /** - * Saves the current processor state. + * Restores the processor's architectural state from the provided context frame back into the hardware trap + * and exception frames. + * + * @param TrapFrame + * Supplies a pointer to the trap frame that will receive the volatile processor state and control registers. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame that will receive the non-volatile integer and FP registers. + * + * @param ContextFrame + * Supplies a pointer to the context frame containing the state to be restored. + * + * @param ContextFlags + * Supplies a bitmask indicating which specific register groups should be restored from the ContextFrame. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::RestoreProcessorContext(IN OUT PKTRAP_FRAME TrapFrame, + IN OUT PKEXCEPTION_FRAME ExceptionFrame, + IN PCONTEXT ContextFrame, + IN ULONG ContextFlags) +{ + UNIMPLEMENTED; +} + +/** + * Restores the processor's low-level hardware control state. + * + * @param CpuState + * Supplies a pointer to the processor state block containing the previously saved control data. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::RestoreProcessorControlState(IN PKPROCESSOR_STATE CpuState) +{ + /* Restore the CR registers */ + AR::CpuFunctions::WriteControlRegister(0, CpuState->SpecialRegisters.Cr0); + AR::CpuFunctions::WriteControlRegister(2, CpuState->SpecialRegisters.Cr2); + AR::CpuFunctions::WriteControlRegister(3, CpuState->SpecialRegisters.Cr3); + AR::CpuFunctions::WriteControlRegister(4, CpuState->SpecialRegisters.Cr4); + AR::CpuFunctions::WriteControlRegister(8, CpuState->SpecialRegisters.Cr8); + + /* Restore the DR registers */ + AR::CpuFunctions::WriteDebugRegister(0, CpuState->SpecialRegisters.KernelDr0); + AR::CpuFunctions::WriteDebugRegister(1, CpuState->SpecialRegisters.KernelDr1); + AR::CpuFunctions::WriteDebugRegister(2, CpuState->SpecialRegisters.KernelDr2); + AR::CpuFunctions::WriteDebugRegister(3, CpuState->SpecialRegisters.KernelDr3); + AR::CpuFunctions::WriteDebugRegister(6, CpuState->SpecialRegisters.KernelDr6); + AR::CpuFunctions::WriteDebugRegister(7, CpuState->SpecialRegisters.KernelDr7); + + /* Restore MSR registers */ + AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_GSBASE, CpuState->SpecialRegisters.MsrGsBase); + AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_KERNEL_GSBASE, CpuState->SpecialRegisters.MsrGsSwap); + AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_CSTAR, CpuState->SpecialRegisters.MsrCStar); + AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_LSTAR, CpuState->SpecialRegisters.MsrLStar); + AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_STAR, CpuState->SpecialRegisters.MsrStar); + AR::CpuFunctions::WriteModelSpecificRegister(X86_MSR_FMASK, CpuState->SpecialRegisters.MsrSyscallMask); + + /* Restore XMM control/status register */ + AR::CpuFunctions::LoadMxcsrRegister(CpuState->SpecialRegisters.MxCsr); + + /* Restore GDT, IDT, LDT and TaskRegister */ + AR::CpuFunctions::LoadGlobalDescriptorTable(&CpuState->SpecialRegisters.Gdtr.Limit); + AR::CpuFunctions::LoadInterruptDescriptorTable(&CpuState->SpecialRegisters.Idtr.Limit); + AR::CpuFunctions::LoadLocalDescriptorTable(CpuState->SpecialRegisters.Ldtr); + AR::CpuFunctions::LoadTaskRegister(CpuState->SpecialRegisters.Tr); +} + +/** + * Restores the executing processor's state. + * + * @param TrapFrame + * Supplies a pointer to the hardware trap frame that will be populated with the restored volatile state. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame that will be populated with the restored non-volatile state. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::RestoreProcessorState(OUT PKTRAP_FRAME TrapFrame, + OUT PKEXCEPTION_FRAME ExceptionFrame) +{ + PKPROCESSOR_CONTROL_BLOCK Prcb; + + /* Retrieve current processor control block */ + Prcb = GetCurrentProcessorControlBlock(); + + /* Restore processor context */ + RestoreProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame, CONTEXT_ALL); + + /* Restore processor control registers */ + RestoreProcessorControlState(&Prcb->ProcessorState); +} + +/** + * Constructs a standardized processor context from the hardware trap and exception frames. + * + * @param TrapFrame + * Supplies a pointer to the trap frame containing volatile processor state, control registers and debug + * registers saved at the time of the interrupt or exception. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame containing non-volatile integer and floating-point registers. + * + * @param ContextFrame + * Supplies a pointer to the context frame that will receive the processor state. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::SaveProcessorContext(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN OUT PCONTEXT ContextFrame) +{ + /* Elevate RunLevel to APC_LEVEL to prevent thread preemption */ + KE::RaiseRunLevel RunLevel(APC_LEVEL); + + /* Check if control registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_CONTROL) + { + /* Copy instruction pointer, stack pointer, and CPU status flags */ + ContextFrame->Flags = TrapFrame->Flags; + ContextFrame->Rbp = TrapFrame->Rbp; + ContextFrame->Rip = TrapFrame->Rip; + ContextFrame->Rsp = TrapFrame->Rsp; + ContextFrame->SegCs = TrapFrame->SegCs; + ContextFrame->SegSs = TrapFrame->SegSs; + } + + /* Check if general-purpose integer registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_INTEGER) + { + /* Copy volatile integer registers directly from the trap frame */ + ContextFrame->Rax = TrapFrame->Rax; + ContextFrame->Rcx = TrapFrame->Rcx; + ContextFrame->Rdx = TrapFrame->Rdx; + ContextFrame->R8 = TrapFrame->R8; + ContextFrame->R9 = TrapFrame->R9; + ContextFrame->R10 = TrapFrame->R10; + ContextFrame->R11 = TrapFrame->R11; + + /* Check if a valid exception frame was provided */ + if(ExceptionFrame) + { + /* Copy non-volatile integer registers from the exception frame */ + ContextFrame->Rbx = ExceptionFrame->Rbx; + ContextFrame->R12 = ExceptionFrame->R12; + ContextFrame->R13 = ExceptionFrame->R13; + ContextFrame->R14 = ExceptionFrame->R14; + ContextFrame->R15 = ExceptionFrame->R15; + ContextFrame->Rdi = ExceptionFrame->Rdi; + ContextFrame->Rsi = ExceptionFrame->Rsi; + } + } + + /* Check if segment registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_SEGMENTS) + { + /* Populate segment selectors with standard Ring 3 values */ + ContextFrame->SegDs = KGDT_R3_DATA | RPL_MASK; + ContextFrame->SegEs = KGDT_R3_DATA | RPL_MASK; + ContextFrame->SegFs = KGDT_R3_CMTEB | RPL_MASK; + ContextFrame->SegGs = KGDT_R3_DATA | RPL_MASK; + } + + /* Check if floating-point registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) + { + /* Copy the SSE control/status register and volatile XMM registers */ + ContextFrame->MxCsr = TrapFrame->MxCsr; + ContextFrame->Xmm0 = TrapFrame->Xmm0; + ContextFrame->Xmm1 = TrapFrame->Xmm1; + ContextFrame->Xmm2 = TrapFrame->Xmm2; + ContextFrame->Xmm3 = TrapFrame->Xmm3; + ContextFrame->Xmm4 = TrapFrame->Xmm4; + ContextFrame->Xmm5 = TrapFrame->Xmm5; + + /* Check if a valid exception frame was provided */ + if(ExceptionFrame) + { + /* Copy non-volatile XMM registers from the exception frame */ + ContextFrame->Xmm6 = ExceptionFrame->Xmm6; + ContextFrame->Xmm7 = ExceptionFrame->Xmm7; + ContextFrame->Xmm8 = ExceptionFrame->Xmm8; + ContextFrame->Xmm9 = ExceptionFrame->Xmm9; + ContextFrame->Xmm10 = ExceptionFrame->Xmm10; + ContextFrame->Xmm11 = ExceptionFrame->Xmm11; + ContextFrame->Xmm12 = ExceptionFrame->Xmm12; + ContextFrame->Xmm13 = ExceptionFrame->Xmm13; + ContextFrame->Xmm14 = ExceptionFrame->Xmm14; + ContextFrame->Xmm15 = ExceptionFrame->Xmm15; + } + } + + /* Check if debug registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS) + { + /* Copy debug registers */ + ContextFrame->Dr0 = TrapFrame->Dr0; + ContextFrame->Dr1 = TrapFrame->Dr1; + ContextFrame->Dr2 = TrapFrame->Dr2; + ContextFrame->Dr3 = TrapFrame->Dr3; + ContextFrame->Dr6 = TrapFrame->Dr6; + ContextFrame->Dr7 = TrapFrame->Dr7; + } +} + +/** + * Saves the current processor's low-level hardware control state. * * @param State - * Supplies a pointer to the processor state structure. + * Supplies a pointer to the processor state block that will receive processor's control data. * * @return This routine does not return any value. * @@ -238,3 +461,36 @@ KE::Processor::SaveProcessorControlState(OUT PKPROCESSOR_STATE CpuState) AR::CpuFunctions::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr); AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr); } + +/** + * Captures the executing processor's state. + * + * @param TrapFrame + * Supplies a pointer to the hardware trap frame containing the processor's volatile state. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame containing the processor's non-volatile state. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::SaveProcessorState(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame) +{ + PKPROCESSOR_CONTROL_BLOCK Prcb; + + /* Retrieve current processor control block */ + Prcb = GetCurrentProcessorControlBlock(); + + /* Set context flags to save whole all context */ + Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_ALL; + + /* Save processor context */ + SaveProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame); + + /* Save processor control registers */ + SaveProcessorControlState(&Prcb->ProcessorState); +} diff --git a/xtoskrnl/ke/i686/proc.cc b/xtoskrnl/ke/i686/proc.cc index ad9ad98..3fa24f4 100644 --- a/xtoskrnl/ke/i686/proc.cc +++ b/xtoskrnl/ke/i686/proc.cc @@ -193,10 +193,193 @@ KE::Processor::RegisterProcessorBlock(ULONG CpuNumber, } /** - * Saves the current processor state. + * Restores the processor's architectural state from the provided context frame back into the hardware trap + * and exception frames. + * + * @param TrapFrame + * Supplies a pointer to the trap frame that will receive the volatile processor state and control registers. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame that will receive the non-volatile integer and FP registers. + * + * @param ContextFrame + * Supplies a pointer to the context frame containing the state to be restored. + * + * @param ContextFlags + * Supplies a bitmask indicating which specific register groups should be restored from the ContextFrame. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::RestoreProcessorContext(IN OUT PKTRAP_FRAME TrapFrame, + IN OUT PKEXCEPTION_FRAME ExceptionFrame, + IN PCONTEXT ContextFrame, + IN ULONG ContextFlags) +{ + UNIMPLEMENTED; +} + +/** + * Restores the processor's low-level hardware control state. + * + * @param CpuState + * Supplies a pointer to the processor state block containing the previously saved control data. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::RestoreProcessorControlState(IN PKPROCESSOR_STATE CpuState) +{ + /* Restore CR registers */ + AR::CpuFunctions::WriteControlRegister(0, CpuState->SpecialRegisters.Cr0); + AR::CpuFunctions::WriteControlRegister(2, CpuState->SpecialRegisters.Cr2); + AR::CpuFunctions::WriteControlRegister(3, CpuState->SpecialRegisters.Cr3); + AR::CpuFunctions::WriteControlRegister(4, CpuState->SpecialRegisters.Cr4); + + /* Restore DR registers */ + AR::CpuFunctions::WriteDebugRegister(0, CpuState->SpecialRegisters.KernelDr0); + AR::CpuFunctions::WriteDebugRegister(1, CpuState->SpecialRegisters.KernelDr1); + AR::CpuFunctions::WriteDebugRegister(2, CpuState->SpecialRegisters.KernelDr2); + AR::CpuFunctions::WriteDebugRegister(3, CpuState->SpecialRegisters.KernelDr3); + AR::CpuFunctions::WriteDebugRegister(6, CpuState->SpecialRegisters.KernelDr6); + AR::CpuFunctions::WriteDebugRegister(7, CpuState->SpecialRegisters.KernelDr7); + + /* Restore GDT, IDT, LDT and TaskRegister */ + AR::CpuFunctions::LoadGlobalDescriptorTable(&CpuState->SpecialRegisters.Gdtr.Limit); + AR::CpuFunctions::LoadInterruptDescriptorTable(&CpuState->SpecialRegisters.Idtr.Limit); + AR::CpuFunctions::LoadLocalDescriptorTable(CpuState->SpecialRegisters.Ldtr); + AR::CpuFunctions::LoadTaskRegister(CpuState->SpecialRegisters.Tr); +} + +/** + * Restores the executing processor's state. + * + * @param TrapFrame + * Supplies a pointer to the hardware trap frame that will be populated with the restored volatile state. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame that will be populated with the restored non-volatile state. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::RestoreProcessorState(OUT PKTRAP_FRAME TrapFrame, + OUT PKEXCEPTION_FRAME ExceptionFrame) +{ + PKPROCESSOR_CONTROL_BLOCK Prcb; + + /* Retrieve current processor control block */ + Prcb = GetCurrentProcessorControlBlock(); + + /* Restore processor context */ + RestoreProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame, + CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS); + + /* Restore processor control registers */ + RestoreProcessorControlState(&Prcb->ProcessorState); +} + +/** + * Constructs a standardized processor context from the hardware trap and exception frames. + * + * @param TrapFrame + * Supplies a pointer to the trap frame containing volatile processor state, control registers and debug + * registers saved at the time of the interrupt or exception. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame containing non-volatile integer and floating-point registers. + * + * @param ContextFrame + * Supplies a pointer to the context frame that will receive the processor state. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::SaveProcessorContext(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN OUT PCONTEXT ContextFrame) +{ + /* Elevate RunLevel to APC_LEVEL to prevent thread preemption */ + KE::RaiseRunLevel RunLevel(APC_LEVEL); + + /* Check if control registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_CONTROL) + { + /* Copy instruction pointer, stack pointer, and CPU status flags */ + ContextFrame->Flags = TrapFrame->Flags; + ContextFrame->Ebp = TrapFrame->Ebp; + ContextFrame->Eip = TrapFrame->Eip; + ContextFrame->Esp = TrapFrame->Esp; + ContextFrame->SegCs = TrapFrame->SegCs; + ContextFrame->SegSs = TrapFrame->SegSs; + } + + /* Check if general-purpose integer registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_INTEGER) + { + /* Copy integer registers directly from the trap frame */ + ContextFrame->Eax = TrapFrame->Eax; + ContextFrame->Ebx = TrapFrame->Ebx; + ContextFrame->Ecx = TrapFrame->Ecx; + ContextFrame->Edx = TrapFrame->Edx; + ContextFrame->Edi = TrapFrame->Edi; + ContextFrame->Esi = TrapFrame->Esi; + } + + /* Check if segment registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_SEGMENTS) + { + /* Populate segment selectors with standard Ring 3 values */ + TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; + TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK; + TrapFrame->SegFs = KGDT_R0_PB; + TrapFrame->SegGs = 0; + } + + /* Check if floating-point registers are requested and if running in user mode */ + if((ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) && ((TrapFrame->SegCs & MODE_MASK) == UserMode)) + { + /* No user-mode support */ + UNIMPLEMENTED; + } + + /* Check if debug registers are requested */ + if(ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS) + { + /* Copy debug registers */ + ContextFrame->Dr0 = TrapFrame->Dr0; + ContextFrame->Dr1 = TrapFrame->Dr1; + ContextFrame->Dr2 = TrapFrame->Dr2; + ContextFrame->Dr3 = TrapFrame->Dr3; + ContextFrame->Dr6 = TrapFrame->Dr6; + ContextFrame->Dr7 = TrapFrame->Dr7; + } + + /* Check if extended registers are requested and if running in user mode */ + if((ContextFrame->ContextFlags & CONTEXT_EXTENDED_REGISTERS) && ((TrapFrame->SegCs & MODE_MASK) == UserMode)) + { + /* No user-mode support */ + UNIMPLEMENTED; + } +} + +/** + * Saves the current processor's low-level hardware control state. * * @param State - * Supplies a pointer to the processor state structure. + * Supplies a pointer to the processor state block that will receive processor's control data. * * @return This routine does not return any value. * @@ -226,3 +409,36 @@ KE::Processor::SaveProcessorControlState(OUT PKPROCESSOR_STATE CpuState) AR::CpuFunctions::StoreLocalDescriptorTable(&CpuState->SpecialRegisters.Ldtr); AR::CpuFunctions::StoreTaskRegister(&CpuState->SpecialRegisters.Tr); } + +/** + * Captures the executing processor's state. + * + * @param TrapFrame + * Supplies a pointer to the hardware trap frame containing the processor's volatile state. + * + * @param ExceptionFrame + * Supplies a pointer to the exception frame containing the processor's non-volatile state. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +KE::Processor::SaveProcessorState(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame) +{ + PKPROCESSOR_CONTROL_BLOCK Prcb; + + /* Retrieve current processor control block */ + Prcb = GetCurrentProcessorControlBlock(); + + /* Set context flags to save whole full context and debug registers */ + Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; + + /* Save processor context */ + SaveProcessorContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame); + + /* Save processor control registers */ + SaveProcessorControlState(&Prcb->ProcessorState); +}