📄 trap.s
字号:
.endfunc
.func KiTrap14
TRAP_FIXUPS kite_a, kite_t, DoFixupV86, DoNotFixupAbios
_KiTrap14:
/* Enter trap */
TRAP_PROLOG kite_a, kite_t
/* Check if we have a VDM alert */
cmp dword ptr PCR[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Get the current thread */
mov edi, PCR[KPCR_CURRENT_THREAD]
/* Get the stack address of the frame */
lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
sub eax, [edi+KTHREAD_INITIAL_STACK]
jz NoFixUp
/* This isn't the base frame, check if it's the second */
cmp eax, -KTRAP_FRAME_EFLAGS
jb NoFixUp
/* Check if we have a TEB */
mov eax, PCR[KPCR_TEB]
or eax, eax
jle NoFixUp
/* Fixup the frame */
call _KiFixupFrame
/* Save CR2 */
NoFixUp:
mov edi, cr2
/* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
je HandlePf
/* Enable interrupts and check if we got here with interrupts disabled */
sti
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
jz IllegalState
HandlePf:
/* Send trap frame and check if this is kernel-mode or usermode */
push ebp
mov eax, [ebp+KTRAP_FRAME_CS]
and eax, MODE_MASK
push eax
/* Send faulting address and check if this is read or write */
push edi
mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
and eax, 1
push eax
/* Call the access fault handler */
call _MmAccessFault@16
test eax, eax
jl AccessFail
/* Access fault handled, return to caller */
jmp _Kei386EoiHelper@0
AccessFail:
/* First check if this is a fault in the S-LIST functions */
mov ecx, offset _ExpInterlockedPopEntrySListFault@0
cmp [ebp+KTRAP_FRAME_EIP], ecx
jz SlistFault
/* Check if this is a fault in the syscall handler */
mov ecx, offset CopyParams
cmp [ebp+KTRAP_FRAME_EIP], ecx
jz SysCallCopyFault
mov ecx, offset ReadBatch
cmp [ebp+KTRAP_FRAME_EIP], ecx
jnz CheckVdmPf
/* FIXME: TODO */
UNHANDLED_PATH
jmp _Kei386EoiHelper@0
SysCallCopyFault:
/* FIXME: TODO */
UNHANDLED_PATH
jmp _Kei386EoiHelper@0
/* Check if the fault occured in a V86 mode */
CheckVdmPf:
mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
and ecx, 1
shr ecx, 1
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz VdmPF
/* Check if the fault occured in a VDM */
mov esi, PCR[KPCR_CURRENT_THREAD]
mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
jz CheckStatus
/* Check if we this was in kernel-mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz CheckStatus
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckStatus
VdmPF:
/* FIXME: TODO */
UNHANDLED_PATH
/* Save EIP and check what kind of status failure we got */
CheckStatus:
mov esi, [ebp+KTRAP_FRAME_EIP]
cmp eax, STATUS_ACCESS_VIOLATION
je AccessViol
cmp eax, STATUS_GUARD_PAGE_VIOLATION
je SpecialCode
cmp eax, STATUS_STACK_OVERFLOW
je SpecialCode
/* Setup an in-page exception to dispatch */
mov edx, ecx
mov ebx, esi
mov esi, edi
mov ecx, 3
mov edi, eax
mov eax, STATUS_IN_PAGE_ERROR
call _CommonDispatchException
AccessViol:
/* Use more proper status code */
mov eax, KI_EXCEPTION_ACCESS_VIOLATION
SpecialCode:
/* Setup a normal page fault exception */
mov ebx, esi
mov edx, ecx
mov esi, edi
jmp _DispatchTwoParam
SlistFault:
/* FIXME: TODO */
UNHANDLED_PATH
IllegalState:
/* This is completely illegal, bugcheck the system */
push ebp
push esi
push ecx
push eax
push edi
push IRQL_NOT_LESS_OR_EQUAL
call _KeBugCheckWithTf@24
VdmAlertGpf:
/* FIXME: NOT SUPPORTED */
UNHANDLED_PATH
.endfunc
.func KiTrap0F
TRAP_FIXUPS kitf_a, kitf_t, DoFixupV86, DoNotFixupAbios
_KiTrap0F:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG kitf_a, kitf_t
sti
/* Raise a fatal exception */
mov eax, 15
jmp _KiSystemFatalException
.endfunc
.func KiTrap16
TRAP_FIXUPS kit10_a, kit10_t, DoFixupV86, DoNotFixupAbios
_KiTrap16:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG kit10_a, kit10_t
/* Check if this is the NPX Thread */
mov eax, PCR[KPCR_CURRENT_THREAD]
cmp eax, PCR[KPCR_NPX_THREAD]
/* Get the initial stack and NPX frame */
mov ecx, [eax+KTHREAD_INITIAL_STACK]
lea ecx, [ecx-NPX_FRAME_LENGTH]
/* If this is a valid fault, handle it */
jz HandleNpxFault
/* Otherwise, re-enable interrupts and set delayed error */
sti
or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
jmp _Kei386EoiHelper@0
.endfunc
.func KiTrap17
TRAP_FIXUPS kit11_a, kit11_t, DoFixupV86, DoNotFixupAbios
_KiTrap17:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG kit11_a, kit11_t
/* FIXME: ROS Doesn't handle alignment faults yet */
mov eax, 17
jmp _KiSystemFatalException
.endfunc
.func KiSystemFatalException
_KiSystemFatalException:
/* Push the trap frame */
push ebp
/* Push empty parameters */
push 0
push 0
push 0
/* Push trap number and bugcheck code */
push eax
push UNEXPECTED_KERNEL_MODE_TRAP
call _KeBugCheckWithTf@24
ret
.endfunc
.func KiCoprocessorError@0
_KiCoprocessorError@0:
/* Get the NPX Thread's Initial stack */
mov eax, PCR[KPCR_NPX_THREAD]
mov eax, [eax+KTHREAD_INITIAL_STACK]
/* Make space for the FPU Save area */
sub eax, SIZEOF_FX_SAVE_AREA
/* Set the CR0 State */
mov dword ptr [eax+FN_CR0_NPX_STATE], 8
/* Update it */
mov eax, cr0
or eax, 8
mov cr0, eax
/* Return to caller */
ret
.endfunc
.func Ki16BitStackException
_Ki16BitStackException:
/* Save stack */
push ss
push esp
/* Go to kernel mode thread stack */
mov eax, PCR[KPCR_CURRENT_THREAD]
add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */
UNHANDLED_PATH
.endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
.globl _KiStartUnexpectedRange@0
_KiStartUnexpectedRange@0:
GENERATE_INT_HANDLERS
.globl _KiEndUnexpectedRange@0
_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 _Kei386EoiHelper2ndEntry
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
_KiDispatchInterrupt@0:
/* Get the PCR and disable interrupts */
mov ebx, PCR[KPCR_SELF]
cli
/* Check if we have to deliver DPCs, timers, or deferred threads */
mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
jz CheckQuantum
/* Save stack pointer and exception list, then clear it */
push ebp
push dword ptr [ebx+KPCR_EXCEPTION_LIST]
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
/* Save the stack and switch to the DPC Stack */
mov edx, esp
mov esp, [ebx+KPCR_PRCB_DPC_STACK]
push edx
/* Deliver DPCs */
mov ecx, [ebx+KPCR_PRCB]
call @KiRetireDpcList@4
/* Restore stack and exception list */
pop esp
pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
pop ebp
CheckQuantum:
/* Re-enable interrupts */
sti
/* Check if we have quantum end */
cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
jnz QuantumEnd
/* Check if we have a thread to swap to */
cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
je Return
/* Make space on the stack to save registers */
sub esp, 3 * 4
mov [esp+8], esi
mov [esp+4], edi
mov [esp+0], ebp
/* Get the current thread */
mov edi, [ebx+KPCR_CURRENT_THREAD]
#ifdef CONFIG_SMP
#error SMP Interrupt not handled!
#endif
/* Get the next thread and clear it */
mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
/* Set us as the current running thread */
mov [ebx+KPCR_CURRENT_THREAD], esi
mov byte ptr [esi+KTHREAD_STATE], Running
mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
/* Put thread in ECX and get the PRCB in EDX */
mov ecx, edi
lea edx, [ebx+KPCR_PRCB_DATA]
call @KiQueueReadyThread@8
/* Set APC_LEVEL and do the swap */
mov cl, APC_LEVEL
call @KiSwapContextInternal@0
/* Restore registers */
mov ebp, [esp+0]
mov edi, [esp+4]
mov esi, [esp+8]
add esp, 3*4
Return:
/* All done */
ret
QuantumEnd:
/* Disable quantum end and process it */
mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
call _KiQuantumEnd@0
ret
.endfunc
.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:
/* Not yet supported */
UNHANDLED_PATH
.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 */
GetIntLock:
mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
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
.globl _KeSynchronizeExecution@12
.func KeSynchronizeExecution@12
_KeSynchronizeExecution@12:
/* Save EBX and put the interrupt object in it */
push ebx
mov ebx, [esp+8]
/* Go to DIRQL */
mov cl, [ebx+KINTERRUPT_SYNCHRONIZE_IRQL]
call @KfRaiseIrql@4
/* Call the routine */
push eax
push [esp+20]
call [esp+20]
/* Lower IRQL */
mov ebx, eax
pop ecx
call @KfLowerIrql@4
/* Return status */
mov eax, ebx
pop ebx
ret 12
.endfunc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -