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/i... ============================================================================== --- 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/k... ============================================================================== --- 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?r... ============================================================================== --- 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?rev... ============================================================================== --- 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.c... ============================================================================== --- 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 */