Author: ros-arm-bringup Date: Sat Jan 2 02:34:27 2010 New Revision: 44871
URL: http://svn.reactos.org/svn/reactos?rev=44871&view=rev Log: NMI Support Patch 10: [NTOS]: Write barebones NMI Trap handler which does a TSS context switch to the NMI TSS and then calls the HAL NMI handler. [NTOS]: Implement KiSaveProcessorState for doing a PRCB context save/restore.
You should now be able to test the new NMI functionality by either building the circuit referenced in my e-mail and attaching it to your PCI bus, or by using "nmi 0" in the QEMU stdio console.
Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.c trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/cpu.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/cpu.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/cpu.c [iso-8859-1] Sat Jan 2 02:34:27 2010 @@ -924,6 +924,26 @@ RtlZeroMemory(Address, Size); }
+VOID +NTAPI +KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame, + IN PKEXCEPTION_FRAME ExceptionFrame) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + + // + // Save full context + // + Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL | + CONTEXT_DEBUG_REGISTERS; + KeTrapFrameToContext(TrapFrame, NULL, &Prcb->ProcessorState.ContextFrame); + + // + // Save control registers + // + KiSaveProcessorControlState(&Prcb->ProcessorState); +} + /* PUBLIC FUNCTIONS **********************************************************/
/*
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Sat Jan 2 02:34:27 2010 @@ -10,6 +10,7 @@
#include <asm.h> #include <internal/i386/asmmacro.S> +#include <internal/i386/callconv.s> .intel_syntax noprefix
#define Running 2 @@ -790,9 +791,138 @@ .globl _KiTrap2 .func KiTrap2 _KiTrap2: - - /* FIXME: This is an NMI, nothing like a normal exception */ - mov eax, 2 + // + // Don't allow any other NMIs to come in for now + // + cli // Disable interrupts + + // + // Save current state data in registers + // + mov eax, PCR[KPCR_TSS] // Save KTSS + mov ecx, PCR[KPCR_CURRENT_THREAD] // Save ETHREAD + mov edi, [ecx+KTHREAD_APCSTATE_PROCESS] // Save EPROCESS + + // + // Migrate state data to TSS + // + mov ecx, [edi+KPROCESS_DIRECTORY_TABLE_BASE] // Page Directory Table + mov [eax+KTSS_CR3], ecx // Saved in CR3 + mov cx, [edi+KPROCESS_IOPM_OFFSET] // IOPM Offset + mov [eax+KTSS_IOMAPBASE], cx // Saved in IOPM Base + mov ecx, [edi+KPROCESS_LDT_DESCRIPTOR0] // Get LDT descriptor + test ecx, ecx // Check if ne + jz 1f // Doesn't exist + mov cx, KGDT_LDT // Load LDT descriptor +1: + mov [eax+KTSS_LDT], cx // Saved in LDT + + // + // Migrate to NMI TSS + // + push PCR[KPCR_TSS] // Save current TSS + mov eax, PCR[KPCR_GDT] // Get GDT + mov ch, [eax+KGDT_NMI_TSS+KGDT_BASE_HI] // Get High KTSS Base + mov cl, [eax+KGDT_NMI_TSS+KGDT_BASE_MID] // Get Mid KTSS Base + shl ecx, 16 // Build Top KTSS Base + mov cx, [eax+KGDT_NMI_TSS+KGDT_BASE_LOW] // Add Low KTSS Base + mov PCR[KPCR_TSS], ecx + + // + // Clear nested flag and activate the NMI TSS + // + pushf // Get EFLAGS + and dword ptr [esp], ~EFLAGS_NESTED_TASK // Clear nested task + popf // Set EFLAGS + mov ecx, PCR[KPCR_GDT] // Get GDT + lea eax, [ecx+KGDT_NMI_TSS] // Get NMI TSS + mov byte ptr [eax+5], 0x89 // DPL 0, Present, NonBusy + + // + // Build the trap frame and save it into the KPRCB + // + mov eax, [esp] // KGDT_TSS from earlier + push 0 // V86 segments + push 0 // V86 segments + push 0 // V86 segments + push 0 // V86 segments + push [eax+KTSS_SS] // TSS fields -> Trap Frame + push [eax+KTSS_ESP] // TSS fields -> Trap Frame + push [eax+KTSS_EFLAGS] // TSS fields -> Trap Frame + push [eax+KTSS_CS] // TSS fields -> Trap Frame + push [eax+KTSS_EIP] // TSS fields -> Trap Frame + push 0 // Error Code + push [eax+KTSS_EBP] // TSS fields -> Trap Frame + push [eax+KTSS_EBX] // TSS fields -> Trap Frame + push [eax+KTSS_ESI] // TSS fields -> Trap Frame + push [eax+KTSS_EDI] // TSS fields -> Trap Frame + push [eax+KTSS_FS] // TSS fields -> Trap Frame + push PCR[KPCR_EXCEPTION_LIST] // SEH Handler from KPCR + push -1 // Bogus previous mode + push [eax+KTSS_EAX] // TSS fields -> Trap Frame + push [eax+KTSS_ECX] // TSS fields -> Trap Frame + push [eax+KTSS_EDX] // TSS fields -> Trap Frame + push [eax+KTSS_DS] // TSS fields -> Trap Frame + push [eax+KTSS_ES] // TSS fields -> Trap Frame + push [eax+KTSS_GS] // TSS fields -> Trap Frame + push 0 // Debug registers + push 0 // Debug registers + push 0 // Debug registers + push 0 // Debug registers + push 0 // Debug registers + push 0 // Debug registers + push 0 // Temp + push 0 // Temp + push 0 // Debug Pointer + push 0 // Debug Marker + push [eax+KTSS_EIP] // Debug EIP + push [eax+KTSS_EBP] // Debug EBP + mov ebp, esp // Set trap frame address + stdCall _KiSaveProcessorState, ebp, 0 // Save to KPRCB CONTEXT + + // + // BUGBUG: Call Registered NMI handlers + // + + // + // Call the platform driver for NMI handling (panic, etc) + // Do this with IRQL at HIGH + // + push PCR[KPCR_IRQL] // Save real IRQL + mov dword ptr PCR[KPCR_IRQL], HIGH_LEVEL // Force HIGH + stdCall _HalHandleNMI, 0 // Call the HAL + pop PCR[KPCR_IRQL] // Restore real IRQL + + // + // In certain situations, nested NMIs can corrupt the TSS, making us lose + // the original context. If this happens, we have no choice but to panic. + // + mov eax, PCR[KPCR_TSS] // Get current TSS + cmp word ptr [eax], KGDT_NMI_TSS // Check who its points to + je 2f // Back to the NMI TSS crash + + // + // Otherwise, recover the original state + // + add esp, KTRAP_FRAME_LENGTH // Clear the trap frame + pop PCR[KPCR_TSS] // Restore original TSS + mov ecx, PCR[KPCR_GDT] // Get GDT + lea eax, [ecx+KGDT_TSS] // Get KTSS + mov byte ptr [eax+5], 0x8B // DPL 0, Present, Busy + pushf // Get EFLAGS + or dword ptr [esp], EFLAGS_NESTED_TASK // Set nested flags + popf // Set EFLAGS + + // + // Return from NMI + // + iretd // Interrupt return + jmp _KiTrap2 // Handle recursion +2: + // + // Crash the system + // + mov eax, EXCEPTION_NMI jmp _KiSystemFatalException .endfunc