通过上面的分析,发现设置一个中断处理是非常复杂的,下面就来通过图来分析一个中断发生时,中断处理的过程如下图:
其实所有上面代码,就是设置这些流程里工作的函数关键代码,以便整个中断连接起来。其中一些函数是在汇编代码里面,这些都需要仔细分析才能理解。
主要调用下面这两个汇编代码,如下:
#001 .func KiInterruptTemplate
#002 _KiInterruptTemplate:
#003
#004 /* Enter interrupt trap */
#005 INT_PROLOG kit_a, kit_t, DoPushFakeErrorCode
#006
#007 _KiInterruptTemplate2ndDispatch:
#008 /* Dummy code, will be replaced by the address of the KINTERRUPT */
#009 mov edi, 0
#010
#011 _KiInterruptTemplateObject:
#012 /* Dummy jump, will be replaced by the actual jump */
#013 jmp _KeSynchronizeExecution@12
#014
#015 _KiInterruptTemplateDispatch:
#016 /* Marks the end of the template so that the jump above can be edited */
#017
#018 TRAP_FIXUPS kit_a, kit_t, DoFixupV86, DoFixupAbios
#019 .endfunc
和
#001 .func KiInterruptDispatch@0
#002 _KiInterruptDispatch@0:
#003
#004 /* Increase interrupt count */
#005 inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
#006
#007 /* Save trap frame */
#008 mov ebp, esp
#009
#010 /* Save vector and IRQL */
#011 mov eax, [edi+KINTERRUPT_VECTOR]
#012 mov ecx, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
#013
#014 /* Save old irql */
#015 push eax
#016 sub esp, 4
#017
#018 /* Begin interrupt */
#019 push esp
#020 push eax
#021 push ecx
#022 call _HalBeginSystemInterrupt@12
#023
#024 /* Check if it was handled */
#025 or al, al
#026 jz SpuriousInt
#027
#028 /* Acquire the lock */
#029 GetIntLock:
#030 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
#031 ACQUIRE_SPINLOCK(esi, IntSpin)
#032
#033 /* Make sure that this interrupt isn't storming */
#034 VERIFY_INT kid
#035
#036 /* Save the tick count */
#037 mov ebx, _KeTickCount
#038
#039 /* Call the ISR */
#040 mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
#041 push eax
#042 push edi
#043 call [edi+KINTERRUPT_SERVICE_ROUTINE]
#044
#045 /* Check if the ISR timed out */
#046 add ebx, _KiISRTimeout
#047 cmp _KeTickCount, ebx
#048 jnc IsrTimeout
#049
#050 ReleaseLock:
#051 /* Release the lock */
#052 RELEASE_SPINLOCK(esi)
#053
#054 /* Exit the interrupt */
#055 INT_EPILOG 0
#056
#057 SpuriousInt:
#058 /* Exit the interrupt */
#059 add esp, 8
#060 INT_EPILOG 1
#061
#062 #ifdef CONFIG_SMP
#063 IntSpin:
#064 SPIN_ON_LOCK(esi, GetIntLock)
#065 #endif
#066
#067 IsrTimeout:
#068 /* Print warning message */
#069 push [edi+KINTERRUPT_SERVICE_ROUTINE]
#070 push offset _IsrTimeoutMsg
#071 call _DbgPrint
#072 add esp,8
#073
#074 /* Break into debugger, then continue */
#075 int 3
#076 jmp ReleaseLock
#077
#078 /* Cleanup verification */
#079 VERIFY_INT_END kid, 0
#080 .endfunc