mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
[NTOS]: The last big step. Now that the HAL is in C, we can handle interrupts in C. Do so using the proposed model that was #if'ed out, but with some improvements.
[NTOS]: Implement KiUnexpectedInterruptTail and KiUnexpectedInterrupt in C as well. This is [PERF] too since the C interrupt handling code is a lot more efficient than the ASM one. Numbers look good here. svn path=/trunk/; revision=45304
This commit is contained in:
parent
ac9c20ac0f
commit
5b14ade9f8
5 changed files with 128 additions and 410 deletions
|
@ -197,7 +197,7 @@ idt _KiUnexpectedInterrupt&Number, INT_32_DPL0
|
||||||
.macro GENERATE_INT_HANDLER Number
|
.macro GENERATE_INT_HANDLER Number
|
||||||
.func KiUnexpectedInterrupt&Number
|
.func KiUnexpectedInterrupt&Number
|
||||||
_KiUnexpectedInterrupt&Number:
|
_KiUnexpectedInterrupt&Number:
|
||||||
push PRIMARY_VECTOR_BASE + Number
|
mov eax, PRIMARY_VECTOR_BASE + Number
|
||||||
jmp _KiEndUnexpectedRange@0
|
jmp _KiEndUnexpectedRange@0
|
||||||
.endfunc
|
.endfunc
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -954,19 +954,6 @@ KiServiceExit2(
|
||||||
IN PKTRAP_FRAME TrapFrame
|
IN PKTRAP_FRAME TrapFrame
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
KiInterruptDispatch(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
KiChainedDispatch(
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
VOID
|
VOID
|
||||||
FASTCALL
|
FASTCALL
|
||||||
KiInterruptDispatch(
|
KiInterruptDispatch(
|
||||||
|
@ -980,7 +967,6 @@ KiChainedDispatch(
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
IN PKINTERRUPT Interrupt
|
IN PKINTERRUPT Interrupt
|
||||||
);
|
);
|
||||||
#endif
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
|
@ -97,9 +97,6 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
|
||||||
{
|
{
|
||||||
DISPATCH_INFO Dispatch;
|
DISPATCH_INFO Dispatch;
|
||||||
PKINTERRUPT_ROUTINE Handler;
|
PKINTERRUPT_ROUTINE Handler;
|
||||||
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
|
|
||||||
PULONG Patch = &Interrupt->DispatchCode[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get vector data */
|
/* Get vector data */
|
||||||
KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
|
KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
|
||||||
|
@ -122,15 +119,6 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
|
||||||
Interrupt->DispatchAddress = Handler;
|
Interrupt->DispatchAddress = Handler;
|
||||||
|
|
||||||
/* Read note in trap.s -- patching not needed since JMP is static */
|
/* Read note in trap.s -- patching not needed since JMP is static */
|
||||||
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
|
|
||||||
/* Jump to the last 4 bytes */
|
|
||||||
Patch = (PULONG)((ULONG_PTR)Patch +
|
|
||||||
((ULONG_PTR)&KiInterruptTemplateDispatch -
|
|
||||||
(ULONG_PTR)KiInterruptTemplate) - 4);
|
|
||||||
|
|
||||||
/* Apply the patch */
|
|
||||||
*Patch = (ULONG)((ULONG_PTR)Handler - ((ULONG_PTR)Patch + 4));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Now set the final handler address */
|
/* Now set the final handler address */
|
||||||
ASSERT(Dispatch.FlatDispatch == NULL);
|
ASSERT(Dispatch.FlatDispatch == NULL);
|
||||||
|
@ -141,6 +129,130 @@ KiConnectVectorToInterrupt(IN PKINTERRUPT Interrupt,
|
||||||
KeRegisterInterruptHandler(Interrupt->Vector, Handler);
|
KeRegisterInterruptHandler(Interrupt->Vector, Handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FORCEINLINE
|
||||||
|
DECLSPEC_NORETURN
|
||||||
|
KiExitInterrupt(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN KIRQL OldIrql,
|
||||||
|
IN BOOLEAN Spurious)
|
||||||
|
{
|
||||||
|
/* Check if this was a real interrupt */
|
||||||
|
if (!Spurious)
|
||||||
|
{
|
||||||
|
/* Set nested trap frame */
|
||||||
|
KeGetPcr()->VdmAlert = (ULONG_PTR)TrapFrame;
|
||||||
|
|
||||||
|
/* It was, disable interrupts and restore the IRQL */
|
||||||
|
_disable();
|
||||||
|
HalEndSystemInterrupt(OldIrql, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now exit the trap */
|
||||||
|
KiEoiHelper(TrapFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
KiUnexpectedInterrupt(VOID)
|
||||||
|
{
|
||||||
|
/* Crash the machine */
|
||||||
|
KeBugCheck(TRAP_CAUSE_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiUnexpectedInterruptTailHandler(IN PKTRAP_FRAME TrapFrame)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
/* Enter trap */
|
||||||
|
KiEnterInterruptTrap(TrapFrame);
|
||||||
|
|
||||||
|
/* Increase interrupt count */
|
||||||
|
KeGetCurrentPrcb()->InterruptCount++;
|
||||||
|
|
||||||
|
/* Start the interrupt */
|
||||||
|
if (HalBeginSystemInterrupt(HIGH_LEVEL, TrapFrame->Eax, &OldIrql))
|
||||||
|
{
|
||||||
|
/* Warn user */
|
||||||
|
DPRINT1("\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n");
|
||||||
|
|
||||||
|
/* Now call the epilogue code */
|
||||||
|
KiExitInterrupt(TrapFrame, OldIrql, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Now call the epilogue code */
|
||||||
|
KiExitInterrupt(TrapFrame, OldIrql, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef
|
||||||
|
FASTCALL
|
||||||
|
VOID
|
||||||
|
(PKI_INTERRUPT_DISPATCH)(
|
||||||
|
IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN PKINTERRUPT Interrupt
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiInterruptDispatch(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN PKINTERRUPT Interrupt)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
/* Increase interrupt count */
|
||||||
|
KeGetCurrentPrcb()->InterruptCount++;
|
||||||
|
|
||||||
|
/* Begin the interrupt, making sure it's not spurious */
|
||||||
|
if (HalBeginSystemInterrupt(Interrupt->SynchronizeIrql,
|
||||||
|
Interrupt->Vector,
|
||||||
|
&OldIrql))
|
||||||
|
{
|
||||||
|
/* Acquire interrupt lock */
|
||||||
|
KxAcquireSpinLock(Interrupt->ActualLock);
|
||||||
|
|
||||||
|
/* Call the ISR */
|
||||||
|
Interrupt->ServiceRoutine(Interrupt, Interrupt->ServiceContext);
|
||||||
|
|
||||||
|
/* Release interrupt lock */
|
||||||
|
KxReleaseSpinLock(Interrupt->ActualLock);
|
||||||
|
|
||||||
|
/* Now call the epilogue code */
|
||||||
|
KiExitInterrupt(TrapFrame, OldIrql, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Now call the epilogue code */
|
||||||
|
KiExitInterrupt(TrapFrame, OldIrql, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN PKINTERRUPT Interrupt)
|
||||||
|
{
|
||||||
|
/* Increase interrupt count */
|
||||||
|
KeGetCurrentPrcb()->InterruptCount++;
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
while (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
||||||
|
IN PKINTERRUPT Interrupt)
|
||||||
|
{
|
||||||
|
/* Enter interrupt frame */
|
||||||
|
KiEnterInterruptTrap(TrapFrame);
|
||||||
|
|
||||||
|
/* Call the correct dispatcher */
|
||||||
|
((PKI_INTERRUPT_DISPATCH*)Interrupt->DispatchAddress)(TrapFrame, Interrupt);
|
||||||
|
}
|
||||||
|
|
||||||
|
KiTrap(KiUnexpectedInterruptTail, KI_PUSH_FAKE_ERROR_CODE);
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -199,12 +311,6 @@ KeInitializeInterrupt(IN PKINTERRUPT Interrupt,
|
||||||
*DispatchCode++ = KiInterruptTemplate[i];
|
*DispatchCode++ = KiInterruptTemplate[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
|
|
||||||
ASSERT((ULONG_PTR)&KiChainedDispatch2ndLvl -
|
|
||||||
(ULONG_PTR)KiInterruptTemplate <= (KINTERRUPT_DISPATCH_CODES * 4));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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 -
|
||||||
|
|
|
@ -152,58 +152,8 @@ GENERATE_INT_HANDLERS
|
||||||
_KiEndUnexpectedRange@0:
|
_KiEndUnexpectedRange@0:
|
||||||
jmp _KiUnexpectedInterruptTail
|
jmp _KiUnexpectedInterruptTail
|
||||||
|
|
||||||
.func KiUnexpectedInterruptTail
|
|
||||||
TRAP_FIXUPS kui_a, kui_t, DoFixupV86, DoFixupAbios
|
|
||||||
_KiUnexpectedInterruptTail:
|
|
||||||
|
|
||||||
/* Enter interrupt trap */
|
/* DPC INTERRUPT HANDLER ******************************************************/
|
||||||
INT_PROLOG kui_a, kui_t, DoNotPushFakeErrorCode
|
|
||||||
|
|
||||||
/* Increase interrupt count */
|
|
||||||
inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
|
|
||||||
|
|
||||||
/* Put vector in EBX and make space for KIRQL */
|
|
||||||
mov ebx, [esp]
|
|
||||||
sub esp, 4
|
|
||||||
|
|
||||||
/* Begin interrupt */
|
|
||||||
push esp
|
|
||||||
push ebx
|
|
||||||
push HIGH_LEVEL
|
|
||||||
call _HalBeginSystemInterrupt@12
|
|
||||||
|
|
||||||
/* Check if it was spurious or not */
|
|
||||||
or al, al
|
|
||||||
jnz Handled
|
|
||||||
|
|
||||||
/* Spurious, ignore it */
|
|
||||||
add esp, 8
|
|
||||||
jmp _Kei386EoiHelper@0
|
|
||||||
|
|
||||||
Handled:
|
|
||||||
/* Unexpected interrupt, print a message on debug builds */
|
|
||||||
#if DBG
|
|
||||||
push [esp+4]
|
|
||||||
push offset _UnexpectedMsg
|
|
||||||
call _DbgPrint
|
|
||||||
add esp, 8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Exit the interrupt */
|
|
||||||
mov esi, $
|
|
||||||
cli
|
|
||||||
call _HalEndSystemInterrupt@8
|
|
||||||
jmp _Kei386EoiHelper@0
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.globl _KiUnexpectedInterrupt
|
|
||||||
_KiUnexpectedInterrupt:
|
|
||||||
|
|
||||||
/* Bugcheck with invalid interrupt code */
|
|
||||||
push TRAP_CAUSE_UNKNOWN
|
|
||||||
call _KeBugCheck@4
|
|
||||||
|
|
||||||
/* INTERRUPT HANDLERS ********************************************************/
|
|
||||||
|
|
||||||
.func KiDispatchInterrupt@0
|
.func KiDispatchInterrupt@0
|
||||||
_KiDispatchInterrupt@0:
|
_KiDispatchInterrupt@0:
|
||||||
|
@ -321,10 +271,8 @@ QuantumEnd:
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is how the new-style interrupt template will look like.
|
|
||||||
*
|
|
||||||
* We setup the stack for a trap frame in the KINTERRUPT DispatchCode itself and
|
* We setup the stack for a trap frame in the KINTERRUPT DispatchCode itself and
|
||||||
* then mov the stack address in ECX, since the handlers are FASTCALL. We also
|
* then move the stack address in ECX, since the handlers are FASTCALL. We also
|
||||||
* need to know the address of the KINTERRUPT. To do this, we maintain the old
|
* need to know the address of the KINTERRUPT. To do this, we maintain the old
|
||||||
* dynamic patching technique (EDX instead of EDI, however) and let the C API
|
* dynamic patching technique (EDX instead of EDI, however) and let the C API
|
||||||
* up in KeInitializeInterrupt replace the 0 with the address. Since this is in
|
* up in KeInitializeInterrupt replace the 0 with the address. Since this is in
|
||||||
|
@ -343,13 +291,9 @@ QuantumEnd:
|
||||||
* use EDI to store the absolute offset, and jump to that instead.
|
* use EDI to store the absolute offset, and jump to that instead.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifdef HAL_INTERRUPT_SUPPORT_IN_C
|
|
||||||
.func KiInterruptTemplate
|
.func KiInterruptTemplate
|
||||||
_KiInterruptTemplate:
|
_KiInterruptTemplate:
|
||||||
push 0
|
TRAP_HANDLER_PROLOG 1, 0
|
||||||
pushad
|
|
||||||
sub esp, KTRAP_FRAME_LENGTH - KTRAP_FRAME_PREVIOUS_MODE
|
|
||||||
mov ecx, esp
|
|
||||||
|
|
||||||
_KiInterruptTemplate2ndDispatch:
|
_KiInterruptTemplate2ndDispatch:
|
||||||
/* Dummy code, will be replaced by the address of the KINTERRUPT */
|
/* Dummy code, will be replaced by the address of the KINTERRUPT */
|
||||||
|
@ -363,221 +307,3 @@ _KiInterruptTemplateObject:
|
||||||
_KiInterruptTemplateDispatch:
|
_KiInterruptTemplateDispatch:
|
||||||
/* Marks the end of the template so that the jump above can be edited */
|
/* Marks the end of the template so that the jump above can be edited */
|
||||||
.endfunc
|
.endfunc
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
.func KiInterruptTemplate
|
|
||||||
_KiInterruptTemplate:
|
|
||||||
|
|
||||||
/* Enter interrupt trap */
|
|
||||||
INT_PROLOG kit_a, kit_t, DoPushFakeErrorCode
|
|
||||||
|
|
||||||
_KiInterruptTemplate2ndDispatch:
|
|
||||||
/* Dummy code, will be replaced by the address of the KINTERRUPT */
|
|
||||||
mov edi, 0
|
|
||||||
|
|
||||||
_KiInterruptTemplateObject:
|
|
||||||
/* Dummy jump, will be replaced by the actual jump */
|
|
||||||
jmp _KeSynchronizeExecution@12
|
|
||||||
|
|
||||||
_KiInterruptTemplateDispatch:
|
|
||||||
/* Marks the end of the template so that the jump above can be edited */
|
|
||||||
|
|
||||||
TRAP_FIXUPS kit_a, kit_t, DoFixupV86, DoFixupAbios
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func KiChainedDispatch2ndLvl@0
|
|
||||||
_KiChainedDispatch2ndLvl@0:
|
|
||||||
|
|
||||||
NextSharedInt:
|
|
||||||
/* Raise IRQL if necessary */
|
|
||||||
mov cl, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
|
|
||||||
cmp cl, [edi+KINTERRUPT_IRQL]
|
|
||||||
je 1f
|
|
||||||
call @KfRaiseIrql@4
|
|
||||||
|
|
||||||
1:
|
|
||||||
/* Acquire the lock */
|
|
||||||
mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
|
|
||||||
GetIntLock2:
|
|
||||||
ACQUIRE_SPINLOCK(esi, IntSpin2)
|
|
||||||
|
|
||||||
/* Make sure that this interrupt isn't storming */
|
|
||||||
VERIFY_INT kid2
|
|
||||||
|
|
||||||
/* Save the tick count */
|
|
||||||
mov esi, _KeTickCount
|
|
||||||
|
|
||||||
/* Call the ISR */
|
|
||||||
mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
|
|
||||||
push eax
|
|
||||||
push edi
|
|
||||||
call [edi+KINTERRUPT_SERVICE_ROUTINE]
|
|
||||||
|
|
||||||
/* Save the ISR result */
|
|
||||||
mov bl, al
|
|
||||||
|
|
||||||
/* Check if the ISR timed out */
|
|
||||||
add esi, _KiISRTimeout
|
|
||||||
cmp _KeTickCount, esi
|
|
||||||
jnc ChainedIsrTimeout
|
|
||||||
|
|
||||||
ReleaseLock2:
|
|
||||||
/* Release the lock */
|
|
||||||
mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
|
|
||||||
RELEASE_SPINLOCK(esi)
|
|
||||||
|
|
||||||
/* Lower IRQL if necessary */
|
|
||||||
mov cl, [edi+KINTERRUPT_IRQL]
|
|
||||||
cmp cl, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
|
|
||||||
je 1f
|
|
||||||
call @KfLowerIrql@4
|
|
||||||
|
|
||||||
1:
|
|
||||||
/* Check if the interrupt is handled */
|
|
||||||
or bl, bl
|
|
||||||
jnz 1f
|
|
||||||
|
|
||||||
/* Try the next shared interrupt handler */
|
|
||||||
mov eax, [edi+KINTERRUPT_INTERRUPT_LIST_HEAD]
|
|
||||||
lea edi, [eax-KINTERRUPT_INTERRUPT_LIST_HEAD]
|
|
||||||
jmp NextSharedInt
|
|
||||||
|
|
||||||
1:
|
|
||||||
ret
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
IntSpin2:
|
|
||||||
SPIN_ON_LOCK(esi, GetIntLock2)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ChainedIsrTimeout:
|
|
||||||
/* Print warning message */
|
|
||||||
push [edi+KINTERRUPT_SERVICE_ROUTINE]
|
|
||||||
push offset _IsrTimeoutMsg
|
|
||||||
call _DbgPrint
|
|
||||||
add esp,8
|
|
||||||
|
|
||||||
/* Break into debugger, then continue */
|
|
||||||
int 3
|
|
||||||
jmp ReleaseLock2
|
|
||||||
|
|
||||||
/* Cleanup verification */
|
|
||||||
VERIFY_INT_END kid2, 0
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func KiChainedDispatch@0
|
|
||||||
_KiChainedDispatch@0:
|
|
||||||
|
|
||||||
/* Increase interrupt count */
|
|
||||||
inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
|
|
||||||
|
|
||||||
/* Save trap frame */
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
/* Save vector and IRQL */
|
|
||||||
mov eax, [edi+KINTERRUPT_VECTOR]
|
|
||||||
mov ecx, [edi+KINTERRUPT_IRQL]
|
|
||||||
|
|
||||||
/* Save old irql */
|
|
||||||
push eax
|
|
||||||
sub esp, 4
|
|
||||||
|
|
||||||
/* Begin interrupt */
|
|
||||||
push esp
|
|
||||||
push eax
|
|
||||||
push ecx
|
|
||||||
call _HalBeginSystemInterrupt@12
|
|
||||||
|
|
||||||
/* Check if it was handled */
|
|
||||||
or al, al
|
|
||||||
jz SpuriousInt
|
|
||||||
|
|
||||||
/* Call the 2nd-level handler */
|
|
||||||
call _KiChainedDispatch2ndLvl@0
|
|
||||||
|
|
||||||
/* Exit the interrupt */
|
|
||||||
INT_EPILOG 0
|
|
||||||
.endfunc
|
|
||||||
|
|
||||||
.func KiInterruptDispatch@0
|
|
||||||
_KiInterruptDispatch@0:
|
|
||||||
|
|
||||||
/* Increase interrupt count */
|
|
||||||
inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
|
|
||||||
|
|
||||||
/* Save trap frame */
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
/* Save vector and IRQL */
|
|
||||||
mov eax, [edi+KINTERRUPT_VECTOR]
|
|
||||||
mov ecx, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
|
|
||||||
|
|
||||||
/* Save old irql */
|
|
||||||
push eax
|
|
||||||
sub esp, 4
|
|
||||||
|
|
||||||
/* Begin interrupt */
|
|
||||||
push esp
|
|
||||||
push eax
|
|
||||||
push ecx
|
|
||||||
call _HalBeginSystemInterrupt@12
|
|
||||||
|
|
||||||
/* Check if it was handled */
|
|
||||||
or al, al
|
|
||||||
jz SpuriousInt
|
|
||||||
|
|
||||||
/* Acquire the lock */
|
|
||||||
mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
|
|
||||||
GetIntLock:
|
|
||||||
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 */
|
|
||||||
INT_EPILOG 0
|
|
||||||
|
|
||||||
SpuriousInt:
|
|
||||||
/* Exit the interrupt */
|
|
||||||
add esp, 8
|
|
||||||
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
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1601,104 +1601,4 @@ KiTrap(KiDebugService, KI_PUSH_FAKE_ERROR_CODE);
|
||||||
KiTrap(KiSystemService, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
|
KiTrap(KiSystemService, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
|
||||||
KiTrap(KiFastCallEntry, KI_FAST_SYSTEM_CALL);
|
KiTrap(KiFastCallEntry, KI_FAST_SYSTEM_CALL);
|
||||||
|
|
||||||
/* HARDWARE INTERRUPTS ********************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This code can only be used once the HAL handles system interrupt code in C.
|
|
||||||
*
|
|
||||||
* This is because the HAL, when ending a system interrupt, might see pending
|
|
||||||
* DPC or APC interrupts, and attempt to piggyback on the interrupt context in
|
|
||||||
* order to deliver them. Once they have been devlivered, it will then "end" the
|
|
||||||
* interrupt context by doing a call to the ASM EOI Handler which naturally will
|
|
||||||
* throw up on our C-style KTRAP_FRAME.
|
|
||||||
*
|
|
||||||
* Once it works, expect a noticeable speed boost during hardware interrupts.
|
|
||||||
*/
|
|
||||||
#ifdef HAL_INTERRUPT_SUPPORT_IN_C
|
|
||||||
|
|
||||||
typedef
|
|
||||||
FASTCALL
|
|
||||||
VOID
|
|
||||||
(PKI_INTERRUPT_DISPATCH)(
|
|
||||||
IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN PKINTERRUPT Interrupt
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FORCEINLINE
|
|
||||||
KiExitInterrupt(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN KIRQL OldIrql,
|
|
||||||
IN BOOLEAN Spurious)
|
|
||||||
{
|
|
||||||
if (Spurious) KiEoiHelper(TrapFrame);
|
|
||||||
|
|
||||||
_disable();
|
|
||||||
|
|
||||||
DPRINT1("Calling HAL to restore IRQL to: %d\n", OldIrql);
|
|
||||||
HalEndSystemInterrupt(OldIrql, 0);
|
|
||||||
|
|
||||||
DPRINT1("Exiting trap\n");
|
|
||||||
KiEoiHelper(TrapFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FASTCALL
|
|
||||||
KiInterruptDispatch(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN PKINTERRUPT Interrupt)
|
|
||||||
{
|
|
||||||
KIRQL OldIrql;
|
|
||||||
|
|
||||||
KeGetCurrentPrcb()->InterruptCount++;
|
|
||||||
|
|
||||||
DPRINT1("Calling HAL with %lx %lx\n", Interrupt->SynchronizeIrql, Interrupt->Vector);
|
|
||||||
if (HalBeginSystemInterrupt(Interrupt->SynchronizeIrql,
|
|
||||||
Interrupt->Vector,
|
|
||||||
&OldIrql))
|
|
||||||
{
|
|
||||||
/* Acquire interrupt lock */
|
|
||||||
KxAcquireSpinLock(Interrupt->ActualLock);
|
|
||||||
|
|
||||||
/* Call the ISR */
|
|
||||||
DPRINT1("Calling ISR: %p with context: %p\n", Interrupt->ServiceRoutine, Interrupt->ServiceContext);
|
|
||||||
Interrupt->ServiceRoutine(Interrupt, Interrupt->ServiceContext);
|
|
||||||
|
|
||||||
/* Release interrupt lock */
|
|
||||||
KxReleaseSpinLock(Interrupt->ActualLock);
|
|
||||||
|
|
||||||
/* Now call the epilogue code */
|
|
||||||
DPRINT1("Exiting interrupt\n");
|
|
||||||
KiExitInterrupt(TrapFrame, OldIrql, FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Now call the epilogue code */
|
|
||||||
DPRINT1("Exiting Spurious interrupt\n");
|
|
||||||
KiExitInterrupt(TrapFrame, OldIrql, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FASTCALL
|
|
||||||
KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN PKINTERRUPT Interrupt)
|
|
||||||
{
|
|
||||||
KeGetCurrentPrcb()->InterruptCount++;
|
|
||||||
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
while (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
FASTCALL
|
|
||||||
KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
|
||||||
IN PKINTERRUPT Interrupt)
|
|
||||||
{
|
|
||||||
/* Enter interrupt frame */
|
|
||||||
KiEnterInterruptTrap(TrapFrame);
|
|
||||||
|
|
||||||
/* Call the correct dispatcher */
|
|
||||||
((PKI_INTERRUPT_DISPATCH*)Interrupt->DispatchAddress)(TrapFrame, Interrupt);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue