[ros-diffs] [ros-arm-bringup] 44871: 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.

ros-arm-bringup at svn.reactos.org ros-arm-bringup at svn.reactos.org
Sat Jan 2 02:34:27 CET 2010


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=44871&r1=44870&r2=44871&view=diff
==============================================================================
--- 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=44871&r1=44870&r2=44871&view=diff
==============================================================================
--- 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
 




More information about the Ros-diffs mailing list