#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
+#define Running 2
+#define WrDispatchInt 0x1F
+
/* GLOBALS *******************************************************************/
.data
_UnexpectedMsg:
.asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
+_UnhandledMsg:
+ .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
+
+_KiTrapPrefixTable:
+ .byte 0xF2 /* REP */
+ .byte 0xF3 /* REP INS/OUTS */
+ .byte 0x67 /* ADDR */
+ .byte 0xF0 /* LOCK */
+ .byte 0x66 /* OP */
+ .byte 0x2E /* SEG */
+ .byte 0x3E /* DS */
+ .byte 0x26 /* ES */
+ .byte 0x64 /* FS */
+ .byte 0x65 /* GS */
+ .byte 0x36 /* SS */
+
+_KiTrapIoTable:
+ .byte 0xE4 /* IN */
+ .byte 0xE5 /* IN */
+ .byte 0xEC /* IN */
+ .byte 0xED /* IN */
+ .byte 0x6C /* INS */
+ .byte 0x6D /* INS */
+ .byte 0xE6 /* OUT */
+ .byte 0xE7 /* OUT */
+ .byte 0xEE /* OUT */
+ .byte 0xEF /* OUT */
+ .byte 0x6E /* OUTS */
+ .byte 0x6F /* OUTS */
+
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
.text
_KiGetTickCount:
_KiCallbackReturn:
_KiRaiseAssertion:
- int 3
+ /* FIXME: TODO */
+ UNHANDLED_PATH
.func KiSystemService
Dr_kss: DR_TRAP_FIXUP
/* Check if we should flush the User Batch */
xor ebx, ebx
+ReadBatch:
or ebx, [ecx+TEB_GDI_BATCH_COUNT]
jz NotWin32K
iret
AbiosExit:
- /* Not yet supported */
- int 3
+ /* FIXME: TODO */
+ UNHANDLED_PATH
.func KiDebugService
Dr_kids: DR_TRAP_FIXUP
/* Call debug service dispatcher */
mov eax, [ebp+KTRAP_FRAME_EAX]
mov ecx, [ebp+KTRAP_FRAME_ECX]
- mov edx, [ebp+KTRAP_FRAME_EAX]
+ mov edx, [ebp+KTRAP_FRAME_EDX]
/* Check for V86 mode */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx
/* Check parameter count */
- cmp eax, 0
+ cmp ecx, 0
jz NoParams
/* Get information */
SetPreviousMode:
- /* Calculate the previous mode */
+ /* Get the caller's CS */
mov eax, [ebp+KTRAP_FRAME_CS]
+
MaskMode:
+ /* Check if it was user-mode or kernel-mode */
and eax, MODE_MASK
/* Dispatch the exception */
/* HARDWARE TRAP HANDLERS ****************************************************/
+.func KiFixupFrame
+_KiFixupFrame:
+
+ /* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
+ UNHANDLED_PATH
+.endfunc
+
.func KiTrap0
Dr_kit0: DR_TRAP_FIXUP
V86_kit0: V86_TRAP_FIXUP
/* We don't support this yet! */
V86Int0:
- int 3
+ /* FIXME: TODO */
+ UNHANDLED_PATH
.endfunc
.func KiTrap1
jz EnableInterrupts
/* We don't support VDM! */
- int 3
+ UNHANDLED_PATH
.endfunc
.globl _KiTrap2
/* Setup EIP, NTSTATUS and parameter count, then dispatch */
mov ebx, [ebp+KTRAP_FRAME_EIP]
dec ebx
- mov eax, STATUS_BREAKPOINT
mov ecx, 3
+ mov eax, STATUS_BREAKPOINT
call _CommonDispatchException
V86Int3:
jz EnableInterrupts3
/* We don't support VDM! */
- int 3
+ UNHANDLED_PATH
.endfunc
.func KiTrap4
/* We don't support this yet! */
V86Int4:
- int 3
+ UNHANDLED_PATH
.endfunc
.func KiTrap5
/* We don't support this yet! */
V86Int5:
- int 3
+ UNHANDLED_PATH
.endfunc
.func KiTrap6
V86_TRAP_PROLOG kit6
/* Not yet supported (Invalid OPCODE from V86) */
- int 3
- jmp $
+ UNHANDLED_PATH
NotV86UD:
/* Push error code */
IsVdmOpcode:
/* Unhandled yet */
- int 3
- jmp $
+ UNHANDLED_PATH
/* Return to caller */
jmp _Kei386EoiHelper@0
jz HandleUserNpx
/* V86 NPX not handled */
- int 3
- jmp $
+ UNHANDLED_PATH
EmulationEnabled:
/* Did this come from kernel-mode? */
jmp _KiSystemFatalException
.endfunc
+.func KiTrapExceptHandler
+_KiTrapExceptHandler:
+
+ /* Setup SEH handler frame */
+ mov esp, [esp+8]
+ pop fs:[KPCR_EXCEPTION_LIST]
+ add esp, 4
+ pop ebp
+
+ /* Check if the fault came from user mode */
+ test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+ jnz SetException
+
+ /* Kernel fault, bugcheck */
+ push ebp
+ push 0
+ push 0
+ push 0
+ push 0
+ push KMODE_EXCEPTION_NOT_HANDLED
+ call _KeBugCheckWithTf@24
+.endfunc
+
.func KiTrap13
Dr_kitd: DR_TRAP_FIXUP
V86_kitd: V86_TRAP_FIXUP
jnz NoReflect
/* FIXME: TODO */
- int 3
+ UNHANDLED_PATH
NoReflect:
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jnz UserModeGpf
- /* FIXME: Check for GPF during GPF */
+ /* Check if we have a VDM alert */
+ cmp dword ptr fs:[KPCR_VDM_ALERT], 0
+ jnz VdmAlertGpf
+
+ /* Check for GPF during GPF */
+ mov eax, [ebp+KTRAP_FRAME_EIP]
+ cmp eax, offset CheckPrivilegedInstruction
+ jbe KmodeGpf
+ cmp eax, offset CheckPrivilegedInstruction2
+
+ /* FIXME: TODO */
+ UNHANDLED_PATH
/* Get the opcode and trap frame */
+KmodeGpf:
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
mov edx, [ebp+KTRAP_FRAME_EBP]
MsrCheck:
/* FIXME: Handle RDMSR/WRMSR */
- int 3
- jmp $
+ UNHANDLED_PATH
NotIretGpf:
UserModeGpf:
- /* FIXME: Unhandled */
- int 3
- jmp $
+ /* If the previous mode was kernel, raise a fatal exception */
+ mov eax, 13
+ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+ jz _KiSystemFatalException
+
+ /* Get the process and check which CS this came from */
+ mov ebx, fs:[KPCR_CURRENT_THREAD]
+ mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
+ cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
+ jz CheckVdmGpf
+
+ /* Check if this is a VDM */
+ cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+ jnz DispatchV86Gpf
+
+ /* Enable interrupts and check if we have an error code */
+ sti
+ cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
+ jnz SetException
+ jmp CheckPrivilegedInstruction
+
+HandleSegPop2:
+ /* Update EIP (will be updated below again) */
+ add dword ptr [ebp+KTRAP_FRAME_EIP], 1
+
+HandleEsPop:
+ /* Clear the segment, update EIP and ESP */
+ mov dword ptr [edx], 0
+ add dword ptr [ebp+KTRAP_FRAME_EIP], 1
+ add dword ptr [ebp+KTRAP_FRAME_ESP], 4
+ jmp _Kei386EoiHelper@0
+
+CheckVdmGpf:
+ /* Check if this is a VDM */
+ cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
+ jz CheckPrivilegedInstruction
+
+ /* Bring interrupts back */
+ sti
+
+ /* Check what kind of instruction this is */
+ mov eax, [ebp+KTRAP_FRAME_EIP]
+ mov eax, [eax]
+
+ /* FIXME: Check for BOP4 */
+
+ /* Check if this is POP ES */
+ mov edx, ebp
+ add edx, KTRAP_FRAME_ES
+ cmp al, 0x07
+ jz HandleEsPop
+
+ /* Check if this is POP FS */
+ add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
+ cmp ax, 0xA10F
+ jz HandleSegPop2
+
+ /* Check if this is POP GS */
+ add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
+ cmp ax, 0xA90F
+ jz HandleSegPop2
+
+CheckPrivilegedInstruction:
+ /* Bring interrupts back */
+ sti
+
+ /* Setup a SEH handler */
+ push ebp
+ push offset _KiTrapExceptHandler
+ push fs:[KPCR_EXCEPTION_LIST]
+ mov fs:[KPCR_EXCEPTION_LIST], esp
+
+ /* Get EIP */
+ mov esi, [ebp+KTRAP_FRAME_EIP]
+
+ /* Setup loop count */
+ mov ecx, 15
+
+InstLoop:
+ /* Save loop count */
+ push ecx
+
+ /* Get the instruction */
+ lods byte ptr [esi]
+
+ /* Now lookup in the prefix table */
+ mov ecx, 11
+ mov edi, offset _KiTrapPrefixTable
+ repnz scasb
+
+ /* Restore loop count */
+ pop ecx
+
+ /* If it's not a prefix byte, check other instructions */
+ jnz NotPrefixByte
+
+ /* FIXME */
+ UNHANDLED_PATH
+
+NotPrefixByte:
+ /* FIXME: Check if it's a HLT */
+
+ /* Check if the instruction has two bytes */
+ cmp al, 0xF
+ jne CheckRing3Io
+
+ /* FIXME */
+ UNHANDLED_PATH
+
+CheckRing3Io:
+ /* Get EFLAGS and IOPL */
+ mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
+ and ebx, 0x3000
+ shr ebx, 12
+
+ /* Check the CS's RPL mask */
+ mov ecx, [ebp+KTRAP_FRAME_CS]
+ and ecx, RPL_MASK
+ cmp ebx, ecx
+ jge NotIoViolation
+
+CheckPrivilegedInstruction2:
+ /* Check if this is a CLI or STI */
+ cmp al, 0xFA
+ je IsPrivInstruction
+ cmp al, 0xFB
+ je IsPrivInstruction
+
+ /* Setup I/O table lookup */
+ mov ecx, 13
+ mov edi, offset _KiTrapIoTable
+
+ /* Loopup in the table */
+ repnz scasb
+ jnz NotIoViolation
+
+ /* FIXME: Check IOPM!!! */
+
+IsPrivInstruction:
+ /* Cleanup the SEH frame */
+ pop fs:[KPCR_EXCEPTION_LIST]
+ add esp, 8
+
+ /* Setup the exception */
+ mov ebx, [ebp+KTRAP_FRAME_EIP]
+ mov eax, STATUS_PRIVILEGED_INSTRUCTION
+ jmp _DispatchNoParam
+
+NotIoViolation:
+ /* Cleanup the SEH frame */
+ pop fs:[KPCR_EXCEPTION_LIST]
+ add esp, 8
+
+SetException:
+ /* Setup the exception */
+ mov ebx, [ebp+KTRAP_FRAME_EIP]
+ mov esi, -1
+ mov eax, STATUS_ACCESS_VIOLATION
+ jmp _DispatchTwoParam
+
+DispatchV86Gpf:
+ /* FIXME */
+ UNHANDLED_PATH
.endfunc
.func KiTrap14
Dr_kit14: DR_TRAP_FIXUP
V86_kit14: V86_TRAP_FIXUP
_KiTrap14:
+
/* Enter trap */
TRAP_PROLOG kit14
- /* Call the C exception handler */
- push 14
+ /* Check if we have a VDM alert */
+ cmp dword ptr fs:[KPCR_VDM_ALERT], 0
+ jnz VdmAlertGpf
+
+ /* Get the current thread */
+ mov edi, fs:[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, fs:[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
- call _KiPageFaultHandler
- add esp, 8
+ mov eax, [ebp+KTRAP_FRAME_CS]
+ and eax, MODE_MASK
+ push eax
- /* Return to caller */
+ /* 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, fs:[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
add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */
- /* TODO */
- int 3
+ UNHANDLED_PATH
.endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
/* Restore stack and exception list */
pop esp
- pop dword ptr [ebx]
+ pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
pop ebp
CheckQuantum:
/* Check if we have a thread to swap to */
cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
- jz Return
+ je Return
- /* FIXME: Schedule new thread */
- int 3
+ /* 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 */
_KiChainedDispatch2ndLvl@0:
/* Not yet supported */
- int 3
+ UNHANDLED_PATH
.endfunc
.func KiChainedDispatch@0