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/i386/asmmacro.S?rev=45040&r1=45039&r2=45040&view=diff
==============================================================================
--- 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 @kfraisei...@4
-
-    /* Save KIRQL and deliver APCs */
-    push eax
-    sti
-    push ebp
-    push 0
-    push UserMode
-    call _kideliver...@12
-
-    /* Restore IRQL */
-    pop ecx
-    call @kfloweri...@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/ke.h?rev=45040&r1=45039&r2=45040&view=diff
==============================================================================
--- 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=45040&r1=45039&r2=45040&view=diff
==============================================================================
--- 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?rev=45040&r1=45039&r2=45040&view=diff
==============================================================================
--- 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 _kebugcheckwit...@24
-    ret
-.endfunc
-
-.func kicoprocessorer...@0
-_kicoprocessorer...@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.c?rev=45040&r1=45039&r2=45040&view=diff
==============================================================================
--- 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


Reply via email to