2 * FILE: ntoskrnl/ke/i386/trap.S
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: System Traps, Entrypoints and Exitpoints
5 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
6 * NOTE: See asmmacro.S for the shared entry/exit code.
9 /* INCLUDES ******************************************************************/
12 #include <internal/i386/asmmacro.S>
13 .intel_syntax noprefix
16 #define WrDispatchInt 0x1F
18 /* GLOBALS *******************************************************************/
23 /* This is the Software Interrupt Table that we handle in this file: */
24 idt _KiTrap0, INT_32_DPL0 /* INT 00: Divide Error (#DE) */
25 idt _KiTrap1, INT_32_DPL0 /* INT 01: Debug Exception (#DB) */
26 idt _KiTrap2, INT_32_DPL0 /* INT 02: NMI Interrupt */
27 idt _KiTrap3, INT_32_DPL3 /* INT 03: Breakpoint Exception (#BP) */
28 idt _KiTrap4, INT_32_DPL3 /* INT 04: Overflow Exception (#OF) */
29 idt _KiTrap5, INT_32_DPL0 /* INT 05: BOUND Range Exceeded (#BR) */
30 idt _KiTrap6, INT_32_DPL0 /* INT 06: Invalid Opcode Code (#UD) */
31 idt _KiTrap7, INT_32_DPL0 /* INT 07: Device Not Available (#NM) */
32 idt _KiTrap8, INT_32_DPL0 /* INT 08: Double Fault Exception (#DF) */
33 idt _KiTrap9, INT_32_DPL0 /* INT 09: RESERVED */
34 idt _KiTrap10, INT_32_DPL0 /* INT 0A: Invalid TSS Exception (#TS) */
35 idt _KiTrap11, INT_32_DPL0 /* INT 0B: Segment Not Present (#NP) */
36 idt _KiTrap12, INT_32_DPL0 /* INT 0C: Stack Fault Exception (#SS) */
37 idt _KiTrap13, INT_32_DPL0 /* INT 0D: General Protection (#GP) */
38 idt _KiTrap14, INT_32_DPL0 /* INT 0E: Page-Fault Exception (#PF) */
39 idt _KiTrap0F, INT_32_DPL0 /* INT 0F: RESERVED */
40 idt _KiTrap16, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF) */
41 idt _KiTrap17, INT_32_DPL0 /* INT 11: Align Check Exception (#AC) */
42 idt _KiTrap0F, INT_32_DPL0 /* INT 12: Machine Check Exception (#MC)*/
43 idt _KiTrap0F, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF) */
45 idt _KiTrap0F, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS */
47 idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler */
48 idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback Return */
49 idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */
50 idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */
51 idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */
52 idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */
53 GENERATE_IDT_STUBS /* INT 30-FF: UNEXPECTED INTERRUPTS */
55 /* System call entrypoints: */
56 .globl _KiFastCallEntry
57 .globl _KiSystemService
59 /* And special system-defined software traps: */
60 .globl _NtRaiseException@12
62 .globl _KiCoprocessorError@0
63 .globl _KiDispatchInterrupt@0
65 /* Interrupt template entrypoints */
66 .globl _KiInterruptTemplate
67 .globl _KiInterruptTemplateObject
68 .globl _KiInterruptTemplateDispatch
70 /* Chained and Normal generic interrupt handlers for 1st and 2nd level entry*/
71 .globl _KiChainedDispatch2ndLvl@0
72 .globl _KiInterruptDispatch@0
73 .globl _KiChainedDispatch@0
75 /* We implement the following trap exit points: */
76 .globl _KiServiceExit /* Exit from syscall */
77 .globl _KiServiceExit2 /* Exit from syscall with complete frame*/
78 .globl _Kei386EoiHelper@0 /* Exit from interrupt or H/W trap */
79 .globl _Kei386EoiHelper2ndEntry /* Exit from unexpected interrupt */
81 .globl _KiIdtDescriptor
86 .globl _KiUnexpectedEntrySize
87 _KiUnexpectedEntrySize:
88 .long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
91 .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
94 .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
98 .byte 0xF3 /* REP INS/OUTS */
100 .byte 0xF0 /* LOCK */
120 .byte 0x6E /* OUTS */
121 .byte 0x6F /* OUTS */
123 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
132 .func KiSystemService
133 Dr_kss: DR_TRAP_FIXUP
136 /* Enter the shared system call prolog */
139 /* Jump to the actual handler */
143 .func KiFastCallEntry
144 Dr_FastCallDrSave: DR_TRAP_FIXUP
147 /* Enter the fast system call prolog */
148 FASTCALL_PROLOG FastCallDrSave
153 * Find out which table offset to use. Converts 0x1124 into 0x10.
154 * The offset is related to the Table Index as such: Offset = TableIndex x 10
157 shr edi, SERVICE_TABLE_SHIFT
158 and edi, SERVICE_TABLE_MASK
161 /* Now add the thread's base system table to the offset */
162 add edi, [esi+KTHREAD_SERVICE_TABLE]
164 /* Get the true syscall ID and check it */
166 and eax, SERVICE_NUMBER_MASK
167 cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
169 /* Invalid ID, try to load Win32K Table */
170 jnb KiBBTUnexpectedRange
172 /* Check if this was Win32K */
173 cmp ecx, SERVICE_TABLE_TEST
177 mov ecx, [fs:KPCR_TEB]
179 /* Check if we should flush the User Batch */
182 or ebx, [ecx+TEB_GDI_BATCH_COUNT]
188 //call [_KeGdiFlushUserBatch]
193 /* Increase total syscall count */
194 inc dword ptr fs:[KPCR_SYSTEM_CALLS]
197 /* Increase per-syscall count */
198 mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
200 inc dword ptr [ecx+eax*4]
203 /* Users's current stack frame pointer is source */
207 /* Allocate room for argument list from kernel stack */
208 mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
212 /* Get pointer to function */
213 mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
216 /* Allocate space on our stack */
219 /* Set the size of the arguments and the destination */
223 /* Make sure we're within the User Probe Address */
224 cmp esi, _MmUserProbeAddress
228 /* Copy the parameters */
231 /* Do the System Call */
236 /* Make sure the user-mode call didn't return at elevated IRQL */
237 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
239 mov esi, eax /* We need to save the syscall's return val */
240 call _KeGetCurrentIrql@0
243 mov eax, esi /* Restore it */
245 /* Get our temporary current thread pointer for sanity check */
246 mov ecx, fs:[KPCR_CURRENT_THREAD]
248 /* Make sure that we are not attached and that APCs are not disabled */
249 mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
252 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
259 /* Deallocate the kernel stack frame */
262 KeReturnFromSystemCall:
264 /* Get the Current Thread */
265 mov ecx, [fs:KPCR_CURRENT_THREAD]
267 /* Restore the old trap frame pointer */
268 mov edx, [ebp+KTRAP_FRAME_EDX]
269 mov [ecx+KTHREAD_TRAP_FRAME], edx
274 /* Disable interrupts */
277 /* Check for, and deliver, User-Mode APCs if needed */
278 CHECK_FOR_APC_DELIVER 1
280 /* Exit and cleanup */
281 TRAP_EPILOG FromSystemCall, DoRestorePreviousMode, DoNotRestoreSegments, DoNotRestoreVolatiles, DoRestoreEverything
284 KiBBTUnexpectedRange:
286 /* If this isn't a Win32K call, fail */
287 cmp ecx, SERVICE_TABLE_TEST
290 /* Set up Win32K Table */
293 call _PsConvertToGuiThread@0
295 /* Check return code */
298 /* Restore registers */
302 /* Reset trap frame address */
304 mov [esi+KTHREAD_TRAP_FRAME], ebp
306 /* Try the Call again, if we suceeded */
310 * The Shadow Table should have a special byte table which tells us
311 * whether we should return FALSE, -1 or STATUS_INVALID_SYSTEM_SERVICE.
314 /* Get the table limit and base */
315 lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
316 mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
317 mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
319 /* Get the table address and add our index into the array */
321 and eax, SERVICE_NUMBER_MASK
324 /* Find out what we should return */
325 movsx eax, byte ptr [edx]
328 /* Return either 0 or -1, we've set it in EAX */
329 jle KeReturnFromSystemCall
331 /* Set STATUS_INVALID_SYSTEM_SERVICE */
332 mov eax, STATUS_INVALID_SYSTEM_SERVICE
333 jmp KeReturnFromSystemCall
337 /* Invalid System Call */
338 mov eax, STATUS_INVALID_SYSTEM_SERVICE
339 jmp KeReturnFromSystemCall
343 /* Check if this came from kernel-mode */
344 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
346 /* It's fine, go ahead with it */
349 /* Caller sent invalid parameters, fail here */
350 mov eax, STATUS_ACCESS_VIOLATION
355 /* Restore ESP0 stack */
356 mov ecx, [fs:KPCR_TSS]
357 mov esp, ss:[ecx+KTSS_ESP0]
359 /* Generate V86M Stack for Trap 6 */
365 /* Generate interrupt stack for Trap 6 */
366 push KGDT_R3_DATA + RPL_MASK
369 push KGDT_R3_CODE + RPL_MASK
375 /* Save current IRQL */
378 /* Set us at passive */
379 mov dword ptr fs:[KPCR_IRQL], 0
387 push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
388 call _KeBugCheckEx@20
392 /* Get the index and APC state */
393 movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
394 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
401 push APC_INDEX_MISMATCH
402 call _KeBugCheckEx@20
409 /* Disable interrupts */
412 /* Check for, and deliver, User-Mode APCs if needed */
413 CHECK_FOR_APC_DELIVER 0
415 /* Exit and cleanup */
416 TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
419 .func Kei386EoiHelper@0
422 /* Disable interrupts */
425 /* Check for, and deliver, User-Mode APCs if needed */
426 CHECK_FOR_APC_DELIVER 0
428 /* Exit and cleanup */
429 _Kei386EoiHelper2ndEntry:
430 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
434 /* Move to EDX position */
435 add esp, KTRAP_FRAME_EDX
437 /* Restore volatiles */
442 /* Move to non-volatiles */
443 lea esp, [ebp+KTRAP_FRAME_EDI]
449 /* Skip error code and return */
458 Dr_kids: DR_TRAP_FIXUP
459 V86_kids: V86_TRAP_FIXUP
462 /* Push error code */
468 /* Increase EIP so we skip the INT3 */
469 inc dword ptr [ebp+KTRAP_FRAME_EIP]
471 /* Call debug service dispatcher */
472 mov eax, [ebp+KTRAP_FRAME_EAX]
473 mov ecx, [ebp+KTRAP_FRAME_ECX]
474 mov edx, [ebp+KTRAP_FRAME_EAX]
476 /* Jump to INT3 handler */
480 .func NtRaiseException@12
481 _NtRaiseException@12:
483 /* NOTE: We -must- be called by Zw* to have the right frame! */
484 /* Push the stack frame */
487 /* Get the current thread and restore its trap frame */
488 mov ebx, [fs:KPCR_CURRENT_THREAD]
489 mov edx, [ebp+KTRAP_FRAME_EDX]
490 mov [ebx+KTHREAD_TRAP_FRAME], edx
492 /* Set up stack frame */
495 /* Get the Trap Frame in EBX */
498 /* Get the exception list and restore */
499 mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
500 mov [fs:KPCR_EXCEPTION_LIST], eax
502 /* Get the parameters */
503 mov edx, [ebp+16] /* Search frames */
504 mov ecx, [ebp+12] /* Context */
505 mov eax, [ebp+8] /* Exception Record */
507 /* Raise the exception */
513 call _KiRaiseException@20
515 /* Restore trap frame in EBP */
519 /* Check the result */
523 /* Restore debug registers too */
530 /* NOTE: We -must- be called by Zw* to have the right frame! */
531 /* Push the stack frame */
534 /* Get the current thread and restore its trap frame */
535 mov ebx, [fs:KPCR_CURRENT_THREAD]
536 mov edx, [ebp+KTRAP_FRAME_EDX]
537 mov [ebx+KTHREAD_TRAP_FRAME], edx
539 /* Set up stack frame */
542 /* Save the parameters */
546 /* Call KiContinue */
552 /* Check if we failed (bad context record) */
556 /* Check if test alert was requested */
557 cmp dword ptr [ebp+12], 0
560 /* Test alert for the thread */
561 mov al, [ebx+KTHREAD_PREVIOUS_MODE]
563 call _KeTestAlertThread@4
566 /* Return to previous context */
577 /* EXCEPTION DISPATCHERS *****************************************************/
579 .func CommonDispatchException
580 _CommonDispatchException:
582 /* Make space for an exception record */
583 sub esp, EXCEPTION_RECORD_LENGTH
586 mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
588 mov [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], eax
589 mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], eax
590 mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], ebx
591 mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx
593 /* Check parameter count */
597 /* Get information */
598 lea ebx, [esp+SIZEOF_EXCEPTION_RECORD]
605 /* Set the record in ECX and check if this was V86 */
607 test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
616 /* Calculate the previous mode */
617 mov eax, [ebp+KTRAP_FRAME_CS]
621 /* Dispatch the exception */
627 call _KiDispatchException@20
631 jmp _Kei386EoiHelper@0
634 .func DispatchNoParam
636 /* Call the common dispatcher */
638 call _CommonDispatchException
641 .func DispatchOneParam
643 /* Call the common dispatcher */
646 call _CommonDispatchException
649 .func DispatchTwoParam
651 /* Call the common dispatcher */
654 call _CommonDispatchException
657 /* HARDWARE TRAP HANDLERS ****************************************************/
662 /* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
667 Dr_kit0: DR_TRAP_FIXUP
668 V86_kit0: V86_TRAP_FIXUP
670 /* Push error code */
677 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
680 /* Check if the frame was from kernelmode */
681 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
684 /* Check the old mode */
685 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
689 /* Re-enable interrupts for user-mode and send the exception */
691 mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO
692 mov ebx, [ebp+KTRAP_FRAME_EIP]
696 /* Check if this is a VDM process */
697 mov ebx, [fs:KPCR_CURRENT_THREAD]
698 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
699 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
702 /* We don't support this yet! */
709 Dr_kit1: DR_TRAP_FIXUP
710 V86_kit1: V86_TRAP_FIXUP
712 /* Push error code */
719 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
722 /* Check if the frame was from kernelmode */
723 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
726 /* Check the old mode */
727 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
731 /* Enable interrupts for user-mode */
735 /* Prepare the exception */
736 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAGS_TF
737 mov ebx, [ebp+KTRAP_FRAME_EIP]
738 mov eax, STATUS_SINGLE_STEP
742 /* Check if this is a VDM process */
743 mov ebx, [fs:KPCR_CURRENT_THREAD]
744 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
745 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
748 /* We don't support VDM! */
756 /* FIXME: This is an NMI, nothing like a normal exception */
758 jmp _KiSystemFatalException
762 Dr_kit3: DR_TRAP_FIXUP
763 V86_kit3: V86_TRAP_FIXUP
765 /* Push error code */
771 /* Set status code */
772 mov eax, 0 //STATUS_SUCCESS
776 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
779 /* Check if the frame was from kernelmode */
780 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
783 /* Check the old mode */
784 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
788 /* Enable interrupts for user-mode */
792 /* Prepare the exception */
797 /* Setup EIP, NTSTATUS and parameter count, then dispatch */
798 mov ebx, [ebp+KTRAP_FRAME_EIP]
800 mov eax, STATUS_BREAKPOINT
802 call _CommonDispatchException
805 /* Check if this is a VDM process */
806 mov ebx, [fs:KPCR_CURRENT_THREAD]
807 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
808 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
811 /* We don't support VDM! */
816 Dr_kit4: DR_TRAP_FIXUP
817 V86_kit4: V86_TRAP_FIXUP
819 /* Push error code */
826 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
829 /* Check if the frame was from kernelmode */
830 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
833 /* Check the old mode */
834 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
838 /* Re-enable interrupts for user-mode and send the exception */
840 mov eax, STATUS_INTEGER_OVERFLOW
841 mov ebx, [ebp+KTRAP_FRAME_EIP]
846 /* Check if this is a VDM process */
847 mov ebx, [fs:KPCR_CURRENT_THREAD]
848 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
849 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
852 /* We don't support this yet! */
858 Dr_kit5: DR_TRAP_FIXUP
859 V86_kit5: V86_TRAP_FIXUP
861 /* Push error code */
868 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
871 /* Check if the frame was from kernelmode */
872 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
875 /* It did, and this should never happen */
877 jmp _KiSystemFatalException
879 /* Check the old mode */
881 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
884 /* Re-enable interrupts for user-mode and send the exception */
887 mov eax, STATUS_ARRAY_BOUNDS_EXCEEDED
888 mov ebx, [ebp+KTRAP_FRAME_EIP]
892 /* Check if this is a VDM process */
893 mov ebx, [fs:KPCR_CURRENT_THREAD]
894 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
895 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
898 /* We don't support this yet! */
904 Dr_kit6: DR_TRAP_FIXUP
905 V86_kit6: V86_TRAP_FIXUP
908 /* It this a V86 GPF? */
909 test dword ptr [esp+8], EFLAGS_V86_MASK
915 /* Not yet supported (Invalid OPCODE from V86) */
919 /* Push error code */
925 /* Check if this happened in kernel mode */
926 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
930 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
933 /* Check if the process is vDM */
934 mov ebx, fs:[KPCR_CURRENT_THREAD]
935 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
936 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
940 /* Get EIP and enable interrupts at this point */
941 mov esi, [ebp+KTRAP_FRAME_EIP]
944 /* Set intruction prefix length */
947 /* Setup a SEH frame */
950 push fs:[KPCR_EXCEPTION_LIST]
951 mov fs:[KPCR_EXCEPTION_LIST], esp
954 /* Get the instruction and check if it's LOCK */
964 pop fs:[KPCR_EXCEPTION_LIST]
969 /* Re-enable interrupts */
972 /* Setup illegal instruction exception and dispatch it */
973 mov ebx, [ebp+KTRAP_FRAME_EIP]
974 mov eax, STATUS_ILLEGAL_INSTRUCTION
980 pop fs:[KPCR_EXCEPTION_LIST]
983 /* Setup invalid lock exception and dispatch it */
984 mov ebx, [ebp+KTRAP_FRAME_EIP]
985 mov eax, STATUS_INVALID_LOCK_SEQUENCE
993 /* Return to caller */
994 jmp _Kei386EoiHelper@0
1000 pop fs:[KPCR_EXCEPTION_LIST]
1004 /* Check if this was user mode */
1005 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1014 push KMODE_EXCEPTION_NOT_HANDLED
1015 call _KeBugCheckWithTf@24
1019 Dr_kit7: DR_TRAP_FIXUP
1020 V86_kit7: V86_TRAP_FIXUP
1022 /* Push error code */
1028 /* Get the current thread and stack */
1030 mov eax, [fs:KPCR_CURRENT_THREAD]
1031 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1032 sub ecx, NPX_FRAME_LENGTH
1034 /* Check if emulation is enabled */
1035 test dword ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
1036 jnz EmulationEnabled
1039 /* Check if the NPX state is loaded */
1040 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1045 and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
1048 /* Check the NPX thread */
1049 mov edx, [fs:KPCR_NPX_THREAD]
1053 /* Get the NPX Stack */
1054 mov esi, [edx+KTHREAD_INITIAL_STACK]
1055 sub esi, NPX_FRAME_LENGTH
1057 /* Check if we have FXSR and check which operand to use */
1058 test byte ptr _KeI386FxsrPresent, 1
1067 /* Set the thread's state to dirty */
1068 mov byte ptr [edx+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1071 /* Check if we have FXSR and choose which operand to use */
1072 test byte ptr _KeI386FxsrPresent, 1
1081 /* Set state loaded */
1082 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1083 mov [fs:KPCR_NPX_THREAD], eax
1085 /* Enable interrupts to happen now */
1089 /* Check if CR0 needs to be reloaded due to a context switch */
1090 cmp dword ptr [ecx+FN_CR0_NPX_STATE], 0
1091 jz _Kei386EoiHelper@0
1093 /* We have to reload CR0... disable interrupts */
1096 /* Get CR0 and update it */
1098 or ebx, [ecx+FN_CR0_NPX_STATE]
1101 /* Restore interrupts and check if TS is back on */
1104 jz _Kei386EoiHelper@0
1106 /* Clear TS, and loop handling again */
1113 /* Set delayed error */
1114 or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
1116 /* Check if this happened during restore */
1117 cmp dword ptr [ebp+KTRAP_FRAME_EIP], offset FrRestore
1120 /* Skip instruction and dispatch the exception */
1121 add dword ptr [ebp+KTRAP_FRAME_EIP], 3
1122 jmp _Kei386EoiHelper@0
1125 /* Check if TS is set */
1127 jnz TsSetOnLoadedState
1130 /* Check if the trap came from V86 mode */
1131 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1134 /* Check if it came from kernel mode */
1135 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1138 /* Check if it came from a VDM */
1139 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1143 /* Get the current thread */
1144 mov eax, fs:[KPCR_CURRENT_THREAD]
1146 /* Check NPX state */
1147 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1149 /* Get the NPX save area */
1150 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1151 lea ecx, [ecx-NPX_FRAME_LENGTH]
1158 and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
1161 /* Check if we have FX support */
1162 test byte ptr _KeI386FxsrPresent, 1
1165 /* Save the state */
1173 /* Make CR0 state not loaded */
1174 or ebx, NPX_STATE_NOT_LOADED
1175 or ebx, [ecx+FN_CR0_NPX_STATE]
1178 /* Update NPX state */
1179 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1180 mov dword ptr fs:[KPCR_NPX_THREAD], 0
1183 /* Clear the TS bit and re-enable interrupts */
1184 and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
1187 /* Check if we have FX support */
1188 test byte ptr _KeI386FxsrPresent, 1
1191 /* Get error offset, control and status words */
1192 mov ebx, [ecx+FX_ERROR_OFFSET]
1193 movzx eax, word ptr [ecx+FX_CONTROL_WORD]
1194 movzx edx, word ptr [ecx+FX_STATUS_WORD]
1196 /* Get the faulting opcode */
1197 mov esi, [ecx+FX_DATA_OFFSET]
1201 /* Get error offset, control and status words */
1202 mov ebx, [ecx+FP_ERROR_OFFSET]
1203 movzx eax, word ptr [ecx+FP_CONTROL_WORD]
1204 movzx edx, word ptr [ecx+FP_STATUS_WORD]
1206 /* Get the faulting opcode */
1207 mov esi, [ecx+FP_DATA_OFFSET]
1210 /* Mask exceptions */
1215 /* Check if what's left is invalid */
1219 /* Check if it was a stack fault */
1223 /* Raise exception */
1224 mov eax, STATUS_FLOAT_INVALID_OPERATION
1225 jmp _DispatchOneParam
1229 /* Raise exception */
1230 mov eax, STATUS_FLOAT_STACK_CHECK
1231 jmp _DispatchTwoParam
1235 /* Check for divide by 0 */
1239 /* Raise exception */
1240 mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
1241 jmp _DispatchOneParam
1244 /* Check for denormal */
1248 /* Raise exception */
1249 mov eax, STATUS_FLOAT_INVALID_OPERATION
1250 jmp _DispatchOneParam
1253 /* Check for overflow */
1257 /* Raise exception */
1258 mov eax, STATUS_FLOAT_OVERFLOW
1259 jmp _DispatchOneParam
1262 /* Check for underflow */
1266 /* Raise exception */
1267 mov eax, STATUS_FLOAT_UNDERFLOW
1268 jmp _DispatchOneParam
1271 /* Check for precision fault */
1275 /* Raise exception */
1276 mov eax, STATUS_FLOAT_INEXACT_RESULT
1277 jmp _DispatchOneParam
1281 /* Strange result, bugcheck the OS */
1288 push TRAP_CAUSE_UNKNOWN
1289 call _KeBugCheckWithTf@24
1292 /* Check if this is a VDM */
1293 mov eax, fs:[KPCR_CURRENT_THREAD]
1294 mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
1295 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1298 /* V86 NPX not handled */
1302 /* Did this come from kernel-mode? */
1303 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
1306 /* It came from user-mode, so this would only be valid inside a VDM */
1307 /* Since we don't actually have VDMs in ROS, bugcheck. */
1311 /* TS shouldn't be set, unless this we don't have a Math Processor */
1315 /* Strange that we got a trap at all, but ignore and continue */
1317 jmp _Kei386EoiHelper@0
1320 /* Cause a bugcheck */
1325 push TRAP_CAUSE_UNKNOWN
1326 call _KeBugCheckEx@20
1333 /* Can't really do too much */
1335 jmp _KiSystemFatalException
1339 Dr_kit9: DR_TRAP_FIXUP
1340 V86_kit9: V86_TRAP_FIXUP
1342 /* Push error code */
1348 /* Enable interrupts and bugcheck */
1351 jmp _KiSystemFatalException
1355 Dr_kit10: DR_TRAP_FIXUP
1356 V86_kit10: V86_TRAP_FIXUP
1362 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1365 /* Check if the frame was from kernelmode */
1366 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1370 /* Check if OF was set during iretd */
1371 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAG_ZERO
1375 /* It was, just mask it out */
1376 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAG_ZERO
1377 jmp _Kei386EoiHelper@0
1380 /* TSS failure for some other reason: crash */
1382 jmp _KiSystemFatalException
1386 Dr_kit11: DR_TRAP_FIXUP
1387 V86_kit11: V86_TRAP_FIXUP
1392 /* FIXME: ROS Doesn't handle segment faults yet */
1394 jmp _KiSystemFatalException
1398 Dr_kit12: DR_TRAP_FIXUP
1399 V86_kit12: V86_TRAP_FIXUP
1404 /* FIXME: ROS Doesn't handle stack faults yet */
1406 jmp _KiSystemFatalException
1409 .func KiTrapExceptHandler
1410 _KiTrapExceptHandler:
1412 /* Setup SEH handler frame */
1414 pop fs:[KPCR_EXCEPTION_LIST]
1418 /* Check if the fault came from user mode */
1419 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1422 /* Kernel fault, bugcheck */
1428 push KMODE_EXCEPTION_NOT_HANDLED
1429 call _KeBugCheckWithTf@24
1433 Dr_kitd: DR_TRAP_FIXUP
1434 V86_kitd: V86_TRAP_FIXUP
1437 /* It this a V86 GPF? */
1438 test dword ptr [esp+12], EFLAGS_V86_MASK
1441 /* Enter V86 Trap */
1442 V86_TRAP_PROLOG kitd
1444 /* Make sure that this is a V86 process */
1445 mov ecx, [fs:KPCR_CURRENT_THREAD]
1446 mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS]
1447 cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0
1450 /* Otherwise, something is very wrong, raise an exception */
1452 mov ebx, [ebp+KTRAP_FRAME_EIP]
1454 mov eax, STATUS_ACCESS_VIOLATION
1455 jmp _DispatchTwoParam
1459 /* Go to APC level */
1463 /* Save old IRQL and enable interrupts */
1467 /* Handle the opcode */
1468 call _Ki386HandleOpcodeV86@0
1470 /* Check if this was VDM */
1479 /* Lower IRQL and disable interrupts */
1484 /* Check if this was a V86 trap */
1485 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1488 /* Exit the V86 Trap */
1493 /* Either this wasn't V86, or it was, but an APC interrupted us */
1494 jmp _Kei386EoiHelper@0
1500 /* Check if this was from kernel-mode */
1501 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1504 /* Check if we have a VDM alert */
1505 cmp dword ptr fs:[KPCR_VDM_ALERT], 0
1508 /* Check for GPF during GPF */
1509 mov eax, [ebp+KTRAP_FRAME_EIP]
1510 cmp eax, offset CheckPrivilegedInstruction
1512 cmp eax, offset CheckPrivilegedInstruction2
1517 /* Get the opcode and trap frame */
1519 mov eax, [ebp+KTRAP_FRAME_EIP]
1521 mov edx, [ebp+KTRAP_FRAME_EBP]
1523 /* We want to check if this was POP [DS/ES/FS/GS] */
1524 add edx, KTRAP_FRAME_DS
1527 add edx, KTRAP_FRAME_ES - KTRAP_FRAME_DS
1530 add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
1533 add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
1537 /* It isn't, was it IRETD? */
1541 /* Get error code */
1542 lea edx, [ebp+KTRAP_FRAME_ESP]
1543 mov ax, [ebp+KTRAP_FRAME_ERROR_CODE]
1547 mov cx, word ptr [edx+4]
1552 /* This should be a Ki386CallBios return */
1553 mov eax, offset _Ki386BiosCallReturnAddress
1557 cmp ax, KGDT_R0_CODE + RPL_MASK
1560 /* Jump to return address */
1561 jmp _Ki386BiosCallReturnAddress
1564 /* Check if the thread was in kernel mode */
1565 mov ebx, [fs:KPCR_CURRENT_THREAD]
1566 test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF
1569 /* Set RPL_MASK for check below */
1570 or word ptr [edx+4], RPL_MASK
1573 /* Check if the IRET goes to user-mode */
1574 test dword ptr [edx+4], RPL_MASK
1577 /* Setup trap frame to copy */
1578 mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
1579 lea edx, [ebp+KTRAP_FRAME_ERROR_CODE]
1583 /* Copy each field */
1589 /* Enable interrupts and adjust stack */
1594 /* Setup exception record */
1595 mov ebx, [ebp+KTRAP_FRAME_EIP]
1596 mov esi, [ebp+KTRAP_FRAME_ERROR_CODE]
1598 mov eax, STATUS_ACCESS_VIOLATION
1599 jmp _DispatchTwoParam
1603 /* FIXME: Handle RDMSR/WRMSR */
1608 /* Check if this was an MSR opcode */
1612 /* Check if DS is Ring 3 */
1613 cmp word ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
1616 /* Otherwise, fix it up */
1617 mov dword ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
1622 /* Check if ES is Ring 3 */
1623 cmp word ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
1626 /* Otherwise, fix it up */
1627 mov dword ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
1633 lea eax, [ebp+KTRAP_FRAME_ESP]
1638 /* Handle segment POP fault by setting it to 0 */
1641 mov dword ptr [edx], eax
1645 /* Do a trap exit */
1646 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoNotRestoreSegments, DoRestoreVolatiles, DoRestoreEverything
1650 /* If the previous mode was kernel, raise a fatal exception */
1652 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1653 jz _KiSystemFatalException
1655 /* Get the process and check which CS this came from */
1656 mov ebx, fs:[KPCR_CURRENT_THREAD]
1657 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
1658 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1661 /* Check if this is a VDM */
1662 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1665 /* Enable interrupts and check if we have an error code */
1667 cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
1669 jmp CheckPrivilegedInstruction
1672 /* Update EIP (will be updated below again) */
1673 add dword ptr [ebp+KTRAP_FRAME_EIP], 1
1676 /* Clear the segment, update EIP and ESP */
1677 mov dword ptr [edx], 0
1678 add dword ptr [ebp+KTRAP_FRAME_EIP], 1
1679 add dword ptr [ebp+KTRAP_FRAME_ESP], 4
1680 jmp _Kei386EoiHelper@0
1683 /* Check if this is a VDM */
1684 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1685 jz CheckPrivilegedInstruction
1687 /* Bring interrupts back */
1690 /* Check what kind of instruction this is */
1691 mov eax, [ebp+KTRAP_FRAME_EIP]
1694 /* FIXME: Check for BOP4 */
1696 /* Check if this is POP ES */
1698 add edx, KTRAP_FRAME_ES
1702 /* Check if this is POP FS */
1703 add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
1707 /* Check if this is POP GS */
1708 add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
1712 CheckPrivilegedInstruction:
1713 /* Bring interrupts back */
1716 /* Setup a SEH handler */
1718 push offset _KiTrapExceptHandler
1719 push fs:[KPCR_EXCEPTION_LIST]
1720 mov fs:[KPCR_EXCEPTION_LIST], esp
1723 mov esi, [ebp+KTRAP_FRAME_EIP]
1725 /* Setup loop count */
1729 /* Save loop count */
1732 /* Get the instruction */
1735 /* Now lookup in the prefix table */
1737 mov edi, offset _KiTrapPrefixTable
1740 /* Restore loop count */
1743 /* If it's not a prefix byte, check other instructions */
1750 /* FIXME: Check if it's a HLT */
1752 /* Check if the instruction has two bytes */
1760 /* Get EFLAGS and IOPL */
1761 mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
1765 /* Check the CS's RPL mask */
1766 mov ecx, [ebp+KTRAP_FRAME_CS]
1771 CheckPrivilegedInstruction2:
1772 /* Check if this is a CLI or STI */
1774 je IsPrivInstruction
1776 je IsPrivInstruction
1778 /* Setup I/O table lookup */
1780 mov edi, offset _KiTrapIoTable
1782 /* Loopup in the table */
1786 /* FIXME: Check IOPM!!! */
1789 /* Cleanup the SEH frame */
1790 pop fs:[KPCR_EXCEPTION_LIST]
1793 /* Setup the exception */
1794 mov ebx, [ebp+KTRAP_FRAME_EIP]
1795 mov eax, STATUS_PRIVILEGED_INSTRUCTION
1796 jmp _DispatchNoParam
1799 /* Cleanup the SEH frame */
1800 pop fs:[KPCR_EXCEPTION_LIST]
1804 /* Setup the exception */
1805 mov ebx, [ebp+KTRAP_FRAME_EIP]
1807 mov eax, STATUS_ACCESS_VIOLATION
1808 jmp _DispatchTwoParam
1816 Dr_kit14: DR_TRAP_FIXUP
1817 V86_kit14: V86_TRAP_FIXUP
1823 /* Check if we have a VDM alert */
1824 cmp dword ptr fs:[KPCR_VDM_ALERT], 0
1827 /* Get the current thread */
1828 mov edi, fs:[KPCR_CURRENT_THREAD]
1830 /* Get the stack address of the frame */
1831 lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
1832 sub eax, [edi+KTHREAD_INITIAL_STACK]
1835 /* This isn't the base frame, check if it's the second */
1836 cmp eax, -KTRAP_FRAME_EFLAGS
1839 /* Check if we have a TEB */
1840 mov eax, fs:[KPCR_TEB]
1844 /* Fixup the frame */
1851 /* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
1852 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
1855 /* Enable interrupts and check if we got here with interrupts disabled */
1857 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
1861 /* Send trap frame and check if this is kernel-mode or usermode */
1863 mov eax, [ebp+KTRAP_FRAME_CS]
1867 /* Send faulting address and check if this is read or write */
1869 mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
1873 /* Call the access fault handler */
1874 call _MmAccessFault@16
1878 /* Access fault handled, return to caller */
1879 jmp _Kei386EoiHelper@0
1882 /* First check if this is a fault in the S-LIST functions */
1883 mov ecx, offset _ExpInterlockedPopEntrySListFault@0
1884 cmp [ebp+KTRAP_FRAME_EIP], ecx
1887 /* Check if this is a fault in the syscall handler */
1888 mov ecx, offset CopyParams
1889 cmp [ebp+KTRAP_FRAME_EIP], ecx
1891 mov ecx, offset ReadBatch
1892 cmp [ebp+KTRAP_FRAME_EIP], ecx
1897 jmp _Kei386EoiHelper@0
1902 jmp _Kei386EoiHelper@0
1904 /* Check if the fault occured in a V86 mode */
1906 mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
1909 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1912 /* Check if the fault occured in a VDM */
1913 mov esi, fs:[KPCR_CURRENT_THREAD]
1914 mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
1915 cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
1918 /* Check if we this was in kernel-mode */
1919 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1921 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1928 /* Save EIP and check what kind of status failure we got */
1930 mov esi, [ebp+KTRAP_FRAME_EIP]
1931 cmp eax, STATUS_ACCESS_VIOLATION
1933 cmp eax, STATUS_GUARD_PAGE_VIOLATION
1935 cmp eax, STATUS_STACK_OVERFLOW
1938 /* Setup an in-page exception to dispatch */
1944 mov eax, STATUS_IN_PAGE_ERROR
1945 call _CommonDispatchException
1948 /* Use more proper status code */
1949 mov eax, KI_EXCEPTION_ACCESS_VIOLATION
1952 /* Setup a normal page fault exception */
1956 jmp _DispatchTwoParam
1964 /* This is completely illegal, bugcheck the system */
1970 push IRQL_NOT_LESS_OR_EQUAL
1971 call _KeBugCheckWithTf@24
1975 /* FIXME: NOT SUPPORTED */
1980 Dr_kit15: DR_TRAP_FIXUP
1981 V86_kit15: V86_TRAP_FIXUP
1983 /* Push error code */
1990 /* Raise a fatal exception */
1992 jmp _KiSystemFatalException
1996 Dr_kit16: DR_TRAP_FIXUP
1997 V86_kit16: V86_TRAP_FIXUP
1999 /* Push error code */
2005 /* Check if this is the NPX Thread */
2006 mov eax, fs:[KPCR_CURRENT_THREAD]
2007 cmp eax, fs:[KPCR_NPX_THREAD]
2009 /* Get the initial stack and NPX frame */
2010 mov ecx, [eax+KTHREAD_INITIAL_STACK]
2011 lea ecx, [ecx-NPX_FRAME_LENGTH]
2013 /* If this is a valid fault, handle it */
2016 /* Otherwise, re-enable interrupts and set delayed error */
2018 or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
2019 jmp _Kei386EoiHelper@0
2023 Dr_kit17: DR_TRAP_FIXUP
2024 V86_kit17: V86_TRAP_FIXUP
2026 /* Push error code */
2032 /* FIXME: ROS Doesn't handle alignment faults yet */
2034 jmp _KiSystemFatalException
2037 .func KiSystemFatalException
2038 _KiSystemFatalException:
2040 /* Push the trap frame */
2043 /* Push empty parameters */
2048 /* Push trap number and bugcheck code */
2050 push UNEXPECTED_KERNEL_MODE_TRAP
2051 call _KeBugCheckWithTf@24
2055 .func KiCoprocessorError@0
2056 _KiCoprocessorError@0:
2058 /* Get the NPX Thread's Initial stack */
2059 mov eax, [fs:KPCR_NPX_THREAD]
2060 mov eax, [eax+KTHREAD_INITIAL_STACK]
2062 /* Make space for the FPU Save area */
2063 sub eax, SIZEOF_FX_SAVE_AREA
2065 /* Set the CR0 State */
2066 mov dword ptr [eax+FN_CR0_NPX_STATE], 8
2073 /* Return to caller */
2077 .func Ki16BitStackException
2078 _Ki16BitStackException:
2084 /* Go to kernel mode thread stack */
2085 mov eax, fs:[KPCR_CURRENT_THREAD]
2086 add esp, [eax+KTHREAD_INITIAL_STACK]
2088 /* Switch to good stack segment */
2092 /* UNEXPECTED INTERRUPT HANDLERS **********************************************/
2094 .globl _KiStartUnexpectedRange@0
2095 _KiStartUnexpectedRange@0:
2097 GENERATE_INT_HANDLERS
2099 .globl _KiEndUnexpectedRange@0
2100 _KiEndUnexpectedRange@0:
2101 jmp _KiUnexpectedInterruptTail
2103 .func KiUnexpectedInterruptTail
2104 V86_kui: V86_TRAP_FIXUP
2105 Dr_kui: DR_TRAP_FIXUP
2106 _KiUnexpectedInterruptTail:
2108 /* Enter interrupt trap */
2109 INT_PROLOG kui, DoNotPushFakeErrorCode
2111 /* Increase interrupt count */
2112 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
2114 /* Put vector in EBX and make space for KIRQL */
2118 /* Begin interrupt */
2122 call _HalBeginSystemInterrupt@12
2124 /* Check if it was spurious or not */
2128 /* Spurious, ignore it */
2130 jmp _Kei386EoiHelper2ndEntry
2133 /* Unexpected interrupt, print a message on debug builds */
2136 push offset _UnexpectedMsg
2141 /* Exit the interrupt */
2144 call _HalEndSystemInterrupt@8
2145 jmp _Kei386EoiHelper@0
2148 .globl _KiUnexpectedInterrupt
2149 _KiUnexpectedInterrupt:
2151 /* Bugcheck with invalid interrupt code */
2152 push TRAP_CAUSE_UNKNOWN
2155 /* INTERRUPT HANDLERS ********************************************************/
2157 .func KiDispatchInterrupt@0
2158 _KiDispatchInterrupt@0:
2160 /* Get the PCR and disable interrupts */
2161 mov ebx, [fs:KPCR_SELF]
2164 /* Check if we have to deliver DPCs, timers, or deferred threads */
2165 mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
2166 or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
2167 or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
2170 /* Save stack pointer and exception list, then clear it */
2172 push dword ptr [ebx+KPCR_EXCEPTION_LIST]
2173 mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
2175 /* Save the stack and switch to the DPC Stack */
2177 //mov esp, [ebx+KPCR_PRCB_DPC_STACK]
2181 mov ecx, [ebx+KPCR_PRCB]
2182 call @KiRetireDpcList@4
2184 /* Restore stack and exception list */
2186 pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
2191 /* Re-enable interrupts */
2194 /* Check if we have quantum end */
2195 cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
2198 /* Check if we have a thread to swap to */
2199 cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
2202 /* Make space on the stack to save registers */
2208 /* Get the current thread */
2209 mov edi, [ebx+KPCR_CURRENT_THREAD]
2212 #error SMP Interrupt not handled!
2215 /* Get the next thread and clear it */
2216 mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
2217 and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
2219 /* Set us as the current running thread */
2220 mov [ebx+KPCR_CURRENT_THREAD], esi
2221 mov byte ptr [esi+KTHREAD_STATE], Running
2222 mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
2224 /* Put thread in ECX and get the PRCB in EDX */
2226 lea edx, [ebx+KPCR_PRCB_DATA]
2227 call @KiQueueReadyThread@8
2229 /* Set APC_LEVEL and do the swap */
2231 call @KiSwapContextInternal@0
2233 /* Restore registers */
2244 /* Disable quantum end and process it */
2245 mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
2246 call _KiQuantumEnd@0
2250 .func KiInterruptTemplate
2251 V86_kit: V86_TRAP_FIXUP
2252 Dr_kit: DR_TRAP_FIXUP
2253 _KiInterruptTemplate:
2255 /* Enter interrupt trap */
2256 INT_PROLOG kit, DoPushFakeErrorCode
2259 _KiInterruptTemplate2ndDispatch:
2260 /* Dummy code, will be replaced by the address of the KINTERRUPT */
2263 _KiInterruptTemplateObject:
2264 /* Dummy jump, will be replaced by the actual jump */
2265 jmp _KeSynchronizeExecution@12
2267 _KiInterruptTemplateDispatch:
2268 /* Marks the end of the template so that the jump above can be edited */
2270 .func KiChainedDispatch2ndLvl@0
2271 _KiChainedDispatch2ndLvl@0:
2273 /* Not yet supported */
2277 .func KiChainedDispatch@0
2278 _KiChainedDispatch@0:
2280 /* Increase interrupt count */
2281 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
2283 /* Save trap frame */
2286 /* Save vector and IRQL */
2287 mov eax, [edi+KINTERRUPT_VECTOR]
2288 mov ecx, [edi+KINTERRUPT_IRQL]
2294 /* Begin interrupt */
2298 call _HalBeginSystemInterrupt@12
2300 /* Check if it was handled */
2304 /* Call the 2nd-level handler */
2305 call _KiChainedDispatch2ndLvl@0
2307 /* Exit the interrupt */
2310 call _HalEndSystemInterrupt@8
2311 jmp _Kei386EoiHelper@0
2314 .func KiInterruptDispatch@0
2315 _KiInterruptDispatch@0:
2317 /* Increase interrupt count */
2318 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
2320 /* Save trap frame */
2323 /* Save vector and IRQL */
2324 mov eax, [edi+KINTERRUPT_VECTOR]
2325 mov ecx, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
2331 /* Begin interrupt */
2335 call _HalBeginSystemInterrupt@12
2337 /* Check if it was handled */
2341 /* Acquire the lock */
2343 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
2344 ACQUIRE_SPINLOCK(esi, IntSpin)
2347 mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
2350 call [edi+KINTERRUPT_SERVICE_ROUTINE]
2352 /* Release the lock */
2353 RELEASE_SPINLOCK(esi)
2355 /* Exit the interrupt */
2357 call _HalEndSystemInterrupt@8
2358 jmp _Kei386EoiHelper@0
2361 /* Exit the interrupt */
2363 jmp _Kei386EoiHelper@0
2367 SPIN_ON_LOCK esi, GetIntLock