PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
#endif
+#if TRAP_DEBUG
+BOOLEAN StopChecking = FALSE;
+#endif
/* TRAP EXIT CODE *************************************************************/
VOID
FORCEINLINE
-KiCommonExit(IN PKTRAP_FRAME TrapFrame, const ULONG Flags)
+KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode)
{
/* Disable interrupts until we return */
_disable();
-
+
/* Check for APC delivery */
KiCheckForApcDelivery(TrapFrame);
-
- /* Debugging checks */
- KiExitTrapDebugChecks(TrapFrame, Flags);
/* Restore the SEH handler chain */
KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
/* Check if there are active debug registers */
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
{
- /* Not handled yet */
- DbgPrint("Need Hardware Breakpoint Support!\n");
- DbgBreakPoint();
- while (TRUE);
+ /* Check if the frame was from user mode or v86 mode */
+ if ((TrapFrame->SegCs & MODE_MASK) ||
+ (TrapFrame->EFlags & EFLAGS_V86_MASK))
+ {
+ /* Handle debug registers */
+ KiHandleDebugRegistersOnTrapExit(TrapFrame);
+ }
}
+
+ /* Debugging checks */
+ KiExitTrapDebugChecks(TrapFrame, SkipPreviousMode);
}
DECLSPEC_NORETURN
KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
{
/* Common trap exit code */
- KiCommonExit(TrapFrame, 0);
+ KiCommonExit(TrapFrame, TRUE);
/* Check if this was a V8086 trap */
if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame);
TrapFrame->Eax = Status;
/* Common trap exit code */
- KiCommonExit(TrapFrame, 0);
+ KiCommonExit(TrapFrame, FALSE);
/* Restore previous mode */
KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode;
KiServiceExit2(IN PKTRAP_FRAME TrapFrame)
{
/* Common trap exit code */
- KiCommonExit(TrapFrame, 0);
+ KiCommonExit(TrapFrame, FALSE);
/* Restore previous mode */
KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode;
}
/* Get legal exceptions that software should handle */
- Error &= (FSW_INVALID_OPERATION |
- FSW_DENORMAL |
- FSW_ZERO_DIVIDE |
- FSW_OVERFLOW |
- FSW_UNDERFLOW |
- FSW_PRECISION);
+ /* 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 |
+ FSW_OVERFLOW |
+ FSW_UNDERFLOW |
+ FSW_PRECISION);
Error &= ~Mask;
-
- if (Error & FSW_STACK_FAULT)
- {
- /* Issue stack check fault */
- KiDispatchException2Args(STATUS_FLOAT_STACK_CHECK,
- ErrorOffset,
- 0,
- DataOffset,
- 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. */
+ if (Error & FSW_STACK_FAULT)
+ {
+ /* Issue stack check fault */
+ KiDispatchException2Args(STATUS_FLOAT_STACK_CHECK,
+ ErrorOffset,
+ 0,
+ DataOffset,
+ TrapFrame);
+ }
+
/* Issue fault */
KiDispatchException1Args(STATUS_FLOAT_INVALID_OPERATION,
ErrorOffset,
if (!VdmDispatchBop(TrapFrame))
{
/* Should only happen in VDM mode */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
/* Bring IRQL back */
if (SaveArea->Cr0NpxState & CR0_EM)
{
/* Not implemented */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
/* Save CR0 and check NPX state */
//Ke386SaveFpuState(NpxSaveArea);
/* Update NPX state */
- Thread->NpxState = NPX_STATE_NOT_LOADED;
+ NpxThread->NpxState = NPX_STATE_NOT_LOADED;
}
/* Load FPU state */
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
-
+
/* Kill the system */
KiSystemFatalException(EXCEPTION_INVALID_TSS, TrapFrame);
}
if (__builtin_expect(Ki386HandleOpcodeV86(TrapFrame) == 0xFF, 0))
{
/* Should only happen in VDM mode */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
/* Bring IRQL back */
}
/* Check for privileged instructions */
+ DPRINT("Instruction (%d) at fault: %lx %lx %lx %lx\n",
+ i,
+ Instructions[i],
+ Instructions[i + 1],
+ Instructions[i + 2],
+ Instructions[i + 3]);
if (Instruction == 0xF4) // HLT
{
/* HLT is privileged */
(Instructions[i + 1] == 0x08) || // INVD
(Instructions[i + 1] == 0x09) || // WBINVD
(Instructions[i + 1] == 0x35) || // SYSEXIT
- (Instructions[i + 1] == 0x26) || // MOV DR, XXX
+ (Instructions[i + 1] == 0x21) || // MOV DR, XXX
(Instructions[i + 1] == 0x06) || // CLTS
(Instructions[i + 1] == 0x20) || // MOV CR, XXX
- (Instructions[i + 1] == 0x24) || // MOV YYY, DR
+ (Instructions[i + 1] == 0x22) || // MOV XXX, CR
+ (Instructions[i + 1] == 0x23) || // MOV YYY, DR
(Instructions[i + 1] == 0x30) || // WRMSR
(Instructions[i + 1] == 0x33)) // RDPMC
// INVLPG, INVLPGA, SYSRET
((PVOID)TrapFrame->Eip < (PVOID)KiTrap0DHandler))
{
/* Not implemented */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
-
+
/*
* NOTE: The ASM trap exit code would restore segment registers by doing
* a POP <SEG>, which could cause an invalid segment if someone had messed
else
{
/* Otherwise, this is another kind of IRET fault */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
}
FIELD_OFFSET(KTRAP_FRAME, EFlags))
{
/* The stack is somewhere in between frames, we need to fix it */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
}
-
+
/* Save CR2 */
Cr2 = __readcr2();
-
- /* HACK: Check if interrupts are disabled and enable them */
+
+ /* Enable interupts */
+ _enable();
+
+ /* Check if we came in with interrupts disabled */
if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
{
- /* Enable interupts */
- _enable();
-#ifdef HACK_ABOVE_FIXED
- if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
- {
- /* This is illegal */
- KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
- Cr2,
- -1,
- TrapFrame->ErrCode & 1,
- TrapFrame->Eip,
- TrapFrame);
- }
-#endif
+ /* This is completely illegal, bugcheck the system */
+ KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
+ Cr2,
+ -1,
+ TrapFrame->ErrCode & 2 ? TRUE : FALSE,
+ TrapFrame->Eip,
+ TrapFrame);
}
/* Check for S-LIST fault in kernel mode */
(TrapFrame->Eip == (ULONG_PTR)ReadBatch))
{
/* Not yet implemented */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
#endif
/* Check for VDM trap */
/* This status code is repurposed so we can recognize it later */
KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION,
TrapFrame->Eip,
- TrapFrame->ErrCode & 1,
+ TrapFrame->ErrCode & 2 ? TRUE : FALSE,
Cr2,
TrapFrame);
}
/* These faults only have two parameters */
KiDispatchException2Args(Status,
TrapFrame->Eip,
- TrapFrame->ErrCode & 1,
+ TrapFrame->ErrCode & 2 ? TRUE : FALSE,
Cr2,
TrapFrame);
}
KiDispatchExceptionFromTrapFrame(STATUS_IN_PAGE_ERROR,
TrapFrame->Eip,
3,
- TrapFrame->ErrCode & 1,
+ TrapFrame->ErrCode & 2 ? TRUE : FALSE,
Cr2,
Status,
TrapFrame);
FASTCALL
KiGetTickCountHandler(IN PKTRAP_FRAME TrapFrame)
{
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_DBGBREAK();
}
VOID
FASTCALL
KiCallbackReturnHandler(IN PKTRAP_FRAME TrapFrame)
{
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_DBGBREAK();
}
DECLSPEC_NORETURN
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
- /* Clear DR7 and check for debugging */
+ /* Default to debugging disabled */
TrapFrame->Dr7 = 0;
- if (__builtin_expect(Thread->DispatcherHeader.DebugActive & 0xFF, 0))
+
+ /* Check if the frame was from user mode */
+ if (TrapFrame->SegCs & MODE_MASK)
{
- UNIMPLEMENTED;
- while (TRUE);
+ /* Check for active debugging */
+ if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
+ {
+ /* Handle debug registers */
+ KiHandleDebugRegistersOnTrapEntry(TrapFrame);
+ }
}
/* Set thread fields */
/* Convert us to a GUI thread -- must wrap in ASM to get new EBP */
Result = 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))
{
/* Set the last error and fail */
//SetLastWin32Error(RtlNtStatusToDosError(Result));
goto ExitCall;
}
-
- /* Reload trap frame and descriptor table pointer from new stack */
- TrapFrame = *(volatile PVOID*)&Thread->TrapFrame;
- DescriptorTable = (PVOID)(*(volatile ULONG_PTR*)&Thread->ServiceTable + Offset);
-
+
/* Validate the system call number again */
if (Id >= DescriptorTable->Limit)
{
if (__builtin_expect((Arguments < (PVOID)MmUserProbeAddress) && !(KiUserTrap(TrapFrame)), 0))
{
/* Access violation */
- UNIMPLEMENTED;
- while (TRUE);
+ UNIMPLEMENTED_FATAL();
}
/* Call pre-service debug hook */
Kei386EoiHelper(VOID)
{
/* We should never see this call happening */
- DPRINT1("Mismatched NT/HAL version");
- while (TRUE);
+ ERROR_FATAL("Mismatched NT/HAL version");
}
/* EOF */