Author: sir_richard
Date: Mon Jan 11 07:08:11 2010
New Revision: 45040
URL: http://svn.reactos.org/svn/reactos?rev=45040&view=rev
Log:
Trap Handlers in C Patch 8 of X:
[NTOS]: Implement KiCoprocessorError in C.
[NTOS]: Make NMI handler fully C, now that the other parts are C too.
[NTOS]: Delete more ASM macros and code that are now unused.
Modified:
trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/ke/i386/cpu.c
trunk/reactos/ntoskrnl/ke/i386/trap.s
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] Mon Jan 11 07:08:11 2010
@@ -114,28 +114,6 @@
.endm
//
-// @name UNHANDLED_V86_PATH
-//
-// This macro prints out that the current code path is for unhandled VDM support
-//
-// @param None
-//
-// @remark None.
-//
-.macro UNHANDLED_V86_PATH
- /* Get EIP */
- call $+5
-
- /* Print debug message */
- push offset _V86UnhandledMsg
- call _DbgPrint
- add esp, 8
-
- /* Loop indefinitely */
- jmp $
-.endm
-
-//
// @name IDT
//
// This macro creates an IDT entry for the given handler
@@ -277,58 +255,6 @@
.endm
//
-// @name INVALID_V86_OPCODE
-//
-// This macro creates one or more entries for unhandled V86 Opcodes
-// in the V86 Opcode Table.
-//
-// @param count.
-// Number of entries to generate.
-//
-// @remark None.
-//
-.macro INVALID_V86_OPCODE count
- .rept \count
- .byte 0
- .endr
-.endm
-
-//
-// @name GENERATE_PREFIX_HANDLER
-//
-// This macro creates a prefix opcode handler.
-//
-// @param None.
-//
-// @remark None.
-//
-.macro GENERATE_PREFIX_HANDLER Name
-.func Opcode&Name&PrefixV86
-_Opcode&Name&PrefixV86:
- or ebx, PREFIX_FLAG_&Name
- jmp _OpcodeGenericPrefixV86
-.endfunc
-.endm
-
-//
-// @name INVALID_V86_OPCODE
-//
-// This macro prints out visible message and hangs the computer.
-//
-// @param None.
-//
-// @remark Temporary debugging use.
-//
-.macro UNHANDLED_V86_OPCODE
- /* Print debug message, breakpoint and freeze */
- push ecx
- push offset V86DebugMsg
- call _DbgPrint
- add esp, 8
- jmp $
-.endm
-
-//
// @name TRAP_FIXUPS
//
// This macro contains out-of-line code for various Trap Frame Fixups, such as:
@@ -522,96 +448,6 @@
cli
jmp 1b
2:
-.endm
-
-//
-// @name TRAP_PROLOG
-//
-// This macro creates a standard trap entry prologue.
-// It should be used for entry into any kernel trap (KiTrapXx), but not for
-// system calls, which require special handling.
-//
-// @param Label
-// Identifying name of the caller function; will be used to append
-// to the name V86 and DR helper functions, which must already exist.
-//
-// @remark Use as follows:
-// _KiTrap00:
-// /* Push fake error code */
-// push 0
-//
-// /* Enter common prologue */
-// TRAP_PROLOG(0)
-//
-// /* Handle trap */
-// <Your Trap Code Here>
-//
-.macro TRAP_PROLOG Label EndLabel
- /* Just to be safe, clear out the HIWORD, since it's reserved */
- mov word ptr [esp+2], 0
-
- /* Save the non-volatiles */
- push ebp
- push ebx
- push esi
- push edi
-
- /* Save FS and set it to PCR */
- push fs
- mov ebx, KGDT_R0_PCR
- .byte 0x66
- mov fs, bx
-
- /* Save exception list and bogus previous mode */
- push fs:[KPCR_EXCEPTION_LIST]
- push -1
-
- /* Save volatiles and segment registers */
- push eax
- push ecx
- push edx
- push ds
- push es
- push gs
-
- /* Set the R3 data segment */
- mov ax, KGDT_R3_DATA + RPL_MASK
-
- /* Skip debug registers and debug stuff */
- sub esp, 0x30
-
- /* Load the segment registers */
- .byte 0x66
- mov ds, ax
- .byte 0x66
- mov es, ax
-
- /* Check if this interrupt happened in 16-bit mode */
- cmp esp, 0x10000
- jb _Ki16BitStackException
-
- /* Set up frame */
- mov ebp, esp
-
- /* Check if this was from V86 Mode */
- test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
- jnz V86_&Label
-
-V86_&EndLabel:
- /* Get current thread */
- mov ecx, fs:[KPCR_CURRENT_THREAD]
- cld
-
- /* Flush DR7 */
- and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
- /* Check if the thread was being debugged */
- test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
- jnz Dr_&Label
-
- /* Set the Trap Frame Debug Header */
-Dr_&EndLabel:
- SET_TF_DEBUG_HEADER
.endm
//
@@ -899,164 +735,6 @@
.endm
//
-// @name V86_TRAP_PROLOG
-//
-// This macro creates a V86 Trap entry prologue.
-// It should be used for entry into any fast-system call (KiGetTickCount,
-// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
-// (KiSystemService)
-//
-// @param Label
-// Unique label identifying the name of the caller function; will be
-// used to append to the name of the DR helper function, which must
-// already exist.
-//
-// @remark None.
-//
-.macro V86_TRAP_PROLOG Label EndLabel
-
- /* Skip everything to the error code */
- sub esp, KTRAP_FRAME_ERROR_CODE
-
- /* Clear the error code */
- mov word ptr [esp+KTRAP_FRAME_ERROR_CODE+2], 0
-
- /* Save the registers we'll trample */
- mov [esp+KTRAP_FRAME_EBX], ebx
- mov [esp+KTRAP_FRAME_EAX], eax
- mov [esp+KTRAP_FRAME_EBP], ebp
- mov [esp+KTRAP_FRAME_ESI], esi
- mov [esp+KTRAP_FRAME_EDI], edi
-
- /* Save PCR and Ring 3 segments */
- mov ebx, KGDT_R0_PCR
- mov eax, KGDT_R3_DATA + RPL_MASK
-
- /* Save ECX and EDX too */
- mov [esp+KTRAP_FRAME_ECX], ecx
- mov [esp+KTRAP_FRAME_EDX], edx
-
- /* Set debugging markers */
- mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
- mov dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
-
- /* Now set segments (use OVERRIDE, 0x66) */
- .byte 0x66
- mov fs, bx
- .byte 0x66
- mov ds, ax
- .byte 0x66
- mov es, ax
-
- /* Set the trap frame in the stack and clear the direction flag */
- mov ebp, esp
- cld
-
- /* Save the exception list */
- mov eax, fs:[KPCR_EXCEPTION_LIST]
- mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax
-
- /* Check if we need debugging */
- mov eax, dr7
- test eax, ~DR7_RESERVED_MASK
- mov [esp+KTRAP_FRAME_DR7], eax
- jnz Dr_&Label
-
-Dr_&EndLabel:
-.endm
-
-//
-// @name V86_TRAP_EPILOG
-//
-// This macro creates an epilogue for leaving V86 traps
-//
-// @param None.
-//
-// @remark None.
-//
-.macro V86_TRAP_EPILOG
-
- /* Get the current thread and make it unalerted */
-ExitBegin:
- mov ebx, PCR[KPCR_CURRENT_THREAD]
- mov byte ptr [ebx+KTHREAD_ALERTED], 0
-
- /* Check if it has User-mode APCs pending */
- cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
- jne PendingUserApc
-
- /* It doesn't, pop the frame */
- add esp, KTRAP_FRAME_EDX
- pop edx
- pop ecx
- pop eax
-
- /* Check if DR registers should be restored */
- test dword ptr [ebp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
- jnz V86DebugRestore
-
- /* Finish popping the rest of the frame, and return to P-mode */
-V86DebugContinue:
- add esp, 12
- pop edi
- pop esi
- pop ebx
- pop ebp
- add esp, 4
- iretd
-
-V86DebugRestore:
-
- /* Get DR0, 1 */
- xor ebx, ebx
- mov esi, [ebp+KTRAP_FRAME_DR0]
- mov edi, [ebp+KTRAP_FRAME_DR1]
-
- /* Clear DR 7 */
- mov dr7, ebx
-
- /* Get DR2 and load DR0-2 */
- mov ebx, [ebp+KTRAP_FRAME_DR2]
- mov dr0, esi
- mov dr1, edi
- mov dr2, ebx
-
- /* Get DR3-7 */
- mov esi, [ebp+KTRAP_FRAME_DR0]
- mov edi, [ebp+KTRAP_FRAME_DR1]
- mov ebx, [ebp+KTRAP_FRAME_DR7]
-
- /* Load them */
- mov dr3, esi
- mov dr6, edi
- mov dr7, ebx
- jmp V86DebugContinue
-
-PendingUserApc:
-
- /* Raise to APC level */
- mov ecx, APC_LEVEL
- call @KfRaiseIrql@4
-
- /* Save KIRQL and deliver APCs */
- push eax
- sti
- push ebp
- push 0
- push UserMode
- call _KiDeliverApc@12
-
- /* Restore IRQL */
- pop ecx
- call @KfLowerIrql@4
- cli
-
- /* Check if we're not in V86 anymore */
- test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
- jnz ExitBegin
-.endm
-
-//
// @name TRAP_EPILOG
//
// This macro creates an epilogue for leaving any system trap.
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Mon Jan 11 07:08:11 2010
@@ -1051,6 +1051,13 @@
);
VOID
+NTAPI
+KiSaveProcessorState(
+ IN PKTRAP_FRAME TrapFrame,
+ IN PKEXCEPTION_FRAME ExceptionFrame
+);
+
+VOID
FASTCALL
KiRetireDpcList(
IN PKPRCB Prcb
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] Mon Jan 11 07:08:11 2010
@@ -944,155 +944,24 @@
KiSaveProcessorControlState(&Prcb->ProcessorState);
}
-/* C TRAP HANDLERS ************************************************************/
-
-BOOLEAN
-NTAPI
-KiNmiFault(IN PVOID InterruptStack)
-{
- PKTSS Tss, NmiTss;
- PKTHREAD Thread;
- PKPROCESS Process;
- PKGDTENTRY TssGdt;
- KTRAP_FRAME TrapFrame;
- KIRQL OldIrql;
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KiCoprocessorError(VOID)
+{
+ PFX_SAVE_AREA NpxArea;
- //
- // In some sort of strange recursion case, we might end up here with the IF
- // flag incorrectly on the interrupt frame -- during a normal NMI this would
- // normally already be set.
- //
- // For sanity's sake, make sure interrupts are disabled for sure.
- // NMIs will already be since the CPU does it for us.
- //
- _disable();
-
- //
- // Get the current TSS, thread, and process
- //
- Tss = PCR->TSS;
- Thread = ((PKIPCR)PCR)->PrcbData.CurrentThread;
- Process = Thread->ApcState.Process;
+ /* Get the FPU area */
+ NpxArea = KiGetThreadNpxArea(KeGetCurrentThread());
- //
- // Save data usually not in the TSS
- //
- Tss->CR3 = Process->DirectoryTableBase[0];
- Tss->IoMapBase = Process->IopmOffset;
- Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
-
- //
- // Now get the base address of the NMI TSS
- //
- TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
- NmiTss = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
- TssGdt->HighWord.Bytes.BaseMid << 16 |
- TssGdt->HighWord.Bytes.BaseHi << 24);
-
- //
- // Switch to it and activate it, masking off the nested flag
- //
- // Note that in reality, we are already on the NMI tss -- we just need to
- // update the PCR to reflect this
- //
- PCR->TSS = NmiTss;
- __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
- TssGdt->HighWord.Bits.Dpl = 0;
- TssGdt->HighWord.Bits.Pres = 1;
- TssGdt->HighWord.Bits.Type = I386_TSS;
-
- //
- // Now build the trap frame based on the original TSS
- //
- // The CPU does a hardware "Context switch" / task switch of sorts and so it
- // takes care of saving our context in the normal TSS.
- //
- // We just have to go get the values...
- //
- RtlZeroMemory(&TrapFrame, sizeof(KTRAP_FRAME));
- TrapFrame.HardwareSegSs = Tss->Ss0;
- TrapFrame.HardwareEsp = Tss->Esp0;
- TrapFrame.EFlags = Tss->EFlags;
- TrapFrame.SegCs = Tss->Cs;
- TrapFrame.Eip = Tss->Eip;
- TrapFrame.Ebp = Tss->Ebp;
- TrapFrame.Ebx = Tss->Ebx;
- TrapFrame.Esi = Tss->Esi;
- TrapFrame.Edi = Tss->Edi;
- TrapFrame.SegFs = Tss->Fs;
- TrapFrame.ExceptionList = PCR->Tib.ExceptionList;
- TrapFrame.PreviousPreviousMode = -1;
- TrapFrame.Eax = Tss->Eax;
- TrapFrame.Ecx = Tss->Ecx;
- TrapFrame.Edx = Tss->Edx;
- TrapFrame.SegDs = Tss->Ds;
- TrapFrame.SegEs = Tss->Es;
- TrapFrame.SegGs = Tss->Gs;
- TrapFrame.DbgEip = Tss->Eip;
- TrapFrame.DbgEbp = Tss->Ebp;
-
- //
- // Store the trap frame in the KPRCB
- //
- KiSaveProcessorState(&TrapFrame, NULL);
-
- //
- // Call any registered NMI handlers and see if they handled it or not
- //
- if (!KiHandleNmi())
- {
- //
- // They did not, so call the platform HAL routine to bugcheck the system
- //
- // Make sure the HAL believes it's running at HIGH IRQL... we can't use
- // the normal APIs here as playing with the IRQL could change the system
- // state
- //
- OldIrql = PCR->Irql;
- PCR->Irql = HIGH_LEVEL;
- HalHandleNMI(NULL);
- PCR->Irql = OldIrql;
- }
-
- //
- // Although the CPU disabled NMIs, we just did a BIOS Call, which could've
- // totally changed things.
- //
- // We have to make sure we're still in our original NMI -- a nested NMI
- // will point back to the NMI TSS, and in that case we're hosed.
- //
- if (PCR->TSS->Backlink != KGDT_NMI_TSS)
- {
- //
- // Restore original TSS
- //
- PCR->TSS = Tss;
-
- //
- // Set it back to busy
- //
- TssGdt->HighWord.Bits.Dpl = 0;
- TssGdt->HighWord.Bits.Pres = 1;
- TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
-
- //
- // Restore nested flag
- //
- __writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
-
- //
- // Handled, return from interrupt
- //
- return TRUE;
- }
-
- //
- // Unhandled: crash the system
- //
- return FALSE;
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
+ /* Set CR0_TS */
+ NpxArea->Cr0NpxState = CR0_TS;
+ __writecr0(__readcr0() | CR0_TS);
+}
/*
* @implemented
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?re…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Mon Jan 11 07:08:11 2010
@@ -577,29 +577,6 @@
GENERATE_TRAP_HANDLER KiTrap0, 1
GENERATE_TRAP_HANDLER KiTrap1, 1
-
-.func KiTrap2
-_KiTrap2:
- //
- // Call the C handler
- //
- stdCall _KiNmiFault, esp // Handle it in C
- or al, al // Check if it got handled
- jne 1f // Resume from NMI
-
- //
- // Return from NMI
- //
- iretd // Interrupt return
- jmp _KiTrap2 // Handle recursion
-1:
- //
- // Crash the system
- //
- mov eax, EXCEPTION_NMI // STOP fault code
- jmp _KiSystemFatalException // Bugcheck helper
-.endfunc
-
GENERATE_TRAP_HANDLER KiTrap3, 1
GENERATE_TRAP_HANDLER KiTrap4, 1
GENERATE_TRAP_HANDLER KiTrap5, 1
@@ -616,61 +593,6 @@
GENERATE_TRAP_HANDLER KiTrap16, 1
GENERATE_TRAP_HANDLER KiTrap17, 1
GENERATE_TRAP_HANDLER KiTrap19, 1
-
-.func KiSystemFatalException
-_KiSystemFatalException:
-
- /* Push the trap frame */
- push ebp
-
- /* Push empty parameters */
- push 0
- push 0
- push 0
-
- /* Push trap number and bugcheck code */
- push eax
- push UNEXPECTED_KERNEL_MODE_TRAP
- call _KeBugCheckWithTf@24
- ret
-.endfunc
-
-.func KiCoprocessorError@0
-_KiCoprocessorError@0:
-
- /* Get the NPX Thread's Initial stack */
- mov eax, PCR[KPCR_NPX_THREAD]
- mov eax, [eax+KTHREAD_INITIAL_STACK]
-
- /* Make space for the FPU Save area */
- sub eax, SIZEOF_FX_SAVE_AREA
-
- /* Set the CR0 State */
- mov dword ptr [eax+FN_CR0_NPX_STATE], 8
-
- /* Update it */
- mov eax, cr0
- or eax, 8
- mov cr0, eax
-
- /* Return to caller */
- ret
-.endfunc
-
-.func Ki16BitStackException
-_Ki16BitStackException:
-
- /* Save stack */
- push ss
- push esp
-
- /* Go to kernel mode thread stack */
- mov eax, PCR[KPCR_CURRENT_THREAD]
- add esp, [eax+KTHREAD_INITIAL_STACK]
-
- /* Switch to good stack segment */
- UNHANDLED_PATH "16-Bit Stack"
-.endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Mon Jan 11 07:08:11 2010
@@ -549,6 +549,151 @@
KiDispatchException0Args(STATUS_SINGLE_STEP,
TrapFrame->Eip,
TrapFrame);
+}
+
+VOID
+KiTrap2(VOID)
+{
+ PKTSS Tss, NmiTss;
+ PKTHREAD Thread;
+ PKPROCESS Process;
+ PKGDTENTRY TssGdt;
+ KTRAP_FRAME TrapFrame;
+ KIRQL OldIrql;
+
+ //
+ // In some sort of strange recursion case, we might end up here with the IF
+ // flag incorrectly on the interrupt frame -- during a normal NMI this would
+ // normally already be set.
+ //
+ // For sanity's sake, make sure interrupts are disabled for sure.
+ // NMIs will already be since the CPU does it for us.
+ //
+ _disable();
+
+ //
+ // Get the current TSS, thread, and process
+ //
+ Tss = PCR->TSS;
+ Thread = ((PKIPCR)PCR)->PrcbData.CurrentThread;
+ Process = Thread->ApcState.Process;
+
+ //
+ // Save data usually not in the TSS
+ //
+ Tss->CR3 = Process->DirectoryTableBase[0];
+ Tss->IoMapBase = Process->IopmOffset;
+ Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0;
+
+ //
+ // Now get the base address of the NMI TSS
+ //
+ TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
+ NmiTss = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow |
+ TssGdt->HighWord.Bytes.BaseMid << 16 |
+ TssGdt->HighWord.Bytes.BaseHi << 24);
+
+ //
+ // Switch to it and activate it, masking off the nested flag
+ //
+ // Note that in reality, we are already on the NMI tss -- we just need to
+ // update the PCR to reflect this
+ //
+ PCR->TSS = NmiTss;
+ __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK);
+ TssGdt->HighWord.Bits.Dpl = 0;
+ TssGdt->HighWord.Bits.Pres = 1;
+ TssGdt->HighWord.Bits.Type = I386_TSS;
+
+ //
+ // Now build the trap frame based on the original TSS
+ //
+ // The CPU does a hardware "Context switch" / task switch of sorts and so it
+ // takes care of saving our context in the normal TSS.
+ //
+ // We just have to go get the values...
+ //
+ RtlZeroMemory(&TrapFrame, sizeof(KTRAP_FRAME));
+ TrapFrame.HardwareSegSs = Tss->Ss0;
+ TrapFrame.HardwareEsp = Tss->Esp0;
+ TrapFrame.EFlags = Tss->EFlags;
+ TrapFrame.SegCs = Tss->Cs;
+ TrapFrame.Eip = Tss->Eip;
+ TrapFrame.Ebp = Tss->Ebp;
+ TrapFrame.Ebx = Tss->Ebx;
+ TrapFrame.Esi = Tss->Esi;
+ TrapFrame.Edi = Tss->Edi;
+ TrapFrame.SegFs = Tss->Fs;
+ TrapFrame.ExceptionList = PCR->Tib.ExceptionList;
+ TrapFrame.PreviousPreviousMode = -1;
+ TrapFrame.Eax = Tss->Eax;
+ TrapFrame.Ecx = Tss->Ecx;
+ TrapFrame.Edx = Tss->Edx;
+ TrapFrame.SegDs = Tss->Ds;
+ TrapFrame.SegEs = Tss->Es;
+ TrapFrame.SegGs = Tss->Gs;
+ TrapFrame.DbgEip = Tss->Eip;
+ TrapFrame.DbgEbp = Tss->Ebp;
+
+ //
+ // Store the trap frame in the KPRCB
+ //
+ KiSaveProcessorState(&TrapFrame, NULL);
+
+ //
+ // Call any registered NMI handlers and see if they handled it or not
+ //
+ if (!KiHandleNmi())
+ {
+ //
+ // They did not, so call the platform HAL routine to bugcheck the system
+ //
+ // Make sure the HAL believes it's running at HIGH IRQL... we can't use
+ // the normal APIs here as playing with the IRQL could change the system
+ // state
+ //
+ OldIrql = PCR->Irql;
+ PCR->Irql = HIGH_LEVEL;
+ HalHandleNMI(NULL);
+ PCR->Irql = OldIrql;
+ }
+
+ //
+ // Although the CPU disabled NMIs, we just did a BIOS Call, which could've
+ // totally changed things.
+ //
+ // We have to make sure we're still in our original NMI -- a nested NMI
+ // will point back to the NMI TSS, and in that case we're hosed.
+ //
+ if (PCR->TSS->Backlink != KGDT_NMI_TSS)
+ {
+ //
+ // Restore original TSS
+ //
+ PCR->TSS = Tss;
+
+ //
+ // Set it back to busy
+ //
+ TssGdt->HighWord.Bits.Dpl = 0;
+ TssGdt->HighWord.Bits.Pres = 1;
+ TssGdt->HighWord.Bits.Type = I386_ACTIVE_TSS;
+
+ //
+ // Restore nested flag
+ //
+ __writeeflags(__readeflags() | EFLAGS_NESTED_TASK);
+
+ //
+ // Handled, return from interrupt
+ //
+ __asm__ __volatile__ ("iret\n");
+ }
+
+ //
+ // Unhandled: crash the system
+ //
+ KiSystemFatalException(EXCEPTION_NMI, NULL);
}
VOID