diff --git a/reactos/include/ndk/asm.h b/reactos/include/ndk/asm.h index 0888ba0f678..012a232941c 100644 --- a/reactos/include/ndk/asm.h +++ b/reactos/include/ndk/asm.h @@ -222,10 +222,12 @@ Author: // #define KINTERRUPT_SERVICE_ROUTINE 0x0C #define KINTERRUPT_SERVICE_CONTEXT 0x10 +#define KINTERRUPT_TICK_COUNT 0x18 #define KINTERRUPT_ACTUAL_LOCK 0x1C #define KINTERRUPT_IRQL 0x20 #define KINTERRUPT_VECTOR 0x24 #define KINTERRUPT_SYNCHRONIZE_IRQL 0x29 +#define KINTERRUPT_DISPATCH_COUNT 0x38 // // KGDTENTRY Offsets @@ -546,6 +548,7 @@ Author: #define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A #define UNEXPECTED_KERNEL_MODE_TRAP 0x7F #define ATTEMPTED_SWITCH_FROM_DPC 0xB8 +#define HARDWARE_INTERRUPT_STORM 0xF2 // // IRQL Levels @@ -607,3 +610,4 @@ Author: #define MAXIMUM_IDTVECTOR 0xFF #endif // !_ASM_H + diff --git a/reactos/include/ndk/ketypes.h b/reactos/include/ndk/ketypes.h index 83354dd0258..2ff4ba75282 100644 --- a/reactos/include/ndk/ketypes.h +++ b/reactos/include/ndk/ketypes.h @@ -622,14 +622,14 @@ typedef struct _KINTERRUPT KSPIN_LOCK SpinLock; ULONG TickCount; PKSPIN_LOCK ActualLock; - PVOID DispatchAddress; + PKINTERRUPT_ROUTINE DispatchAddress; ULONG Vector; KIRQL Irql; KIRQL SynchronizeIrql; BOOLEAN FloatingSave; BOOLEAN Connected; - CHAR Number; - UCHAR ShareVector; + CCHAR Number; + BOOLEAN ShareVector; KINTERRUPT_MODE Mode; #if (NTDDI_VERSION >= NTDDI_LONGHORN) KINTERRUPT_POLARITY Polarity; diff --git a/reactos/ntoskrnl/include/internal/i386/asmmacro.S b/reactos/ntoskrnl/include/internal/i386/asmmacro.S index 2972df214ad..72040970fdd 100644 --- a/reactos/ntoskrnl/include/internal/i386/asmmacro.S +++ b/reactos/ntoskrnl/include/internal/i386/asmmacro.S @@ -353,7 +353,7 @@ _KiUnexpectedInterrupt&Number: /* 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 @@ -440,7 +440,7 @@ _KiUnexpectedInterrupt&Number: 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 */ @@ -476,7 +476,7 @@ _KiUnexpectedInterrupt&Number: 1: /* Get current thread */ - mov ecx, [fs:KPCR_CURRENT_THREAD] + mov ecx, PCR[KPCR_CURRENT_THREAD] cld /* Flush DR7 */ @@ -555,10 +555,10 @@ _KiUnexpectedInterrupt&Number: 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 @@ -579,7 +579,7 @@ _KiUnexpectedInterrupt&Number: 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 */ @@ -631,13 +631,13 @@ _KiUnexpectedInterrupt&Number: 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] @@ -705,7 +705,7 @@ _KiUnexpectedInterrupt&Number: 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. */ @@ -728,7 +728,7 @@ _KiUnexpectedInterrupt&Number: 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] @@ -831,7 +831,7 @@ _KiUnexpectedInterrupt&Number: 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 */ @@ -854,7 +854,7 @@ _KiUnexpectedInterrupt&Number: /* 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 */ @@ -954,7 +954,7 @@ PendingUserApc: jnz 1f /* Assert exception list */ - cmp dword ptr fs:[KPCR_EXCEPTION_LIST], 0 + cmp dword ptr PCR[KPCR_EXCEPTION_LIST], 0 jnz 2f 1: @@ -975,7 +975,7 @@ PendingUserApc: #endif /* Restore it */ - mov [fs:KPCR_EXCEPTION_LIST], edx + mov PCR[KPCR_EXCEPTION_LIST], edx .if \RestorePreviousMode /* Get previous mode */ @@ -990,7 +990,7 @@ PendingUserApc: #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 @@ -1211,3 +1211,117 @@ FastExit: 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 + + diff --git a/reactos/ntoskrnl/ke/i386/irqobj.c b/reactos/ntoskrnl/ke/i386/irqobj.c index 9b07ea9127b..deb5a7a1863 100644 --- a/reactos/ntoskrnl/ke/i386/irqobj.c +++ b/reactos/ntoskrnl/ke/i386/irqobj.c @@ -9,12 +9,17 @@ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES ****************************************************************/ +/* INCLUDES *****************************************************************/ #include #define NDEBUG #include +/* GLOBALS *******************************************************************/ + +ULONG KiISRTimeout = 55; +USHORT KiISROverflow = 30000; + /* PRIVATE FUNCTIONS *********************************************************/ VOID @@ -172,6 +177,8 @@ KeInitializeInterrupt(IN PKINTERRUPT Interrupt, Interrupt->ShareVector = ShareVector; Interrupt->Number = ProcessorNumber; Interrupt->FloatingSave = FloatingSave; + Interrupt->TickCount = (ULONG)-1; + Interrupt->DispatchCount = (ULONG)-1; /* Loop the template in memory */ for (i = 0; i < KINTERRUPT_DISPATCH_CODES; i++) @@ -180,6 +187,14 @@ KeInitializeInterrupt(IN PKINTERRUPT Interrupt, *DispatchCode++ = KiInterruptTemplate[i]; } + /* Sanity check */ + DPRINT1("Template Size: %lx. Code Size: %lx\n", + (ULONG_PTR)&KiInterruptTemplateDispatch - + (ULONG_PTR)KiInterruptTemplate, + KINTERRUPT_DISPATCH_CODES * 4); + ASSERT((ULONG_PTR)&KiInterruptTemplateDispatch - + (ULONG_PTR)KiInterruptTemplate <= (KINTERRUPT_DISPATCH_CODES * 4)); + /* Jump to the last 4 bytes */ Patch = (PULONG)((ULONG_PTR)Patch + ((ULONG_PTR)&KiInterruptTemplateObject - @@ -216,7 +231,6 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt) (Interrupt->SynchronizeIrql < Irql) || (Interrupt->FloatingSave)) { - DPRINT1("Invalid interrupt object\n"); return FALSE; } @@ -254,7 +268,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt) (Dispatch.Interrupt->Mode == Interrupt->Mode)) { /* The vector is shared and the interrupts are compatible */ - ASSERT(FALSE); // FIXME: NOT YET SUPPORTED/TESTED + while (TRUE); // FIXME: NOT YET SUPPORTED/TESTED Interrupt->Connected = Connected = TRUE; ASSERT(Irql <= SYNCH_LEVEL); @@ -275,6 +289,14 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt) KiReleaseDispatcherLock(OldIrql); KeRevertToUserAffinityThread(); + /* Check if we failed while trying to connect */ + if ((Connected) && (Error)) + { + DPRINT1("HalEnableSystemInterrupt failed\n"); + KeDisconnectInterrupt(Interrupt); + Connected = FALSE; + } + /* Return to caller */ return Connected; } diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index cba533b27eb..8aabaf63c74 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -93,6 +93,12 @@ _UnexpectedMsg: _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 */ @@ -174,7 +180,7 @@ SharedCode: 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 @@ -191,7 +197,7 @@ ReadBatch: 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 */ @@ -243,7 +249,7 @@ AfterSysCall: 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] @@ -262,7 +268,7 @@ SkipCheck: 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] @@ -353,7 +359,7 @@ AccessViolation: 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 */ @@ -373,10 +379,10 @@ BadStack: #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 */ @@ -485,7 +491,7 @@ _NtRaiseException@12: 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 @@ -497,7 +503,7 @@ _NtRaiseException@12: /* 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 */ @@ -532,7 +538,7 @@ _NtContinue@8: 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 @@ -696,7 +702,7 @@ SendException: 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 @@ -742,7 +748,7 @@ PrepInt1: 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 @@ -806,7 +812,7 @@ PrepInt3: 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 @@ -847,7 +853,7 @@ SendException4: 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 @@ -893,7 +899,7 @@ SendException5: 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 @@ -934,7 +940,7 @@ NotV86UD: 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 @@ -950,8 +956,8 @@ UmodeOpcode: /* 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 */ @@ -964,7 +970,7 @@ OpcodeLoop: loop OpcodeLoop /* Undo SEH frame */ - pop fs:[KPCR_EXCEPTION_LIST] + pop PCR[KPCR_EXCEPTION_LIST] add esp, 8 KmodeOpcode: @@ -980,7 +986,7 @@ 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 */ @@ -1000,7 +1006,7 @@ OpcodeSEH: /* Get SEH frame */ mov esp, [esp+8] - pop fs:[KPCR_EXCEPTION_LIST] + pop PCR[KPCR_EXCEPTION_LIST] add esp, 4 pop ebp @@ -1030,7 +1036,7 @@ _KiTrap7: /* 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 @@ -1049,7 +1055,7 @@ CheckState: mov cr0, ebx /* Check the NPX thread */ - mov edx, [fs:KPCR_NPX_THREAD] + mov edx, PCR[KPCR_NPX_THREAD] or edx, edx jz NoNpxThread @@ -1083,7 +1089,7 @@ FrRestore: 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 @@ -1144,7 +1150,7 @@ HandleNpxFault: 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 @@ -1180,7 +1186,7 @@ MakeCr0Dirty: /* 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 */ @@ -1293,7 +1299,7 @@ UnexpectedNpx: 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 @@ -1414,7 +1420,7 @@ _KiTrapExceptHandler: /* Setup SEH handler frame */ mov esp, [esp+8] - pop fs:[KPCR_EXCEPTION_LIST] + pop PCR[KPCR_EXCEPTION_LIST] add esp, 4 pop ebp @@ -1445,7 +1451,7 @@ _KiTrap13: 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 @@ -1505,7 +1511,7 @@ NotV86: 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 */ @@ -1565,7 +1571,7 @@ KmodeGpf: 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 @@ -1656,7 +1662,7 @@ 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 @@ -1719,8 +1725,8 @@ CheckPrivilegedInstruction: /* 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] @@ -1790,7 +1796,7 @@ CheckPrivilegedInstruction2: IsPrivInstruction: /* Cleanup the SEH frame */ - pop fs:[KPCR_EXCEPTION_LIST] + pop PCR[KPCR_EXCEPTION_LIST] add esp, 8 /* Setup the exception */ @@ -1800,7 +1806,7 @@ IsPrivInstruction: NotIoViolation: /* Cleanup the SEH frame */ - pop fs:[KPCR_EXCEPTION_LIST] + pop PCR[KPCR_EXCEPTION_LIST] add esp, 8 SetException: @@ -1824,11 +1830,11 @@ _KiTrap14: 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] @@ -1840,7 +1846,7 @@ _KiTrap14: jb NoFixUp /* Check if we have a TEB */ - mov eax, fs:[KPCR_TEB] + mov eax, PCR[KPCR_TEB] or eax, eax jle NoFixUp @@ -1913,7 +1919,7 @@ CheckVdmPf: 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 @@ -2006,8 +2012,8 @@ _KiTrap16: 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] @@ -2059,7 +2065,7 @@ _KiSystemFatalException: _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 */ @@ -2085,7 +2091,7 @@ _Ki16BitStackException: 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 */ @@ -2112,7 +2118,7 @@ _KiUnexpectedInterruptTail: 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] @@ -2161,7 +2167,7 @@ _KiUnexpectedInterrupt: _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 */ @@ -2281,7 +2287,7 @@ _KiChainedDispatch2ndLvl@0: _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 @@ -2308,17 +2314,14 @@ _KiChainedDispatch@0: 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 @@ -2346,27 +2349,51 @@ GetIntLock: 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