Author: sir_richard
Date: Fri Jan 29 00:18:53 2010
New Revision: 45304
URL:
http://svn.reactos.org/svn/reactos?rev=45304&view=rev
Log:
[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.
Modified:
trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/ke/i386/irqobj.c
trunk/reactos/ntoskrnl/ke/i386/trap.s
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] Fri Jan 29
00:18:53 2010
@@ -197,7 +197,7 @@
.macro GENERATE_INT_HANDLER Number
.func KiUnexpectedInterrupt&Number
_KiUnexpectedInterrupt&Number:
- push PRIMARY_VECTOR_BASE + Number
+ mov eax, PRIMARY_VECTOR_BASE + Number
jmp _KiEndUnexpectedRange@0
.endfunc
.endm
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Fri Jan 29 00:18:53 2010
@@ -954,19 +954,6 @@
IN PKTRAP_FRAME TrapFrame
);
-#ifndef HAL_INTERRUPT_SUPPORT_IN_C
-VOID
-NTAPI
-KiInterruptDispatch(
- VOID
-);
-
-VOID
-NTAPI
-KiChainedDispatch(
- VOID
-);
-#else
VOID
FASTCALL
KiInterruptDispatch(
@@ -980,7 +967,6 @@
IN PKTRAP_FRAME TrapFrame,
IN PKINTERRUPT Interrupt
);
-#endif
VOID
NTAPI
Modified: trunk/reactos/ntoskrnl/ke/i386/irqobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/irqobj.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/irqobj.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/irqobj.c [iso-8859-1] Fri Jan 29 00:18:53 2010
@@ -97,9 +97,6 @@
{
DISPATCH_INFO Dispatch;
PKINTERRUPT_ROUTINE Handler;
-#ifndef HAL_INTERRUPT_SUPPORT_IN_C
- PULONG Patch = &Interrupt->DispatchCode[0];
-#endif
/* Get vector data */
KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
@@ -122,15 +119,6 @@
Interrupt->DispatchAddress = Handler;
/* 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 */
ASSERT(Dispatch.FlatDispatch == NULL);
@@ -140,6 +128,130 @@
/* Register the interrupt */
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 **********************************************************/
@@ -199,12 +311,6 @@
*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 */
Patch = (PULONG)((ULONG_PTR)Patch +
((ULONG_PTR)&KiInterruptTemplateObject -
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?re…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Fri Jan 29 00:18:53 2010
@@ -152,58 +152,8 @@
_KiEndUnexpectedRange@0:
jmp _KiUnexpectedInterruptTail
-.func KiUnexpectedInterruptTail
-TRAP_FIXUPS kui_a, kui_t, DoFixupV86, DoFixupAbios
-_KiUnexpectedInterruptTail:
-
- /* Enter interrupt trap */
- 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 ********************************************************/
+
+/* DPC INTERRUPT HANDLER ******************************************************/
.func KiDispatchInterrupt@0
_KiDispatchInterrupt@0:
@@ -321,10 +271,8 @@
.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
- * 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
* 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
@@ -343,13 +291,9 @@
* use EDI to store the absolute offset, and jump to that instead.
*
*/
-#ifdef HAL_INTERRUPT_SUPPORT_IN_C
.func KiInterruptTemplate
_KiInterruptTemplate:
- push 0
- pushad
- sub esp, KTRAP_FRAME_LENGTH - KTRAP_FRAME_PREVIOUS_MODE
- mov ecx, esp
+ TRAP_HANDLER_PROLOG 1, 0
_KiInterruptTemplate2ndDispatch:
/* Dummy code, will be replaced by the address of the KINTERRUPT */
@@ -363,221 +307,3 @@
_KiInterruptTemplateDispatch:
/* Marks the end of the template so that the jump above can be edited */
.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
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Fri Jan 29 00:18:53 2010
@@ -1601,104 +1601,4 @@
KiTrap(KiSystemService, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
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 */