2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/include/i386/asmmacro.S
5 * PURPOSE: Assembly Macros for Spinlocks and common Trap Code
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
13 // Arguments for TRAP_EPILOG
14 #define FromSystemCall 1
15 #define DoRestorePreviousMode 1
16 #define DoRestoreEverything 1
17 #define DoRestoreSegments 1
18 #define DoRestoreVolatiles 1
19 #define DoPushFakeErrorCode 1
21 #define DoFixupAbios 1
22 #define NotFromSystemCall 0
23 #define DoNotRestorePreviousMode 0
24 #define DoNotRestoreEverything 0
25 #define DoNotRestoreSegments 0
26 #define DoNotRestoreVolatiles 0
27 #define DoNotPushFakeErrorCode 0
28 #define DoNotFixupV86 0
29 #define DoNotFixupAbios 0
32 #define INT_32_DPL0 0x8E00
33 #define INT_32_DPL3 0xEE00
35 .intel_syntax noprefix
38 // These macros are inlined equivalents of KiAcquire/ReleaseSpinlock, that is,
39 // they will not be compiled into non-SMP builds. Usage is as follows:
43 // ACQUIRE_SPINLOCK(reg, .spin)
44 // <thread-safe code here>
45 // RELEASE_SPINLOCK(reg)
50 // <any necessary steps to be able to jump back safely>
51 / SPIN_ON_LOCK(reg, .BeginYourFunction)
56 #define ACQUIRE_SPINLOCK(x, y) \
57 lock bts dword ptr [x], 0; \
59 #define RELEASE_SPINLOCK(x) mov byte ptr [x], 0
60 #define SPIN_ON_LOCK(x, y) \
62 test dword ptr [x], 1; \
68 #define ACQUIRE_SPINLOCK(x, y)
69 #define RELEASE_SPINLOCK(x)
73 // @name UNHANDLED_PATH
86 /* Print debug message */
88 push offset _UnhandledMsg
92 /* Loop indefinitely */
99 // This macro creates an IDT entry for the given handler
102 // Pointer to the IDT handler
105 // Descriptor Bits to associate
109 .macro idt Handler, Bits
116 // @name GENERATE_IDT_STUB
118 // This macro creates an IDT entry for an unexpected interrupt handler.
124 .macro GENERATE_IDT_STUB Number
125 idt _KiUnexpectedInterrupt&Number, INT_32_DPL0
129 // @name GENERATE_IDT_STUBS
131 // This macro creates unexpected interrupt IDT entries.
138 .macro GENERATE_IDT_STUBS
147 // @name GENERATE_INT_HANDLER
149 // This macro creates an unexpected interrupt handler.
155 .macro GENERATE_INT_HANDLER Number
156 .func KiUnexpectedInterrupt&Number
157 _KiUnexpectedInterrupt&Number:
158 push PRIMARY_VECTOR_BASE + Number
159 jmp _KiEndUnexpectedRange@0
164 // @name GENERATE_INT_HANDLERS
166 // This macro creates the unexpected interrupt handlers.
173 .macro GENERATE_INT_HANDLERS
176 GENERATE_INT_HANDLER %i
182 // @name INVALID_V86_OPCODE
184 // This macro creates one or more entries for unhandled V86 Opcodes
185 // in the V86 Opcode Table.
188 // Number of entries to generate.
192 .macro INVALID_V86_OPCODE count
199 // @name INVALID_V86_OPCODE
201 // This macro prints out visible message and hangs the computer.
205 // @remark Temporary debugging use.
207 .macro UNHANDLED_V86_OPCODE
208 /* Print debug message, breakpoint and freeze */
210 push offset V86DebugMsg
219 // This macro contains out-of-line code for various Trap Frame Fixups, such as:
221 // - DR Fixup: Loads and restores DR registers.
222 // - V86 Fixup: Loads and restores V86 segments.
223 // - ABIOS Fixup: Loads and restores the ABIOS state and stack.
227 // @remark ebp = PKTRAP_FRAME
229 .macro TRAP_FIXUPS Label, EndLabel, V86Fix, AbiosFix
232 /* Check if this was V86 mode */
233 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
236 /* Check if it was user mode */
237 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
247 mov [ebp+KTRAP_FRAME_DR0], ebx
248 mov [ebp+KTRAP_FRAME_DR1], ecx
249 mov [ebp+KTRAP_FRAME_DR2], edi
257 mov [ebp+KTRAP_FRAME_DR3], ebx
258 mov [ebp+KTRAP_FRAME_DR6], ecx
259 mov [ebp+KTRAP_FRAME_DR7], edi
266 mov edi, fs:[KPCR_PRCB]
269 mov ebx, [edi+KPRCB_DR0]
270 mov ecx, [edi+KPRCB_DR1]
277 mov ebx, [edi+KPRCB_DR2]
278 mov ecx, [edi+KPRCB_DR3]
285 mov ebx, [edi+KPRCB_DR6]
286 mov ecx, [edi+KPRCB_DR7]
301 /* Get V86 segment registers */
302 mov eax, [ebp+KTRAP_FRAME_V86_FS]
303 mov ebx, [ebp+KTRAP_FRAME_V86_GS]
304 mov ecx, [ebp+KTRAP_FRAME_V86_ES]
305 mov edx, [ebp+KTRAP_FRAME_V86_DS]
307 /* Restore them into Protected Mode trap frame */
308 mov [ebp+KTRAP_FRAME_FS], ax
309 mov [ebp+KTRAP_FRAME_GS], bx
310 mov [ebp+KTRAP_FRAME_ES], cx
311 mov [ebp+KTRAP_FRAME_DS], dx
313 /* Go back to mainline code */
319 // @name SET_TF_DEBUG_HEADER
321 // This macro sets up the debug header in the trap frame.
325 // @remark ebp = PKTRAP_FRAME.
326 // edi/ebx = Have been saved and can be used.
328 .macro SET_TF_DEBUG_HEADER
329 /* Get the Debug Trap Frame EBP/EIP */
330 mov ebx, [ebp+KTRAP_FRAME_EBP]
331 mov edi, [ebp+KTRAP_FRAME_EIP]
333 /* Write the debug data */
334 mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx
335 mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
336 mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx
337 mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
341 // @name CHECK_FOR_APC_DELIVER
343 // This macro checks if the trapframe indicates a return to user-mode,
344 // and, if so, checks if user-mode APCs should be delivered.
346 // @param PreserveEax
347 // Determines if EAX should be preserved. Implies that the segment
348 // registers will also be saved.
350 // @remark ebp = PKTRAP_FRAME.
351 // ebx = Saved and will be used.
353 .macro CHECK_FOR_APC_DELIVER PreserveEax
354 /* Check for V86 mode */
355 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
358 /* Deliver APCs only if we were called from user mode */
359 test byte ptr [ebp+KTRAP_FRAME_CS], 1
362 /* Get the current thread */
364 mov ebx, PCR[KPCR_CURRENT_THREAD]
366 /* Make it non-alerted */
367 mov byte ptr [ebx+KTHREAD_ALERTED], 0
369 /* And only if any are actually pending */
370 cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
373 /* Save pointer to Trap Frame */
377 /* Save some stuff that raising IRQL will kill */
378 mov [ebx+KTRAP_FRAME_EAX], eax
379 mov dword ptr [ebx+KTRAP_FRAME_FS], KGDT_R3_TEB + RPL_MASK
380 mov dword ptr [ebx+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
381 mov dword ptr [ebx+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
382 mov dword ptr [ebx+KTRAP_FRAME_GS], 0
385 /* Raise IRQL to APC_LEVEL */
397 call _KiDeliverApc@12
399 /* Return to old IRQL */
403 /* Restore EAX (only in volatile case) */
405 mov eax, [ebx+KTRAP_FRAME_EAX]
415 // This macro creates a standard trap entry prologue.
416 // It should be used for entry into any kernel trap (KiTrapXx), but not for
417 // system calls, which require special handling.
420 // Identifying name of the caller function; will be used to append
421 // to the name V86 and DR helper functions, which must already exist.
423 // @remark Use as follows:
425 // /* Push fake error code */
428 // /* Enter common prologue */
432 // <Your Trap Code Here>
434 .macro TRAP_PROLOG Label EndLabel
435 /* Just to be safe, clear out the HIWORD, since it's reserved */
436 mov word ptr [esp+2], 0
438 /* Save the non-volatiles */
444 /* Save FS and set it to PCR */
450 /* Save exception list and bogus previous mode */
451 push fs:[KPCR_EXCEPTION_LIST]
454 /* Save volatiles and segment registers */
462 /* Set the R3 data segment */
463 mov ax, KGDT_R3_DATA + RPL_MASK
465 /* Skip debug registers and debug stuff */
468 /* Load the segment registers */
474 /* Check if this interrupt happened in 16-bit mode */
476 jb _Ki16BitStackException
481 /* Check if this was from V86 Mode */
482 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
486 /* Get current thread */
487 mov ecx, fs:[KPCR_CURRENT_THREAD]
491 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
493 /* Check if the thread was being debugged */
494 test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
497 /* Set the Trap Frame Debug Header */
505 // This macro creates a standard interrupt entry prologue.
506 // It should be used for entry into any interrupt, including software.
509 // Identifying name of the caller function; will be used to append
510 // to the name V86, ABIOS and DR helper functions, which must exist.
512 // @remark For software interrupts, make sure that a fake INT stack is created.
514 .macro INT_PROLOG Label EndLabel FakeErrorCode
517 /* Save fake error code */
521 /* Save the non-volatiles */
527 /* Skip debug registers and other stuff */
534 mov [esp+KTRAP_FRAME_EAX], eax
535 mov [esp+KTRAP_FRAME_ECX], ecx
536 mov [esp+KTRAP_FRAME_EDX], edx
537 mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
539 /* Check if this was from V86 Mode */
540 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
543 /* Check if this was kernel mode */
545 cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
549 mov word ptr [esp+KTRAP_FRAME_FS], fs
550 mov word ptr [esp+KTRAP_FRAME_DS], ds
551 mov word ptr [esp+KTRAP_FRAME_ES], es
552 mov [esp+KTRAP_FRAME_GS], gs
554 /* Load the segment registers (use OVERRIDE (0x66)) */
556 mov eax, KGDT_R3_DATA | RPL_MASK
565 /* Get the previous exception list */
566 mov ebx, fs:[KPCR_EXCEPTION_LIST]
568 /* Set the exception handler chain terminator */
569 mov dword ptr fs:[KPCR_EXCEPTION_LIST], -1
571 /* Save the previous exception list */
572 mov [esp+KTRAP_FRAME_EXCEPTION_LIST], ebx
575 /* Setup the 16-bit stack */
576 lea eax, [esp+KTRAP_FRAME_ERROR_CODE]
577 lea ecx, [esp+KTRAP_FRAME_EIP]
582 /* Check if this is the ABIOS stack */
583 /* cmp esp, 0x10000*/
586 /* Delete error code */
587 and dword ptr [esp+KTRAP_FRAME_ERROR_CODE], 0
589 /* Get the current thread and clear direction flag */
590 mov ecx, PCR[KPCR_CURRENT_THREAD]
594 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
596 /* Check if the thread was being debugged */
597 test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
604 /* Save DR registers if needed */
607 /* Set the trap frame debug header */
613 // @name SYSCALL_PROLOG
615 // This macro creates a system call entry prologue.
616 // It should be used for entry into any fast-system call (KiGetTickCount,
617 // KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
621 // Unique label identifying the name of the caller function; will be
622 // used to append to the name of the DR helper function, which must
627 .macro SYSCALL_PROLOG Label EndLabel
628 /* Create a trap frame */
636 /* Load PCR Selector into fs */
641 /* Get a pointer to the current thread */
642 mov esi, PCR[KPCR_CURRENT_THREAD]
644 /* Save the previous exception list */
645 push PCR[KPCR_EXCEPTION_LIST]
647 /* Set the exception handler chain terminator */
648 mov dword ptr PCR[KPCR_EXCEPTION_LIST], -1
650 /* Save the old previous mode */
651 push [esi+KTHREAD_PREVIOUS_MODE]
653 /* Skip the other registers */
656 /* Set the new previous mode based on the saved CS selector */
659 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], bl
661 /* Go on the Kernel stack frame */
664 /* Save the old trap frame pointer where EDX would be saved */
665 mov ebx, [esi+KTHREAD_TRAP_FRAME]
666 mov [ebp+KTRAP_FRAME_EDX], ebx
669 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
671 /* Check if the thread was being debugged */
672 test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
674 /* Set the thread's trap frame and clear direction flag */
675 mov [esi+KTHREAD_TRAP_FRAME], ebp
678 /* Save DR registers if needed */
681 /* Set the trap frame debug header */
685 /* Enable interrupts */
690 // @name FASTCALL_PROLOG
695 // Unique label identifying the name of the caller function; will be
696 // used to append to the name of the DR helper function, which must
701 .macro FASTCALL_PROLOG Label EndLabel
703 /* Set user selector */
704 mov ecx, KGDT_R3_DATA | RPL_MASK
710 /* Set DS/ES to User Selector */
714 /* Set the current stack to Kernel Stack */
715 mov ecx, PCR[KPCR_TSS]
716 mov esp, [ecx+KTSS_ESP0]
718 /* Set up a fake INT Stack. */
719 push KGDT_R3_DATA + RPL_MASK
720 push edx /* Ring 3 SS:ESP */
721 pushf /* Ring 3 EFLAGS */
722 push 2 /* Ring 0 EFLAGS */
723 add edx, 8 /* Skip user parameter list */
724 popf /* Set our EFLAGS */
725 or dword ptr [esp], EFLAGS_INTERRUPT_MASK /* Re-enable IRQs in EFLAGS, to fake INT */
726 push KGDT_R3_CODE + RPL_MASK
727 push dword ptr ds:KUSER_SHARED_SYSCALL_RET
729 /* Setup the Trap Frame stack */
735 push KGDT_R3_TEB + RPL_MASK
737 /* Save pointer to our PCR */
738 mov ebx, PCR[KPCR_SELF]
740 /* Get a pointer to the current thread */
741 mov esi, [ebx+KPCR_CURRENT_THREAD]
743 /* Set the exception handler chain terminator */
744 push [ebx+KPCR_EXCEPTION_LIST]
745 mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
747 /* Use the thread's stack */
748 mov ebp, [esi+KTHREAD_INITIAL_STACK]
750 /* Push previous mode */
753 /* Skip the other registers */
756 /* Make space for us on the stack */
759 /* Write the previous mode */
760 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
767 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
769 /* Check if the thread was being debugged */
770 test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
772 /* Set the thread's trap frame */
773 mov [esi+KTHREAD_TRAP_FRAME], ebp
775 /* Save DR registers if needed */
778 /* Set the trap frame debug header */
782 /* Enable interrupts */
787 // @name V86_TRAP_PROLOG
789 // This macro creates a V86 Trap entry prologue.
790 // It should be used for entry into any fast-system call (KiGetTickCount,
791 // KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
795 // Unique label identifying the name of the caller function; will be
796 // used to append to the name of the DR helper function, which must
801 .macro V86_TRAP_PROLOG Label EndLabel
803 /* Skip everything to the error code */
804 sub esp, KTRAP_FRAME_ERROR_CODE
806 /* Clear the error code */
807 mov word ptr [esp+KTRAP_FRAME_ERROR_CODE+2], 0
809 /* Save the registers we'll trample */
810 mov [esp+KTRAP_FRAME_EBX], ebx
811 mov [esp+KTRAP_FRAME_EAX], eax
812 mov [esp+KTRAP_FRAME_EBP], ebp
813 mov [esp+KTRAP_FRAME_ESI], esi
814 mov [esp+KTRAP_FRAME_EDI], edi
816 /* Save PCR and Ring 3 segments */
818 mov eax, KGDT_R3_DATA + RPL_MASK
820 /* Save ECX and EDX too */
821 mov [esp+KTRAP_FRAME_ECX], ecx
822 mov [esp+KTRAP_FRAME_EDX], edx
824 /* Set debugging markers */
825 mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
826 mov dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
828 /* Now set segments (use OVERRIDE, 0x66) */
836 /* Set the trap frame in the stack and clear the direction flag */
840 /* Save the exception list */
841 mov eax, fs:[KPCR_EXCEPTION_LIST]
842 mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax
844 /* Check if we need debugging */
846 test eax, ~DR7_RESERVED_MASK
847 mov [esp+KTRAP_FRAME_DR7], eax
854 // @name V86_TRAP_EPILOG
856 // This macro creates an epilogue for leaving V86 traps
862 .macro V86_TRAP_EPILOG
864 /* Get the current thread and make it unalerted */
866 mov ebx, PCR[KPCR_CURRENT_THREAD]
867 mov byte ptr [ebx+KTHREAD_ALERTED], 0
869 /* Check if it has User-mode APCs pending */
870 cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
873 /* It doesn't, pop the frame */
874 add esp, KTRAP_FRAME_EDX
879 /* Check if DR registers should be restored */
880 test dword ptr [ebp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
883 /* Finish popping the rest of the frame, and return to P-mode */
897 mov esi, [ebp+KTRAP_FRAME_DR0]
898 mov edi, [ebp+KTRAP_FRAME_DR1]
903 /* Get DR2 and load DR0-2 */
904 mov ebx, [ebp+KTRAP_FRAME_DR2]
910 mov esi, [ebp+KTRAP_FRAME_DR0]
911 mov edi, [ebp+KTRAP_FRAME_DR1]
912 mov ebx, [ebp+KTRAP_FRAME_DR7]
922 /* Raise to APC level */
926 /* Save KIRQL and deliver APCs */
932 call _KiDeliverApc@12
939 /* Check if we're not in V86 anymore */
940 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
947 // This macro creates an epilogue for leaving any system trap.
948 // It is used for exiting system calls, exceptions, interrupts and generic
952 // Specifies whether this trap will exit a system call. If so, special
953 // code will be assembled to potentially use SYSEXIT instead of IRETD.
955 // @param RestorePreviousMode
956 // Specifies if the previous mode should be restored.
958 // @param RestoreSegments
959 // Specifies if the segment registers should be restored.
961 // @param RestoreVolatiles
962 // Specifies if the volatile registers should be restored.
964 // @param RestoreAllRegs
965 // Specifies if volatiles and segments should both be restored.
969 .macro TRAP_EPILOG SystemCall, RestorePreviousMode, RestoreSegments, RestoreVolatiles, RestoreAllRegs
971 /* Assert the flags */
974 test edx, EFLAGS_INTERRUPT_MASK
977 /* Assert the stack */
981 /* Assert the trap frame */
985 sub dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
993 /* Assert exception list */
994 cmp dword ptr PCR[KPCR_EXCEPTION_LIST], 0
1003 /* Get exception list */
1004 mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
1007 /* Assert the saved exception list */
1015 mov PCR[KPCR_EXCEPTION_LIST], edx
1017 .if \RestorePreviousMode
1018 /* Get previous mode */
1019 mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
1022 /* Assert the saved previous mode */
1029 /* Restore the previous mode */
1030 mov esi, PCR[KPCR_CURRENT_THREAD]
1031 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
1035 /* Assert the saved previous mode */
1036 mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
1044 /* Check for debug registers */
1045 test dword ptr [esp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
1050 test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1053 /* Check if the frame was edited */
1054 test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
1058 /* Check the old mode */
1059 cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1060 bt word ptr [esp+KTRAP_FRAME_CS], 0
1065 .if \RestoreVolatiles
1066 /* Restore volatiles */
1067 mov edx, [esp+KTRAP_FRAME_EDX]
1068 mov ecx, [esp+KTRAP_FRAME_ECX]
1069 mov eax, [esp+KTRAP_FRAME_EAX]
1072 /* Check if we were called from kernel mode */
1073 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
1076 .if \RestoreSegments
1077 /* Restore segment registers */
1078 lea esp, [ebp+KTRAP_FRAME_GS]
1086 lea esp, [ebp+KTRAP_FRAME_FS]
1090 /* Skip debug information and unsaved registers */
1091 lea esp, [ebp+KTRAP_FRAME_EDI]
1097 /* Check for ABIOS */
1098 cmp word ptr [esp+8], 0x80
1101 /* Pop error code */
1105 /* Check if previous CS is from user-mode */
1106 test dword ptr [esp+4], 1
1108 /* It is, so use Fast Exit */
1111 /* Jump back to stub */
1123 /* Is SYSEXIT Supported/Wanted? */
1124 cmp dword ptr ss:[_KiFastSystemCallDisable], 0
1126 test dword ptr [esp+8], EFLAGS_TF
1129 /* Restore FS to TIB */
1130 mov ecx, KGDT_R3_TEB + RPL_MASK
1133 /* We will be cleaning up the stack ourselves */
1134 pop edx /* New Ring 3 EIP */
1135 add esp, 4 /* Skip Ring 3 DS */
1136 and dword ptr [esp], 0xfffffdff /* Remove EFLAGS_INTERRUPT_MASK from EFLAGS */
1137 popf /* Restore old EFLAGS */
1138 pop ecx /* Old Ring 3 SS:ESP */
1142 * ECX points to the old User Stack.
1143 * EDX points to the instruction to execute in usermode after the sysenter
1152 mov eax, [esp+KTRAP_FRAME_EAX]
1154 /* Skip registers */
1157 /* Restore segments and volatiles */
1164 /* Jump back to mainline code */
1170 /* Fix up the mask */
1171 add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
1179 /* Check if this was V86 mode */
1180 test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1183 /* Check if it was user mode */
1184 test word ptr [esp+KTRAP_FRAME_CS], MODE_MASK
1193 mov esi, [ebp+KTRAP_FRAME_DR0]
1194 mov edi, [ebp+KTRAP_FRAME_DR1]
1195 mov ebx, [ebp+KTRAP_FRAME_DR2]
1203 mov esi, [ebp+KTRAP_FRAME_DR3]
1204 mov edi, [ebp+KTRAP_FRAME_DR6]
1205 mov ebx, [ebp+KTRAP_FRAME_DR7]
1214 /* Restore real CS value */
1215 mov ebx, [esp+KTRAP_FRAME_TEMPCS]
1216 mov [esp+KTRAP_FRAME_CS], ebx
1219 * If ESP was modified, then a special interrupt exit stack
1220 * must be created to "update" ESP's value in a legal manner
1222 mov ebx, [esp+KTRAP_FRAME_TEMPESP]
1224 mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
1226 /* Copy Interrupt Stack */
1227 mov esi, [esp+KTRAP_FRAME_EFLAGS]
1229 mov esi, [esp+KTRAP_FRAME_CS]
1231 mov esi, [esp+KTRAP_FRAME_EIP]
1234 .if \RestoreVolatiles
1235 /* Restore volatiles */
1236 mov eax, [esp+KTRAP_FRAME_EAX]
1237 mov edx, [esp+KTRAP_FRAME_EDX]
1238 mov ecx, [esp+KTRAP_FRAME_ECX]
1242 add esp, KTRAP_FRAME_EDI
1254 // This macro creates an epilogue for leaving any system trap.
1255 // It is used for exiting system calls, exceptions, interrupts and generic
1258 // @param Spurious - TRUE if the interrupt was unexpected and spurious.
1262 .macro INT_EPILOG Spurious
1265 /* Just exit the trap */
1266 jmp _Kei386EoiHelper@0
1268 /* Disable interrupts */
1271 /* End the interrupt and do EOI */
1272 call _HalEndSystemInterrupt@8
1273 jmp _Kei386EoiHelper@0
1279 .macro VERIFY_INT Label
1280 /* Get the current time and mask it to 192 ticks */
1281 mov eax, _KeTickCount
1284 /* Check if we're in the same tick area */
1285 cmp eax, dword ptr [edi+KINTERRUPT_TICK_COUNT]
1289 /* If we got here, then our count is too large */
1290 dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT]
1295 .macro VERIFY_INT_END Label, Info
1298 /* Decrement the dispatch count and check if we should bug check */
1299 dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2]
1302 /* Update the tick count */
1304 mov [edi+KINTERRUPT_TICK_COUNT], eax
1308 /* Check if the debugger is enabled */
1309 cmp byte ptr __KdDebuggerEnabled, 0
1312 /* It isn't, bugcheck */
1315 push [edi+KINTERRUPT_SERVICE_CONTEXT]
1316 push [edi+KINTERRUPT_SERVICE_ROUTINE]
1317 push HARDWARE_INTERRUPT_STORM
1318 call _KeBugCheckEx@20
1321 /* Debugger enabled, do a debug print + break instead */
1322 push [edi+KINTERRUPT_SERVICE_ROUTINE]
1323 push offset _IsrOverflowMsg
1328 /* Breakpoint handled, get the new tick count */
1329 mov eax, _KeTickCount
1333 /* Reset tick count */
1334 mov dword ptr [edi+KINTERRUPT_TICK_COUNT], eax
1335 mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2], 64
1338 /* Put default overflow count and continue */
1339 mov ax, _KiISROverflow
1340 mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT], ax
1344 /* Check if we wrapped */
1346 cmp eax, [edi+KINTERRUPT_TICK_COUNT]
1349 /* We did, start over */
1350 mov eax, _KeTickCount
1356 /* We don't verify interrupts on retail builds */
1357 .macro VERIFY_INT Label
1359 .macro VERIFY_INT_END Label, Info