- Finish the work around for the Pentium cmpxchg8b lock errata: We detected the errat...
[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 #define Running 2
16 #define WrDispatchInt 0x1F
17
18 /* GLOBALS *******************************************************************/
19
20 .data
21 .globl _KiIdt
22 _KiIdt:
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) */
44 .rept 22
45 idt _KiTrap0F, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS */
46 .endr
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 */
54
55 /* System call entrypoints: */
56 .globl _KiFastCallEntry
57 .globl _KiSystemService
58
59 /* And special system-defined software traps: */
60 .globl _NtRaiseException@12
61 .globl _NtContinue@8
62 .globl _KiCoprocessorError@0
63 .globl _KiDispatchInterrupt@0
64
65 /* Interrupt template entrypoints */
66 .globl _KiInterruptTemplate
67 .globl _KiInterruptTemplateObject
68 .globl _KiInterruptTemplateDispatch
69
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
74
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 */
80
81 .globl _KiIdtDescriptor
82 _KiIdtDescriptor:
83 .short 0
84 .short 0x7FF
85 .long _KiIdt
86
87 .globl _KiUnexpectedEntrySize
88 _KiUnexpectedEntrySize:
89 .long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
90
91 _UnexpectedMsg:
92 .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
93
94 _UnhandledMsg:
95 .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
96
97 _IsrTimeoutMsg:
98 .asciz "\n*** ISR at %lx took over .5 second\n"
99
100 _IsrOverflowMsg:
101 .asciz "\n*** ISR at %lx appears to have an interrupt storm\n"
102
103 _KiTrapPrefixTable:
104 .byte 0xF2 /* REP */
105 .byte 0xF3 /* REP INS/OUTS */
106 .byte 0x67 /* ADDR */
107 .byte 0xF0 /* LOCK */
108 .byte 0x66 /* OP */
109 .byte 0x2E /* SEG */
110 .byte 0x3E /* DS */
111 .byte 0x26 /* ES */
112 .byte 0x64 /* FS */
113 .byte 0x65 /* GS */
114 .byte 0x36 /* SS */
115
116 _KiTrapIoTable:
117 .byte 0xE4 /* IN */
118 .byte 0xE5 /* IN */
119 .byte 0xEC /* IN */
120 .byte 0xED /* IN */
121 .byte 0x6C /* INS */
122 .byte 0x6D /* INS */
123 .byte 0xE6 /* OUT */
124 .byte 0xE7 /* OUT */
125 .byte 0xEE /* OUT */
126 .byte 0xEF /* OUT */
127 .byte 0x6E /* OUTS */
128 .byte 0x6F /* OUTS */
129
130 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
131 .text
132
133 _KiGetTickCount:
134 _KiCallbackReturn:
135 /* FIXME: TODO */
136 UNHANDLED_PATH
137
138 .func KiSystemService
139 TRAP_FIXUPS kss_a, kss_t, DoNotFixupV86, DoNotFixupAbios
140 _KiSystemService:
141
142 /* Enter the shared system call prolog */
143 SYSCALL_PROLOG kss_a, kss_t
144
145 /* Jump to the actual handler */
146 jmp SharedCode
147 .endfunc
148
149 .func KiFastCallEntry
150 TRAP_FIXUPS FastCallDrSave, FastCallDrReturn, DoNotFixupV86, DoNotFixupAbios
151 _KiFastCallEntry:
152
153 /* Enter the fast system call prolog */
154 FASTCALL_PROLOG FastCallDrSave, FastCallDrReturn
155
156 SharedCode:
157
158 /*
159 * Find out which table offset to use. Converts 0x1124 into 0x10.
160 * The offset is related to the Table Index as such: Offset = TableIndex x 10
161 */
162 mov edi, eax
163 shr edi, SERVICE_TABLE_SHIFT
164 and edi, SERVICE_TABLE_MASK
165 mov ecx, edi
166
167 /* Now add the thread's base system table to the offset */
168 add edi, [esi+KTHREAD_SERVICE_TABLE]
169
170 /* Get the true syscall ID and check it */
171 mov ebx, eax
172 and eax, SERVICE_NUMBER_MASK
173 cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
174
175 /* Invalid ID, try to load Win32K Table */
176 jnb KiBBTUnexpectedRange
177
178 /* Check if this was Win32K */
179 cmp ecx, SERVICE_TABLE_TEST
180 jnz NotWin32K
181
182 /* Get the TEB */
183 mov ecx, PCR[KPCR_TEB]
184
185 /* Check if we should flush the User Batch */
186 xor ebx, ebx
187 ReadBatch:
188 or ebx, [ecx+TEB_GDI_BATCH_COUNT]
189 jz NotWin32K
190
191 /* Flush it */
192 push edx
193 push eax
194 call [_KeGdiFlushUserBatch]
195 pop eax
196 pop edx
197
198 NotWin32K:
199 /* Increase total syscall count */
200 inc dword ptr PCR[KPCR_SYSTEM_CALLS]
201
202 #if DBG
203 /* Increase per-syscall count */
204 mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
205 jecxz NoCountTable
206 inc dword ptr [ecx+eax*4]
207 #endif
208
209 /* Users's current stack frame pointer is source */
210 NoCountTable:
211 mov esi, edx
212
213 /* Allocate room for argument list from kernel stack */
214 mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
215 xor ecx, ecx
216 mov cl, [eax+ebx]
217
218 /* Get pointer to function */
219 mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
220 mov ebx, [edi+eax*4]
221
222 /* Allocate space on our stack */
223 sub esp, ecx
224
225 /* Set the size of the arguments and the destination */
226 shr ecx, 2
227 mov edi, esp
228
229 /* Make sure we're within the User Probe Address */
230 cmp esi, _MmUserProbeAddress
231 jnb AccessViolation
232
233 CopyParams:
234 /* Copy the parameters */
235 rep movsd
236
237 /* Do the System Call */
238 call ebx
239
240 AfterSysCall:
241 #if DBG
242 /* Make sure the user-mode call didn't return at elevated IRQL */
243 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
244 jz SkipCheck
245 mov esi, eax /* We need to save the syscall's return val */
246 call _KeGetCurrentIrql@0
247 or al, al
248 jnz InvalidIrql
249 mov eax, esi /* Restore it */
250
251 /* Get our temporary current thread pointer for sanity check */
252 mov ecx, PCR[KPCR_CURRENT_THREAD]
253
254 /* Make sure that we are not attached and that APCs are not disabled */
255 mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
256 or dl, dl
257 jnz InvalidIndex
258 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
259 or edx, edx
260 jnz InvalidIndex
261 #endif
262
263 SkipCheck:
264
265 /* Deallocate the kernel stack frame */
266 mov esp, ebp
267
268 KeReturnFromSystemCall:
269
270 /* Get the Current Thread */
271 mov ecx, PCR[KPCR_CURRENT_THREAD]
272
273 /* Restore the old trap frame pointer */
274 mov edx, [ebp+KTRAP_FRAME_EDX]
275 mov [ecx+KTHREAD_TRAP_FRAME], edx
276 .endfunc
277
278 .func KiServiceExit
279 _KiServiceExit:
280 /* Disable interrupts */
281 cli
282
283 /* Check for, and deliver, User-Mode APCs if needed */
284 CHECK_FOR_APC_DELIVER 1
285
286 /* Exit and cleanup */
287 TRAP_EPILOG FromSystemCall, DoRestorePreviousMode, DoNotRestoreSegments, DoNotRestoreVolatiles, DoRestoreEverything
288 .endfunc
289
290 KiBBTUnexpectedRange:
291
292 /* If this isn't a Win32K call, fail */
293 cmp ecx, SERVICE_TABLE_TEST
294 jne InvalidCall
295
296 /* Set up Win32K Table */
297 push edx
298 push ebx
299 call _PsConvertToGuiThread@0
300
301 /* Check return code */
302 or eax, eax
303
304 /* Restore registers */
305 pop eax
306 pop edx
307
308 /* Reset trap frame address */
309 mov ebp, esp
310 mov [esi+KTHREAD_TRAP_FRAME], ebp
311
312 /* Try the Call again, if we suceeded */
313 jz SharedCode
314
315 /*
316 * The Shadow Table should have a special byte table which tells us
317 * whether we should return FALSE, -1 or STATUS_INVALID_SYSTEM_SERVICE.
318 */
319
320 /* Get the table limit and base */
321 lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
322 mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
323 mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
324
325 /* Get the table address and add our index into the array */
326 lea edx, [edx+ecx*4]
327 and eax, SERVICE_NUMBER_MASK
328 add edx, eax
329
330 /* Find out what we should return */
331 movsx eax, byte ptr [edx]
332 or eax, eax
333
334 /* Return either 0 or -1, we've set it in EAX */
335 jle KeReturnFromSystemCall
336
337 /* Set STATUS_INVALID_SYSTEM_SERVICE */
338 mov eax, STATUS_INVALID_SYSTEM_SERVICE
339 jmp KeReturnFromSystemCall
340
341 InvalidCall:
342
343 /* Invalid System Call */
344 mov eax, STATUS_INVALID_SYSTEM_SERVICE
345 jmp KeReturnFromSystemCall
346
347 AccessViolation:
348
349 /* Check if this came from kernel-mode */
350 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
351
352 /* It's fine, go ahead with it */
353 jz CopyParams
354
355 /* Caller sent invalid parameters, fail here */
356 mov eax, STATUS_ACCESS_VIOLATION
357 jmp AfterSysCall
358
359 BadStack:
360
361 /* Restore ESP0 stack */
362 mov ecx, PCR[KPCR_TSS]
363 mov esp, ss:[ecx+KTSS_ESP0]
364
365 /* Generate V86M Stack for Trap 6 */
366 push 0
367 push 0
368 push 0
369 push 0
370
371 /* Generate interrupt stack for Trap 6 */
372 push KGDT_R3_DATA + RPL_MASK
373 push 0
374 push 0x20202
375 push KGDT_R3_CODE + RPL_MASK
376 push 0
377 jmp _KiTrap6
378
379 #if DBG
380 InvalidIrql:
381 /* Save current IRQL */
382 push PCR[KPCR_IRQL]
383
384 /* Set us at passive */
385 mov dword ptr PCR[KPCR_IRQL], 0
386 cli
387
388 /* Bugcheck */
389 push 0
390 push 0
391 push eax
392 push ebx
393 push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
394 call _KeBugCheckEx@20
395
396 InvalidIndex:
397
398 /* Get the index and APC state */
399 movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
400 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
401
402 /* Bugcheck */
403 push 0
404 push edx
405 push eax
406 push ebx
407 push APC_INDEX_MISMATCH
408 call _KeBugCheckEx@20
409 ret
410 #endif
411
412 .func KiServiceExit2
413 _KiServiceExit2:
414
415 /* Disable interrupts */
416 cli
417
418 /* Check for, and deliver, User-Mode APCs if needed */
419 CHECK_FOR_APC_DELIVER 0
420
421 /* Exit and cleanup */
422 TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
423 .endfunc
424
425 .func Kei386EoiHelper@0
426 _Kei386EoiHelper@0:
427
428 /* Disable interrupts */
429 cli
430
431 /* Check for, and deliver, User-Mode APCs if needed */
432 CHECK_FOR_APC_DELIVER 0
433
434 /* Exit and cleanup */
435 _Kei386EoiHelper2ndEntry:
436 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
437 .endfunc
438
439 V86_Exit:
440 /* Move to EDX position */
441 add esp, KTRAP_FRAME_EDX
442
443 /* Restore volatiles */
444 pop edx
445 pop ecx
446 pop eax
447
448 /* Move to non-volatiles */
449 lea esp, [ebp+KTRAP_FRAME_EDI]
450 pop edi
451 pop esi
452 pop ebx
453 pop ebp
454
455 /* Skip error code and return */
456 add esp, 4
457 iret
458
459 AbiosExit:
460 /* FIXME: TODO */
461 UNHANDLED_PATH
462
463 .func KiRaiseAssertion
464 TRAP_FIXUPS kira_a, kira_t, DoFixupV86, DoFixupAbios
465 _KiRaiseAssertion:
466
467 /* Push error code */
468 push 0
469
470 /* Enter trap */
471 TRAP_PROLOG kira_a, kira_t
472
473 /*
474 * Modify EIP so it points to the faulting instruction and set it as the
475 * exception address. Note that the 'int 2C' instruction used for this call
476 * is 2 bytes long as opposed to 1 byte 'int 3'.
477 */
478 sub dword ptr [ebp+KTRAP_FRAME_EIP], 2
479 mov ebx, [ebp+KTRAP_FRAME_EIP]
480
481 /* Raise an assertion failure */
482 mov eax, STATUS_ASSERTION_FAILURE
483 jmp _DispatchNoParam
484 .endfunc
485
486 .func KiDebugService
487 TRAP_FIXUPS kids_a, kids_t, DoFixupV86, DoFixupAbios
488 _KiDebugService:
489
490 /* Push error code */
491 push 0
492
493 /* Enter trap */
494 TRAP_PROLOG kids_a, kids_t
495
496 /* Increase EIP so we skip the INT3 */
497 inc dword ptr [ebp+KTRAP_FRAME_EIP]
498
499 /* Call debug service dispatcher */
500 mov eax, [ebp+KTRAP_FRAME_EAX]
501 mov ecx, [ebp+KTRAP_FRAME_ECX]
502 mov edx, [ebp+KTRAP_FRAME_EDX]
503
504 /* Jump to INT3 handler */
505 jmp PrepareInt3
506 .endfunc
507
508 .func NtRaiseException@12
509 _NtRaiseException@12:
510
511 /* NOTE: We -must- be called by Zw* to have the right frame! */
512 /* Push the stack frame */
513 push ebp
514
515 /* Get the current thread and restore its trap frame */
516 mov ebx, PCR[KPCR_CURRENT_THREAD]
517 mov edx, [ebp+KTRAP_FRAME_EDX]
518 mov [ebx+KTHREAD_TRAP_FRAME], edx
519
520 /* Set up stack frame */
521 mov ebp, esp
522
523 /* Get the Trap Frame in EBX */
524 mov ebx, [ebp+0]
525
526 /* Get the exception list and restore */
527 mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
528 mov PCR[KPCR_EXCEPTION_LIST], eax
529
530 /* Get the parameters */
531 mov edx, [ebp+16] /* Search frames */
532 mov ecx, [ebp+12] /* Context */
533 mov eax, [ebp+8] /* Exception Record */
534
535 /* Raise the exception */
536 push edx
537 push ebx
538 push 0
539 push ecx
540 push eax
541 call _KiRaiseException@20
542
543 /* Restore trap frame in EBP */
544 pop ebp
545 mov esp, ebp
546
547 /* Check the result */
548 or eax, eax
549 jz _KiServiceExit2
550
551 /* Restore debug registers too */
552 jmp _KiServiceExit
553 .endfunc
554
555 .func NtContinue@8
556 _NtContinue@8:
557
558 /* NOTE: We -must- be called by Zw* to have the right frame! */
559 /* Push the stack frame */
560 push ebp
561
562 /* Get the current thread and restore its trap frame */
563 mov ebx, PCR[KPCR_CURRENT_THREAD]
564 mov edx, [ebp+KTRAP_FRAME_EDX]
565 mov [ebx+KTHREAD_TRAP_FRAME], edx
566
567 /* Set up stack frame */
568 mov ebp, esp
569
570 /* Save the parameters */
571 mov eax, [ebp+0]
572 mov ecx, [ebp+8]
573
574 /* Call KiContinue */
575 push eax
576 push 0
577 push ecx
578 call _KiContinue@12
579
580 /* Check if we failed (bad context record) */
581 or eax, eax
582 jnz Error
583
584 /* Check if test alert was requested */
585 cmp dword ptr [ebp+12], 0
586 je DontTest
587
588 /* Test alert for the thread */
589 mov al, [ebx+KTHREAD_PREVIOUS_MODE]
590 push eax
591 call _KeTestAlertThread@4
592
593 DontTest:
594 /* Return to previous context */
595 pop ebp
596 mov esp, ebp
597 jmp _KiServiceExit2
598
599 Error:
600 pop ebp
601 mov esp, ebp
602 jmp _KiServiceExit
603 .endfunc
604
605 /* EXCEPTION DISPATCHERS *****************************************************/
606
607 .func CommonDispatchException
608 _CommonDispatchException:
609
610 /* Make space for an exception record */
611 sub esp, EXCEPTION_RECORD_LENGTH
612
613 /* Set it up */
614 mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
615 xor eax, eax
616 mov [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], eax
617 mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], eax
618 mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], ebx
619 mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx
620
621 /* Check parameter count */
622 cmp ecx, 0
623 jz NoParams
624
625 /* Get information */
626 lea ebx, [esp+SIZEOF_EXCEPTION_RECORD]
627 mov [ebx], edx
628 mov [ebx+4], esi
629 mov [ebx+8], edi
630
631 NoParams:
632
633 /* Set the record in ECX and check if this was V86 */
634 mov ecx, esp
635 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
636 jz SetPreviousMode
637
638 /* Set V86 mode */
639 mov eax, 0xFFFF
640 jmp MaskMode
641
642 SetPreviousMode:
643
644 /* Get the caller's CS */
645 mov eax, [ebp+KTRAP_FRAME_CS]
646
647 MaskMode:
648 /* Check if it was user-mode or kernel-mode */
649 and eax, MODE_MASK
650
651 /* Dispatch the exception */
652 push 1
653 push eax
654 push ebp
655 push 0
656 push ecx
657 call _KiDispatchException@20
658
659 /* End the trap */
660 mov esp, ebp
661 jmp _Kei386EoiHelper@0
662 .endfunc
663
664 .func DispatchNoParam
665 _DispatchNoParam:
666 /* Call the common dispatcher */
667 xor ecx, ecx
668 call _CommonDispatchException
669 .endfunc
670
671 .func DispatchOneParamZero
672 _DispatchOneParamZero:
673 /* Call the common dispatcher */
674 xor edx, edx
675 mov ecx, 1
676 call _CommonDispatchException
677 .endfunc
678
679 .func DispatchTwoParamZero
680 _DispatchTwoParamZero:
681 /* Call the common dispatcher */
682 xor edx, edx
683 mov ecx, 2
684 call _CommonDispatchException
685 .endfunc
686
687 .func DispatchTwoParam
688 _DispatchTwoParam:
689 /* Call the common dispatcher */
690 mov ecx, 2
691 call _CommonDispatchException
692 .endfunc
693
694 /* HARDWARE TRAP HANDLERS ****************************************************/
695
696 .func KiFixupFrame
697 _KiFixupFrame:
698
699 /* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
700 UNHANDLED_PATH
701 .endfunc
702
703 .func KiTrap0
704 TRAP_FIXUPS kit0_a, kit0_t, DoFixupV86, DoNotFixupAbios
705 _KiTrap0:
706 /* Push error code */
707 push 0
708
709 /* Enter trap */
710 TRAP_PROLOG kit0_a, kit0_t
711
712 /* Check for V86 */
713 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
714 jnz V86Int0
715
716 /* Check if the frame was from kernelmode */
717 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
718 jz SendException
719
720 /* Check the old mode */
721 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
722 jne VdmCheck
723
724 SendException:
725 /* Re-enable interrupts for user-mode and send the exception */
726 sti
727 mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO
728 mov ebx, [ebp+KTRAP_FRAME_EIP]
729 jmp _DispatchNoParam
730
731 VdmCheck:
732 /* Check if this is a VDM process */
733 mov ebx, PCR[KPCR_CURRENT_THREAD]
734 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
735 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
736 jz SendException
737
738 /* We don't support this yet! */
739 V86Int0:
740 /* FIXME: TODO */
741 UNHANDLED_PATH
742 .endfunc
743
744 .func KiTrap1
745 TRAP_FIXUPS kit1_a, kit1_t, DoFixupV86, DoNotFixupAbios
746 _KiTrap1:
747 /* Push error code */
748 push 0
749
750 /* Enter trap */
751 TRAP_PROLOG kit1_a, kit1_t
752
753 /* Check for V86 */
754 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
755 jnz V86Int1
756
757 /* Check if the frame was from kernelmode */
758 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
759 jz PrepInt1
760
761 /* Check the old mode */
762 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
763 jne V86Int1
764
765 EnableInterrupts:
766 /* Enable interrupts for user-mode */
767 sti
768
769 PrepInt1:
770 /* Prepare the exception */
771 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAGS_TF
772 mov ebx, [ebp+KTRAP_FRAME_EIP]
773 mov eax, STATUS_SINGLE_STEP
774 jmp _DispatchNoParam
775
776 V86Int1:
777 /* Check if this is a VDM process */
778 mov ebx, PCR[KPCR_CURRENT_THREAD]
779 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
780 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
781 jz EnableInterrupts
782
783 /* We don't support VDM! */
784 UNHANDLED_PATH
785 .endfunc
786
787 .globl _KiTrap2
788 .func KiTrap2
789 _KiTrap2:
790
791 /* FIXME: This is an NMI, nothing like a normal exception */
792 mov eax, 2
793 jmp _KiSystemFatalException
794 .endfunc
795
796 .func KiTrap3
797 TRAP_FIXUPS kit3_a, kit3_t, DoFixupV86, DoNotFixupAbios
798 _KiTrap3:
799 /* Push error code */
800 push 0
801
802 /* Enter trap */
803 TRAP_PROLOG kit3_a, kit3_t
804
805 /*
806 * Set the special code to indicate that this is a software breakpoint
807 * and not a debug service call
808 */
809 mov eax, BREAKPOINT_BREAK
810
811 /* Check for V86 */
812 PrepareInt3:
813 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
814 jnz V86Int3
815
816 /* Check if the frame was from kernelmode */
817 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
818 jz PrepInt3
819
820 /* Check the old mode */
821 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
822 jne V86Int3
823
824 EnableInterrupts3:
825 /* Enable interrupts for user-mode */
826 sti
827
828 PrepInt3:
829
830 /* Prepare the exception */
831 mov esi, ecx
832 mov edi, edx
833 mov edx, eax
834
835 /* Setup EIP, NTSTATUS and parameter count, then dispatch */
836 mov ebx, [ebp+KTRAP_FRAME_EIP]
837 dec ebx
838 mov ecx, 3
839 mov eax, STATUS_BREAKPOINT
840 call _CommonDispatchException
841
842 V86Int3:
843 /* Check if this is a VDM process */
844 mov ebx, PCR[KPCR_CURRENT_THREAD]
845 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
846 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
847 jz EnableInterrupts3
848
849 /* We don't support VDM! */
850 UNHANDLED_PATH
851 .endfunc
852
853 .func KiTrap4
854 TRAP_FIXUPS kit4_a, kit4_t, DoFixupV86, DoNotFixupAbios
855 _KiTrap4:
856 /* Push error code */
857 push 0
858
859 /* Enter trap */
860 TRAP_PROLOG kit4_a, kit4_t
861
862 /* Check for V86 */
863 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
864 jnz V86Int4
865
866 /* Check if the frame was from kernelmode */
867 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
868 jz SendException4
869
870 /* Check the old mode */
871 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
872 jne VdmCheck4
873
874 SendException4:
875 /* Re-enable interrupts for user-mode and send the exception */
876 sti
877 mov eax, STATUS_INTEGER_OVERFLOW
878 mov ebx, [ebp+KTRAP_FRAME_EIP]
879 dec ebx
880 jmp _DispatchNoParam
881
882 VdmCheck4:
883 /* Check if this is a VDM process */
884 mov ebx, PCR[KPCR_CURRENT_THREAD]
885 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
886 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
887 jz SendException4
888
889 /* We don't support this yet! */
890 V86Int4:
891 UNHANDLED_PATH
892 .endfunc
893
894 .func KiTrap5
895 TRAP_FIXUPS kit5_a, kit5_t, DoFixupV86, DoNotFixupAbios
896 _KiTrap5:
897 /* Push error code */
898 push 0
899
900 /* Enter trap */
901 TRAP_PROLOG kit5_a, kit5_t
902
903 /* Check for V86 */
904 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
905 jnz V86Int5
906
907 /* Check if the frame was from kernelmode */
908 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
909 jnz CheckMode
910
911 /* It did, and this should never happen */
912 mov eax, 5
913 jmp _KiSystemFatalException
914
915 /* Check the old mode */
916 CheckMode:
917 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
918 jne VdmCheck5
919
920 /* Re-enable interrupts for user-mode and send the exception */
921 SendException5:
922 sti
923 mov eax, STATUS_ARRAY_BOUNDS_EXCEEDED
924 mov ebx, [ebp+KTRAP_FRAME_EIP]
925 jmp _DispatchNoParam
926
927 VdmCheck5:
928 /* Check if this is a VDM process */
929 mov ebx, PCR[KPCR_CURRENT_THREAD]
930 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
931 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
932 jz SendException5
933
934 /* We don't support this yet! */
935 V86Int5:
936 UNHANDLED_PATH
937 .endfunc
938
939 .func KiTrap6
940 TRAP_FIXUPS kit6_a, kit6_t, DoFixupV86, DoNotFixupAbios
941 _KiTrap6:
942
943 /* It this a V86 GPF? */
944 test dword ptr [esp+8], EFLAGS_V86_MASK
945 jz NotV86UD
946
947 /* Enter V86 Trap */
948 V86_TRAP_PROLOG kit6_a, kit6_v
949
950 VdmOpCodeFault:
951 /* Not yet supported (Invalid OPCODE from V86) */
952 UNHANDLED_PATH
953
954 NotV86UD:
955 /* Push error code */
956 push 0
957
958 /* Enter trap */
959 TRAP_PROLOG kit6_a, kit6_t
960
961 DispatchLockErrata:
962 /* Check if this happened in kernel mode */
963 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
964 jz KmodeOpcode
965
966 /* Check for VDM */
967 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
968 jz UmodeOpcode
969
970 /* Check if the process is vDM */
971 mov ebx, PCR[KPCR_CURRENT_THREAD]
972 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
973 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
974 jnz IsVdmOpcode
975
976 UmodeOpcode:
977 /* Get EIP and enable interrupts at this point */
978 mov esi, [ebp+KTRAP_FRAME_EIP]
979 sti
980
981 /* Set intruction prefix length */
982 mov ecx, 4
983
984 /* Setup a SEH frame */
985 push ebp
986 push OpcodeSEH
987 push PCR[KPCR_EXCEPTION_LIST]
988 mov PCR[KPCR_EXCEPTION_LIST], esp
989
990 OpcodeLoop:
991 /* Get the instruction and check if it's LOCK */
992 mov al, [esi]
993 cmp al, 0xF0
994 jz LockCrash
995
996 /* Keep moving */
997 add esi, 1
998 loop OpcodeLoop
999
1000 /* Undo SEH frame */
1001 pop PCR[KPCR_EXCEPTION_LIST]
1002 add esp, 8
1003
1004 KmodeOpcode:
1005
1006 /* Re-enable interrupts */
1007 sti
1008
1009 /* Setup illegal instruction exception and dispatch it */
1010 mov ebx, [ebp+KTRAP_FRAME_EIP]
1011 mov eax, STATUS_ILLEGAL_INSTRUCTION
1012 jmp _DispatchNoParam
1013
1014 LockCrash:
1015
1016 /* Undo SEH Frame */
1017 pop PCR[KPCR_EXCEPTION_LIST]
1018 add esp, 8
1019
1020 /* Setup invalid lock exception and dispatch it */
1021 mov ebx, [ebp+KTRAP_FRAME_EIP]
1022 mov eax, STATUS_INVALID_LOCK_SEQUENCE
1023 jmp _DispatchNoParam
1024
1025 IsVdmOpcode:
1026
1027 /* Unhandled yet */
1028 UNHANDLED_PATH
1029
1030 /* Return to caller */
1031 jmp _Kei386EoiHelper@0
1032
1033 OpcodeSEH:
1034
1035 /* Get SEH frame */
1036 mov esp, [esp+8]
1037 pop PCR[KPCR_EXCEPTION_LIST]
1038 add esp, 4
1039 pop ebp
1040
1041 /* Check if this was user mode */
1042 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1043 jnz KmodeOpcode
1044
1045 /* Do a bugcheck */
1046 push ebp
1047 push 0
1048 push 0
1049 push 0
1050 push 0
1051 push KMODE_EXCEPTION_NOT_HANDLED
1052 call _KeBugCheckWithTf@24
1053 .endfunc
1054
1055 .func KiTrap7
1056 TRAP_FIXUPS kit7_a, kit7_t, DoFixupV86, DoNotFixupAbios
1057 _KiTrap7:
1058 /* Push error code */
1059 push 0
1060
1061 /* Enter trap */
1062 TRAP_PROLOG kit7_a, kit7_t
1063
1064 /* Get the current thread and stack */
1065 StartTrapHandle:
1066 mov eax, PCR[KPCR_CURRENT_THREAD]
1067 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1068 sub ecx, NPX_FRAME_LENGTH
1069
1070 /* Check if emulation is enabled */
1071 test byte ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
1072 jnz EmulationEnabled
1073
1074 CheckState:
1075 /* Check if the NPX state is loaded */
1076 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1077 mov ebx, cr0
1078 jz IsLoaded
1079
1080 /* Remove flags */
1081 and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
1082 mov cr0, ebx
1083
1084 /* Check the NPX thread */
1085 mov edx, PCR[KPCR_NPX_THREAD]
1086 or edx, edx
1087 jz NoNpxThread
1088
1089 /* Get the NPX Stack */
1090 mov esi, [edx+KTHREAD_INITIAL_STACK]
1091 sub esi, NPX_FRAME_LENGTH
1092
1093 /* Check if we have FXSR and check which operand to use */
1094 test byte ptr _KeI386FxsrPresent, 1
1095 jz FnSave
1096 fxsave [esi]
1097 jmp AfterSave
1098
1099 FnSave:
1100 fnsave [esi]
1101
1102 AfterSave:
1103 /* Set the thread's state to dirty */
1104 mov byte ptr [edx+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1105
1106 NoNpxThread:
1107 /* Check if we have FXSR and choose which operand to use */
1108 test byte ptr _KeI386FxsrPresent, 1
1109 jz FrRestore
1110 fxrstor [ecx]
1111 jmp AfterRestore
1112
1113 FrRestore:
1114 frstor [ecx]
1115
1116 AfterRestore:
1117 /* Set state loaded */
1118 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1119 mov PCR[KPCR_NPX_THREAD], eax
1120
1121 /* Enable interrupts to happen now */
1122 sti
1123 nop
1124
1125 /* Check if CR0 needs to be reloaded due to a context switch */
1126 cmp dword ptr [ecx+FN_CR0_NPX_STATE], 0
1127 jz _Kei386EoiHelper@0
1128
1129 /* We have to reload CR0... disable interrupts */
1130 cli
1131
1132 /* Get CR0 and update it */
1133 mov ebx, cr0
1134 or ebx, [ecx+FN_CR0_NPX_STATE]
1135 mov cr0, ebx
1136
1137 /* Restore interrupts and check if TS is back on */
1138 sti
1139 test bl, CR0_TS
1140 jz _Kei386EoiHelper@0
1141
1142 /* Clear TS, and loop handling again */
1143 clts
1144 cli
1145 jmp StartTrapHandle
1146
1147 KernelNpx:
1148
1149 /* Set delayed error */
1150 or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
1151
1152 /* Check if this happened during restore */
1153 cmp dword ptr [ebp+KTRAP_FRAME_EIP], offset FrRestore
1154 jnz UserNpx
1155
1156 /* Skip instruction and dispatch the exception */
1157 add dword ptr [ebp+KTRAP_FRAME_EIP], 3
1158 jmp _Kei386EoiHelper@0
1159
1160 IsLoaded:
1161 /* Check if TS is set */
1162 test bl, CR0_TS
1163 jnz TsSetOnLoadedState
1164
1165 HandleNpxFault:
1166 /* Check if the trap came from V86 mode */
1167 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1168 jnz V86Npx
1169
1170 /* Check if it came from kernel mode */
1171 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1172 jz KernelNpx
1173
1174 /* Check if it came from a VDM */
1175 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1176 jne V86Npx
1177
1178 UserNpx:
1179 /* Get the current thread */
1180 mov eax, PCR[KPCR_CURRENT_THREAD]
1181
1182 /* Check NPX state */
1183 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1184
1185 /* Get the NPX save area */
1186 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1187 lea ecx, [ecx-NPX_FRAME_LENGTH]
1188 jz NoSaveRestore
1189
1190 HandleUserNpx:
1191
1192 /* Set new CR0 */
1193 mov ebx, cr0
1194 and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
1195 mov cr0, ebx
1196
1197 /* Check if we have FX support */
1198 test byte ptr _KeI386FxsrPresent, 1
1199 jz FnSave2
1200
1201 /* Save the state */
1202 fxsave [ecx]
1203 jmp MakeCr0Dirty
1204 FnSave2:
1205 fnsave [ecx]
1206 wait
1207
1208 MakeCr0Dirty:
1209 /* Make CR0 state not loaded */
1210 or ebx, NPX_STATE_NOT_LOADED
1211 or ebx, [ecx+FN_CR0_NPX_STATE]
1212 mov cr0, ebx
1213
1214 /* Update NPX state */
1215 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1216 mov dword ptr PCR[KPCR_NPX_THREAD], 0
1217
1218 NoSaveRestore:
1219 /* Clear the TS bit and re-enable interrupts */
1220 and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
1221 sti
1222
1223 /* Check if we have FX support */
1224 test byte ptr _KeI386FxsrPresent, 1
1225 jz FnError
1226
1227 /* Get error offset, control and status words */
1228 mov ebx, [ecx+FX_ERROR_OFFSET]
1229 movzx eax, word ptr [ecx+FX_CONTROL_WORD]
1230 movzx edx, word ptr [ecx+FX_STATUS_WORD]
1231
1232 /* Get the faulting opcode */
1233 mov esi, [ecx+FX_DATA_OFFSET]
1234 jmp CheckError
1235
1236 FnError:
1237 /* Get error offset, control and status words */
1238 mov ebx, [ecx+FP_ERROR_OFFSET]
1239 movzx eax, word ptr [ecx+FP_CONTROL_WORD]
1240 movzx edx, word ptr [ecx+FP_STATUS_WORD]
1241
1242 /* Get the faulting opcode */
1243 mov esi, [ecx+FP_DATA_OFFSET]
1244
1245 CheckError:
1246 /* Mask exceptions */
1247 and eax, 0x3F
1248 not eax
1249 and eax, edx
1250
1251 /* Check if what's left is invalid */
1252 test al, 1
1253 jz ValidNpxOpcode
1254
1255 /* Check if it was a stack fault */
1256 test al, 64
1257 jnz InvalidStack
1258
1259 /* Raise exception */
1260 mov eax, STATUS_FLOAT_INVALID_OPERATION
1261 jmp _DispatchOneParamZero
1262
1263 InvalidStack:
1264
1265 /* Raise exception */
1266 mov eax, STATUS_FLOAT_STACK_CHECK
1267 jmp _DispatchTwoParamZero
1268
1269 ValidNpxOpcode:
1270
1271 /* Check for divide by 0 */
1272 test al, 4
1273 jz 1f
1274
1275 /* Raise exception */
1276 mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
1277 jmp _DispatchOneParamZero
1278
1279 1:
1280 /* Check for denormal */
1281 test al, 2
1282 jz 1f
1283
1284 /* Raise exception */
1285 mov eax, STATUS_FLOAT_INVALID_OPERATION
1286 jmp _DispatchOneParamZero
1287
1288 1:
1289 /* Check for overflow */
1290 test al, 8
1291 jz 1f
1292
1293 /* Raise exception */
1294 mov eax, STATUS_FLOAT_OVERFLOW
1295 jmp _DispatchOneParamZero
1296
1297 1:
1298 /* Check for underflow */
1299 test al, 16
1300 jz 1f
1301
1302 /* Raise exception */
1303 mov eax, STATUS_FLOAT_UNDERFLOW
1304 jmp _DispatchOneParamZero
1305
1306 1:
1307 /* Check for precision fault */
1308 test al, 32
1309 jz UnexpectedNpx
1310
1311 /* Raise exception */
1312 mov eax, STATUS_FLOAT_INEXACT_RESULT
1313 jmp _DispatchOneParamZero
1314
1315 UnexpectedNpx:
1316
1317 /* Strange result, bugcheck the OS */
1318 sti
1319 push ebp
1320 push 0
1321 push 0
1322 push eax
1323 push 1
1324 push TRAP_CAUSE_UNKNOWN
1325 call _KeBugCheckWithTf@24
1326
1327 V86Npx:
1328 /* Check if this is a VDM */
1329 mov eax, PCR[KPCR_CURRENT_THREAD]
1330 mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
1331 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1332 jz HandleUserNpx
1333
1334 /* V86 NPX not handled */
1335 UNHANDLED_PATH
1336
1337 EmulationEnabled:
1338 /* Did this come from kernel-mode? */
1339 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
1340 jz CheckState
1341
1342 /* It came from user-mode, so this would only be valid inside a VDM */
1343 /* Since we don't actually have VDMs in ROS, bugcheck. */
1344 jmp UnexpectedNpx
1345
1346 TsSetOnLoadedState:
1347 /* TS shouldn't be set, unless this we don't have a Math Processor */
1348 test bl, CR0_MP
1349 jnz BogusTrap
1350
1351 /* Strange that we got a trap at all, but ignore and continue */
1352 clts
1353 jmp _Kei386EoiHelper@0
1354
1355 BogusTrap:
1356 /* Cause a bugcheck */
1357 push 0
1358 push 0
1359 push ebx
1360 push 2
1361 push TRAP_CAUSE_UNKNOWN
1362 call _KeBugCheckEx@20
1363 .endfunc
1364
1365 .globl _KiTrap8
1366 .func KiTrap8
1367 _KiTrap8:
1368 /* Can't really do too much */
1369 mov eax, 8
1370 jmp _KiSystemFatalException
1371 .endfunc
1372
1373 .func KiTrap9
1374 TRAP_FIXUPS kit9_a, kit9_t, DoFixupV86, DoNotFixupAbios
1375 _KiTrap9:
1376 /* Push error code */
1377 push 0
1378
1379 /* Enter trap */
1380 TRAP_PROLOG kit9_a, kit9_t
1381
1382 /* Enable interrupts and bugcheck */
1383 sti
1384 mov eax, 9
1385 jmp _KiSystemFatalException
1386 .endfunc
1387
1388 .func KiTrap10
1389 TRAP_FIXUPS kita_a, kita_t, DoFixupV86, DoNotFixupAbios
1390 _KiTrap10:
1391 /* Enter trap */
1392 TRAP_PROLOG kita_a, kita_t
1393
1394 /* Check for V86 */
1395 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1396 jnz V86IntA
1397
1398 /* Check if the frame was from kernelmode */
1399 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1400 jz Fatal
1401
1402 V86IntA:
1403 /* Check if OF was set during iretd */
1404 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAG_ZERO
1405 sti
1406 jz Fatal
1407
1408 /* It was, just mask it out */
1409 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAG_ZERO
1410 jmp _Kei386EoiHelper@0
1411
1412 Fatal:
1413 /* TSS failure for some other reason: crash */
1414 mov eax, 10
1415 jmp _KiSystemFatalException
1416 .endfunc
1417
1418 .func KiTrap11
1419 TRAP_FIXUPS kitb_a, kitb_t, DoFixupV86, DoNotFixupAbios
1420 _KiTrap11:
1421 /* Enter trap */
1422 TRAP_PROLOG kitb_a, kitb_t
1423
1424 /* FIXME: ROS Doesn't handle segment faults yet */
1425 mov eax, 11
1426 jmp _KiSystemFatalException
1427 .endfunc
1428
1429 .func KiTrap12
1430 TRAP_FIXUPS kitc_a, kitc_t, DoFixupV86, DoNotFixupAbios
1431 _KiTrap12:
1432 /* Enter trap */
1433 TRAP_PROLOG kitc_a, kitc_t
1434
1435 /* FIXME: ROS Doesn't handle stack faults yet */
1436 mov eax, 12
1437 jmp _KiSystemFatalException
1438 .endfunc
1439
1440 .func KiTrapExceptHandler
1441 _KiTrapExceptHandler:
1442
1443 /* Setup SEH handler frame */
1444 mov esp, [esp+8]
1445 pop PCR[KPCR_EXCEPTION_LIST]
1446 add esp, 4
1447 pop ebp
1448
1449 /* Check if the fault came from user mode */
1450 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1451 jnz SetException
1452
1453 /* Kernel fault, bugcheck */
1454 push ebp
1455 push 0
1456 push 0
1457 push 0
1458 push 0
1459 push KMODE_EXCEPTION_NOT_HANDLED
1460 call _KeBugCheckWithTf@24
1461 .endfunc
1462
1463 .func KiTrap13
1464 TRAP_FIXUPS kitd_a, kitd_t, DoFixupV86, DoNotFixupAbios
1465 _KiTrap13:
1466
1467 /* It this a V86 GPF? */
1468 test dword ptr [esp+12], EFLAGS_V86_MASK
1469 jz NotV86
1470
1471 /* Enter V86 Trap */
1472 V86_TRAP_PROLOG kitd_a, kitd_v
1473
1474 /* Make sure that this is a V86 process */
1475 mov ecx, PCR[KPCR_CURRENT_THREAD]
1476 mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS]
1477 cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0
1478 jnz RaiseIrql
1479
1480 /* Otherwise, something is very wrong, raise an exception */
1481 sti
1482 jmp SetException
1483
1484 RaiseIrql:
1485
1486 /* Go to APC level */
1487 mov ecx, APC_LEVEL
1488 call @KfRaiseIrql@4
1489
1490 /* Save old IRQL and enable interrupts */
1491 push eax
1492 sti
1493
1494 /* Handle the opcode */
1495 call _Ki386HandleOpcodeV86@0
1496
1497 /* Check if this was VDM */
1498 test al, 0xFF
1499 jnz NoReflect
1500
1501 /* FIXME: TODO */
1502 UNHANDLED_PATH
1503
1504 NoReflect:
1505
1506 /* Lower IRQL and disable interrupts */
1507 pop ecx
1508 call @KfLowerIrql@4
1509 cli
1510
1511 /* Check if this was a V86 trap */
1512 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1513 jz NotV86Trap
1514
1515 /* Exit the V86 Trap */
1516 V86_TRAP_EPILOG
1517
1518 NotV86Trap:
1519
1520 /* Either this wasn't V86, or it was, but an APC interrupted us */
1521 jmp _Kei386EoiHelper@0
1522
1523 NotV86:
1524 /* Enter trap */
1525 TRAP_PROLOG kitd_a, kitd_t
1526
1527 /* Check if this was from kernel-mode */
1528 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1529 jnz UserModeGpf
1530
1531 /* Check if we have a VDM alert */
1532 cmp dword ptr PCR[KPCR_VDM_ALERT], 0
1533 jnz VdmAlertGpf
1534
1535 /* Check for GPF during GPF */
1536 mov eax, [ebp+KTRAP_FRAME_EIP]
1537 cmp eax, offset CheckPrivilegedInstruction
1538 jbe KmodeGpf
1539 cmp eax, offset CheckPrivilegedInstruction2
1540 jae KmodeGpf
1541
1542 /* FIXME: TODO */
1543 UNHANDLED_PATH
1544
1545 /* Get the opcode and trap frame */
1546 KmodeGpf:
1547 mov eax, [ebp+KTRAP_FRAME_EIP]
1548 mov eax, [eax]
1549 mov edx, [ebp+KTRAP_FRAME_EBP]
1550
1551 /* We want to check if this was POP [DS/ES/FS/GS] */
1552 add edx, KTRAP_FRAME_DS
1553 cmp al, 0x1F
1554 jz SegPopGpf
1555 add edx, KTRAP_FRAME_ES - KTRAP_FRAME_DS
1556 cmp al, 7
1557 jz SegPopGpf
1558 add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
1559 cmp ax, 0xA10F
1560 jz SegPopGpf
1561 add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
1562 cmp ax, 0xA90F
1563 jz SegPopGpf
1564
1565 /* It isn't, was it IRETD? */
1566 cmp al, 0xCF
1567 jne NotIretGpf
1568
1569 /* Get error code */
1570 lea edx, [ebp+KTRAP_FRAME_ESP]
1571 mov ax, [ebp+KTRAP_FRAME_ERROR_CODE]
1572 and ax, ~RPL_MASK
1573
1574 /* Get CS */
1575 mov cx, word ptr [edx+4]
1576 and cx, ~RPL_MASK
1577 cmp cx, ax
1578 jnz NotCsGpf
1579
1580 /* This should be a Ki386CallBios return */
1581 mov eax, offset _Ki386BiosCallReturnAddress
1582 cmp eax, [edx]
1583 jne NotBiosGpf
1584 mov eax, [edx+4]
1585 cmp ax, KGDT_R0_CODE + RPL_MASK
1586 jne NotBiosGpf
1587
1588 /* Jump to return address */
1589 jmp _Ki386BiosCallReturnAddress
1590
1591 NotBiosGpf:
1592 /* Check if the thread was in kernel mode */
1593 mov ebx, PCR[KPCR_CURRENT_THREAD]
1594 test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF
1595 jz UserModeGpf
1596
1597 /* Set RPL_MASK for check below */
1598 or word ptr [edx+4], RPL_MASK
1599
1600 NotCsGpf:
1601 /* Check if the IRET goes to user-mode */
1602 test dword ptr [edx+4], RPL_MASK
1603 jz UserModeGpf
1604
1605 /* Setup trap frame to copy */
1606 mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
1607 lea edx, [ebp+KTRAP_FRAME_ERROR_CODE]
1608
1609 TrapCopy:
1610
1611 /* Copy each field */
1612 mov eax, [edx]
1613 mov [edx+12], eax
1614 sub edx, 4
1615 loop TrapCopy
1616
1617 /* Enable interrupts and adjust stack */
1618 sti
1619 add esp, 12
1620 add ebp, 12
1621
1622 /* Setup exception record */
1623 mov ebx, [ebp+KTRAP_FRAME_EIP]
1624 mov esi, [ebp+KTRAP_FRAME_ERROR_CODE]
1625 and esi, 0xFFFF
1626 mov eax, STATUS_ACCESS_VIOLATION
1627 jmp _DispatchTwoParamZero
1628
1629 MsrCheck:
1630
1631 /* FIXME: Handle RDMSR/WRMSR */
1632 UNHANDLED_PATH
1633
1634 NotIretGpf:
1635
1636 /* Check if this was an MSR opcode */
1637 cmp al, 0xF
1638 jz MsrCheck
1639
1640 /* Check if DS is Ring 3 */
1641 cmp word ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
1642 jz CheckEs
1643
1644 /* Otherwise, fix it up */
1645 mov dword ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
1646 jmp ExitGpfTrap
1647
1648 CheckEs:
1649
1650 /* Check if ES is Ring 3 */
1651 cmp word ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
1652 jz UserModeGpf
1653
1654 /* Otherwise, fix it up */
1655 mov dword ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
1656 jmp ExitGpfTrap
1657
1658 SegPopGpf:
1659
1660 /* Sanity check */
1661 lea eax, [ebp+KTRAP_FRAME_ESP]
1662 cmp edx, eax
1663 jz HandleSegPop
1664 int 3
1665
1666 /* Handle segment POP fault by setting it to 0 */
1667 HandleSegPop:
1668 xor eax, eax
1669 mov dword ptr [edx], eax
1670
1671 ExitGpfTrap:
1672
1673 /* Do a trap exit */
1674 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoNotRestoreSegments, DoRestoreVolatiles, DoRestoreEverything
1675
1676 UserModeGpf:
1677
1678 /* If the previous mode was kernel, raise a fatal exception */
1679 mov eax, 13
1680 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1681 jz _KiSystemFatalException
1682
1683 /* Get the process and check which CS this came from */
1684 mov ebx, PCR[KPCR_CURRENT_THREAD]
1685 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
1686 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1687 jz CheckVdmGpf
1688
1689 /* Check if this is a VDM */
1690 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1691 jnz DispatchV86Gpf
1692
1693 /* Enable interrupts and check if we have an error code */
1694 sti
1695 cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
1696 jnz SetException
1697 jmp CheckPrivilegedInstruction
1698
1699 HandleSegPop2:
1700 /* Update EIP (will be updated below again) */
1701 add dword ptr [ebp+KTRAP_FRAME_EIP], 1
1702
1703 HandleEsPop:
1704 /* Clear the segment, update EIP and ESP */
1705 mov dword ptr [edx], 0
1706 add dword ptr [ebp+KTRAP_FRAME_EIP], 1
1707 add dword ptr [ebp+KTRAP_FRAME_ESP], 4
1708 jmp _Kei386EoiHelper@0
1709
1710 CheckVdmGpf:
1711 /* Check if this is a VDM */
1712 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1713 jz CheckPrivilegedInstruction
1714
1715 /* Bring interrupts back */
1716 sti
1717
1718 /* Check what kind of instruction this is */
1719 mov eax, [ebp+KTRAP_FRAME_EIP]
1720 mov eax, [eax]
1721
1722 /* FIXME: Check for BOP4 */
1723
1724 /* Check if this is POP ES */
1725 mov edx, ebp
1726 add edx, KTRAP_FRAME_ES
1727 cmp al, 0x07
1728 jz HandleEsPop
1729
1730 /* Check if this is POP FS */
1731 add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
1732 cmp ax, 0xA10F
1733 jz HandleSegPop2
1734
1735 /* Check if this is POP GS */
1736 add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
1737 cmp ax, 0xA90F
1738 jz HandleSegPop2
1739
1740 CheckPrivilegedInstruction:
1741 /* Bring interrupts back */
1742 sti
1743
1744 /* Setup a SEH handler */
1745 push ebp
1746 push offset _KiTrapExceptHandler
1747 push PCR[KPCR_EXCEPTION_LIST]
1748 mov PCR[KPCR_EXCEPTION_LIST], esp
1749
1750 /* Get EIP */
1751 mov esi, [ebp+KTRAP_FRAME_EIP]
1752
1753 /* Setup loop count */
1754 mov ecx, 15
1755
1756 InstLoop:
1757 /* Save loop count */
1758 push ecx
1759
1760 /* Get the instruction */
1761 lods byte ptr [esi]
1762
1763 /* Now lookup in the prefix table */
1764 mov ecx, 11
1765 mov edi, offset _KiTrapPrefixTable
1766 repnz scasb
1767
1768 /* Restore loop count */
1769 pop ecx
1770
1771 /* If it's not a prefix byte, check other instructions */
1772 jnz NotPrefixByte
1773
1774 /* Keep looping */
1775 loop InstLoop
1776
1777 /* Fixup the stack */
1778 pop PCR[KPCR_EXCEPTION_LIST]
1779 add esp, 8
1780
1781 /* Illegal instruction */
1782 jmp KmodeOpcode
1783
1784 NotPrefixByte:
1785 /* Check if it's a HLT */
1786 cmp al, 0x0F4
1787 je IsPrivInstruction
1788
1789 /* Check if the instruction has two bytes */
1790 cmp al, 0xF
1791 jne CheckRing3Io
1792
1793 /* Check if this is a LLDT or LTR */
1794 lods byte ptr [esi]
1795 cmp al, 0
1796 jne NotLldt
1797
1798 /* Check if this is an LLDT */
1799 lods byte ptr [esi]
1800 and al, 0x38
1801 cmp al, 0x10
1802 je IsPrivInstruction
1803
1804 /* Check if this is an LTR */
1805 cmp al, 0x18
1806 je IsPrivInstruction
1807
1808 /* Otherwise, access violation */
1809 jmp NotIoViolation
1810
1811 NotLldt:
1812 /* Check if this is LGDT or LIDT or LMSW */
1813 cmp al, 0x01
1814 jne NotGdt
1815
1816 /* Check if this is an LGDT */
1817 lods byte ptr [esi]
1818 and al, 0x38
1819 cmp al, 0x10
1820 je IsPrivInstruction
1821
1822 /* Check if this is an LIDT */
1823 cmp al, 0x18
1824 je IsPrivInstruction
1825
1826 /* Check if this is an LMSW */
1827 cmp al, 0x30
1828 je IsPrivInstruction
1829
1830 /* Otherwise, access violation */
1831 jmp NotIoViolation
1832
1833 NotGdt:
1834 /* Check if it's INVD or WBINVD */
1835 cmp al, 0x8
1836 je IsPrivInstruction
1837 cmp al, 0x9
1838 je IsPrivInstruction
1839
1840 /* Check if it's sysexit */
1841 cmp al, 0x35
1842 je IsPrivInstruction
1843
1844 /* Check if it's a DR move */
1845 cmp al, 0x26
1846 je IsPrivInstruction
1847
1848 /* Check if it's a CLTS */
1849 cmp al, 0x6
1850 je IsPrivInstruction
1851
1852 /* Check if it's a CR move */
1853 cmp al, 0x20
1854 jb NotIoViolation
1855
1856 /* Check if it's a DR move */
1857 cmp al, 0x24
1858 jbe IsPrivInstruction
1859
1860 /* Everything else is an access violation */
1861 jmp NotIoViolation
1862
1863 CheckRing3Io:
1864 /* Get EFLAGS and IOPL */
1865 mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
1866 and ebx, EFLAGS_IOPL
1867 shr ebx, 12
1868
1869 /* Check the CS's RPL mask */
1870 mov ecx, [ebp+KTRAP_FRAME_CS]
1871 and ecx, RPL_MASK
1872 cmp ebx, ecx
1873 jge NotIoViolation
1874
1875 CheckPrivilegedInstruction2:
1876 /* Check if this is a CLI or STI */
1877 cmp al, 0xFA
1878 je IsPrivInstruction
1879 cmp al, 0xFB
1880 je IsPrivInstruction
1881
1882 /* Setup I/O table lookup */
1883 mov ecx, 13
1884 mov edi, offset _KiTrapIoTable
1885
1886 /* Loopup in the table */
1887 repnz scasb
1888 jnz NotIoViolation
1889
1890 /* FIXME: Check IOPM!!! */
1891
1892 IsPrivInstruction:
1893 /* Cleanup the SEH frame */
1894 pop PCR[KPCR_EXCEPTION_LIST]
1895 add esp, 8
1896
1897 /* Setup the exception */
1898 mov ebx, [ebp+KTRAP_FRAME_EIP]
1899 mov eax, STATUS_PRIVILEGED_INSTRUCTION
1900 jmp _DispatchNoParam
1901
1902 NotIoViolation:
1903 /* Cleanup the SEH frame */
1904 pop PCR[KPCR_EXCEPTION_LIST]
1905 add esp, 8
1906
1907 SetException:
1908 /* Setup the exception */
1909 mov ebx, [ebp+KTRAP_FRAME_EIP]
1910 mov esi, -1
1911 mov eax, STATUS_ACCESS_VIOLATION
1912 jmp _DispatchTwoParamZero
1913
1914 DispatchV86Gpf:
1915 /* FIXME */
1916 UNHANDLED_PATH
1917 .endfunc
1918
1919 .func KiTrap14
1920 TRAP_FIXUPS kite_a, kite_t, DoFixupV86, DoNotFixupAbios
1921 _KiTrap14:
1922
1923 /* Enter trap */
1924 TRAP_PROLOG kite_a, kite_t
1925
1926 /* Check if we have a VDM alert */
1927 cmp dword ptr PCR[KPCR_VDM_ALERT], 0
1928 jnz VdmAlertGpf
1929
1930 /* Get the current thread */
1931 mov edi, PCR[KPCR_CURRENT_THREAD]
1932
1933 /* Get the stack address of the frame */
1934 lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
1935 sub eax, [edi+KTHREAD_INITIAL_STACK]
1936 jz NoFixUp
1937
1938 /* This isn't the base frame, check if it's the second */
1939 cmp eax, -KTRAP_FRAME_EFLAGS
1940 jb NoFixUp
1941
1942 /* Check if we have a TEB */
1943 mov eax, PCR[KPCR_TEB]
1944 or eax, eax
1945 jle NoFixUp
1946
1947 /* Fixup the frame */
1948 call _KiFixupFrame
1949
1950 /* Save CR2 */
1951 NoFixUp:
1952 mov edi, cr2
1953
1954 /* Check if this processor has the cmpxchg8b lock errata */
1955 cmp byte ptr _KiI386PentiumLockErrataPresent, 0
1956 jnz HandleLockErrata
1957
1958 NotLockErrata:
1959 /* HACK: Handle page faults with interrupts disabled */
1960 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
1961 je HandlePf
1962
1963 /* Enable interrupts and check if we got here with interrupts disabled */
1964 sti
1965 #ifdef HACK_ABOVE_FIXED
1966 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
1967 jz IllegalState
1968 #endif
1969
1970 HandlePf:
1971 /* Send trap frame and check if this is kernel-mode or usermode */
1972 push ebp
1973 mov eax, [ebp+KTRAP_FRAME_CS]
1974 and eax, MODE_MASK
1975 push eax
1976
1977 /* Send faulting address and check if this is read or write */
1978 push edi
1979 mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
1980 and eax, 1
1981 push eax
1982
1983 /* Call the access fault handler */
1984 call _MmAccessFault@16
1985 test eax, eax
1986 jl AccessFail
1987
1988 /* Access fault handled, return to caller */
1989 jmp _Kei386EoiHelper@0
1990
1991 AccessFail:
1992 /* First check if this is a fault in the S-LIST functions */
1993 mov ecx, offset _ExpInterlockedPopEntrySListFault@0
1994 cmp [ebp+KTRAP_FRAME_EIP], ecx
1995 jz SlistFault
1996
1997 /* Check if this is a fault in the syscall handler */
1998 mov ecx, offset CopyParams
1999 cmp [ebp+KTRAP_FRAME_EIP], ecx
2000 jz SysCallCopyFault
2001 mov ecx, offset ReadBatch
2002 cmp [ebp+KTRAP_FRAME_EIP], ecx
2003 jnz CheckVdmPf
2004
2005 /* FIXME: TODO */
2006 UNHANDLED_PATH
2007 jmp _Kei386EoiHelper@0
2008
2009 SysCallCopyFault:
2010 /* FIXME: TODO */
2011 UNHANDLED_PATH
2012 jmp _Kei386EoiHelper@0
2013
2014 /* Check if the fault occured in a V86 mode */
2015 CheckVdmPf:
2016 mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
2017 shr ecx, 1
2018 and ecx, 1
2019 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
2020 jnz VdmPF
2021
2022 /* Check if the fault occured in a VDM */
2023 mov esi, PCR[KPCR_CURRENT_THREAD]
2024 mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
2025 cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
2026 jz CheckStatus
2027
2028 /* Check if we this was in kernel-mode */
2029 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
2030 jz CheckStatus
2031 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
2032 jz CheckStatus
2033
2034 VdmPF:
2035 /* FIXME: TODO */
2036 UNHANDLED_PATH
2037
2038 /* Save EIP and check what kind of status failure we got */
2039 CheckStatus:
2040 mov esi, [ebp+KTRAP_FRAME_EIP]
2041 cmp eax, STATUS_ACCESS_VIOLATION
2042 je AccessViol
2043 cmp eax, STATUS_GUARD_PAGE_VIOLATION
2044 je SpecialCode
2045 cmp eax, STATUS_STACK_OVERFLOW
2046 je SpecialCode
2047
2048 /* Setup an in-page exception to dispatch */
2049 mov edx, ecx
2050 mov ebx, esi
2051 mov esi, edi
2052 mov ecx, 3
2053 mov edi, eax
2054 mov eax, STATUS_IN_PAGE_ERROR
2055 call _CommonDispatchException
2056
2057 AccessViol:
2058 /* Use more proper status code */
2059 mov eax, KI_EXCEPTION_ACCESS_VIOLATION
2060
2061 SpecialCode:
2062 /* Setup a normal page fault exception */
2063 mov ebx, esi
2064 mov edx, ecx
2065 mov esi, edi
2066 jmp _DispatchTwoParam
2067
2068 SlistFault:
2069 /* FIXME: TODO */
2070 UNHANDLED_PATH
2071
2072 IllegalState:
2073
2074 /* This is completely illegal, bugcheck the system */
2075 push ebp
2076 push esi
2077 push ecx
2078 push eax
2079 push edi
2080 push IRQL_NOT_LESS_OR_EQUAL
2081 call _KeBugCheckWithTf@24
2082
2083 VdmAlertGpf:
2084
2085 /* FIXME: NOT SUPPORTED */
2086 UNHANDLED_PATH
2087
2088 HandleLockErrata:
2089
2090 /* Fail if this isn't a write fault */
2091 test word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0x4
2092 jnz NotLockErrata
2093
2094 /* Also make sure the page fault is for IDT entry 6 */
2095 mov eax, PCR[KPCR_IDT]
2096 add eax, 0x30
2097 cmp eax, edi
2098 jne NotLockErrata
2099
2100 /*
2101 * This is a write fault to the Invalid Opcode handler entry.
2102 * We assume this is the lock errata and not a real write fault.
2103 */
2104
2105 /* Clear the error code */
2106 and dword ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
2107
2108 /* Check if this happened in V86 mode */
2109 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
2110 jnz VdmOpCodeFault
2111
2112 /* Dispatch this to the invalid opcode handler */
2113 jmp DispatchLockErrata
2114 .endfunc
2115
2116 .func KiTrap0F
2117 TRAP_FIXUPS kitf_a, kitf_t, DoFixupV86, DoNotFixupAbios
2118 _KiTrap0F:
2119 /* Push error code */
2120 push 0
2121
2122 /* Enter trap */
2123 TRAP_PROLOG kitf_a, kitf_t
2124 sti
2125
2126 /* Raise a fatal exception */
2127 mov eax, 15
2128 jmp _KiSystemFatalException
2129 .endfunc
2130
2131 .func KiTrap16
2132 TRAP_FIXUPS kit10_a, kit10_t, DoFixupV86, DoNotFixupAbios
2133 _KiTrap16:
2134 /* Push error code */
2135 push 0
2136
2137 /* Enter trap */
2138 TRAP_PROLOG kit10_a, kit10_t
2139
2140 /* Check if this is the NPX Thread */
2141 mov eax, PCR[KPCR_CURRENT_THREAD]
2142 cmp eax, PCR[KPCR_NPX_THREAD]
2143
2144 /* Get the initial stack and NPX frame */
2145 mov ecx, [eax+KTHREAD_INITIAL_STACK]
2146 lea ecx, [ecx-NPX_FRAME_LENGTH]
2147
2148 /* If this is a valid fault, handle it */
2149 jz HandleNpxFault
2150
2151 /* Otherwise, re-enable interrupts and set delayed error */
2152 sti
2153 or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
2154 jmp _Kei386EoiHelper@0
2155 .endfunc
2156
2157 .func KiTrap17
2158 TRAP_FIXUPS kit11_a, kit11_t, DoFixupV86, DoNotFixupAbios
2159 _KiTrap17:
2160 /* Push error code */
2161 push 0
2162
2163 /* Enter trap */
2164 TRAP_PROLOG kit11_a, kit11_t
2165
2166 /* FIXME: ROS Doesn't handle alignment faults yet */
2167 mov eax, 17
2168 jmp _KiSystemFatalException
2169 .endfunc
2170
2171 .globl _KiTrap19
2172 .func KiTrap19
2173 TRAP_FIXUPS kit19_a, kit19_t, DoFixupV86, DoNotFixupAbios
2174 _KiTrap19:
2175 /* Push error code */
2176 push 0
2177
2178 /* Enter trap */
2179 TRAP_PROLOG kit19_a, kit19_t
2180
2181 /* Check if this is the NPX Thread */
2182 mov eax, PCR[KPCR_CURRENT_THREAD]
2183 cmp eax, PCR[KPCR_NPX_THREAD]
2184
2185 /* If this is a valid fault, handle it */
2186 jz HandleXmmiFault
2187
2188 /* Otherwise, bugcheck */
2189 mov eax, 19
2190 jmp _KiSystemFatalException
2191
2192 HandleXmmiFault:
2193 /* Get the initial stack and NPX frame */
2194 mov ecx, [eax+KTHREAD_INITIAL_STACK]
2195 lea ecx, [ecx-NPX_FRAME_LENGTH]
2196
2197 /* Check if the trap came from V86 mode */
2198 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
2199 jnz V86Xmmi
2200
2201 /* Check if it came from kernel mode */
2202 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
2203 jz KernelXmmi
2204
2205 /* Check if it came from a VDM */
2206 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
2207 jne VdmXmmi
2208
2209 HandleUserXmmi:
2210 /* Set new CR0 */
2211 mov ebx, cr0
2212 and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
2213 mov cr0, ebx
2214
2215 /* Check if we have FX support */
2216 test byte ptr _KeI386FxsrPresent, 1
2217 jz XmmiFnSave2
2218
2219 /* Save the state */
2220 fxsave [ecx]
2221 jmp XmmiMakeCr0Dirty
2222 XmmiFnSave2:
2223 fnsave [ecx]
2224 wait
2225
2226 XmmiMakeCr0Dirty:
2227 /* Make CR0 state not loaded */
2228 or ebx, NPX_STATE_NOT_LOADED
2229 or ebx, [ecx+FN_CR0_NPX_STATE]
2230 mov cr0, ebx
2231
2232 /* Update NPX state */
2233 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
2234 mov dword ptr PCR[KPCR_NPX_THREAD], 0
2235
2236 /* Clear the TS bit and re-enable interrupts */
2237 and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
2238
2239 /* Re-enable interrupts for user-mode and send the exception */
2240 sti
2241 mov ebx, [ebp+KTRAP_FRAME_EIP]
2242
2243 /* Get MxCSR and get current mask (bits 7-12) */
2244 movzx eax, word ptr [ecx+FX_MXCSR]
2245 mov edx, eax
2246 shr edx, 7
2247 not edx
2248
2249 /* Set faulting opcode address to 0 */
2250 mov esi, 0
2251
2252 /* Apply legal exceptions mask */
2253 and eax, 0x3f
2254
2255 /* Apply the mask we got in MXCSR itself */
2256 and eax, edx
2257
2258 /* Check for invalid operation */
2259 test al, 1
2260 jz 1f
2261
2262 /* Raise exception */
2263 mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
2264 jmp _DispatchOneParamZero
2265
2266 1:
2267 /* Check for zero divide */
2268 test al, 2
2269 jz 1f
2270
2271 /* Raise exception */
2272 mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
2273 jmp _DispatchOneParamZero
2274
2275 1:
2276 /* Check for denormal */
2277 test al, 4
2278 jz 1f
2279
2280 /* Raise exception */
2281 mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
2282 jmp _DispatchOneParamZero
2283
2284 1:
2285 /* Check for overflow*/
2286 test al, 8
2287 jz 1f
2288
2289 /* Raise exception */
2290 mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
2291 jmp _DispatchOneParamZero
2292
2293 1:
2294 /* Check for denormal */
2295 test al, 16
2296 jz 1f
2297
2298 /* Raise exception */
2299 mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
2300 jmp _DispatchOneParamZero
2301
2302 1:
2303 /* Check for Precision */
2304 test al, 32
2305 jz UnexpectedXmmi
2306
2307 /* Raise exception */
2308 mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
2309 jmp _DispatchOneParamZero
2310
2311 UnexpectedXmmi:
2312 /* Strange result, bugcheck the OS */
2313 sti
2314 push ebp
2315 push 1
2316 push 0
2317 push eax
2318 push 13
2319 push TRAP_CAUSE_UNKNOWN
2320 call _KeBugCheckWithTf@24
2321
2322 VdmXmmi:
2323 /* Check if this is a VDM */
2324 mov eax, PCR[KPCR_CURRENT_THREAD]
2325 mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
2326 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
2327 jz HandleUserXmmi
2328
2329 V86Xmmi:
2330 /* V86 XMMI not handled */
2331 UNHANDLED_PATH
2332
2333 KernelXmmi:
2334 /* Another weird situation */
2335 push ebp
2336 push 2
2337 push 0
2338 push eax
2339 push 13
2340 push TRAP_CAUSE_UNKNOWN
2341 call _KeBugCheckWithTf@24
2342 .endfunc
2343
2344
2345 .func KiSystemFatalException
2346 _KiSystemFatalException:
2347
2348 /* Push the trap frame */
2349 push ebp
2350
2351 /* Push empty parameters */
2352 push 0
2353 push 0
2354 push 0
2355
2356 /* Push trap number and bugcheck code */
2357 push eax
2358 push UNEXPECTED_KERNEL_MODE_TRAP
2359 call _KeBugCheckWithTf@24
2360 ret
2361 .endfunc
2362
2363 .func KiCoprocessorError@0
2364 _KiCoprocessorError@0:
2365
2366 /* Get the NPX Thread's Initial stack */
2367 mov eax, PCR[KPCR_NPX_THREAD]
2368 mov eax, [eax+KTHREAD_INITIAL_STACK]
2369
2370 /* Make space for the FPU Save area */
2371 sub eax, SIZEOF_FX_SAVE_AREA
2372
2373 /* Set the CR0 State */
2374 mov dword ptr [eax+FN_CR0_NPX_STATE], 8
2375
2376 /* Update it */
2377 mov eax, cr0
2378 or eax, 8
2379 mov cr0, eax
2380
2381 /* Return to caller */
2382 ret
2383 .endfunc
2384
2385 .func Ki16BitStackException
2386 _Ki16BitStackException:
2387
2388 /* Save stack */
2389 push ss
2390 push esp
2391
2392 /* Go to kernel mode thread stack */
2393 mov eax, PCR[KPCR_CURRENT_THREAD]
2394 add esp, [eax+KTHREAD_INITIAL_STACK]
2395
2396 /* Switch to good stack segment */
2397 UNHANDLED_PATH
2398 .endfunc
2399
2400 /* UNEXPECTED INTERRUPT HANDLERS **********************************************/
2401
2402 .globl _KiStartUnexpectedRange@0
2403 _KiStartUnexpectedRange@0:
2404
2405 GENERATE_INT_HANDLERS
2406
2407 .globl _KiEndUnexpectedRange@0
2408 _KiEndUnexpectedRange@0:
2409 jmp _KiUnexpectedInterruptTail
2410
2411 .func KiUnexpectedInterruptTail
2412 TRAP_FIXUPS kui_a, kui_t, DoFixupV86, DoFixupAbios
2413 _KiUnexpectedInterruptTail:
2414
2415 /* Enter interrupt trap */
2416 INT_PROLOG kui_a, kui_t, DoNotPushFakeErrorCode
2417
2418 /* Increase interrupt count */
2419 inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
2420
2421 /* Put vector in EBX and make space for KIRQL */
2422 mov ebx, [esp]
2423 sub esp, 4
2424
2425 /* Begin interrupt */
2426 push esp
2427 push ebx
2428 push HIGH_LEVEL
2429 call _HalBeginSystemInterrupt@12
2430
2431 /* Check if it was spurious or not */
2432 or al, al
2433 jnz Handled
2434
2435 /* Spurious, ignore it */
2436 add esp, 8
2437 jmp _Kei386EoiHelper2ndEntry
2438
2439 Handled:
2440 /* Unexpected interrupt, print a message on debug builds */
2441 #if DBG
2442 push [esp+4]
2443 push offset _UnexpectedMsg
2444 call _DbgPrint
2445 add esp, 8
2446 #endif
2447
2448 /* Exit the interrupt */
2449 mov esi, $
2450 cli
2451 call _HalEndSystemInterrupt@8
2452 jmp _Kei386EoiHelper@0
2453 .endfunc
2454
2455 .globl _KiUnexpectedInterrupt
2456 _KiUnexpectedInterrupt:
2457
2458 /* Bugcheck with invalid interrupt code */
2459 push TRAP_CAUSE_UNKNOWN
2460 call _KeBugCheck@4
2461
2462 /* INTERRUPT HANDLERS ********************************************************/
2463
2464 .func KiDispatchInterrupt@0
2465 _KiDispatchInterrupt@0:
2466
2467 /* Get the PCR and disable interrupts */
2468 mov ebx, PCR[KPCR_SELF]
2469 cli
2470
2471 /* Check if we have to deliver DPCs, timers, or deferred threads */
2472 mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
2473 or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
2474 or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
2475 jz CheckQuantum
2476
2477 /* Save stack pointer and exception list, then clear it */
2478 push ebp
2479 push dword ptr [ebx+KPCR_EXCEPTION_LIST]
2480 mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
2481
2482 /* Save the stack and switch to the DPC Stack */
2483 mov edx, esp
2484 mov esp, [ebx+KPCR_PRCB_DPC_STACK]
2485 push edx
2486
2487 /* Deliver DPCs */
2488 mov ecx, [ebx+KPCR_PRCB]
2489 call @KiRetireDpcList@4
2490
2491 /* Restore stack and exception list */
2492 pop esp
2493 pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
2494 pop ebp
2495
2496 CheckQuantum:
2497
2498 /* Re-enable interrupts */
2499 sti
2500
2501 /* Check if we have quantum end */
2502 cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
2503 jnz QuantumEnd
2504
2505 /* Check if we have a thread to swap to */
2506 cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
2507 je Return
2508
2509 /* Make space on the stack to save registers */
2510 sub esp, 3 * 4
2511 mov [esp+8], esi
2512 mov [esp+4], edi
2513 mov [esp+0], ebp
2514
2515 /* Get the current thread */
2516 mov edi, [ebx+KPCR_CURRENT_THREAD]
2517
2518 #ifdef CONFIG_SMP
2519 /* Raise to synch level */
2520 call _KeRaiseIrqlToSynchLevel@0
2521
2522 /* Set context swap busy */
2523 mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1
2524
2525 /* Acquire the PRCB Lock */
2526 lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
2527 jnb GetNext
2528 lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]
2529 call @KefAcquireSpinLockAtDpcLevel@4
2530 #endif
2531
2532 GetNext:
2533 /* Get the next thread and clear it */
2534 mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
2535 and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
2536
2537 /* Set us as the current running thread */
2538 mov [ebx+KPCR_CURRENT_THREAD], esi
2539 mov byte ptr [esi+KTHREAD_STATE_], Running
2540 mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
2541
2542 /* Put thread in ECX and get the PRCB in EDX */
2543 mov ecx, edi
2544 lea edx, [ebx+KPCR_PRCB_DATA]
2545 call @KiQueueReadyThread@8
2546
2547 /* Set APC_LEVEL and do the swap */
2548 mov cl, APC_LEVEL
2549 call @KiSwapContextInternal@0
2550
2551 #ifdef CONFIG_SMP
2552 /* Lower IRQL back to dispatch */
2553 mov cl, DISPATCH_LEVEL
2554 call @KfLowerIrql@4
2555 #endif
2556
2557 /* Restore registers */
2558 mov ebp, [esp+0]
2559 mov edi, [esp+4]
2560 mov esi, [esp+8]
2561 add esp, 3*4
2562
2563 Return:
2564 /* All done */
2565 ret
2566
2567 QuantumEnd:
2568 /* Disable quantum end and process it */
2569 mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
2570 call _KiQuantumEnd@0
2571 ret
2572 .endfunc
2573
2574 .func KiInterruptTemplate
2575 _KiInterruptTemplate:
2576
2577 /* Enter interrupt trap */
2578 INT_PROLOG kit_a, kit_t, DoPushFakeErrorCode
2579
2580 _KiInterruptTemplate2ndDispatch:
2581 /* Dummy code, will be replaced by the address of the KINTERRUPT */
2582 mov edi, 0
2583
2584 _KiInterruptTemplateObject:
2585 /* Dummy jump, will be replaced by the actual jump */
2586 jmp _KeSynchronizeExecution@12
2587
2588 _KiInterruptTemplateDispatch:
2589 /* Marks the end of the template so that the jump above can be edited */
2590
2591 TRAP_FIXUPS kit_a, kit_t, DoFixupV86, DoFixupAbios
2592 .endfunc
2593
2594 .func KiChainedDispatch2ndLvl@0
2595 _KiChainedDispatch2ndLvl@0:
2596
2597 NextSharedInt:
2598 /* Raise IRQL if necessary */
2599 mov cl, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
2600 cmp cl, [edi+KINTERRUPT_IRQL]
2601 je 1f
2602 call @KfRaiseIrql@4
2603
2604 1:
2605 /* Acquire the lock */
2606 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
2607 GetIntLock2:
2608 ACQUIRE_SPINLOCK(esi, IntSpin2)
2609
2610 /* Make sure that this interrupt isn't storming */
2611 VERIFY_INT kid2
2612
2613 /* Save the tick count */
2614 mov esi, _KeTickCount
2615
2616 /* Call the ISR */
2617 mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
2618 push eax
2619 push edi
2620 call [edi+KINTERRUPT_SERVICE_ROUTINE]
2621
2622 /* Save the ISR result */
2623 mov bl, al
2624
2625 /* Check if the ISR timed out */
2626 add esi, _KiISRTimeout
2627 cmp _KeTickCount, esi
2628 jnc ChainedIsrTimeout
2629
2630 ReleaseLock2:
2631 /* Release the lock */
2632 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
2633 RELEASE_SPINLOCK(esi)
2634
2635 /* Lower IRQL if necessary */
2636 mov cl, [edi+KINTERRUPT_IRQL]
2637 cmp cl, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
2638 je 1f
2639 call @KfLowerIrql@4
2640
2641 1:
2642 /* Check if the interrupt is handled */
2643 or bl, bl
2644 jnz 1f
2645
2646 /* Try the next shared interrupt handler */
2647 mov eax, [edi+KINTERRUPT_INTERRUPT_LIST_HEAD]
2648 lea edi, [eax-KINTERRUPT_INTERRUPT_LIST_HEAD]
2649 jmp NextSharedInt
2650
2651 1:
2652 ret
2653
2654 #ifdef CONFIG_SMP
2655 IntSpin2:
2656 SPIN_ON_LOCK(esi, GetIntLock2)
2657 #endif
2658
2659 ChainedIsrTimeout:
2660 /* Print warning message */
2661 push [edi+KINTERRUPT_SERVICE_ROUTINE]
2662 push offset _IsrTimeoutMsg
2663 call _DbgPrint
2664 add esp,8
2665
2666 /* Break into debugger, then continue */
2667 int 3
2668 jmp ReleaseLock2
2669
2670 /* Cleanup verification */
2671 VERIFY_INT_END kid2, 0
2672 .endfunc
2673
2674 .func KiChainedDispatch@0
2675 _KiChainedDispatch@0:
2676
2677 /* Increase interrupt count */
2678 inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
2679
2680 /* Save trap frame */
2681 mov ebp, esp
2682
2683 /* Save vector and IRQL */
2684 mov eax, [edi+KINTERRUPT_VECTOR]
2685 mov ecx, [edi+KINTERRUPT_IRQL]
2686
2687 /* Save old irql */
2688 push eax
2689 sub esp, 4
2690
2691 /* Begin interrupt */
2692 push esp
2693 push eax
2694 push ecx
2695 call _HalBeginSystemInterrupt@12
2696
2697 /* Check if it was handled */
2698 or al, al
2699 jz SpuriousInt
2700
2701 /* Call the 2nd-level handler */
2702 call _KiChainedDispatch2ndLvl@0
2703
2704 /* Exit the interrupt */
2705 INT_EPILOG 0
2706 .endfunc
2707
2708 .func KiInterruptDispatch@0
2709 _KiInterruptDispatch@0:
2710
2711 /* Increase interrupt count */
2712 inc dword ptr PCR[KPCR_PRCB_INTERRUPT_COUNT]
2713
2714 /* Save trap frame */
2715 mov ebp, esp
2716
2717 /* Save vector and IRQL */
2718 mov eax, [edi+KINTERRUPT_VECTOR]
2719 mov ecx, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
2720
2721 /* Save old irql */
2722 push eax
2723 sub esp, 4
2724
2725 /* Begin interrupt */
2726 push esp
2727 push eax
2728 push ecx
2729 call _HalBeginSystemInterrupt@12
2730
2731 /* Check if it was handled */
2732 or al, al
2733 jz SpuriousInt
2734
2735 /* Acquire the lock */
2736 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
2737 GetIntLock:
2738 ACQUIRE_SPINLOCK(esi, IntSpin)
2739
2740 /* Make sure that this interrupt isn't storming */
2741 VERIFY_INT kid
2742
2743 /* Save the tick count */
2744 mov ebx, _KeTickCount
2745
2746 /* Call the ISR */
2747 mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
2748 push eax
2749 push edi
2750 call [edi+KINTERRUPT_SERVICE_ROUTINE]
2751
2752 /* Check if the ISR timed out */
2753 add ebx, _KiISRTimeout
2754 cmp _KeTickCount, ebx
2755 jnc IsrTimeout
2756
2757 ReleaseLock:
2758 /* Release the lock */
2759 RELEASE_SPINLOCK(esi)
2760
2761 /* Exit the interrupt */
2762 INT_EPILOG 0
2763
2764 SpuriousInt:
2765 /* Exit the interrupt */
2766 add esp, 8
2767 INT_EPILOG 1
2768
2769 #ifdef CONFIG_SMP
2770 IntSpin:
2771 SPIN_ON_LOCK(esi, GetIntLock)
2772 #endif
2773
2774 IsrTimeout:
2775 /* Print warning message */
2776 push [edi+KINTERRUPT_SERVICE_ROUTINE]
2777 push offset _IsrTimeoutMsg
2778 call _DbgPrint
2779 add esp,8
2780
2781 /* Break into debugger, then continue */
2782 int 3
2783 jmp ReleaseLock
2784
2785 /* Cleanup verification */
2786 VERIFY_INT_END kid, 0
2787 .endfunc
2788
2789 .globl _KeSynchronizeExecution@12
2790 .func KeSynchronizeExecution@12
2791 _KeSynchronizeExecution@12:
2792
2793 /* Save EBX and put the interrupt object in it */
2794 push ebx
2795 mov ebx, [esp+8]
2796
2797 /* Go to DIRQL */
2798 mov cl, [ebx+KINTERRUPT_SYNCHRONIZE_IRQL]
2799 call @KfRaiseIrql@4
2800 push eax
2801
2802 #ifdef CONFIG_SMP
2803 /* Acquire the interrupt spinlock FIXME: Write this in assembly */
2804 mov ecx, [ebx+KINTERRUPT_ACTUAL_LOCK]
2805 call @KefAcquireSpinLockAtDpcLevel@4
2806 #endif
2807
2808 /* Call the routine */
2809 push [esp+20]
2810 call [esp+20]
2811
2812 #ifdef CONFIG_SMP
2813 /* Release the interrupt spinlock FIXME: Write this in assembly */
2814 push eax
2815 mov ecx, [ebx+KINTERRUPT_ACTUAL_LOCK]
2816 call @KefReleaseSpinLockFromDpcLevel@4
2817 pop eax
2818 #endif
2819
2820 /* Lower IRQL */
2821 mov ebx, eax
2822 pop ecx
2823 call @KfLowerIrql@4
2824
2825 /* Return status */
2826 mov eax, ebx
2827 pop ebx
2828 ret 12
2829 .endfunc
2830
2831 /*++
2832 * Kii386SpinOnSpinLock
2833 *
2834 * FILLMEIN
2835 *
2836 * Params:
2837 * SpinLock - FILLMEIN
2838 *
2839 * Flags - FILLMEIN
2840 *
2841 * Returns:
2842 * None.
2843 *
2844 * Remarks:
2845 * FILLMEIN
2846 *
2847 *--*/
2848 .globl _Kii386SpinOnSpinLock@8
2849 .func Kii386SpinOnSpinLock@8
2850 _Kii386SpinOnSpinLock@8:
2851
2852 #ifdef CONFIG_SMP
2853 /* FIXME: TODO */
2854 int 3
2855 #endif
2856
2857 ret 8
2858 .endfunc