/* Get the current thread */
1:
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
/* Make it non-alerted */
mov byte ptr [ebx+KTHREAD_ALERTED], 0
mov fs, bx
/* Save exception list and bogus previous mode */
- push fs:[KPCR_EXCEPTION_LIST]
+ push PCR[KPCR_EXCEPTION_LIST]
push -1
/* Save volatiles and segment registers */
1:
/* Get current thread */
- mov ecx, [fs:KPCR_CURRENT_THREAD]
+ mov ecx, PCR[KPCR_CURRENT_THREAD]
cld
/* Flush DR7 */
1:
/* Get the previous exception list */
- mov ebx, [fs:KPCR_EXCEPTION_LIST]
+ mov ebx, PCR[KPCR_EXCEPTION_LIST]
/* Set the exception handler chain terminator */
- mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
+ mov dword ptr PCR[KPCR_EXCEPTION_LIST], -1
/* Save the previous exception list */
mov [esp+KTRAP_FRAME_EXCEPTION_LIST], ebx
and dword ptr [esp+KTRAP_FRAME_ERROR_CODE], 0
/* Get the current thread and clear direction flag */
- mov ecx, [fs:KPCR_CURRENT_THREAD]
+ mov ecx, PCR[KPCR_CURRENT_THREAD]
cld
/* Flush DR7 */
mov fs, bx
/* Get a pointer to the current thread */
- mov esi, [fs:KPCR_CURRENT_THREAD]
+ mov esi, PCR[KPCR_CURRENT_THREAD]
/* Save the previous exception list */
- push [fs:KPCR_EXCEPTION_LIST]
+ push PCR[KPCR_EXCEPTION_LIST]
/* Set the exception handler chain terminator */
- mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
+ mov dword ptr PCR[KPCR_EXCEPTION_LIST], -1
/* Save the old previous mode */
push [esi+KTHREAD_PREVIOUS_MODE]
mov es, cx
/* Set the current stack to Kernel Stack */
- mov ecx, [fs:KPCR_TSS]
+ mov ecx, PCR[KPCR_TSS]
mov esp, [ecx+KTSS_ESP0]
/* Set up a fake INT Stack. */
push KGDT_R3_TEB + RPL_MASK
/* Save pointer to our PCR */
- mov ebx, [fs:KPCR_SELF]
+ mov ebx, PCR[KPCR_SELF]
/* Get a pointer to the current thread */
mov esi, [ebx+KPCR_CURRENT_THREAD]
cld
/* Save the exception list */
- mov eax, [fs:KPCR_EXCEPTION_LIST]
+ mov eax, PCR[KPCR_EXCEPTION_LIST]
mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax
/* Check if we need debugging */
/* Get the current thread and make it unalerted */
ExitBegin:
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov byte ptr [ebx+KTHREAD_ALERTED], 0
/* Check if it has User-mode APCs pending */
jnz 1f
/* Assert exception list */
- cmp dword ptr fs:[KPCR_EXCEPTION_LIST], 0
+ cmp dword ptr PCR[KPCR_EXCEPTION_LIST], 0
jnz 2f
1:
#endif
/* Restore it */
- mov [fs:KPCR_EXCEPTION_LIST], edx
+ mov PCR[KPCR_EXCEPTION_LIST], edx
.if \RestorePreviousMode
/* Get previous mode */
#endif
/* Restore the previous mode */
- mov esi, [fs:KPCR_CURRENT_THREAD]
+ mov esi, PCR[KPCR_CURRENT_THREAD]
mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
.else
iret
.endm
+//
+// @name INT_EPILOG
+//
+// This macro creates an epilogue for leaving any system trap.
+// It is used for exiting system calls, exceptions, interrupts and generic
+// traps.
+//
+// @param Spurious - TRUE if the interrupt was unexpected and spurious.
+//
+// @remark None.
+//
+.macro INT_EPILOG Spurious
+
+.if \Spurious
+ /* Just exit the trap */
+ jmp _Kei386EoiHelper@0
+.else
+ /* Disable interrupts */
+ cli
+
+ /* End the interrupt and do EOI */
+ call _HalEndSystemInterrupt@8
+ jmp _Kei386EoiHelper@0
+.endif
+.endm
+
+#ifdef DBG
+
+.macro VERIFY_INT Label
+ /* Get the current time and mask it to 192 ticks */
+ mov eax, _KeTickCount
+ and eax, 0xC0
+
+ /* Check if we're in the same tick area */
+ cmp eax, dword ptr [edi+KINTERRUPT_TICK_COUNT]
+ jg VfRst_&Label
+ jl VfWrap_&Label
+
+ /* If we got here, then our count is too large */
+ dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT]
+ jz VfOvr_&Label
+Vf_&Label:
+.endm
+
+.macro VERIFY_INT_END Label, Info
+VfOvr_&Label:
+
+ /* Decrement the dispatch count and check if we should bug check */
+ dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2]
+ jz 1f
+
+ /* Update the tick count */
+ add eax, 0x40
+ mov [edi+KINTERRUPT_TICK_COUNT], eax
+ jmp VfRstDef_&Label
+
+.1:
+ /* Check if the debugger is enabled */
+ cmp byte ptr __KdDebuggerEnabled, 0
+ jnz 1f
+
+ /* It isn't, bugcheck */
+ push Info
+ push edi
+ push [edi+KINTERRUPT_SERVICE_CONTEXT]
+ push [edi+KINTERRUPT_SERVICE_ROUTINE]
+ push HARDWARE_INTERRUPT_STORM
+ call _KeBugCheckEx@20
+
+1:
+ /* Debugger enabled, do a debug print + break instead */
+ push [edi+KINTERRUPT_SERVICE_ROUTINE]
+ push offset _IsrOverflowMsg
+ call _DbgPrint
+ add esp, 8
+ int 3
+
+ /* Breakpoint handled, get the new tick count */
+ mov eax, _KeTickCount
+ and eax, 0xC0
+
+VfRst_&Label:
+ /* Reset tick count */
+ mov dword ptr [edi+KINTERRUPT_TICK_COUNT], eax
+ mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2], 64
+
+VfRstDef_&Label:
+ /* Put default overflow count and continue */
+ mov ax, _KiISROverflow
+ mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT], ax
+ jmp Vf_&Label
+
+VfWrap_&Label:
+ /* Check if we wrapped */
+ add eax, 0x40
+ cmp eax, [edi+KINTERRUPT_TICK_COUNT]
+ je Vf_&Label
+
+ /* We did, start over */
+ mov eax, _KeTickCount
+ jmp VfRst_&Label
+.endm
+
+#else
+
+/* We don't verify interrupts on retail builds */
+.macro VERIFY_INT Label
+.endm
+.macro VERIFY_INT_END Label, Info
+.endm
+
+#endif
+
+
_UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
+_IsrTimeoutMsg:
+ .asciz "\n*** ISR at %lx took over .5 second\n"
+
+_IsrOverflowMsg:
+ .asciz "\n*** ISR at %lx appears to have an interrupt storm\n"
+
_KiTrapPrefixTable:
.byte 0xF2 /* REP */
.byte 0xF3 /* REP INS/OUTS */
jnz NotWin32K
/* Get the TEB */
- mov ecx, [fs:KPCR_TEB]
+ mov ecx, PCR[KPCR_TEB]
/* Check if we should flush the User Batch */
xor ebx, ebx
NotWin32K:
/* Increase total syscall count */
- inc dword ptr fs:[KPCR_SYSTEM_CALLS]
+ inc dword ptr PCR[KPCR_SYSTEM_CALLS]
#ifdef DBG
/* Increase per-syscall count */
mov eax, esi /* Restore it */
/* Get our temporary current thread pointer for sanity check */
- mov ecx, fs:[KPCR_CURRENT_THREAD]
+ mov ecx, PCR[KPCR_CURRENT_THREAD]
/* Make sure that we are not attached and that APCs are not disabled */
mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
KeReturnFromSystemCall:
/* Get the Current Thread */
- mov ecx, [fs:KPCR_CURRENT_THREAD]
+ mov ecx, PCR[KPCR_CURRENT_THREAD]
/* Restore the old trap frame pointer */
mov edx, [ebp+KTRAP_FRAME_EDX]
BadStack:
/* Restore ESP0 stack */
- mov ecx, [fs:KPCR_TSS]
+ mov ecx, PCR[KPCR_TSS]
mov esp, ss:[ecx+KTSS_ESP0]
/* Generate V86M Stack for Trap 6 */
#ifdef DBG
InvalidIrql:
/* Save current IRQL */
- push fs:[KPCR_IRQL]
+ push PCR[KPCR_IRQL]
/* Set us at passive */
- mov dword ptr fs:[KPCR_IRQL], 0
+ mov dword ptr PCR[KPCR_IRQL], 0
cli
/* Bugcheck */
push ebp
/* Get the current thread and restore its trap frame */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov edx, [ebp+KTRAP_FRAME_EDX]
mov [ebx+KTHREAD_TRAP_FRAME], edx
/* Get the exception list and restore */
mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
- mov [fs:KPCR_EXCEPTION_LIST], eax
+ mov PCR[KPCR_EXCEPTION_LIST], eax
/* Get the parameters */
mov edx, [ebp+16] /* Search frames */
push ebp
/* Get the current thread and restore its trap frame */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov edx, [ebp+KTRAP_FRAME_EDX]
mov [ebx+KTHREAD_TRAP_FRAME], edx
VdmCheck:
/* Check if this is a VDM process */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz SendException
V86Int1:
/* Check if this is a VDM process */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz EnableInterrupts
V86Int3:
/* Check if this is a VDM process */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz EnableInterrupts3
VdmCheck4:
/* Check if this is a VDM process */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz SendException4
VdmCheck5:
/* Check if this is a VDM process */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz SendException5
jz UmodeOpcode
/* Check if the process is vDM */
- mov ebx, fs:[KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jnz IsVdmOpcode
/* Setup a SEH frame */
push ebp
push OpcodeSEH
- push fs:[KPCR_EXCEPTION_LIST]
- mov fs:[KPCR_EXCEPTION_LIST], esp
+ push PCR[KPCR_EXCEPTION_LIST]
+ mov PCR[KPCR_EXCEPTION_LIST], esp
OpcodeLoop:
/* Get the instruction and check if it's LOCK */
loop OpcodeLoop
/* Undo SEH frame */
- pop fs:[KPCR_EXCEPTION_LIST]
+ pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8
KmodeOpcode:
LockCrash:
/* Undo SEH Frame */
- pop fs:[KPCR_EXCEPTION_LIST]
+ pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8
/* Setup invalid lock exception and dispatch it */
/* Get SEH frame */
mov esp, [esp+8]
- pop fs:[KPCR_EXCEPTION_LIST]
+ pop PCR[KPCR_EXCEPTION_LIST]
add esp, 4
pop ebp
/* Get the current thread and stack */
StartTrapHandle:
- mov eax, [fs:KPCR_CURRENT_THREAD]
+ mov eax, PCR[KPCR_CURRENT_THREAD]
mov ecx, [eax+KTHREAD_INITIAL_STACK]
sub ecx, NPX_FRAME_LENGTH
mov cr0, ebx
/* Check the NPX thread */
- mov edx, [fs:KPCR_NPX_THREAD]
+ mov edx, PCR[KPCR_NPX_THREAD]
or edx, edx
jz NoNpxThread
AfterRestore:
/* Set state loaded */
mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
- mov [fs:KPCR_NPX_THREAD], eax
+ mov PCR[KPCR_NPX_THREAD], eax
/* Enable interrupts to happen now */
sti
UserNpx:
/* Get the current thread */
- mov eax, fs:[KPCR_CURRENT_THREAD]
+ mov eax, PCR[KPCR_CURRENT_THREAD]
/* Check NPX state */
cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
/* Update NPX state */
mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
- mov dword ptr fs:[KPCR_NPX_THREAD], 0
+ mov dword ptr PCR[KPCR_NPX_THREAD], 0
NoSaveRestore:
/* Clear the TS bit and re-enable interrupts */
V86Npx:
/* Check if this is a VDM */
- mov eax, fs:[KPCR_CURRENT_THREAD]
+ mov eax, PCR[KPCR_CURRENT_THREAD]
mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz HandleUserNpx
/* Setup SEH handler frame */
mov esp, [esp+8]
- pop fs:[KPCR_EXCEPTION_LIST]
+ pop PCR[KPCR_EXCEPTION_LIST]
add esp, 4
pop ebp
V86_TRAP_PROLOG kitd
/* Make sure that this is a V86 process */
- mov ecx, [fs:KPCR_CURRENT_THREAD]
+ mov ecx, PCR[KPCR_CURRENT_THREAD]
mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0
jnz RaiseIrql
jnz UserModeGpf
/* Check if we have a VDM alert */
- cmp dword ptr fs:[KPCR_VDM_ALERT], 0
+ cmp dword ptr PCR[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Check for GPF during GPF */
NotBiosGpf:
/* Check if the thread was in kernel mode */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF
jz UserModeGpf
jz _KiSystemFatalException
/* Get the process and check which CS this came from */
- mov ebx, fs:[KPCR_CURRENT_THREAD]
+ mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckVdmGpf
/* Setup a SEH handler */
push ebp
push offset _KiTrapExceptHandler
- push fs:[KPCR_EXCEPTION_LIST]
- mov fs:[KPCR_EXCEPTION_LIST], esp
+ push PCR[KPCR_EXCEPTION_LIST]
+ mov PCR[KPCR_EXCEPTION_LIST], esp
/* Get EIP */
mov esi, [ebp+KTRAP_FRAME_EIP]
IsPrivInstruction:
/* Cleanup the SEH frame */
- pop fs:[KPCR_EXCEPTION_LIST]
+ pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8
/* Setup the exception */
NotIoViolation:
/* Cleanup the SEH frame */
- pop fs:[KPCR_EXCEPTION_LIST]
+ pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8
SetException:
TRAP_PROLOG kit14
/* Check if we have a VDM alert */
- cmp dword ptr fs:[KPCR_VDM_ALERT], 0
+ cmp dword ptr PCR[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Get the current thread */
- mov edi, fs:[KPCR_CURRENT_THREAD]
+ mov edi, PCR[KPCR_CURRENT_THREAD]
/* Get the stack address of the frame */
lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
jb NoFixUp
/* Check if we have a TEB */
- mov eax, fs:[KPCR_TEB]
+ mov eax, PCR[KPCR_TEB]
or eax, eax
jle NoFixUp
jnz VdmPF
/* Check if the fault occured in a VDM */
- mov esi, fs:[KPCR_CURRENT_THREAD]
+ mov esi, PCR[KPCR_CURRENT_THREAD]
mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
jz CheckStatus
TRAP_PROLOG kit16
/* Check if this is the NPX Thread */
- mov eax, fs:[KPCR_CURRENT_THREAD]
- cmp eax, fs:[KPCR_NPX_THREAD]
+ mov eax, PCR[KPCR_CURRENT_THREAD]
+ cmp eax, PCR[KPCR_NPX_THREAD]
/* Get the initial stack and NPX frame */
mov ecx, [eax+KTHREAD_INITIAL_STACK]
_KiCoprocessorError@0:
/* Get the NPX Thread's Initial stack */
- mov eax, [fs:KPCR_NPX_THREAD]
+ mov eax, PCR[KPCR_NPX_THREAD]
mov eax, [eax+KTHREAD_INITIAL_STACK]
/* Make space for the FPU Save area */
push esp
/* Go to kernel mode thread stack */
- mov eax, fs:[KPCR_CURRENT_THREAD]
+ mov eax, PCR[KPCR_CURRENT_THREAD]
add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */
INT_PROLOG kui, DoNotPushFakeErrorCode
/* Increase interrupt count */
- inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
+ inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
/* Put vector in EBX and make space for KIRQL */
mov ebx, [esp]
_KiDispatchInterrupt@0:
/* Get the PCR and disable interrupts */
- mov ebx, [fs:KPCR_SELF]
+ mov ebx, PCR[KPCR_SELF]
cli
/* Check if we have to deliver DPCs, timers, or deferred threads */
_KiChainedDispatch@0:
/* Increase interrupt count */
- inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
+ inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
/* Save trap frame */
mov ebp, esp
call _KiChainedDispatch2ndLvl@0
/* Exit the interrupt */
- mov esi, $
- cli
- call _HalEndSystemInterrupt@8
- jmp _Kei386EoiHelper@0
+ INT_EPILOG 0
.endfunc
.func KiInterruptDispatch@0
_KiInterruptDispatch@0:
/* Increase interrupt count */
- inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
+ inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
/* Save trap frame */
mov ebp, esp
mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
ACQUIRE_SPINLOCK(esi, IntSpin)
+ /* Make sure that this interrupt isn't storming */
+ VERIFY_INT kid
+
+ /* Save the tick count */
+ mov ebx, _KeTickCount
+
/* Call the ISR */
mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
push eax
push edi
call [edi+KINTERRUPT_SERVICE_ROUTINE]
+ /* Check if the ISR timed out */
+ add ebx, _KiISRTimeout
+ cmp _KeTickCount, ebx
+ jnc IsrTimeout
+
+ReleaseLock:
/* Release the lock */
RELEASE_SPINLOCK(esi)
/* Exit the interrupt */
- cli
- call _HalEndSystemInterrupt@8
- jmp _Kei386EoiHelper@0
+ INT_EPILOG 0
SpuriousInt:
/* Exit the interrupt */
add esp, 8
- jmp _Kei386EoiHelper@0
+ INT_EPILOG 1
#ifdef CONFIG_SMP
IntSpin:
SPIN_ON_LOCK esi, GetIntLock
#endif
+
+IsrTimeout:
+ /* Print warning message */
+ push [edi+KINTERRUPT_SERVICE_ROUTINE]
+ push offset _IsrTimeoutMsg
+ call _DbgPrint
+ add esp,8
+
+ /* Break into debugger, then continue */
+ int 3
+ jmp ReleaseLock
+
+ /* Cleanup verification */
+ VERIFY_INT_END kid, 0
.endfunc