[NTOS:KE]
[reactos.git] / reactos / ntoskrnl / ke / i386 / traphdlr.c
index 9e5defe..be5dd31 100644 (file)
@@ -12,8 +12,8 @@
 #define NDEBUG
 #include <debug.h>
 
-VOID KiFastCallEntry(VOID);
-VOID KiFastCallEntryWithSingleStep(VOID);
+VOID __cdecl KiFastCallEntry(VOID);
+VOID __cdecl KiFastCallEntryWithSingleStep(VOID);
 
 extern PVOID FrRestore;
 VOID FASTCALL Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea);
@@ -56,7 +56,7 @@ PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
 PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
 PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
 #endif
-#if TRAP_DEBUG
+#if DBG
 BOOLEAN StopChecking = FALSE;
 #endif
 
@@ -173,6 +173,7 @@ KiServiceExit(IN PKTRAP_FRAME TrapFrame,
         {
             /* We can use the sysexit handler */
             KiFastCallExitHandler(TrapFrame);
+            UNREACHABLE;
         }
     }
 
@@ -262,8 +263,8 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
         }
     }
 
-    /* User or kernel trap -- get ready to issue an exception */
-    if (Thread->NpxState == NPX_STATE_NOT_LOADED)
+    /* User or kernel trap -- check if we need to unload the current state */
+    if (Thread->NpxState == NPX_STATE_LOADED)
     {
         /* Update CR0 */
         Cr0 = __readcr0();
@@ -310,8 +311,6 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
     }
 
     /* Get legal exceptions that software should handle */
-    /* We do this by first masking off from the Mask the bits we need, */
-    /* This is done so we can keep the FSW_STACK_FAULT bit in Error. */
     Mask &= (FSW_INVALID_OPERATION |
              FSW_DENORMAL |
              FSW_ZERO_DIVIDE |
@@ -323,9 +322,10 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
     /* Check for invalid operation */
     if (Error & FSW_INVALID_OPERATION)
     {
-        /* NOTE: Stack fault is handled differently than any other case. */
-        /* 1. It's only raised for invalid operation. */
-        /* 2. It's only raised if invalid operation is not masked. */
+        /*
+         * Now check if this is actually a Stack Fault. This is needed because
+         * on x86 the Invalid Operation error is set for Stack Check faults as well.
+         */
         if (Error & FSW_STACK_FAULT)
         {
             /* Issue stack check fault */
@@ -335,12 +335,14 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
                                      DataOffset,
                                      TrapFrame);
         }
-
-        /* Issue fault */
-        KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
-                                 ErrorOffset,
-                                 0,
-                                 TrapFrame);
+        else
+        {
+            /* This is an invalid operation fault after all, so raise that instead */
+            KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
+                                     ErrorOffset,
+                                     0,
+                                     TrapFrame);
+        }
     }
 
     /* Check for divide by zero */
@@ -527,7 +529,7 @@ KiTrap02(VOID)
     TrapFrame.Edi = Tss->Edi;
     TrapFrame.SegFs = Tss->Fs;
     TrapFrame.ExceptionList = PCR->NtTib.ExceptionList;
-    TrapFrame.PreviousPreviousMode = -1;
+    TrapFrame.PreviousPreviousMode = (ULONG)-1;
     TrapFrame.Eax = Tss->Eax;
     TrapFrame.Ecx = Tss->Ecx;
     TrapFrame.Edx = Tss->Edx;
@@ -681,7 +683,7 @@ KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
         }
 
         /* Go to APC level */
-        OldIrql = KfRaiseIrql(APC_LEVEL);
+        KeRaiseIrql(APC_LEVEL, &OldIrql);
         _enable();
 
         /* Check for BOP */
@@ -692,7 +694,7 @@ KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
         }
 
         /* Bring IRQL back */
-        KfLowerIrql(OldIrql);
+        KeLowerIrql(OldIrql);
         _disable();
 
         /* Do a quick V86 exit if possible */
@@ -936,7 +938,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
         }
 
         /* Go to APC level */
-        OldIrql = KfRaiseIrql(APC_LEVEL);
+        KeRaiseIrql(APC_LEVEL, &OldIrql);
         _enable();
 
         /* Handle the V86 opcode */
@@ -947,7 +949,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
         }
 
         /* Bring IRQL back */
-        KfLowerIrql(OldIrql);
+        KeLowerIrql(OldIrql);
         _disable();
 
         /* Do a quick V86 exit if possible */
@@ -1195,6 +1197,8 @@ FASTCALL
 KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
 {
     PKTHREAD Thread;
+    BOOLEAN Present;
+    BOOLEAN StoreInstruction;
     ULONG_PTR Cr2;
     NTSTATUS Status;
 
@@ -1217,17 +1221,21 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
     /* Save CR2 */
     Cr2 = __readcr2();
 
-    /* Enable interupts */
+    /* Enable interrupts */
     _enable();
 
+    /* Interpret the error code */
+    Present = (TrapFrame->ErrCode & 1) != 0;
+    StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
+
     /* Check if we came in with interrupts disabled */
     if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
     {
         /* This is completely illegal, bugcheck the system */
         KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
                          Cr2,
-                         -1,
-                         TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                         (ULONG_PTR)-1,
+                         StoreInstruction,
                          TrapFrame->Eip,
                          TrapFrame);
     }
@@ -1265,7 +1273,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
             /* Do what windows does and issue an invalid access violation */
             KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION,
                                      TrapFrame->Eip,
-                                     TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                     StoreInstruction,
                                      Cr2,
                                      TrapFrame);
 #endif
@@ -1273,7 +1281,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
     }
 
     /* Call the access fault handler */
-    Status = MmAccessFault(TrapFrame->ErrCode & 1,
+    Status = MmAccessFault(Present,
                            (PVOID)Cr2,
                            KiUserTrap(TrapFrame),
                            TrapFrame);
@@ -1296,8 +1304,20 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
         UNIMPLEMENTED_FATAL();
     }
 #endif
+
     /* Check for VDM trap */
-    ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
+    if (KiVdmTrap(TrapFrame))
+    {
+        DPRINT1("VDM PAGE FAULT at %lx:%lx for address %lx\n",
+                TrapFrame->SegCs, TrapFrame->Eip, Cr2);
+        if (VdmDispatchPageFault(TrapFrame))
+        {
+            /* Return and end VDM execution */
+            DPRINT1("VDM page fault with status 0x%lx resolved\n", Status);
+            KiEoiHelper(TrapFrame);
+        }
+        DPRINT1("VDM page fault with status 0x%lx NOT resolved\n", Status);
+    }
 
     /* Either kernel or user trap (non VDM) so dispatch exception */
     if (Status == STATUS_ACCESS_VIOLATION)
@@ -1305,7 +1325,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
         /* This status code is repurposed so we can recognize it later */
         KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION,
                                  TrapFrame->Eip,
-                                 TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                 StoreInstruction,
                                  Cr2,
                                  TrapFrame);
     }
@@ -1315,7 +1335,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
         /* These faults only have two parameters */
         KiDispatchException2Args(Status,
                                  TrapFrame->Eip,
-                                 TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                 StoreInstruction,
                                  Cr2,
                                  TrapFrame);
     }
@@ -1325,7 +1345,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
                                      0,
                                      TrapFrame->Eip,
                                      3,
-                                     TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+                                     StoreInstruction,
                                      Cr2,
                                      Status,
                                      TrapFrame);
@@ -1520,7 +1540,17 @@ VOID
 FASTCALL
 KiGetTickCountHandler(IN PKTRAP_FRAME TrapFrame)
 {
-    UNIMPLEMENTED_DBGBREAK();
+    /* Save trap frame */
+    KiEnterTrap(TrapFrame);
+
+    /*
+     * Just fail the request
+     */
+    DbgPrint("INT 0x2A attempted, returning 0 tick count\n");
+    TrapFrame->Eax = 0;
+
+    /* Exit the trap */
+    KiEoiHelper(TrapFrame);
 }
 
 VOID
@@ -1537,7 +1567,7 @@ KiCallbackReturnHandler(IN PKTRAP_FRAME TrapFrame)
     Thread = KeGetCurrentThread();
     Thread->TrapFrame = TrapFrame;
     Thread->PreviousMode = KiUserTrap(TrapFrame);
-    NT_ASSERT(Thread->PreviousMode != KernelMode);
+    ASSERT(Thread->PreviousMode != KernelMode);
 
     /* Pass the register parameters to NtCallbackReturn.
        Result pointer is in ecx, result length in edx, status in eax */
@@ -1611,7 +1641,8 @@ KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
 {
     PKTHREAD Thread;
     PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
-    ULONG Id, Offset, StackBytes, Result;
+    ULONG Id, Offset, StackBytes;
+    NTSTATUS Status;
     PVOID Handler;
     ULONG SystemCallNumber = TrapFrame->Eax;
 
@@ -1669,18 +1700,18 @@ KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
         if (!(Offset & SERVICE_TABLE_TEST))
         {
             /* Fail the call */
-            Result = STATUS_INVALID_SYSTEM_SERVICE;
+            Status = STATUS_INVALID_SYSTEM_SERVICE;
             goto ExitCall;
         }
 
         /* Convert us to a GUI thread -- must wrap in ASM to get new EBP */
-        Result = KiConvertToGuiThread();
+        Status = KiConvertToGuiThread();
 
         /* Reload trap frame and descriptor table pointer from new stack */
         TrapFrame = *(volatile PVOID*)&Thread->TrapFrame;
         DescriptorTable = (PVOID)(*(volatile ULONG_PTR*)&Thread->ServiceTable + Offset);
 
-        if (!NT_SUCCESS(Result))
+        if (!NT_SUCCESS(Status))
         {
             /* Set the last error and fail */
             goto ExitCall;
@@ -1690,7 +1721,7 @@ KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
         if (Id >= DescriptorTable->Limit)
         {
             /* Fail the call */
-            Result = STATUS_INVALID_SYSTEM_SERVICE;
+            Status = STATUS_INVALID_SYSTEM_SERVICE;
             goto ExitCall;
         }
     }
@@ -1723,10 +1754,10 @@ KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
 
     /* Get the handler and make the system call */
     Handler = (PVOID)DescriptorTable->Base[Id];
-    Result = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
+    Status = KiSystemCallTrampoline(Handler, Arguments, StackBytes);
 
     /* Call post-service debug hook */
-    Result = KiDbgPostServiceHook(SystemCallNumber, Result);
+    Status = KiDbgPostServiceHook(SystemCallNumber, Status);
 
     /* Make sure we're exiting correctly */
     KiExitSystemCallDebugChecks(Id, TrapFrame);
@@ -1736,7 +1767,14 @@ ExitCall:
     Thread->TrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
 
     /* Exit from system call */
-    KiServiceExit(TrapFrame, Result);
+    KiServiceExit(TrapFrame, Status);
+}
+
+VOID
+FASTCALL
+KiCheckForSListAddress(IN PKTRAP_FRAME TrapFrame)
+{
+    UNIMPLEMENTED;
 }
 
 /*
@@ -1747,7 +1785,7 @@ NTAPI
 Kei386EoiHelper(VOID)
 {
     /* We should never see this call happening */
-    ERROR_FATAL("Mismatched NT/HAL version");
+    KeBugCheck(MISMATCHED_HAL);
 }
 
 /* EOF */