- New ISR Timeout detection code.

- New Interrupt Storm detection code.
- Use PCR everywhere instead of fs:[ or [fs:. Significant improvements on UP builds because we use ds:[KPCRADDRESSS] for them.
- Ongoing work.

svn path=/trunk/; revision=26137
This commit is contained in:
Alex Ionescu 2007-03-19 03:29:29 +00:00
parent 42c0ac532c
commit 32ca724933
5 changed files with 245 additions and 78 deletions

View file

@ -222,10 +222,12 @@ Author:
// //
#define KINTERRUPT_SERVICE_ROUTINE 0x0C #define KINTERRUPT_SERVICE_ROUTINE 0x0C
#define KINTERRUPT_SERVICE_CONTEXT 0x10 #define KINTERRUPT_SERVICE_CONTEXT 0x10
#define KINTERRUPT_TICK_COUNT 0x18
#define KINTERRUPT_ACTUAL_LOCK 0x1C #define KINTERRUPT_ACTUAL_LOCK 0x1C
#define KINTERRUPT_IRQL 0x20 #define KINTERRUPT_IRQL 0x20
#define KINTERRUPT_VECTOR 0x24 #define KINTERRUPT_VECTOR 0x24
#define KINTERRUPT_SYNCHRONIZE_IRQL 0x29 #define KINTERRUPT_SYNCHRONIZE_IRQL 0x29
#define KINTERRUPT_DISPATCH_COUNT 0x38
// //
// KGDTENTRY Offsets // KGDTENTRY Offsets
@ -546,6 +548,7 @@ Author:
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A #define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
#define UNEXPECTED_KERNEL_MODE_TRAP 0x7F #define UNEXPECTED_KERNEL_MODE_TRAP 0x7F
#define ATTEMPTED_SWITCH_FROM_DPC 0xB8 #define ATTEMPTED_SWITCH_FROM_DPC 0xB8
#define HARDWARE_INTERRUPT_STORM 0xF2
// //
// IRQL Levels // IRQL Levels
@ -607,3 +610,4 @@ Author:
#define MAXIMUM_IDTVECTOR 0xFF #define MAXIMUM_IDTVECTOR 0xFF
#endif // !_ASM_H #endif // !_ASM_H

View file

@ -622,14 +622,14 @@ typedef struct _KINTERRUPT
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock;
ULONG TickCount; ULONG TickCount;
PKSPIN_LOCK ActualLock; PKSPIN_LOCK ActualLock;
PVOID DispatchAddress; PKINTERRUPT_ROUTINE DispatchAddress;
ULONG Vector; ULONG Vector;
KIRQL Irql; KIRQL Irql;
KIRQL SynchronizeIrql; KIRQL SynchronizeIrql;
BOOLEAN FloatingSave; BOOLEAN FloatingSave;
BOOLEAN Connected; BOOLEAN Connected;
CHAR Number; CCHAR Number;
UCHAR ShareVector; BOOLEAN ShareVector;
KINTERRUPT_MODE Mode; KINTERRUPT_MODE Mode;
#if (NTDDI_VERSION >= NTDDI_LONGHORN) #if (NTDDI_VERSION >= NTDDI_LONGHORN)
KINTERRUPT_POLARITY Polarity; KINTERRUPT_POLARITY Polarity;

View file

@ -353,7 +353,7 @@ _KiUnexpectedInterrupt&Number:
/* Get the current thread */ /* Get the current thread */
1: 1:
mov ebx, [fs:KPCR_CURRENT_THREAD] mov ebx, PCR[KPCR_CURRENT_THREAD]
/* Make it non-alerted */ /* Make it non-alerted */
mov byte ptr [ebx+KTHREAD_ALERTED], 0 mov byte ptr [ebx+KTHREAD_ALERTED], 0
@ -440,7 +440,7 @@ _KiUnexpectedInterrupt&Number:
mov fs, bx mov fs, bx
/* Save exception list and bogus previous mode */ /* Save exception list and bogus previous mode */
push fs:[KPCR_EXCEPTION_LIST] push PCR[KPCR_EXCEPTION_LIST]
push -1 push -1
/* Save volatiles and segment registers */ /* Save volatiles and segment registers */
@ -476,7 +476,7 @@ _KiUnexpectedInterrupt&Number:
1: 1:
/* Get current thread */ /* Get current thread */
mov ecx, [fs:KPCR_CURRENT_THREAD] mov ecx, PCR[KPCR_CURRENT_THREAD]
cld cld
/* Flush DR7 */ /* Flush DR7 */
@ -555,10 +555,10 @@ _KiUnexpectedInterrupt&Number:
1: 1:
/* Get the previous exception list */ /* Get the previous exception list */
mov ebx, [fs:KPCR_EXCEPTION_LIST] mov ebx, PCR[KPCR_EXCEPTION_LIST]
/* Set the exception handler chain terminator */ /* 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 */ /* Save the previous exception list */
mov [esp+KTRAP_FRAME_EXCEPTION_LIST], ebx mov [esp+KTRAP_FRAME_EXCEPTION_LIST], ebx
@ -579,7 +579,7 @@ _KiUnexpectedInterrupt&Number:
and dword ptr [esp+KTRAP_FRAME_ERROR_CODE], 0 and dword ptr [esp+KTRAP_FRAME_ERROR_CODE], 0
/* Get the current thread and clear direction flag */ /* Get the current thread and clear direction flag */
mov ecx, [fs:KPCR_CURRENT_THREAD] mov ecx, PCR[KPCR_CURRENT_THREAD]
cld cld
/* Flush DR7 */ /* Flush DR7 */
@ -631,13 +631,13 @@ _KiUnexpectedInterrupt&Number:
mov fs, bx mov fs, bx
/* Get a pointer to the current thread */ /* Get a pointer to the current thread */
mov esi, [fs:KPCR_CURRENT_THREAD] mov esi, PCR[KPCR_CURRENT_THREAD]
/* Save the previous exception list */ /* Save the previous exception list */
push [fs:KPCR_EXCEPTION_LIST] push PCR[KPCR_EXCEPTION_LIST]
/* Set the exception handler chain terminator */ /* 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 */ /* Save the old previous mode */
push [esi+KTHREAD_PREVIOUS_MODE] push [esi+KTHREAD_PREVIOUS_MODE]
@ -705,7 +705,7 @@ _KiUnexpectedInterrupt&Number:
mov es, cx mov es, cx
/* Set the current stack to Kernel Stack */ /* Set the current stack to Kernel Stack */
mov ecx, [fs:KPCR_TSS] mov ecx, PCR[KPCR_TSS]
mov esp, [ecx+KTSS_ESP0] mov esp, [ecx+KTSS_ESP0]
/* Set up a fake INT Stack. */ /* Set up a fake INT Stack. */
@ -728,7 +728,7 @@ _KiUnexpectedInterrupt&Number:
push KGDT_R3_TEB + RPL_MASK push KGDT_R3_TEB + RPL_MASK
/* Save pointer to our PCR */ /* Save pointer to our PCR */
mov ebx, [fs:KPCR_SELF] mov ebx, PCR[KPCR_SELF]
/* Get a pointer to the current thread */ /* Get a pointer to the current thread */
mov esi, [ebx+KPCR_CURRENT_THREAD] mov esi, [ebx+KPCR_CURRENT_THREAD]
@ -831,7 +831,7 @@ _KiUnexpectedInterrupt&Number:
cld cld
/* Save the exception list */ /* Save the exception list */
mov eax, [fs:KPCR_EXCEPTION_LIST] mov eax, PCR[KPCR_EXCEPTION_LIST]
mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax
/* Check if we need debugging */ /* Check if we need debugging */
@ -854,7 +854,7 @@ _KiUnexpectedInterrupt&Number:
/* Get the current thread and make it unalerted */ /* Get the current thread and make it unalerted */
ExitBegin: ExitBegin:
mov ebx, [fs:KPCR_CURRENT_THREAD] mov ebx, PCR[KPCR_CURRENT_THREAD]
mov byte ptr [ebx+KTHREAD_ALERTED], 0 mov byte ptr [ebx+KTHREAD_ALERTED], 0
/* Check if it has User-mode APCs pending */ /* Check if it has User-mode APCs pending */
@ -954,7 +954,7 @@ PendingUserApc:
jnz 1f jnz 1f
/* Assert exception list */ /* Assert exception list */
cmp dword ptr fs:[KPCR_EXCEPTION_LIST], 0 cmp dword ptr PCR[KPCR_EXCEPTION_LIST], 0
jnz 2f jnz 2f
1: 1:
@ -975,7 +975,7 @@ PendingUserApc:
#endif #endif
/* Restore it */ /* Restore it */
mov [fs:KPCR_EXCEPTION_LIST], edx mov PCR[KPCR_EXCEPTION_LIST], edx
.if \RestorePreviousMode .if \RestorePreviousMode
/* Get previous mode */ /* Get previous mode */
@ -990,7 +990,7 @@ PendingUserApc:
#endif #endif
/* Restore the previous mode */ /* Restore the previous mode */
mov esi, [fs:KPCR_CURRENT_THREAD] mov esi, PCR[KPCR_CURRENT_THREAD]
mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
.else .else
@ -1211,3 +1211,117 @@ FastExit:
iret iret
.endm .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

View file

@ -9,12 +9,17 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/ */
/* INCLUDES ****************************************************************/ /* INCLUDES *****************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* GLOBALS *******************************************************************/
ULONG KiISRTimeout = 55;
USHORT KiISROverflow = 30000;
/* PRIVATE FUNCTIONS *********************************************************/ /* PRIVATE FUNCTIONS *********************************************************/
VOID VOID
@ -172,6 +177,8 @@ KeInitializeInterrupt(IN PKINTERRUPT Interrupt,
Interrupt->ShareVector = ShareVector; Interrupt->ShareVector = ShareVector;
Interrupt->Number = ProcessorNumber; Interrupt->Number = ProcessorNumber;
Interrupt->FloatingSave = FloatingSave; Interrupt->FloatingSave = FloatingSave;
Interrupt->TickCount = (ULONG)-1;
Interrupt->DispatchCount = (ULONG)-1;
/* Loop the template in memory */ /* Loop the template in memory */
for (i = 0; i < KINTERRUPT_DISPATCH_CODES; i++) for (i = 0; i < KINTERRUPT_DISPATCH_CODES; i++)
@ -180,6 +187,14 @@ KeInitializeInterrupt(IN PKINTERRUPT Interrupt,
*DispatchCode++ = KiInterruptTemplate[i]; *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 */ /* Jump to the last 4 bytes */
Patch = (PULONG)((ULONG_PTR)Patch + Patch = (PULONG)((ULONG_PTR)Patch +
((ULONG_PTR)&KiInterruptTemplateObject - ((ULONG_PTR)&KiInterruptTemplateObject -
@ -216,7 +231,6 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
(Interrupt->SynchronizeIrql < Irql) || (Interrupt->SynchronizeIrql < Irql) ||
(Interrupt->FloatingSave)) (Interrupt->FloatingSave))
{ {
DPRINT1("Invalid interrupt object\n");
return FALSE; return FALSE;
} }
@ -254,7 +268,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
(Dispatch.Interrupt->Mode == Interrupt->Mode)) (Dispatch.Interrupt->Mode == Interrupt->Mode))
{ {
/* The vector is shared and the interrupts are compatible */ /* 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; Interrupt->Connected = Connected = TRUE;
ASSERT(Irql <= SYNCH_LEVEL); ASSERT(Irql <= SYNCH_LEVEL);
@ -275,6 +289,14 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
KiReleaseDispatcherLock(OldIrql); KiReleaseDispatcherLock(OldIrql);
KeRevertToUserAffinityThread(); KeRevertToUserAffinityThread();
/* Check if we failed while trying to connect */
if ((Connected) && (Error))
{
DPRINT1("HalEnableSystemInterrupt failed\n");
KeDisconnectInterrupt(Interrupt);
Connected = FALSE;
}
/* Return to caller */ /* Return to caller */
return Connected; return Connected;
} }

View file

@ -93,6 +93,12 @@ _UnexpectedMsg:
_UnhandledMsg: _UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n" .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: _KiTrapPrefixTable:
.byte 0xF2 /* REP */ .byte 0xF2 /* REP */
.byte 0xF3 /* REP INS/OUTS */ .byte 0xF3 /* REP INS/OUTS */
@ -174,7 +180,7 @@ SharedCode:
jnz NotWin32K jnz NotWin32K
/* Get the TEB */ /* Get the TEB */
mov ecx, [fs:KPCR_TEB] mov ecx, PCR[KPCR_TEB]
/* Check if we should flush the User Batch */ /* Check if we should flush the User Batch */
xor ebx, ebx xor ebx, ebx
@ -191,7 +197,7 @@ ReadBatch:
NotWin32K: NotWin32K:
/* Increase total syscall count */ /* Increase total syscall count */
inc dword ptr fs:[KPCR_SYSTEM_CALLS] inc dword ptr PCR[KPCR_SYSTEM_CALLS]
#ifdef DBG #ifdef DBG
/* Increase per-syscall count */ /* Increase per-syscall count */
@ -243,7 +249,7 @@ AfterSysCall:
mov eax, esi /* Restore it */ mov eax, esi /* Restore it */
/* Get our temporary current thread pointer for sanity check */ /* 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 */ /* Make sure that we are not attached and that APCs are not disabled */
mov dl, [ecx+KTHREAD_APC_STATE_INDEX] mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
@ -262,7 +268,7 @@ SkipCheck:
KeReturnFromSystemCall: KeReturnFromSystemCall:
/* Get the Current Thread */ /* Get the Current Thread */
mov ecx, [fs:KPCR_CURRENT_THREAD] mov ecx, PCR[KPCR_CURRENT_THREAD]
/* Restore the old trap frame pointer */ /* Restore the old trap frame pointer */
mov edx, [ebp+KTRAP_FRAME_EDX] mov edx, [ebp+KTRAP_FRAME_EDX]
@ -353,7 +359,7 @@ AccessViolation:
BadStack: BadStack:
/* Restore ESP0 stack */ /* Restore ESP0 stack */
mov ecx, [fs:KPCR_TSS] mov ecx, PCR[KPCR_TSS]
mov esp, ss:[ecx+KTSS_ESP0] mov esp, ss:[ecx+KTSS_ESP0]
/* Generate V86M Stack for Trap 6 */ /* Generate V86M Stack for Trap 6 */
@ -373,10 +379,10 @@ BadStack:
#ifdef DBG #ifdef DBG
InvalidIrql: InvalidIrql:
/* Save current IRQL */ /* Save current IRQL */
push fs:[KPCR_IRQL] push PCR[KPCR_IRQL]
/* Set us at passive */ /* Set us at passive */
mov dword ptr fs:[KPCR_IRQL], 0 mov dword ptr PCR[KPCR_IRQL], 0
cli cli
/* Bugcheck */ /* Bugcheck */
@ -485,7 +491,7 @@ _NtRaiseException@12:
push ebp push ebp
/* Get the current thread and restore its trap frame */ /* 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 edx, [ebp+KTRAP_FRAME_EDX]
mov [ebx+KTHREAD_TRAP_FRAME], edx mov [ebx+KTHREAD_TRAP_FRAME], edx
@ -497,7 +503,7 @@ _NtRaiseException@12:
/* Get the exception list and restore */ /* Get the exception list and restore */
mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST] mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
mov [fs:KPCR_EXCEPTION_LIST], eax mov PCR[KPCR_EXCEPTION_LIST], eax
/* Get the parameters */ /* Get the parameters */
mov edx, [ebp+16] /* Search frames */ mov edx, [ebp+16] /* Search frames */
@ -532,7 +538,7 @@ _NtContinue@8:
push ebp push ebp
/* Get the current thread and restore its trap frame */ /* 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 edx, [ebp+KTRAP_FRAME_EDX]
mov [ebx+KTHREAD_TRAP_FRAME], edx mov [ebx+KTHREAD_TRAP_FRAME], edx
@ -696,7 +702,7 @@ SendException:
VdmCheck: VdmCheck:
/* Check if this is a VDM process */ /* 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] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz SendException jz SendException
@ -742,7 +748,7 @@ PrepInt1:
V86Int1: V86Int1:
/* Check if this is a VDM process */ /* 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] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz EnableInterrupts jz EnableInterrupts
@ -806,7 +812,7 @@ PrepInt3:
V86Int3: V86Int3:
/* Check if this is a VDM process */ /* 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] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz EnableInterrupts3 jz EnableInterrupts3
@ -847,7 +853,7 @@ SendException4:
VdmCheck4: VdmCheck4:
/* Check if this is a VDM process */ /* 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] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz SendException4 jz SendException4
@ -893,7 +899,7 @@ SendException5:
VdmCheck5: VdmCheck5:
/* Check if this is a VDM process */ /* 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] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz SendException5 jz SendException5
@ -934,7 +940,7 @@ NotV86UD:
jz UmodeOpcode jz UmodeOpcode
/* Check if the process is vDM */ /* Check if the process is vDM */
mov ebx, fs:[KPCR_CURRENT_THREAD] mov ebx, PCR[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jnz IsVdmOpcode jnz IsVdmOpcode
@ -950,8 +956,8 @@ UmodeOpcode:
/* Setup a SEH frame */ /* Setup a SEH frame */
push ebp push ebp
push OpcodeSEH push OpcodeSEH
push fs:[KPCR_EXCEPTION_LIST] push PCR[KPCR_EXCEPTION_LIST]
mov fs:[KPCR_EXCEPTION_LIST], esp mov PCR[KPCR_EXCEPTION_LIST], esp
OpcodeLoop: OpcodeLoop:
/* Get the instruction and check if it's LOCK */ /* Get the instruction and check if it's LOCK */
@ -964,7 +970,7 @@ OpcodeLoop:
loop OpcodeLoop loop OpcodeLoop
/* Undo SEH frame */ /* Undo SEH frame */
pop fs:[KPCR_EXCEPTION_LIST] pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8 add esp, 8
KmodeOpcode: KmodeOpcode:
@ -980,7 +986,7 @@ KmodeOpcode:
LockCrash: LockCrash:
/* Undo SEH Frame */ /* Undo SEH Frame */
pop fs:[KPCR_EXCEPTION_LIST] pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8 add esp, 8
/* Setup invalid lock exception and dispatch it */ /* Setup invalid lock exception and dispatch it */
@ -1000,7 +1006,7 @@ OpcodeSEH:
/* Get SEH frame */ /* Get SEH frame */
mov esp, [esp+8] mov esp, [esp+8]
pop fs:[KPCR_EXCEPTION_LIST] pop PCR[KPCR_EXCEPTION_LIST]
add esp, 4 add esp, 4
pop ebp pop ebp
@ -1030,7 +1036,7 @@ _KiTrap7:
/* Get the current thread and stack */ /* Get the current thread and stack */
StartTrapHandle: StartTrapHandle:
mov eax, [fs:KPCR_CURRENT_THREAD] mov eax, PCR[KPCR_CURRENT_THREAD]
mov ecx, [eax+KTHREAD_INITIAL_STACK] mov ecx, [eax+KTHREAD_INITIAL_STACK]
sub ecx, NPX_FRAME_LENGTH sub ecx, NPX_FRAME_LENGTH
@ -1049,7 +1055,7 @@ CheckState:
mov cr0, ebx mov cr0, ebx
/* Check the NPX thread */ /* Check the NPX thread */
mov edx, [fs:KPCR_NPX_THREAD] mov edx, PCR[KPCR_NPX_THREAD]
or edx, edx or edx, edx
jz NoNpxThread jz NoNpxThread
@ -1083,7 +1089,7 @@ FrRestore:
AfterRestore: AfterRestore:
/* Set state loaded */ /* Set state loaded */
mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_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 */ /* Enable interrupts to happen now */
sti sti
@ -1144,7 +1150,7 @@ HandleNpxFault:
UserNpx: UserNpx:
/* Get the current thread */ /* Get the current thread */
mov eax, fs:[KPCR_CURRENT_THREAD] mov eax, PCR[KPCR_CURRENT_THREAD]
/* Check NPX state */ /* Check NPX state */
cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
@ -1180,7 +1186,7 @@ MakeCr0Dirty:
/* Update NPX state */ /* Update NPX state */
mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED 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: NoSaveRestore:
/* Clear the TS bit and re-enable interrupts */ /* Clear the TS bit and re-enable interrupts */
@ -1293,7 +1299,7 @@ UnexpectedNpx:
V86Npx: V86Npx:
/* Check if this is a VDM */ /* Check if this is a VDM */
mov eax, fs:[KPCR_CURRENT_THREAD] mov eax, PCR[KPCR_CURRENT_THREAD]
mov ebx, [eax+KTHREAD_APCSTATE_PROCESS] mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz HandleUserNpx jz HandleUserNpx
@ -1414,7 +1420,7 @@ _KiTrapExceptHandler:
/* Setup SEH handler frame */ /* Setup SEH handler frame */
mov esp, [esp+8] mov esp, [esp+8]
pop fs:[KPCR_EXCEPTION_LIST] pop PCR[KPCR_EXCEPTION_LIST]
add esp, 4 add esp, 4
pop ebp pop ebp
@ -1445,7 +1451,7 @@ _KiTrap13:
V86_TRAP_PROLOG kitd V86_TRAP_PROLOG kitd
/* Make sure that this is a V86 process */ /* 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] mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0
jnz RaiseIrql jnz RaiseIrql
@ -1505,7 +1511,7 @@ NotV86:
jnz UserModeGpf jnz UserModeGpf
/* Check if we have a VDM alert */ /* 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 jnz VdmAlertGpf
/* Check for GPF during GPF */ /* Check for GPF during GPF */
@ -1565,7 +1571,7 @@ KmodeGpf:
NotBiosGpf: NotBiosGpf:
/* Check if the thread was in kernel mode */ /* 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 test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF
jz UserModeGpf jz UserModeGpf
@ -1656,7 +1662,7 @@ UserModeGpf:
jz _KiSystemFatalException jz _KiSystemFatalException
/* Get the process and check which CS this came from */ /* 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] mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckVdmGpf jz CheckVdmGpf
@ -1719,8 +1725,8 @@ CheckPrivilegedInstruction:
/* Setup a SEH handler */ /* Setup a SEH handler */
push ebp push ebp
push offset _KiTrapExceptHandler push offset _KiTrapExceptHandler
push fs:[KPCR_EXCEPTION_LIST] push PCR[KPCR_EXCEPTION_LIST]
mov fs:[KPCR_EXCEPTION_LIST], esp mov PCR[KPCR_EXCEPTION_LIST], esp
/* Get EIP */ /* Get EIP */
mov esi, [ebp+KTRAP_FRAME_EIP] mov esi, [ebp+KTRAP_FRAME_EIP]
@ -1790,7 +1796,7 @@ CheckPrivilegedInstruction2:
IsPrivInstruction: IsPrivInstruction:
/* Cleanup the SEH frame */ /* Cleanup the SEH frame */
pop fs:[KPCR_EXCEPTION_LIST] pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8 add esp, 8
/* Setup the exception */ /* Setup the exception */
@ -1800,7 +1806,7 @@ IsPrivInstruction:
NotIoViolation: NotIoViolation:
/* Cleanup the SEH frame */ /* Cleanup the SEH frame */
pop fs:[KPCR_EXCEPTION_LIST] pop PCR[KPCR_EXCEPTION_LIST]
add esp, 8 add esp, 8
SetException: SetException:
@ -1824,11 +1830,11 @@ _KiTrap14:
TRAP_PROLOG kit14 TRAP_PROLOG kit14
/* Check if we have a VDM alert */ /* 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 jnz VdmAlertGpf
/* Get the current thread */ /* Get the current thread */
mov edi, fs:[KPCR_CURRENT_THREAD] mov edi, PCR[KPCR_CURRENT_THREAD]
/* Get the stack address of the frame */ /* Get the stack address of the frame */
lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH] lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
@ -1840,7 +1846,7 @@ _KiTrap14:
jb NoFixUp jb NoFixUp
/* Check if we have a TEB */ /* Check if we have a TEB */
mov eax, fs:[KPCR_TEB] mov eax, PCR[KPCR_TEB]
or eax, eax or eax, eax
jle NoFixUp jle NoFixUp
@ -1913,7 +1919,7 @@ CheckVdmPf:
jnz VdmPF jnz VdmPF
/* Check if the fault occured in a VDM */ /* 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] mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0 cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
jz CheckStatus jz CheckStatus
@ -2006,8 +2012,8 @@ _KiTrap16:
TRAP_PROLOG kit16 TRAP_PROLOG kit16
/* Check if this is the NPX Thread */ /* Check if this is the NPX Thread */
mov eax, fs:[KPCR_CURRENT_THREAD] mov eax, PCR[KPCR_CURRENT_THREAD]
cmp eax, fs:[KPCR_NPX_THREAD] cmp eax, PCR[KPCR_NPX_THREAD]
/* Get the initial stack and NPX frame */ /* Get the initial stack and NPX frame */
mov ecx, [eax+KTHREAD_INITIAL_STACK] mov ecx, [eax+KTHREAD_INITIAL_STACK]
@ -2059,7 +2065,7 @@ _KiSystemFatalException:
_KiCoprocessorError@0: _KiCoprocessorError@0:
/* Get the NPX Thread's Initial stack */ /* 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] mov eax, [eax+KTHREAD_INITIAL_STACK]
/* Make space for the FPU Save area */ /* Make space for the FPU Save area */
@ -2085,7 +2091,7 @@ _Ki16BitStackException:
push esp push esp
/* Go to kernel mode thread stack */ /* Go to kernel mode thread stack */
mov eax, fs:[KPCR_CURRENT_THREAD] mov eax, PCR[KPCR_CURRENT_THREAD]
add esp, [eax+KTHREAD_INITIAL_STACK] add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */ /* Switch to good stack segment */
@ -2112,7 +2118,7 @@ _KiUnexpectedInterruptTail:
INT_PROLOG kui, DoNotPushFakeErrorCode INT_PROLOG kui, DoNotPushFakeErrorCode
/* Increase interrupt count */ /* 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 */ /* Put vector in EBX and make space for KIRQL */
mov ebx, [esp] mov ebx, [esp]
@ -2161,7 +2167,7 @@ _KiUnexpectedInterrupt:
_KiDispatchInterrupt@0: _KiDispatchInterrupt@0:
/* Get the PCR and disable interrupts */ /* Get the PCR and disable interrupts */
mov ebx, [fs:KPCR_SELF] mov ebx, PCR[KPCR_SELF]
cli cli
/* Check if we have to deliver DPCs, timers, or deferred threads */ /* Check if we have to deliver DPCs, timers, or deferred threads */
@ -2281,7 +2287,7 @@ _KiChainedDispatch2ndLvl@0:
_KiChainedDispatch@0: _KiChainedDispatch@0:
/* Increase interrupt count */ /* Increase interrupt count */
inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT] inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
/* Save trap frame */ /* Save trap frame */
mov ebp, esp mov ebp, esp
@ -2308,17 +2314,14 @@ _KiChainedDispatch@0:
call _KiChainedDispatch2ndLvl@0 call _KiChainedDispatch2ndLvl@0
/* Exit the interrupt */ /* Exit the interrupt */
mov esi, $ INT_EPILOG 0
cli
call _HalEndSystemInterrupt@8
jmp _Kei386EoiHelper@0
.endfunc .endfunc
.func KiInterruptDispatch@0 .func KiInterruptDispatch@0
_KiInterruptDispatch@0: _KiInterruptDispatch@0:
/* Increase interrupt count */ /* Increase interrupt count */
inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT] inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
/* Save trap frame */ /* Save trap frame */
mov ebp, esp mov ebp, esp
@ -2346,27 +2349,51 @@ GetIntLock:
mov esi, [edi+KINTERRUPT_ACTUAL_LOCK] mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
ACQUIRE_SPINLOCK(esi, IntSpin) 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 */ /* Call the ISR */
mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT] mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
push eax push eax
push edi push edi
call [edi+KINTERRUPT_SERVICE_ROUTINE] call [edi+KINTERRUPT_SERVICE_ROUTINE]
/* Check if the ISR timed out */
add ebx, _KiISRTimeout
cmp _KeTickCount, ebx
jnc IsrTimeout
ReleaseLock:
/* Release the lock */ /* Release the lock */
RELEASE_SPINLOCK(esi) RELEASE_SPINLOCK(esi)
/* Exit the interrupt */ /* Exit the interrupt */
cli INT_EPILOG 0
call _HalEndSystemInterrupt@8
jmp _Kei386EoiHelper@0
SpuriousInt: SpuriousInt:
/* Exit the interrupt */ /* Exit the interrupt */
add esp, 8 add esp, 8
jmp _Kei386EoiHelper@0 INT_EPILOG 1
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
IntSpin: IntSpin:
SPIN_ON_LOCK esi, GetIntLock SPIN_ON_LOCK esi, GetIntLock
#endif #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 .endfunc