- Remove useless stack operations in KiInterruptDispatch that I used for debugging.
[reactos.git] / reactos / ntoskrnl / ke / i386 / trap.s
1 /*
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.
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <asm.h>
12 #include <internal/i386/asmmacro.S>
13 .intel_syntax noprefix
14
15 /* GLOBALS *******************************************************************/
16
17 .globl _KiIdt
18 _KiIdt:
19 /* This is the Software Interrupt Table that we handle in this file: */
20 idt _KiTrap0, INT_32_DPL0 /* INT 00: Divide Error (#DE) */
21 idt _KiTrap1, INT_32_DPL0 /* INT 01: Debug Exception (#DB) */
22 idt _KiTrap2, INT_32_DPL0 /* INT 02: NMI Interrupt */
23 idt _KiTrap3, INT_32_DPL3 /* INT 03: Breakpoint Exception (#BP) */
24 idt _KiTrap4, INT_32_DPL3 /* INT 04: Overflow Exception (#OF) */
25 idt _KiTrap5, INT_32_DPL0 /* INT 05: BOUND Range Exceeded (#BR) */
26 idt _KiTrap6, INT_32_DPL0 /* INT 06: Invalid Opcode Code (#UD) */
27 idt _KiTrap7, INT_32_DPL0 /* INT 07: Device Not Available (#NM) */
28 idt _KiTrap8, INT_32_DPL0 /* INT 08: Double Fault Exception (#DF) */
29 idt _KiTrap9, INT_32_DPL0 /* INT 09: RESERVED */
30 idt _KiTrap10, INT_32_DPL0 /* INT 0A: Invalid TSS Exception (#TS) */
31 idt _KiTrap11, INT_32_DPL0 /* INT 0B: Segment Not Present (#NP) */
32 idt _KiTrap12, INT_32_DPL0 /* INT 0C: Stack Fault Exception (#SS) */
33 idt _KiTrap13, INT_32_DPL0 /* INT 0D: General Protection (#GP) */
34 idt _KiTrap14, INT_32_DPL0 /* INT 0E: Page-Fault Exception (#PF) */
35 idt _KiTrap0F, INT_32_DPL0 /* INT 0F: RESERVED */
36 idt _KiTrap16, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF) */
37 idt _KiTrap17, INT_32_DPL0 /* INT 11: Align Check Exception (#AC) */
38 idt _KiTrap0F, INT_32_DPL0 /* INT 12: Machine Check Exception (#MC)*/
39 idt _KiTrap0F, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF) */
40 .rept 22
41 idt _KiTrap0F, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS */
42 .endr
43 idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler */
44 idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback Return */
45 idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */
46 idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */
47 idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */
48 idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */
49 GENERATE_IDT_STUBS /* INT 30-FF: UNEXPECTED INTERRUPTS */
50
51 /* System call entrypoints: */
52 .globl _KiFastCallEntry
53 .globl _KiSystemService
54
55 /* And special system-defined software traps: */
56 .globl _NtRaiseException@12
57 .globl _NtContinue@8
58
59 /* Interrupt template entrypoints */
60 .globl _KiInterruptTemplate
61 .globl _KiInterruptTemplateObject
62 .globl _KiInterruptTemplateDispatch
63
64 /* Chained and Normal generic interrupt handlers for 1st and 2nd level entry*/
65 .globl _KiChainedDispatch2ndLvl@0
66 .globl _KiInterruptDispatch@0
67 .globl _KiChainedDispatch@0
68
69 /* We implement the following trap exit points: */
70 .globl _KiServiceExit /* Exit from syscall */
71 .globl _KiServiceExit2 /* Exit from syscall with complete frame*/
72 .globl _Kei386EoiHelper@0 /* Exit from interrupt or H/W trap */
73 .globl _Kei386EoiHelper2ndEntry /* Exit from unexpected interrupt */
74
75 .globl _KiIdtDescriptor
76 _KiIdtDescriptor:
77 .short 0x800
78 .long _KiIdt
79
80 .globl _KiUnexpectedEntrySize
81 _KiUnexpectedEntrySize:
82 .long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
83
84 _UnexpectedMsg:
85 .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
86
87 Broken:
88 .asciz "\n\x7\x7!!! Broken TrapFrame. Magic: %08lx MagicB: %08lx!!!\n"
89
90 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
91
92 _KiGetTickCount:
93 _KiCallbackReturn:
94 _KiRaiseAssertion:
95 int 3
96
97 .func KiSystemService
98 _KiSystemService:
99
100 /* Enter the shared system call prolog */
101 SYSCALL_PROLOG
102
103 /* Jump to the actual handler */
104 jmp SharedCode
105 .endfunc
106
107 .func KiFastCallEntry
108 _KiFastCallEntry:
109
110 /* Set FS to PCR */
111 mov ecx, KGDT_R0_PCR
112 mov fs, cx
113
114 /* Set DS/ES to Kernel Selector */
115 mov ecx, KGDT_R0_DATA
116 mov ds, cx
117 mov es, cx
118
119 /* Set the current stack to Kernel Stack */
120 mov ecx, [fs:KPCR_TSS]
121 mov esp, ss:[ecx+KTSS_ESP0]
122
123 /* Set up a fake INT Stack. */
124 push KGDT_R3_DATA + RPL_MASK
125 push edx /* Ring 3 SS:ESP */
126 pushf /* Ring 3 EFLAGS */
127 push 2 /* Ring 0 EFLAGS */
128 add edx, 8 /* Skip user parameter list */
129 popf /* Set our EFLAGS */
130 or dword ptr [esp], EFLAGS_INTERRUPT_MASK /* Re-enable IRQs in EFLAGS, to fake INT */
131 push KGDT_R3_CODE + RPL_MASK
132 push KUSER_SHARED_SYSCALL_RET
133
134 /* Setup the Trap Frame stack */
135 push 0
136 push ebp
137 push ebx
138 push esi
139 push edi
140 push KGDT_R3_TEB + RPL_MASK
141
142 /* Save pointer to our PCR */
143 mov ebx, [fs:KPCR_SELF]
144
145 /* Get a pointer to the current thread */
146 mov esi, [ebx+KPCR_CURRENT_THREAD]
147
148 /* Set the exception handler chain terminator */
149 push [ebx+KPCR_EXCEPTION_LIST]
150 mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
151
152 /* Use the thread's stack */
153 mov ebp, [esi+KTHREAD_INITIAL_STACK]
154
155 /* Push previous mode */
156 push UserMode
157
158 /* Skip the other registers */
159 sub esp, 0x48
160
161 /* Hack: it seems that on VMWare someone damages ES/DS on exit. Investigate! */
162 mov dword ptr [esp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
163 mov dword ptr [esp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
164
165 /* Make space for us on the stack */
166 sub ebp, 0x29C
167
168 /* Write the previous mode */
169 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
170
171 /* Sanity check */
172 cmp ebp, esp
173 jnz BadStack
174
175 /* Flush DR7 */
176 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
177
178 /* Check if the thread was being debugged */
179 test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
180
181 /* Set the thread's trap frame */
182 mov [esi+KTHREAD_TRAP_FRAME], ebp
183
184 /* Save DR registers if needed */
185 //jnz Dr_FastCallDrSave
186
187 /* Set the trap frame debug header */
188 SET_TF_DEBUG_HEADER
189
190 /* Enable interrupts */
191 sti
192
193 SharedCode:
194
195 /*
196 * Find out which table offset to use. Converts 0x1124 into 0x10.
197 * The offset is related to the Table Index as such: Offset = TableIndex x 10
198 */
199 mov edi, eax
200 shr edi, SERVICE_TABLE_SHIFT
201 and edi, SERVICE_TABLE_MASK
202 mov ecx, edi
203
204 /* Now add the thread's base system table to the offset */
205 add edi, [esi+KTHREAD_SERVICE_TABLE]
206
207 /* Get the true syscall ID and check it */
208 mov ebx, eax
209 and eax, SERVICE_NUMBER_MASK
210 cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
211
212 /* Invalid ID, try to load Win32K Table */
213 jnb KiBBTUnexpectedRange
214
215 /* Check if this was Win32K */
216 cmp ecx, SERVICE_TABLE_TEST
217 jnz NotWin32K
218
219 /* Get the TEB */
220 mov ecx, [fs:KPCR_TEB]
221
222 /* Check if we should flush the User Batch */
223 xor ebx, ebx
224 or ebx, [ecx+TEB_GDI_BATCH_COUNT]
225 jz NotWin32K
226
227 /* Flush it */
228 push edx
229 push eax
230 //call [_KeGdiFlushUserBatch]
231 pop eax
232 pop edx
233
234 NotWin32K:
235 /* Increase total syscall count */
236 inc dword ptr fs:[KPCR_SYSTEM_CALLS]
237
238 #ifdef DBG
239 /* Increase per-syscall count */
240 mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
241 jecxz NoCountTable
242 inc dword ptr [ecx+eax*4]
243 #endif
244
245 /* Users's current stack frame pointer is source */
246 NoCountTable:
247 mov esi, edx
248
249 /* Allocate room for argument list from kernel stack */
250 mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
251 xor ecx, ecx
252 mov cl, [eax+ebx]
253
254 /* Get pointer to function */
255 mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
256 mov ebx, [edi+eax*4]
257
258 /* Allocate space on our stack */
259 sub esp, ecx
260
261 /* Set the size of the arguments and the destination */
262 shr ecx, 2
263 mov edi, esp
264
265 /* Make sure we're within the User Probe Address */
266 cmp esi, _MmUserProbeAddress
267 jnb AccessViolation
268
269 CopyParams:
270 /* Copy the parameters */
271 rep movsd
272
273 #ifdef DBG
274 /*
275 * The following lines are for the benefit of GDB. It will see the return
276 * address of the "call ebx" below, find the last label before it and
277 * thinks that that's the start of the function. It will then check to see
278 * if it starts with a standard function prolog (push ebp, mov ebp,esp1).
279 * When that standard function prolog is not found, it will stop the
280 * stack backtrace. Since we do want to backtrace into usermode, let's
281 * make GDB happy and create a standard prolog.
282 */
283 KiSystemService:
284 push ebp
285 mov ebp,esp
286 pop ebp
287 #endif
288
289 /* Do the System Call */
290 call ebx
291
292 AfterSysCall:
293 #ifdef DBG
294 /* Make sure the user-mode call didn't return at elevated IRQL */
295 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
296 jz SkipCheck
297 mov esi, eax /* We need to save the syscall's return val */
298 call _KeGetCurrentIrql@0
299 or al, al
300 jnz InvalidIrql
301 mov eax, esi /* Restore it */
302
303 /* Get our temporary current thread pointer for sanity check */
304 mov ecx, fs:[KPCR_CURRENT_THREAD]
305
306 /* Make sure that we are not attached and that APCs are not disabled */
307 mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
308 or dl, dl
309 jnz InvalidIndex
310 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
311 or edx, edx
312 jnz InvalidIndex
313 #endif
314
315 SkipCheck:
316
317 /* Deallocate the kernel stack frame */
318 mov esp, ebp
319
320 KeReturnFromSystemCall:
321
322 /* Get the Current Thread */
323 mov ecx, [fs:KPCR_CURRENT_THREAD]
324
325 /* Restore the old trap frame pointer */
326 mov edx, [ebp+KTRAP_FRAME_EDX]
327 mov [ecx+KTHREAD_TRAP_FRAME], edx
328 .endfunc
329
330 .func KiServiceExit
331 _KiServiceExit:
332 /* Disable interrupts */
333 cli
334
335 /* Check for, and deliver, User-Mode APCs if needed */
336 CHECK_FOR_APC_DELIVER 1
337
338 /* Hack for VMWare: Sometimes ES/DS seem to be invalid when returning to user-mode. Investigate! */
339 mov es, [ebp+KTRAP_FRAME_ES]
340 mov ds, [ebp+KTRAP_FRAME_DS]
341
342 /* Exit and cleanup */
343 TRAP_EPILOG FromSystemCall, DoRestorePreviousMode, DoNotRestoreSegments, DoNotRestoreVolatiles, DoRestoreEverything
344 .endfunc
345
346 KiBBTUnexpectedRange:
347
348 /* If this isn't a Win32K call, fail */
349 cmp ecx, SERVICE_TABLE_TEST
350 jne InvalidCall
351
352 /* Set up Win32K Table */
353 push edx
354 push ebx
355 call _PsConvertToGuiThread@0
356
357 /* Check return code */
358 or eax, eax
359
360 /* Restore registers */
361 pop eax
362 pop edx
363
364 /* Reset trap frame address */
365 mov ebp, esp
366 mov [esi+KTHREAD_TRAP_FRAME], ebp
367
368 /* Try the Call again, if we suceeded */
369 jz SharedCode
370
371 /*
372 * The Shadow Table should have a special byte table which tells us
373 * whether we should return FALSE, -1 or STATUS_INVALID_SYSTEM_SERVICE.
374 */
375
376 /* Get the table limit and base */
377 lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
378 mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
379 mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
380
381 /* Get the table address and add our index into the array */
382 lea edx, [edx+ecx*4]
383 and eax, SERVICE_NUMBER_MASK
384 add edx, eax
385
386 /* Find out what we should return */
387 movsx eax, byte ptr [edx]
388 or eax, eax
389
390 /* Return either 0 or -1, we've set it in EAX */
391 jle KeReturnFromSystemCall
392
393 /* Set STATUS_INVALID_SYSTEM_SERVICE */
394 mov eax, STATUS_INVALID_SYSTEM_SERVICE
395 jmp KeReturnFromSystemCall
396
397 InvalidCall:
398
399 /* Invalid System Call */
400 mov eax, STATUS_INVALID_SYSTEM_SERVICE
401 jmp KeReturnFromSystemCall
402
403 AccessViolation:
404
405 /* Check if this came from kernel-mode */
406 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
407
408 /* It's fine, go ahead with it */
409 jz CopyParams
410
411 /* Caller sent invalid parameters, fail here */
412 mov eax, STATUS_ACCESS_VIOLATION
413 jmp AfterSysCall
414
415 BadStack:
416
417 /* Restore ESP0 stack */
418 mov ecx, [fs:KPCR_TSS]
419 mov esp, ss:[ecx+KTSS_ESP0]
420
421 /* Generate V86M Stack for Trap 6 */
422 push 0
423 push 0
424 push 0
425 push 0
426
427 /* Generate interrupt stack for Trap 6 */
428 push KGDT_R3_DATA + RPL_MASK
429 push 0
430 push 0x20202
431 push KGDT_R3_CODE + RPL_MASK
432 push 0
433 jmp _KiTrap6
434
435 #ifdef DBG
436 InvalidIrql:
437 /* Save current IRQL */
438 push fs:[KPCR_IRQL]
439
440 /* Set us at passive */
441 mov dword ptr fs:[KPCR_IRQL], 0
442 cli
443
444 /* Bugcheck */
445 push 0
446 push 0
447 push eax
448 push ebx
449 push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
450 call _KeBugCheckEx@20
451
452 InvalidIndex:
453
454 /* Get the index and APC state */
455 movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
456 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
457
458 /* Bugcheck */
459 push 0
460 push edx
461 push eax
462 push ebx
463 push APC_INDEX_MISMATCH
464 call _KeBugCheckEx@20
465 ret
466 #endif
467
468 .func KiServiceExit2
469 _KiServiceExit2:
470
471 /* Disable interrupts */
472 cli
473
474 /* Check for, and deliver, User-Mode APCs if needed */
475 CHECK_FOR_APC_DELIVER 0
476
477 /* Exit and cleanup */
478 TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
479 .endfunc
480
481 .func Kei386EoiHelper@0
482 _Kei386EoiHelper@0:
483
484 /* Disable interrupts */
485 cli
486
487 /* Check for, and deliver, User-Mode APCs if needed */
488 CHECK_FOR_APC_DELIVER 0
489
490 /* Exit and cleanup */
491 _Kei386EoiHelper2ndEntry:
492 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
493 .endfunc
494
495 V86_Exit:
496 /* Move to EDX position */
497 add esp, KTRAP_FRAME_EDX
498
499 /* Restore volatiles */
500 pop edx
501 pop ecx
502 pop eax
503
504 /* Move to non-volatiles */
505 lea esp, [ebp+KTRAP_FRAME_EDI]
506 pop edi
507 pop esi
508 pop ebx
509 pop ebp
510
511 /* Skip error code and return */
512 add esp, 4
513 iret
514
515 AbiosExit:
516 /* Not yet supported */
517 int 3
518
519 .func KiDebugService
520 _KiDebugService:
521
522 /* Push error code */
523 push 0
524
525 /* Enter trap */
526 TRAP_PROLOG(kids)
527
528 /* Increase EIP so we skip the INT3 */
529 //inc dword ptr [ebp+KTRAP_FRAME_EIP]
530
531 /* Call debug service dispatcher */
532 mov eax, [ebp+KTRAP_FRAME_EAX]
533 mov ecx, [ebp+KTRAP_FRAME_ECX]
534 mov edx, [ebp+KTRAP_FRAME_EAX]
535
536 /* Check for V86 mode */
537 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
538 jnz NotUserMode
539
540 /* Check if this is kernel or user-mode */
541 test byte ptr [ebp+KTRAP_FRAME_CS], 1
542 jz CallDispatch
543 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
544 jnz NotUserMode
545
546 /* Re-enable interrupts */
547 VdmProc:
548 sti
549
550 /* Call the debug routine */
551 CallDispatch:
552 mov esi, ecx
553 mov edi, edx
554 mov edx, eax
555 mov ecx, 3
556 push edi
557 push esi
558 push edx
559 call _KdpServiceDispatcher@12
560
561 NotUserMode:
562
563 /* Get the current process */
564 mov ebx, [fs:KPCR_CURRENT_THREAD]
565 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
566
567 /* Check if this is a VDM Process */
568 //cmp dword ptr [ebx+KPROCESS_VDM_OBJECTS], 0
569 //jz VdmProc
570
571 /* Exit through common routine */
572 jmp _Kei386EoiHelper@0
573 .endfunc
574
575 .func NtRaiseException@12
576 _NtRaiseException@12:
577
578 /* NOTE: We -must- be called by Zw* to have the right frame! */
579 /* Push the stack frame */
580 push ebp
581
582 /* Get the current thread and restore its trap frame */
583 mov ebx, [fs:KPCR_CURRENT_THREAD]
584 mov edx, [ebp+KTRAP_FRAME_EDX]
585 mov [ebx+KTHREAD_TRAP_FRAME], edx
586
587 /* Set up stack frame */
588 mov ebp, esp
589
590 /* Get the Trap Frame in EBX */
591 mov ebx, [ebp+0]
592
593 /* Get the exception list and restore */
594 mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
595 mov [fs:KPCR_EXCEPTION_LIST], eax
596
597 /* Get the parameters */
598 mov edx, [ebp+16] /* Search frames */
599 mov ecx, [ebp+12] /* Context */
600 mov eax, [ebp+8] /* Exception Record */
601
602 /* Raise the exception */
603 push edx
604 push ebx
605 push 0
606 push ecx
607 push eax
608 call _KiRaiseException@20
609
610 /* Restore trap frame in EBP */
611 pop ebp
612 mov esp, ebp
613
614 /* Check the result */
615 or eax, eax
616 jz _KiServiceExit2
617
618 /* Restore debug registers too */
619 jmp _KiServiceExit
620 .endfunc
621
622 .func NtContinue@8
623 _NtContinue@8:
624
625 /* NOTE: We -must- be called by Zw* to have the right frame! */
626 /* Push the stack frame */
627 push ebp
628
629 /* Get the current thread and restore its trap frame */
630 mov ebx, [fs:KPCR_CURRENT_THREAD]
631 mov edx, [ebp+KTRAP_FRAME_EDX]
632 mov [ebx+KTHREAD_TRAP_FRAME], edx
633
634 /* Set up stack frame */
635 mov ebp, esp
636
637 /* Save the parameters */
638 mov eax, [ebp+0]
639 mov ecx, [ebp+8]
640
641 /* Call KiContinue */
642 push eax
643 push 0
644 push ecx
645 call _KiContinue@12
646
647 /* Check if we failed (bad context record) */
648 or eax, eax
649 jnz Error
650
651 /* Check if test alert was requested */
652 cmp dword ptr [ebp+12], 0
653 je DontTest
654
655 /* Test alert for the thread */
656 mov al, [ebx+KTHREAD_PREVIOUS_MODE]
657 push eax
658 call _KeTestAlertThread@4
659
660 DontTest:
661 /* Return to previous context */
662 pop ebp
663 mov esp, ebp
664 jmp _KiServiceExit2
665
666 Error:
667 pop ebp
668 mov esp, ebp
669 jmp _KiServiceExit
670 .endfunc
671
672 /* EXCEPTION DISPATCHERS *****************************************************/
673
674 .func CommonDispatchException
675 _CommonDispatchException:
676
677 /* Make space for an exception record */
678 sub esp, EXCEPTION_RECORD_LENGTH
679
680 /* Set it up */
681 mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
682 xor eax, eax
683 mov [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], eax
684 mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], eax
685 mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], ebx
686 mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx
687
688 /* Check parameter count */
689 cmp eax, 0
690 jz NoParams
691
692 /* Get information */
693 lea ebx, [esp+SIZEOF_EXCEPTION_RECORD]
694 mov [ebx], edx
695 mov [ebx+4], esi
696 mov [ebx+8], edi
697
698 NoParams:
699
700 /* Set the record in ECX and check if this was V86 */
701 mov ecx, esp
702 test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
703 jz SetPreviousMode
704
705 /* Set V86 mode */
706 mov eax, 0xFFFF
707 jmp MaskMode
708
709 SetPreviousMode:
710
711 /* Calculate the previous mode */
712 mov eax, [ebp+KTRAP_FRAME_CS]
713 MaskMode:
714 and eax, MODE_MASK
715
716 /* Dispatch the exception */
717 push 1
718 push eax
719 push ebp
720 push 0
721 push ecx
722 call _KiDispatchException@20
723
724 /* End the trap */
725 mov esp, ebp
726 jmp _Kei386EoiHelper@0
727 .endfunc
728
729 .func DispatchNoParam
730 _DispatchNoParam:
731 /* Call the common dispatcher */
732 xor ecx, ecx
733 call _CommonDispatchException
734 .endfunc
735
736 .func DispatchOneParam
737 _DispatchOneParam:
738 /* Call the common dispatcher */
739 xor edx, edx
740 mov ecx, 1
741 call _CommonDispatchException
742 .endfunc
743
744 .func DispatchTwoParam
745 _DispatchTwoParam:
746 /* Call the common dispatcher */
747 xor edx, edx
748 mov ecx, 2
749 call _CommonDispatchException
750 .endfunc
751
752 /* HARDWARE TRAP HANDLERS ****************************************************/
753
754 .func KiTrap0
755 _KiTrap0:
756 /* Push error code */
757 push 0
758
759 /* Enter trap */
760 TRAP_PROLOG(0)
761
762 /* Check for V86 */
763 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
764 jnz V86Int0
765
766 /* Check if the frame was from kernelmode */
767 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
768 jz SendException
769
770 /* Check the old mode */
771 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
772 jne VdmCheck
773
774 SendException:
775 /* Re-enable interrupts for user-mode and send the exception */
776 sti
777 mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO
778 mov ebx, [ebp+KTRAP_FRAME_EIP]
779 jmp _DispatchNoParam
780
781 VdmCheck:
782 /* Check if this is a VDM process */
783 mov ebx, [fs:KPCR_CURRENT_THREAD]
784 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
785 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
786 jz SendException
787
788 /* We don't support this yet! */
789 V86Int0:
790 int 3
791 .endfunc
792
793 .func KiTrap1
794 _KiTrap1:
795 /* Push error code */
796 push 0
797
798 /* Enter trap */
799 TRAP_PROLOG(1)
800
801 /* Check for V86 */
802 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
803 jnz V86Int1
804
805 /* Check if the frame was from kernelmode */
806 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
807 jz PrepInt1
808
809 /* Check the old mode */
810 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
811 jne V86Int1
812
813 EnableInterrupts:
814 /* Enable interrupts for user-mode */
815 sti
816
817 PrepInt1:
818 /* Prepare the exception */
819 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAGS_TF
820 mov ebx, [ebp+KTRAP_FRAME_EIP]
821 mov eax, STATUS_SINGLE_STEP
822 jmp _DispatchNoParam
823
824 V86Int1:
825 /* Check if this is a VDM process */
826 mov ebx, [fs:KPCR_CURRENT_THREAD]
827 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
828 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
829 jz EnableInterrupts
830
831 /* We don't support VDM! */
832 int 3
833 .endfunc
834
835 .func KiTrap2
836 _KiTrap2:
837
838 /* FIXME: This is an NMI, nothing like a normal exception */
839 mov eax, 2
840 jmp _KiSystemFatalException
841 .endfunc
842
843 .func KiTrap3
844 _KiTrap3:
845 /* Push error code */
846 push 0
847
848 /* Enter trap */
849 TRAP_PROLOG(3)
850
851 /* Check for V86 */
852 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
853 jnz V86Int3
854
855 /* Check if the frame was from kernelmode */
856 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
857 jz PrepInt3
858
859 /* Check the old mode */
860 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
861 jne V86Int3
862
863 EnableInterrupts3:
864 /* Enable interrupts for user-mode */
865 sti
866
867 PrepInt3:
868 /* Prepare the exception */
869 mov esi, ecx
870 mov edi, edx
871 mov edx, eax
872
873 /* Setup EIP, NTSTATUS and parameter count, then dispatch */
874 mov ebx, [ebp+KTRAP_FRAME_EIP]
875 dec ebx
876 mov eax, STATUS_BREAKPOINT
877 mov ecx, 3
878 call _CommonDispatchException
879
880 V86Int3:
881 /* Check if this is a VDM process */
882 mov ebx, [fs:KPCR_CURRENT_THREAD]
883 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
884 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
885 jz EnableInterrupts3
886
887 /* We don't support VDM! */
888 int 3
889 .endfunc
890
891 .func KiTrap4
892 _KiTrap4:
893 /* Push error code */
894 push 0
895
896 /* Enter trap */
897 TRAP_PROLOG(4)
898
899 /* Check for V86 */
900 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
901 jnz V86Int4
902
903 /* Check if the frame was from kernelmode */
904 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
905 jz SendException4
906
907 /* Check the old mode */
908 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
909 jne VdmCheck4
910
911 SendException4:
912 /* Re-enable interrupts for user-mode and send the exception */
913 sti
914 mov eax, STATUS_INTEGER_OVERFLOW
915 mov ebx, [ebp+KTRAP_FRAME_EIP]
916 dec ebx
917 jmp _DispatchNoParam
918
919 VdmCheck4:
920 /* Check if this is a VDM process */
921 mov ebx, [fs:KPCR_CURRENT_THREAD]
922 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
923 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
924 jz SendException4
925
926 /* We don't support this yet! */
927 V86Int4:
928 int 3
929 .endfunc
930
931 .func KiTrap5
932 _KiTrap5:
933 /* Push error code */
934 push 0
935
936 /* Enter trap */
937 TRAP_PROLOG(5)
938
939 /* Check for V86 */
940 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
941 jnz V86Int5
942
943 /* Check if the frame was from kernelmode */
944 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
945 jnz CheckMode
946
947 /* It did, and this should never happen */
948 mov eax, 5
949 jmp _KiSystemFatalException
950
951 /* Check the old mode */
952 CheckMode:
953 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
954 jne VdmCheck5
955
956 /* Re-enable interrupts for user-mode and send the exception */
957 SendException5:
958 sti
959 mov eax, STATUS_ARRAY_BOUNDS_EXCEEDED
960 mov ebx, [ebp+KTRAP_FRAME_EIP]
961 jmp _DispatchNoParam
962
963 VdmCheck5:
964 /* Check if this is a VDM process */
965 mov ebx, [fs:KPCR_CURRENT_THREAD]
966 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
967 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
968 jz SendException5
969
970 /* We don't support this yet! */
971 V86Int5:
972 int 3
973 .endfunc
974
975 .func KiTrap6
976 _KiTrap6:
977 /* Push error code */
978 push 0
979
980 /* Enter trap */
981 TRAP_PROLOG(6)
982
983 /* Call the C exception handler */
984 push 6
985 push ebp
986 call _KiTrapHandler
987 add esp, 8
988
989 /* Check for v86 recovery */
990 cmp eax, 1
991
992 /* Return to caller */
993 jne _Kei386EoiHelper@0
994 jmp _KiV86Complete
995 .endfunc
996
997 .func KiTrap7
998 _KiTrap7:
999 /* Push error code */
1000 push 0
1001
1002 /* Enter trap */
1003 TRAP_PROLOG(7)
1004
1005 /* Get the current thread and stack */
1006 StartTrapHandle:
1007 mov eax, [fs:KPCR_CURRENT_THREAD]
1008 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1009 sub ecx, NPX_FRAME_LENGTH
1010
1011 /* Check if emulation is enabled */
1012 test dword ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
1013 jnz EmulationEnabled
1014
1015 CheckState:
1016 /* Check if the NPX state is loaded */
1017 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1018 mov ebx, cr0
1019 jz IsLoaded
1020
1021 /* Remove flags */
1022 and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
1023 mov cr0, ebx
1024
1025 /* Check the NPX thread */
1026 mov edx, [fs:KPCR_NPX_THREAD]
1027 or edx, edx
1028 jz NoNpxThread
1029
1030 /* Get the NPX Stack */
1031 mov esi, [edx+KTHREAD_INITIAL_STACK]
1032 sub esi, NPX_FRAME_LENGTH
1033
1034 /* Check if we have FXSR and check which operand to use */
1035 test byte ptr _KeI386FxsrPresent, 1
1036 jz FnSave
1037 fxsave [esi]
1038 jmp AfterSave
1039
1040 FnSave:
1041 fnsave [esi]
1042
1043 AfterSave:
1044 /* Set the thread's state to dirty */
1045 mov byte ptr [edx+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1046
1047 NoNpxThread:
1048 /* Check if we have FXSR and choose which operand to use */
1049 test byte ptr _KeI386FxsrPresent, 1
1050 jz FrRestore
1051 fxrstor [ecx]
1052 jmp AfterRestore
1053
1054 FrRestore:
1055 frstor [esi]
1056
1057 AfterRestore:
1058 /* Set state loaded */
1059 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1060 mov [fs:KPCR_NPX_THREAD], eax
1061
1062 /* Enable interrupts to happen now */
1063 sti
1064 nop
1065
1066 /* Check if CR0 needs to be reloaded due to a context switch */
1067 cmp dword ptr [ecx+FN_CR0_NPX_STATE], 0
1068 jz _Kei386EoiHelper@0
1069
1070 /* We have to reload CR0... disable interrupts */
1071 cli
1072
1073 /* Get CR0 and update it */
1074 mov ebx, cr0
1075 or ebx, [ecx+FN_CR0_NPX_STATE]
1076 mov cr0, ebx
1077
1078 /* Restore interrupts and check if TS is back on */
1079 sti
1080 test bl, CR0_TS
1081 jz _Kei386EoiHelper@0
1082
1083 /* Clear TS, and loop handling again */
1084 clts
1085 cli
1086 jmp StartTrapHandle
1087
1088 IsLoaded:
1089 /* Check if TS is set */
1090 test bl, CR0_TS
1091 jnz TsSetOnLoadedState
1092
1093 /* Check if the trap came from user-mode */
1094 int 3
1095
1096 EmulationEnabled:
1097 /* Did this come from kernel-mode? */
1098 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
1099 jz CheckState
1100
1101 /* It came from user-mode, so this would only be valid inside a VDM */
1102 /* Since we don't actually have VDMs in ROS, bugcheck. */
1103 jmp BogusTrap2
1104
1105 TsSetOnLoadedState:
1106 /* TS shouldn't be set, unless this we don't have a Math Processor */
1107 test bl, CR0_MP
1108 jnz BogusTrap
1109
1110 /* Strange that we got a trap at all, but ignore and continue */
1111 clts
1112 jmp _Kei386EoiHelper@0
1113
1114 BogusTrap2:
1115 /* Cause a bugcheck */
1116 sti
1117 push 0
1118 push 0
1119 push eax
1120 push 1
1121 push TRAP_CAUSE_UNKNOWN
1122 call _KeBugCheckEx@20
1123
1124 BogusTrap:
1125 /* Cause a bugcheck */
1126 push 0
1127 push 0
1128 push ebx
1129 push 2
1130 push TRAP_CAUSE_UNKNOWN
1131 call _KeBugCheckEx@20
1132 .endfunc
1133
1134 .globl _KiTrap8
1135 .func KiTrap8
1136 _KiTrap8:
1137
1138 /* Can't really do too much */
1139 mov eax, 8
1140 jmp _KiSystemFatalException
1141 .endfunc
1142
1143 .func KiTrap9
1144 _KiTrap9:
1145 /* Push error code */
1146 push 0
1147
1148 /* Enter trap */
1149 TRAP_PROLOG(9)
1150
1151 /* Enable interrupts and bugcheck */
1152 sti
1153 mov eax, 9
1154 jmp _KiSystemFatalException
1155 .endfunc
1156
1157 .func KiTrap10
1158 _KiTrap10:
1159 /* Enter trap */
1160 TRAP_PROLOG(10)
1161
1162 /* Check for V86 */
1163 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1164 jnz V86IntA
1165
1166 /* Check if the frame was from kernelmode */
1167 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1168 jz Fatal
1169
1170 V86IntA:
1171 /* Check if OF was set during iretd */
1172 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAG_ZERO
1173 sti
1174 jz Fatal
1175
1176 /* It was, just mask it out */
1177 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAG_ZERO
1178 jmp _Kei386EoiHelper@0
1179
1180 Fatal:
1181 /* TSS failure for some other reason: crash */
1182 mov eax, 10
1183 jmp _KiSystemFatalException
1184 .endfunc
1185
1186 .func KiTrap11
1187 _KiTrap11:
1188 /* Enter trap */
1189 TRAP_PROLOG(11)
1190
1191 /* FIXME: ROS Doesn't handle segment faults yet */
1192 mov eax, 11
1193 jmp _KiSystemFatalException
1194 .endfunc
1195
1196 .func KiTrap12
1197 _KiTrap12:
1198 /* Enter trap */
1199 TRAP_PROLOG(12)
1200
1201 /* FIXME: ROS Doesn't handle stack faults yet */
1202 mov eax, 12
1203 jmp _KiSystemFatalException
1204 .endfunc
1205
1206 .func KiTrap13
1207 _KiTrap13:
1208 /* Enter trap */
1209 TRAP_PROLOG(13)
1210
1211 /* Call the C exception handler */
1212 push 13
1213 push ebp
1214 call _KiTrapHandler
1215 add esp, 8
1216
1217 /* Check for v86 recovery */
1218 cmp eax, 1
1219
1220 /* Return to caller */
1221 jne _Kei386EoiHelper@0
1222 jmp _KiV86Complete
1223 .endfunc
1224
1225 .func KiTrap14
1226 _KiTrap14:
1227 /* Enter trap */
1228 TRAP_PROLOG(14)
1229
1230 /* Call the C exception handler */
1231 push 14
1232 push ebp
1233 call _KiPageFaultHandler
1234 add esp, 8
1235
1236 /* Return to caller */
1237 jmp _Kei386EoiHelper@0
1238 .endfunc
1239
1240 .func KiTrap0F
1241 _KiTrap0F:
1242 /* Push error code */
1243 push 0
1244
1245 /* Enter trap */
1246 TRAP_PROLOG(15)
1247 sti
1248
1249 /* Raise a fatal exception */
1250 mov eax, 15
1251 jmp _KiSystemFatalException
1252 .endfunc
1253
1254 .func KiTrap16
1255 _KiTrap16:
1256 /* Push error code */
1257 push 0
1258
1259 /* Enter trap */
1260 TRAP_PROLOG(16)
1261
1262 /* FIXME: ROS Doesn't handle FPU faults yet */
1263 mov eax, 16
1264 jmp _KiSystemFatalException
1265 .endfunc
1266
1267 .func KiTrap17
1268 _KiTrap17:
1269 /* Push error code */
1270 push 0
1271
1272 /* Enter trap */
1273 TRAP_PROLOG(17)
1274
1275 /* FIXME: ROS Doesn't handle alignment faults yet */
1276 mov eax, 17
1277 jmp _KiSystemFatalException
1278 .endfunc
1279
1280 .func KiSystemFatalException
1281 _KiSystemFatalException:
1282
1283 /* Push the trap frame */
1284 push ebp
1285
1286 /* Push empty parameters */
1287 push 0
1288 push 0
1289 push 0
1290
1291 /* Push trap number and bugcheck code */
1292 push eax
1293 push UNEXPECTED_KERNEL_MODE_TRAP
1294 call _KeBugCheckWithTf@24
1295 ret
1296 .endfunc
1297
1298 /* UNEXPECTED INTERRUPT HANDLERS **********************************************/
1299
1300 .globl _KiStartUnexpectedRange@0
1301 _KiStartUnexpectedRange@0:
1302
1303 GENERATE_INT_HANDLERS
1304
1305 .globl _KiEndUnexpectedRange@0
1306 _KiEndUnexpectedRange@0:
1307 jmp _KiUnexpectedInterruptTail
1308
1309 .func KiUnexpectedInterruptTail
1310 _KiUnexpectedInterruptTail:
1311
1312 /* Enter interrupt trap */
1313 INT_PROLOG kui, DoNotPushFakeErrorCode
1314
1315 /* Increase interrupt count */
1316 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
1317
1318 /* Put vector in EBX and make space for KIRQL */
1319 mov ebx, [esp]
1320 sub esp, 4
1321
1322 /* Begin interrupt */
1323 push esp
1324 push ebx
1325 push HIGH_LEVEL
1326 call _HalBeginSystemInterrupt@12
1327
1328 /* Check if it was spurious or not */
1329 or eax, eax
1330 jnz Handled
1331
1332 /* Spurious, ignore it */
1333 add esp, 8
1334 jmp _Kei386EoiHelper2ndEntry
1335
1336 Handled:
1337 /* Unexpected interrupt, print a message on debug builds */
1338 #if DBG
1339 push [esp+4]
1340 push offset _UnexpectedMsg
1341 call _DbgPrint
1342 add esp, 8
1343 #endif
1344
1345 /* Exit the interrupt */
1346 mov esi, $
1347 cli
1348 call _HalEndSystemInterrupt@8
1349 jmp _Kei386EoiHelper@0
1350 .endfunc
1351
1352 .globl _KiUnexpectedInterrupt
1353 _KiUnexpectedInterrupt:
1354
1355 /* Bugcheck with invalid interrupt code */
1356 push 0x12
1357 call _KeBugCheck@4
1358
1359 /* INTERRUPT HANDLERS ********************************************************/
1360
1361 .func KiInterruptTemplate
1362 _KiInterruptTemplate:
1363
1364 /* Enter interrupt trap */
1365 INT_PROLOG kit, DoPushFakeErrorCode
1366 .endfunc
1367
1368 _KiInterruptTemplate2ndDispatch:
1369 /* Dummy code, will be replaced by the address of the KINTERRUPT */
1370 mov edi, 0
1371
1372 _KiInterruptTemplateObject:
1373 /* Dummy jump, will be replaced by the actual jump */
1374 jmp _KeSynchronizeExecution@12
1375
1376 _KiInterruptTemplateDispatch:
1377 /* Marks the end of the template so that the jump above can be edited */
1378
1379 .func KiChainedDispatch2ndLvl@0
1380 _KiChainedDispatch2ndLvl@0:
1381
1382 /* Not yet supported */
1383 int 3
1384 .endfunc
1385
1386 .func KiChainedDispatch@0
1387 _KiChainedDispatch@0:
1388
1389 /* Increase interrupt count */
1390 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
1391
1392 /* Save trap frame */
1393 mov ebp, esp
1394
1395 /* Save vector and IRQL */
1396 mov eax, [edi+KINTERRUPT_VECTOR]
1397 mov ecx, [edi+KINTERRUPT_IRQL]
1398
1399 /* Save old irql */
1400 push eax
1401 sub esp, 4
1402
1403 /* Begin interrupt */
1404 push esp
1405 push eax
1406 push ecx
1407 call _HalBeginSystemInterrupt@12
1408
1409 /* Check if it was handled */
1410 or eax, eax
1411 jz SpuriousInt
1412
1413 /* Call the 2nd-level handler */
1414 call _KiChainedDispatch2ndLvl@0
1415
1416 /* Exit the interrupt */
1417 mov esi, $
1418 cli
1419 call _HalEndSystemInterrupt@8
1420 jmp _Kei386EoiHelper@0
1421 .endfunc
1422
1423 .func KiInterruptDispatch@0
1424 _KiInterruptDispatch@0:
1425
1426 /* Increase interrupt count */
1427 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
1428
1429 /* Save trap frame */
1430 mov ebp, esp
1431
1432 /* Save vector and IRQL */
1433 mov eax, [edi+KINTERRUPT_VECTOR]
1434 mov ecx, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
1435
1436 /* Save old irql */
1437 push eax
1438 sub esp, 4
1439
1440 /* Begin interrupt */
1441 push esp
1442 push eax
1443 push ecx
1444 call _HalBeginSystemInterrupt@12
1445
1446 /* Check if it was handled */
1447 or eax, eax
1448 jz SpuriousInt
1449
1450 /* Acquire the lock */
1451 GetIntLock:
1452 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
1453 ACQUIRE_SPINLOCK(esi, IntSpin)
1454
1455 /* Call the ISR */
1456 mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
1457 push eax
1458 push edi
1459 call [edi+KINTERRUPT_SERVICE_ROUTINE]
1460
1461 /* Release the lock */
1462 RELEASE_SPINLOCK(esi)
1463
1464 /* Exit the interrupt */
1465 mov esi, $
1466 cli
1467 call _HalEndSystemInterrupt@8
1468 jmp _Kei386EoiHelper@0
1469
1470 SpuriousInt:
1471 /* Exit the interrupt */
1472 add esp, 8
1473 mov esi, $
1474 jmp _Kei386EoiHelper@0
1475
1476 #ifdef CONFIG_SMP
1477 IntSpin:
1478 SPIN_ON_LOCK esi, GetIntLock
1479 #endif
1480 .endfunc