- Remove KD APIs from stub HAL, they've been in kdcom for a while (merge from kd...
[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 0x800
84 .long _KiIdt
85
86 .globl _KiUnexpectedEntrySize
87 _KiUnexpectedEntrySize:
88 .long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
89
90 _UnexpectedMsg:
91 .asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
92
93 _UnhandledMsg:
94 .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
95
96 _KiTrapPrefixTable:
97 .byte 0xF2 /* REP */
98 .byte 0xF3 /* REP INS/OUTS */
99 .byte 0x67 /* ADDR */
100 .byte 0xF0 /* LOCK */
101 .byte 0x66 /* OP */
102 .byte 0x2E /* SEG */
103 .byte 0x3E /* DS */
104 .byte 0x26 /* ES */
105 .byte 0x64 /* FS */
106 .byte 0x65 /* GS */
107 .byte 0x36 /* SS */
108
109 _KiTrapIoTable:
110 .byte 0xE4 /* IN */
111 .byte 0xE5 /* IN */
112 .byte 0xEC /* IN */
113 .byte 0xED /* IN */
114 .byte 0x6C /* INS */
115 .byte 0x6D /* INS */
116 .byte 0xE6 /* OUT */
117 .byte 0xE7 /* OUT */
118 .byte 0xEE /* OUT */
119 .byte 0xEF /* OUT */
120 .byte 0x6E /* OUTS */
121 .byte 0x6F /* OUTS */
122
123 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
124 .text
125
126 _KiGetTickCount:
127 _KiCallbackReturn:
128 _KiRaiseAssertion:
129 /* FIXME: TODO */
130 UNHANDLED_PATH
131
132 .func KiSystemService
133 Dr_kss: DR_TRAP_FIXUP
134 _KiSystemService:
135
136 /* Enter the shared system call prolog */
137 SYSCALL_PROLOG kss
138
139 /* Jump to the actual handler */
140 jmp SharedCode
141 .endfunc
142
143 .func KiFastCallEntry
144 Dr_FastCallDrSave: DR_TRAP_FIXUP
145 _KiFastCallEntry:
146
147 /* Enter the fast system call prolog */
148 FASTCALL_PROLOG FastCallDrSave
149
150 SharedCode:
151
152 /*
153 * Find out which table offset to use. Converts 0x1124 into 0x10.
154 * The offset is related to the Table Index as such: Offset = TableIndex x 10
155 */
156 mov edi, eax
157 shr edi, SERVICE_TABLE_SHIFT
158 and edi, SERVICE_TABLE_MASK
159 mov ecx, edi
160
161 /* Now add the thread's base system table to the offset */
162 add edi, [esi+KTHREAD_SERVICE_TABLE]
163
164 /* Get the true syscall ID and check it */
165 mov ebx, eax
166 and eax, SERVICE_NUMBER_MASK
167 cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
168
169 /* Invalid ID, try to load Win32K Table */
170 jnb KiBBTUnexpectedRange
171
172 /* Check if this was Win32K */
173 cmp ecx, SERVICE_TABLE_TEST
174 jnz NotWin32K
175
176 /* Get the TEB */
177 mov ecx, [fs:KPCR_TEB]
178
179 /* Check if we should flush the User Batch */
180 xor ebx, ebx
181 ReadBatch:
182 or ebx, [ecx+TEB_GDI_BATCH_COUNT]
183 jz NotWin32K
184
185 /* Flush it */
186 push edx
187 push eax
188 //call [_KeGdiFlushUserBatch]
189 pop eax
190 pop edx
191
192 NotWin32K:
193 /* Increase total syscall count */
194 inc dword ptr fs:[KPCR_SYSTEM_CALLS]
195
196 #ifdef DBG
197 /* Increase per-syscall count */
198 mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
199 jecxz NoCountTable
200 inc dword ptr [ecx+eax*4]
201 #endif
202
203 /* Users's current stack frame pointer is source */
204 NoCountTable:
205 mov esi, edx
206
207 /* Allocate room for argument list from kernel stack */
208 mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
209 xor ecx, ecx
210 mov cl, [eax+ebx]
211
212 /* Get pointer to function */
213 mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
214 mov ebx, [edi+eax*4]
215
216 /* Allocate space on our stack */
217 sub esp, ecx
218
219 /* Set the size of the arguments and the destination */
220 shr ecx, 2
221 mov edi, esp
222
223 /* Make sure we're within the User Probe Address */
224 cmp esi, _MmUserProbeAddress
225 jnb AccessViolation
226
227 CopyParams:
228 /* Copy the parameters */
229 rep movsd
230
231 /* Do the System Call */
232 call ebx
233
234 AfterSysCall:
235 #ifdef DBG
236 /* Make sure the user-mode call didn't return at elevated IRQL */
237 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
238 jz SkipCheck
239 mov esi, eax /* We need to save the syscall's return val */
240 call _KeGetCurrentIrql@0
241 or al, al
242 jnz InvalidIrql
243 mov eax, esi /* Restore it */
244
245 /* Get our temporary current thread pointer for sanity check */
246 mov ecx, fs:[KPCR_CURRENT_THREAD]
247
248 /* Make sure that we are not attached and that APCs are not disabled */
249 mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
250 or dl, dl
251 jnz InvalidIndex
252 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
253 or edx, edx
254 jnz InvalidIndex
255 #endif
256
257 SkipCheck:
258
259 /* Deallocate the kernel stack frame */
260 mov esp, ebp
261
262 KeReturnFromSystemCall:
263
264 /* Get the Current Thread */
265 mov ecx, [fs:KPCR_CURRENT_THREAD]
266
267 /* Restore the old trap frame pointer */
268 mov edx, [ebp+KTRAP_FRAME_EDX]
269 mov [ecx+KTHREAD_TRAP_FRAME], edx
270 .endfunc
271
272 .func KiServiceExit
273 _KiServiceExit:
274 /* Disable interrupts */
275 cli
276
277 /* Check for, and deliver, User-Mode APCs if needed */
278 CHECK_FOR_APC_DELIVER 1
279
280 /* Exit and cleanup */
281 TRAP_EPILOG FromSystemCall, DoRestorePreviousMode, DoNotRestoreSegments, DoNotRestoreVolatiles, DoRestoreEverything
282 .endfunc
283
284 KiBBTUnexpectedRange:
285
286 /* If this isn't a Win32K call, fail */
287 cmp ecx, SERVICE_TABLE_TEST
288 jne InvalidCall
289
290 /* Set up Win32K Table */
291 push edx
292 push ebx
293 call _PsConvertToGuiThread@0
294
295 /* Check return code */
296 or eax, eax
297
298 /* Restore registers */
299 pop eax
300 pop edx
301
302 /* Reset trap frame address */
303 mov ebp, esp
304 mov [esi+KTHREAD_TRAP_FRAME], ebp
305
306 /* Try the Call again, if we suceeded */
307 jz SharedCode
308
309 /*
310 * The Shadow Table should have a special byte table which tells us
311 * whether we should return FALSE, -1 or STATUS_INVALID_SYSTEM_SERVICE.
312 */
313
314 /* Get the table limit and base */
315 lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
316 mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
317 mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
318
319 /* Get the table address and add our index into the array */
320 lea edx, [edx+ecx*4]
321 and eax, SERVICE_NUMBER_MASK
322 add edx, eax
323
324 /* Find out what we should return */
325 movsx eax, byte ptr [edx]
326 or eax, eax
327
328 /* Return either 0 or -1, we've set it in EAX */
329 jle KeReturnFromSystemCall
330
331 /* Set STATUS_INVALID_SYSTEM_SERVICE */
332 mov eax, STATUS_INVALID_SYSTEM_SERVICE
333 jmp KeReturnFromSystemCall
334
335 InvalidCall:
336
337 /* Invalid System Call */
338 mov eax, STATUS_INVALID_SYSTEM_SERVICE
339 jmp KeReturnFromSystemCall
340
341 AccessViolation:
342
343 /* Check if this came from kernel-mode */
344 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
345
346 /* It's fine, go ahead with it */
347 jz CopyParams
348
349 /* Caller sent invalid parameters, fail here */
350 mov eax, STATUS_ACCESS_VIOLATION
351 jmp AfterSysCall
352
353 BadStack:
354
355 /* Restore ESP0 stack */
356 mov ecx, [fs:KPCR_TSS]
357 mov esp, ss:[ecx+KTSS_ESP0]
358
359 /* Generate V86M Stack for Trap 6 */
360 push 0
361 push 0
362 push 0
363 push 0
364
365 /* Generate interrupt stack for Trap 6 */
366 push KGDT_R3_DATA + RPL_MASK
367 push 0
368 push 0x20202
369 push KGDT_R3_CODE + RPL_MASK
370 push 0
371 jmp _KiTrap6
372
373 #ifdef DBG
374 InvalidIrql:
375 /* Save current IRQL */
376 push fs:[KPCR_IRQL]
377
378 /* Set us at passive */
379 mov dword ptr fs:[KPCR_IRQL], 0
380 cli
381
382 /* Bugcheck */
383 push 0
384 push 0
385 push eax
386 push ebx
387 push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
388 call _KeBugCheckEx@20
389
390 InvalidIndex:
391
392 /* Get the index and APC state */
393 movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
394 mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
395
396 /* Bugcheck */
397 push 0
398 push edx
399 push eax
400 push ebx
401 push APC_INDEX_MISMATCH
402 call _KeBugCheckEx@20
403 ret
404 #endif
405
406 .func KiServiceExit2
407 _KiServiceExit2:
408
409 /* Disable interrupts */
410 cli
411
412 /* Check for, and deliver, User-Mode APCs if needed */
413 CHECK_FOR_APC_DELIVER 0
414
415 /* Exit and cleanup */
416 TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
417 .endfunc
418
419 .func Kei386EoiHelper@0
420 _Kei386EoiHelper@0:
421
422 /* Disable interrupts */
423 cli
424
425 /* Check for, and deliver, User-Mode APCs if needed */
426 CHECK_FOR_APC_DELIVER 0
427
428 /* Exit and cleanup */
429 _Kei386EoiHelper2ndEntry:
430 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
431 .endfunc
432
433 V86_Exit:
434 /* Move to EDX position */
435 add esp, KTRAP_FRAME_EDX
436
437 /* Restore volatiles */
438 pop edx
439 pop ecx
440 pop eax
441
442 /* Move to non-volatiles */
443 lea esp, [ebp+KTRAP_FRAME_EDI]
444 pop edi
445 pop esi
446 pop ebx
447 pop ebp
448
449 /* Skip error code and return */
450 add esp, 4
451 iret
452
453 AbiosExit:
454 /* FIXME: TODO */
455 UNHANDLED_PATH
456
457 .func KiDebugService
458 Dr_kids: DR_TRAP_FIXUP
459 V86_kids: V86_TRAP_FIXUP
460 _KiDebugService:
461
462 /* Push error code */
463 push 0
464
465 /* Enter trap */
466 TRAP_PROLOG kids
467
468 /* Increase EIP so we skip the INT3 */
469 inc dword ptr [ebp+KTRAP_FRAME_EIP]
470
471 /* Call debug service dispatcher */
472 mov eax, [ebp+KTRAP_FRAME_EAX]
473 mov ecx, [ebp+KTRAP_FRAME_ECX]
474 mov edx, [ebp+KTRAP_FRAME_EDX]
475
476 /* Check for V86 mode */
477 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
478 jnz NotUserMode
479
480 /* Check if this is kernel or user-mode */
481 test byte ptr [ebp+KTRAP_FRAME_CS], 1
482 jz CallDispatch
483 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
484 jnz NotUserMode
485
486 /* Re-enable interrupts */
487 VdmProc:
488 sti
489
490 /* Call the debug routine */
491 CallDispatch:
492 mov esi, ecx
493 mov edi, edx
494 mov edx, eax
495 mov ecx, 3
496 push edi
497 push esi
498 push edx
499 call _KdpServiceDispatcher@12
500
501 NotUserMode:
502
503 /* Get the current process */
504 mov ebx, [fs:KPCR_CURRENT_THREAD]
505 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
506
507 /* Check if this is a VDM Process */
508 //cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
509 //jz VdmProc
510
511 /* Exit through common routine */
512 jmp _Kei386EoiHelper@0
513 .endfunc
514
515 .func NtRaiseException@12
516 _NtRaiseException@12:
517
518 /* NOTE: We -must- be called by Zw* to have the right frame! */
519 /* Push the stack frame */
520 push ebp
521
522 /* Get the current thread and restore its trap frame */
523 mov ebx, [fs:KPCR_CURRENT_THREAD]
524 mov edx, [ebp+KTRAP_FRAME_EDX]
525 mov [ebx+KTHREAD_TRAP_FRAME], edx
526
527 /* Set up stack frame */
528 mov ebp, esp
529
530 /* Get the Trap Frame in EBX */
531 mov ebx, [ebp+0]
532
533 /* Get the exception list and restore */
534 mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
535 mov [fs:KPCR_EXCEPTION_LIST], eax
536
537 /* Get the parameters */
538 mov edx, [ebp+16] /* Search frames */
539 mov ecx, [ebp+12] /* Context */
540 mov eax, [ebp+8] /* Exception Record */
541
542 /* Raise the exception */
543 push edx
544 push ebx
545 push 0
546 push ecx
547 push eax
548 call _KiRaiseException@20
549
550 /* Restore trap frame in EBP */
551 pop ebp
552 mov esp, ebp
553
554 /* Check the result */
555 or eax, eax
556 jz _KiServiceExit2
557
558 /* Restore debug registers too */
559 jmp _KiServiceExit
560 .endfunc
561
562 .func NtContinue@8
563 _NtContinue@8:
564
565 /* NOTE: We -must- be called by Zw* to have the right frame! */
566 /* Push the stack frame */
567 push ebp
568
569 /* Get the current thread and restore its trap frame */
570 mov ebx, [fs:KPCR_CURRENT_THREAD]
571 mov edx, [ebp+KTRAP_FRAME_EDX]
572 mov [ebx+KTHREAD_TRAP_FRAME], edx
573
574 /* Set up stack frame */
575 mov ebp, esp
576
577 /* Save the parameters */
578 mov eax, [ebp+0]
579 mov ecx, [ebp+8]
580
581 /* Call KiContinue */
582 push eax
583 push 0
584 push ecx
585 call _KiContinue@12
586
587 /* Check if we failed (bad context record) */
588 or eax, eax
589 jnz Error
590
591 /* Check if test alert was requested */
592 cmp dword ptr [ebp+12], 0
593 je DontTest
594
595 /* Test alert for the thread */
596 mov al, [ebx+KTHREAD_PREVIOUS_MODE]
597 push eax
598 call _KeTestAlertThread@4
599
600 DontTest:
601 /* Return to previous context */
602 pop ebp
603 mov esp, ebp
604 jmp _KiServiceExit2
605
606 Error:
607 pop ebp
608 mov esp, ebp
609 jmp _KiServiceExit
610 .endfunc
611
612 /* EXCEPTION DISPATCHERS *****************************************************/
613
614 .func CommonDispatchException
615 _CommonDispatchException:
616
617 /* Make space for an exception record */
618 sub esp, EXCEPTION_RECORD_LENGTH
619
620 /* Set it up */
621 mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
622 xor eax, eax
623 mov [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], eax
624 mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], eax
625 mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], ebx
626 mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx
627
628 /* Check parameter count */
629 cmp ecx, 0
630 jz NoParams
631
632 /* Get information */
633 lea ebx, [esp+SIZEOF_EXCEPTION_RECORD]
634 mov [ebx], edx
635 mov [ebx+4], esi
636 mov [ebx+8], edi
637
638 NoParams:
639
640 /* Set the record in ECX and check if this was V86 */
641 mov ecx, esp
642 test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
643 jz SetPreviousMode
644
645 /* Set V86 mode */
646 mov eax, 0xFFFF
647 jmp MaskMode
648
649 SetPreviousMode:
650
651 /* Get the caller's CS */
652 mov eax, [ebp+KTRAP_FRAME_CS]
653
654 MaskMode:
655 /* Check if it was user-mode or kernel-mode */
656 and eax, MODE_MASK
657
658 /* Dispatch the exception */
659 push 1
660 push eax
661 push ebp
662 push 0
663 push ecx
664 call _KiDispatchException@20
665
666 /* End the trap */
667 mov esp, ebp
668 jmp _Kei386EoiHelper@0
669 .endfunc
670
671 .func DispatchNoParam
672 _DispatchNoParam:
673 /* Call the common dispatcher */
674 xor ecx, ecx
675 call _CommonDispatchException
676 .endfunc
677
678 .func DispatchOneParam
679 _DispatchOneParam:
680 /* Call the common dispatcher */
681 xor edx, edx
682 mov ecx, 1
683 call _CommonDispatchException
684 .endfunc
685
686 .func DispatchTwoParam
687 _DispatchTwoParam:
688 /* Call the common dispatcher */
689 xor edx, edx
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 Dr_kit0: DR_TRAP_FIXUP
705 V86_kit0: V86_TRAP_FIXUP
706 _KiTrap0:
707 /* Push error code */
708 push 0
709
710 /* Enter trap */
711 TRAP_PROLOG kit0
712
713 /* Check for V86 */
714 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
715 jnz V86Int0
716
717 /* Check if the frame was from kernelmode */
718 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
719 jz SendException
720
721 /* Check the old mode */
722 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
723 jne VdmCheck
724
725 SendException:
726 /* Re-enable interrupts for user-mode and send the exception */
727 sti
728 mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO
729 mov ebx, [ebp+KTRAP_FRAME_EIP]
730 jmp _DispatchNoParam
731
732 VdmCheck:
733 /* Check if this is a VDM process */
734 mov ebx, [fs:KPCR_CURRENT_THREAD]
735 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
736 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
737 jz SendException
738
739 /* We don't support this yet! */
740 V86Int0:
741 /* FIXME: TODO */
742 UNHANDLED_PATH
743 .endfunc
744
745 .func KiTrap1
746 Dr_kit1: DR_TRAP_FIXUP
747 V86_kit1: V86_TRAP_FIXUP
748 _KiTrap1:
749 /* Push error code */
750 push 0
751
752 /* Enter trap */
753 TRAP_PROLOG kit1
754
755 /* Check for V86 */
756 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
757 jnz V86Int1
758
759 /* Check if the frame was from kernelmode */
760 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
761 jz PrepInt1
762
763 /* Check the old mode */
764 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
765 jne V86Int1
766
767 EnableInterrupts:
768 /* Enable interrupts for user-mode */
769 sti
770
771 PrepInt1:
772 /* Prepare the exception */
773 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAGS_TF
774 mov ebx, [ebp+KTRAP_FRAME_EIP]
775 mov eax, STATUS_SINGLE_STEP
776 jmp _DispatchNoParam
777
778 V86Int1:
779 /* Check if this is a VDM process */
780 mov ebx, [fs:KPCR_CURRENT_THREAD]
781 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
782 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
783 jz EnableInterrupts
784
785 /* We don't support VDM! */
786 UNHANDLED_PATH
787 .endfunc
788
789 .globl _KiTrap2
790 .func KiTrap2
791 _KiTrap2:
792
793 /* FIXME: This is an NMI, nothing like a normal exception */
794 mov eax, 2
795 jmp _KiSystemFatalException
796 .endfunc
797
798 .func KiTrap3
799 Dr_kit3: DR_TRAP_FIXUP
800 V86_kit3: V86_TRAP_FIXUP
801 _KiTrap3:
802 /* Push error code */
803 push 0
804
805 /* Enter trap */
806 TRAP_PROLOG kit3
807
808 /* Set status code */
809 mov eax, 0 //STATUS_SUCCESS
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 /* Prepare the exception */
830 mov esi, ecx
831 mov edi, edx
832 mov edx, eax
833
834 /* Setup EIP, NTSTATUS and parameter count, then dispatch */
835 mov ebx, [ebp+KTRAP_FRAME_EIP]
836 dec ebx
837 mov ecx, 3
838 mov eax, STATUS_BREAKPOINT
839 call _CommonDispatchException
840
841 V86Int3:
842 /* Check if this is a VDM process */
843 mov ebx, [fs:KPCR_CURRENT_THREAD]
844 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
845 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
846 jz EnableInterrupts3
847
848 /* We don't support VDM! */
849 UNHANDLED_PATH
850 .endfunc
851
852 .func KiTrap4
853 Dr_kit4: DR_TRAP_FIXUP
854 V86_kit4: V86_TRAP_FIXUP
855 _KiTrap4:
856 /* Push error code */
857 push 0
858
859 /* Enter trap */
860 TRAP_PROLOG kit4
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, [fs: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 Dr_kit5: DR_TRAP_FIXUP
896 V86_kit5: V86_TRAP_FIXUP
897 _KiTrap5:
898 /* Push error code */
899 push 0
900
901 /* Enter trap */
902 TRAP_PROLOG kit5
903
904 /* Check for V86 */
905 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
906 jnz V86Int5
907
908 /* Check if the frame was from kernelmode */
909 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
910 jnz CheckMode
911
912 /* It did, and this should never happen */
913 mov eax, 5
914 jmp _KiSystemFatalException
915
916 /* Check the old mode */
917 CheckMode:
918 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
919 jne VdmCheck5
920
921 /* Re-enable interrupts for user-mode and send the exception */
922 SendException5:
923 sti
924 mov eax, STATUS_ARRAY_BOUNDS_EXCEEDED
925 mov ebx, [ebp+KTRAP_FRAME_EIP]
926 jmp _DispatchNoParam
927
928 VdmCheck5:
929 /* Check if this is a VDM process */
930 mov ebx, [fs:KPCR_CURRENT_THREAD]
931 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
932 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
933 jz SendException5
934
935 /* We don't support this yet! */
936 V86Int5:
937 UNHANDLED_PATH
938 .endfunc
939
940 .func KiTrap6
941 Dr_kit6: DR_TRAP_FIXUP
942 V86_kit6: V86_TRAP_FIXUP
943 _KiTrap6:
944
945 /* It this a V86 GPF? */
946 test dword ptr [esp+8], EFLAGS_V86_MASK
947 jz NotV86UD
948
949 /* Enter V86 Trap */
950 V86_TRAP_PROLOG kit6
951
952 /* Not yet supported (Invalid OPCODE from V86) */
953 UNHANDLED_PATH
954
955 NotV86UD:
956 /* Push error code */
957 push 0
958
959 /* Enter trap */
960 TRAP_PROLOG kit6
961
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, fs:[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 fs:[KPCR_EXCEPTION_LIST]
988 mov fs:[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 fs:[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 fs:[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 fs:[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 Dr_kit7: DR_TRAP_FIXUP
1057 V86_kit7: V86_TRAP_FIXUP
1058 _KiTrap7:
1059 /* Push error code */
1060 push 0
1061
1062 /* Enter trap */
1063 TRAP_PROLOG kit7
1064
1065 /* Get the current thread and stack */
1066 StartTrapHandle:
1067 mov eax, [fs:KPCR_CURRENT_THREAD]
1068 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1069 sub ecx, NPX_FRAME_LENGTH
1070
1071 /* Check if emulation is enabled */
1072 test dword ptr [ecx+FN_CR0_NPX_STATE], CR0_EM
1073 jnz EmulationEnabled
1074
1075 CheckState:
1076 /* Check if the NPX state is loaded */
1077 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1078 mov ebx, cr0
1079 jz IsLoaded
1080
1081 /* Remove flags */
1082 and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
1083 mov cr0, ebx
1084
1085 /* Check the NPX thread */
1086 mov edx, [fs:KPCR_NPX_THREAD]
1087 or edx, edx
1088 jz NoNpxThread
1089
1090 /* Get the NPX Stack */
1091 mov esi, [edx+KTHREAD_INITIAL_STACK]
1092 sub esi, NPX_FRAME_LENGTH
1093
1094 /* Check if we have FXSR and check which operand to use */
1095 test byte ptr _KeI386FxsrPresent, 1
1096 jz FnSave
1097 fxsave [esi]
1098 jmp AfterSave
1099
1100 FnSave:
1101 fnsave [esi]
1102
1103 AfterSave:
1104 /* Set the thread's state to dirty */
1105 mov byte ptr [edx+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1106
1107 NoNpxThread:
1108 /* Check if we have FXSR and choose which operand to use */
1109 test byte ptr _KeI386FxsrPresent, 1
1110 jz FrRestore
1111 fxrstor [ecx]
1112 jmp AfterRestore
1113
1114 FrRestore:
1115 frstor [esi]
1116
1117 AfterRestore:
1118 /* Set state loaded */
1119 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_LOADED
1120 mov [fs:KPCR_NPX_THREAD], eax
1121
1122 /* Enable interrupts to happen now */
1123 sti
1124 nop
1125
1126 /* Check if CR0 needs to be reloaded due to a context switch */
1127 cmp dword ptr [ecx+FN_CR0_NPX_STATE], 0
1128 jz _Kei386EoiHelper@0
1129
1130 /* We have to reload CR0... disable interrupts */
1131 cli
1132
1133 /* Get CR0 and update it */
1134 mov ebx, cr0
1135 or ebx, [ecx+FN_CR0_NPX_STATE]
1136 mov cr0, ebx
1137
1138 /* Restore interrupts and check if TS is back on */
1139 sti
1140 test bl, CR0_TS
1141 jz _Kei386EoiHelper@0
1142
1143 /* Clear TS, and loop handling again */
1144 clts
1145 cli
1146 jmp StartTrapHandle
1147
1148 KernelNpx:
1149
1150 /* Set delayed error */
1151 or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
1152
1153 /* Check if this happened during restore */
1154 cmp dword ptr [ebp+KTRAP_FRAME_EIP], offset FrRestore
1155 jnz UserNpx
1156
1157 /* Skip instruction and dispatch the exception */
1158 add dword ptr [ebp+KTRAP_FRAME_EIP], 3
1159 jmp _Kei386EoiHelper@0
1160
1161 IsLoaded:
1162 /* Check if TS is set */
1163 test bl, CR0_TS
1164 jnz TsSetOnLoadedState
1165
1166 HandleNpxFault:
1167 /* Check if the trap came from V86 mode */
1168 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1169 jnz V86Npx
1170
1171 /* Check if it came from kernel mode */
1172 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1173 jz KernelNpx
1174
1175 /* Check if it came from a VDM */
1176 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1177 jne V86Npx
1178
1179 UserNpx:
1180 /* Get the current thread */
1181 mov eax, fs:[KPCR_CURRENT_THREAD]
1182
1183 /* Check NPX state */
1184 cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1185
1186 /* Get the NPX save area */
1187 mov ecx, [eax+KTHREAD_INITIAL_STACK]
1188 lea ecx, [ecx-NPX_FRAME_LENGTH]
1189 jz NoSaveRestore
1190
1191 HandleUserNpx:
1192
1193 /* Set new CR0 */
1194 mov ebx, cr0
1195 and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
1196 mov cr0, ebx
1197
1198 /* Check if we have FX support */
1199 test byte ptr _KeI386FxsrPresent, 1
1200 jz FnSave2
1201
1202 /* Save the state */
1203 fxsave [ecx]
1204 jmp MakeCr0Dirty
1205 FnSave2:
1206 fnsave [ecx]
1207 wait
1208
1209 MakeCr0Dirty:
1210 /* Make CR0 state not loaded */
1211 or ebx, NPX_STATE_NOT_LOADED
1212 or ebx, [ecx+FN_CR0_NPX_STATE]
1213 mov cr0, ebx
1214
1215 /* Update NPX state */
1216 mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
1217 mov dword ptr fs:[KPCR_NPX_THREAD], 0
1218
1219 NoSaveRestore:
1220 /* Clear the TS bit and re-enable interrupts */
1221 and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
1222 sti
1223
1224 /* Check if we have FX support */
1225 test byte ptr _KeI386FxsrPresent, 1
1226 jz FnError
1227
1228 /* Get error offset, control and status words */
1229 mov ebx, [ecx+FX_ERROR_OFFSET]
1230 movzx eax, word ptr [ecx+FX_CONTROL_WORD]
1231 movzx edx, word ptr [ecx+FX_STATUS_WORD]
1232
1233 /* Get the faulting opcode */
1234 mov esi, [ecx+FX_DATA_OFFSET]
1235 jmp CheckError
1236
1237 FnError:
1238 /* Get error offset, control and status words */
1239 mov ebx, [ecx+FP_ERROR_OFFSET]
1240 movzx eax, word ptr [ecx+FP_CONTROL_WORD]
1241 movzx edx, word ptr [ecx+FP_STATUS_WORD]
1242
1243 /* Get the faulting opcode */
1244 mov esi, [ecx+FP_DATA_OFFSET]
1245
1246 CheckError:
1247 /* Mask exceptions */
1248 and eax, 0x3F
1249 not eax
1250 and eax, edx
1251
1252 /* Check if what's left is invalid */
1253 test al, 1
1254 jz ValidNpxOpcode
1255
1256 /* Check if it was a stack fault */
1257 test al, 64
1258 jnz InvalidStack
1259
1260 /* Raise exception */
1261 mov eax, STATUS_FLOAT_INVALID_OPERATION
1262 jmp _DispatchOneParam
1263
1264 InvalidStack:
1265
1266 /* Raise exception */
1267 mov eax, STATUS_FLOAT_STACK_CHECK
1268 jmp _DispatchTwoParam
1269
1270 ValidNpxOpcode:
1271
1272 /* Check for divide by 0 */
1273 test al, 4
1274 jz 1f
1275
1276 /* Raise exception */
1277 mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
1278 jmp _DispatchOneParam
1279
1280 1:
1281 /* Check for denormal */
1282 test al, 2
1283 jz 1f
1284
1285 /* Raise exception */
1286 mov eax, STATUS_FLOAT_INVALID_OPERATION
1287 jmp _DispatchOneParam
1288
1289 1:
1290 /* Check for overflow */
1291 test al, 8
1292 jz 1f
1293
1294 /* Raise exception */
1295 mov eax, STATUS_FLOAT_OVERFLOW
1296 jmp _DispatchOneParam
1297
1298 1:
1299 /* Check for underflow */
1300 test al, 16
1301 jz 1f
1302
1303 /* Raise exception */
1304 mov eax, STATUS_FLOAT_UNDERFLOW
1305 jmp _DispatchOneParam
1306
1307 1:
1308 /* Check for precision fault */
1309 test al, 32
1310 jz UnexpectedNpx
1311
1312 /* Raise exception */
1313 mov eax, STATUS_FLOAT_INEXACT_RESULT
1314 jmp _DispatchOneParam
1315
1316 UnexpectedNpx:
1317
1318 /* Strange result, bugcheck the OS */
1319 sti
1320 push ebp
1321 push 0
1322 push 0
1323 push eax
1324 push 1
1325 push TRAP_CAUSE_UNKNOWN
1326 call _KeBugCheckWithTf@24
1327
1328 V86Npx:
1329 /* Check if this is a VDM */
1330 mov eax, fs:[KPCR_CURRENT_THREAD]
1331 mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
1332 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1333 jz HandleUserNpx
1334
1335 /* V86 NPX not handled */
1336 UNHANDLED_PATH
1337
1338 EmulationEnabled:
1339 /* Did this come from kernel-mode? */
1340 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
1341 jz CheckState
1342
1343 /* It came from user-mode, so this would only be valid inside a VDM */
1344 /* Since we don't actually have VDMs in ROS, bugcheck. */
1345 jmp UnexpectedNpx
1346
1347 TsSetOnLoadedState:
1348 /* TS shouldn't be set, unless this we don't have a Math Processor */
1349 test bl, CR0_MP
1350 jnz BogusTrap
1351
1352 /* Strange that we got a trap at all, but ignore and continue */
1353 clts
1354 jmp _Kei386EoiHelper@0
1355
1356 BogusTrap:
1357 /* Cause a bugcheck */
1358 push 0
1359 push 0
1360 push ebx
1361 push 2
1362 push TRAP_CAUSE_UNKNOWN
1363 call _KeBugCheckEx@20
1364 .endfunc
1365
1366 .globl _KiTrap8
1367 .func KiTrap8
1368 _KiTrap8:
1369
1370 /* Can't really do too much */
1371 mov eax, 8
1372 jmp _KiSystemFatalException
1373 .endfunc
1374
1375 .func KiTrap9
1376 Dr_kit9: DR_TRAP_FIXUP
1377 V86_kit9: V86_TRAP_FIXUP
1378 _KiTrap9:
1379 /* Push error code */
1380 push 0
1381
1382 /* Enter trap */
1383 TRAP_PROLOG kit9
1384
1385 /* Enable interrupts and bugcheck */
1386 sti
1387 mov eax, 9
1388 jmp _KiSystemFatalException
1389 .endfunc
1390
1391 .func KiTrap10
1392 Dr_kit10: DR_TRAP_FIXUP
1393 V86_kit10: V86_TRAP_FIXUP
1394 _KiTrap10:
1395 /* Enter trap */
1396 TRAP_PROLOG kit10
1397
1398 /* Check for V86 */
1399 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1400 jnz V86IntA
1401
1402 /* Check if the frame was from kernelmode */
1403 test word ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1404 jz Fatal
1405
1406 V86IntA:
1407 /* Check if OF was set during iretd */
1408 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAG_ZERO
1409 sti
1410 jz Fatal
1411
1412 /* It was, just mask it out */
1413 and dword ptr [ebp+KTRAP_FRAME_EFLAGS], ~EFLAG_ZERO
1414 jmp _Kei386EoiHelper@0
1415
1416 Fatal:
1417 /* TSS failure for some other reason: crash */
1418 mov eax, 10
1419 jmp _KiSystemFatalException
1420 .endfunc
1421
1422 .func KiTrap11
1423 Dr_kit11: DR_TRAP_FIXUP
1424 V86_kit11: V86_TRAP_FIXUP
1425 _KiTrap11:
1426 /* Enter trap */
1427 TRAP_PROLOG kit11
1428
1429 /* FIXME: ROS Doesn't handle segment faults yet */
1430 mov eax, 11
1431 jmp _KiSystemFatalException
1432 .endfunc
1433
1434 .func KiTrap12
1435 Dr_kit12: DR_TRAP_FIXUP
1436 V86_kit12: V86_TRAP_FIXUP
1437 _KiTrap12:
1438 /* Enter trap */
1439 TRAP_PROLOG kit12
1440
1441 /* FIXME: ROS Doesn't handle stack faults yet */
1442 mov eax, 12
1443 jmp _KiSystemFatalException
1444 .endfunc
1445
1446 .func KiTrapExceptHandler
1447 _KiTrapExceptHandler:
1448
1449 /* Setup SEH handler frame */
1450 mov esp, [esp+8]
1451 pop fs:[KPCR_EXCEPTION_LIST]
1452 add esp, 4
1453 pop ebp
1454
1455 /* Check if the fault came from user mode */
1456 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1457 jnz SetException
1458
1459 /* Kernel fault, bugcheck */
1460 push ebp
1461 push 0
1462 push 0
1463 push 0
1464 push 0
1465 push KMODE_EXCEPTION_NOT_HANDLED
1466 call _KeBugCheckWithTf@24
1467 .endfunc
1468
1469 .func KiTrap13
1470 Dr_kitd: DR_TRAP_FIXUP
1471 V86_kitd: V86_TRAP_FIXUP
1472 _KiTrap13:
1473
1474 /* It this a V86 GPF? */
1475 test dword ptr [esp+12], EFLAGS_V86_MASK
1476 jz NotV86
1477
1478 /* Enter V86 Trap */
1479 V86_TRAP_PROLOG kitd
1480
1481 /* Make sure that this is a V86 process */
1482 mov ecx, [fs:KPCR_CURRENT_THREAD]
1483 mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS]
1484 cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0
1485 jnz RaiseIrql
1486
1487 /* Otherwise, something is very wrong, raise an exception */
1488 sti
1489 mov ebx, [ebp+KTRAP_FRAME_EIP]
1490 mov esi, -1
1491 mov eax, STATUS_ACCESS_VIOLATION
1492 jmp _DispatchTwoParam
1493
1494 RaiseIrql:
1495
1496 /* Go to APC level */
1497 mov ecx, APC_LEVEL
1498 call @KfRaiseIrql@4
1499
1500 /* Save old IRQL and enable interrupts */
1501 push eax
1502 sti
1503
1504 /* Handle the opcode */
1505 call _Ki386HandleOpcodeV86@0
1506
1507 /* Check if this was VDM */
1508 test al, 0xFF
1509 jnz NoReflect
1510
1511 /* FIXME: TODO */
1512 UNHANDLED_PATH
1513
1514 NoReflect:
1515
1516 /* Lower IRQL and disable interrupts */
1517 pop ecx
1518 call @KfLowerIrql@4
1519 cli
1520
1521 /* Check if this was a V86 trap */
1522 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1523 jz NotV86Trap
1524
1525 /* Exit the V86 Trap */
1526 V86_TRAP_EPILOG
1527
1528 NotV86Trap:
1529
1530 /* Either this wasn't V86, or it was, but an APC interrupted us */
1531 jmp _Kei386EoiHelper@0
1532
1533 NotV86:
1534 /* Enter trap */
1535 TRAP_PROLOG kitd
1536
1537 /* Check if this was from kernel-mode */
1538 test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1539 jnz UserModeGpf
1540
1541 /* Check if we have a VDM alert */
1542 cmp dword ptr fs:[KPCR_VDM_ALERT], 0
1543 jnz VdmAlertGpf
1544
1545 /* Check for GPF during GPF */
1546 mov eax, [ebp+KTRAP_FRAME_EIP]
1547 cmp eax, offset CheckPrivilegedInstruction
1548 jbe KmodeGpf
1549 cmp eax, offset CheckPrivilegedInstruction2
1550
1551 /* FIXME: TODO */
1552 UNHANDLED_PATH
1553
1554 /* Get the opcode and trap frame */
1555 KmodeGpf:
1556 mov eax, [ebp+KTRAP_FRAME_EIP]
1557 mov eax, [eax]
1558 mov edx, [ebp+KTRAP_FRAME_EBP]
1559
1560 /* We want to check if this was POP [DS/ES/FS/GS] */
1561 add edx, KTRAP_FRAME_DS
1562 cmp al, 0x1F
1563 jz SegPopGpf
1564 add edx, KTRAP_FRAME_ES - KTRAP_FRAME_DS
1565 cmp al, 7
1566 jz SegPopGpf
1567 add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
1568 cmp ax, 0xA10F
1569 jz SegPopGpf
1570 add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
1571 cmp ax, 0xA90F
1572 jz SegPopGpf
1573
1574 /* It isn't, was it IRETD? */
1575 cmp al, 0xCF
1576 jne NotIretGpf
1577
1578 /* Get error code */
1579 lea edx, [ebp+KTRAP_FRAME_ESP]
1580 mov ax, [ebp+KTRAP_FRAME_ERROR_CODE]
1581 and ax, ~RPL_MASK
1582
1583 /* Get CS */
1584 mov cx, word ptr [edx+4]
1585 and cx, ~RPL_MASK
1586 cmp cx, ax
1587 jnz NotCsGpf
1588
1589 /* This should be a Ki386CallBios return */
1590 mov eax, offset _Ki386BiosCallReturnAddress
1591 cmp eax, [edx]
1592 jne NotBiosGpf
1593 mov eax, [edx+4]
1594 cmp ax, KGDT_R0_CODE + RPL_MASK
1595 jne NotBiosGpf
1596
1597 /* Jump to return address */
1598 jmp _Ki386BiosCallReturnAddress
1599
1600 NotBiosGpf:
1601 /* Check if the thread was in kernel mode */
1602 mov ebx, [fs:KPCR_CURRENT_THREAD]
1603 test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF
1604 jz UserModeGpf
1605
1606 /* Set RPL_MASK for check below */
1607 or word ptr [edx+4], RPL_MASK
1608
1609 NotCsGpf:
1610 /* Check if the IRET goes to user-mode */
1611 test dword ptr [edx+4], RPL_MASK
1612 jz UserModeGpf
1613
1614 /* Setup trap frame to copy */
1615 mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
1616 lea edx, [ebp+KTRAP_FRAME_ERROR_CODE]
1617
1618 TrapCopy:
1619
1620 /* Copy each field */
1621 mov eax, [edx]
1622 mov [edx+12], eax
1623 sub edx, 4
1624 loop TrapCopy
1625
1626 /* Enable interrupts and adjust stack */
1627 sti
1628 add esp, 12
1629 add ebp, 12
1630
1631 /* Setup exception record */
1632 mov ebx, [ebp+KTRAP_FRAME_EIP]
1633 mov esi, [ebp+KTRAP_FRAME_ERROR_CODE]
1634 and esi, 0xFFFF
1635 mov eax, STATUS_ACCESS_VIOLATION
1636 jmp _DispatchTwoParam
1637
1638 MsrCheck:
1639
1640 /* FIXME: Handle RDMSR/WRMSR */
1641 UNHANDLED_PATH
1642
1643 NotIretGpf:
1644
1645 /* Check if this was an MSR opcode */
1646 cmp al, 0xF
1647 jz MsrCheck
1648
1649 /* Check if DS is Ring 3 */
1650 cmp word ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
1651 jz CheckEs
1652
1653 /* Otherwise, fix it up */
1654 mov dword ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
1655 jmp ExitGpfTrap
1656
1657 CheckEs:
1658
1659 /* Check if ES is Ring 3 */
1660 cmp word ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
1661 jz UserModeGpf
1662
1663 /* Otherwise, fix it up */
1664 mov dword ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
1665 jmp ExitGpfTrap
1666
1667 SegPopGpf:
1668
1669 /* Sanity check */
1670 lea eax, [ebp+KTRAP_FRAME_ESP]
1671 cmp edx, eax
1672 jz HandleSegPop
1673 int 3
1674
1675 /* Handle segment POP fault by setting it to 0 */
1676 HandleSegPop:
1677 xor eax, eax
1678 mov dword ptr [edx], eax
1679
1680 ExitGpfTrap:
1681
1682 /* Do a trap exit */
1683 TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoNotRestoreSegments, DoRestoreVolatiles, DoRestoreEverything
1684
1685 UserModeGpf:
1686
1687 /* If the previous mode was kernel, raise a fatal exception */
1688 mov eax, 13
1689 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1690 jz _KiSystemFatalException
1691
1692 /* Get the process and check which CS this came from */
1693 mov ebx, fs:[KPCR_CURRENT_THREAD]
1694 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
1695 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1696 jz CheckVdmGpf
1697
1698 /* Check if this is a VDM */
1699 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1700 jnz DispatchV86Gpf
1701
1702 /* Enable interrupts and check if we have an error code */
1703 sti
1704 cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
1705 jnz SetException
1706 jmp CheckPrivilegedInstruction
1707
1708 HandleSegPop2:
1709 /* Update EIP (will be updated below again) */
1710 add dword ptr [ebp+KTRAP_FRAME_EIP], 1
1711
1712 HandleEsPop:
1713 /* Clear the segment, update EIP and ESP */
1714 mov dword ptr [edx], 0
1715 add dword ptr [ebp+KTRAP_FRAME_EIP], 1
1716 add dword ptr [ebp+KTRAP_FRAME_ESP], 4
1717 jmp _Kei386EoiHelper@0
1718
1719 CheckVdmGpf:
1720 /* Check if this is a VDM */
1721 cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
1722 jz CheckPrivilegedInstruction
1723
1724 /* Bring interrupts back */
1725 sti
1726
1727 /* Check what kind of instruction this is */
1728 mov eax, [ebp+KTRAP_FRAME_EIP]
1729 mov eax, [eax]
1730
1731 /* FIXME: Check for BOP4 */
1732
1733 /* Check if this is POP ES */
1734 mov edx, ebp
1735 add edx, KTRAP_FRAME_ES
1736 cmp al, 0x07
1737 jz HandleEsPop
1738
1739 /* Check if this is POP FS */
1740 add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES
1741 cmp ax, 0xA10F
1742 jz HandleSegPop2
1743
1744 /* Check if this is POP GS */
1745 add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
1746 cmp ax, 0xA90F
1747 jz HandleSegPop2
1748
1749 CheckPrivilegedInstruction:
1750 /* Bring interrupts back */
1751 sti
1752
1753 /* Setup a SEH handler */
1754 push ebp
1755 push offset _KiTrapExceptHandler
1756 push fs:[KPCR_EXCEPTION_LIST]
1757 mov fs:[KPCR_EXCEPTION_LIST], esp
1758
1759 /* Get EIP */
1760 mov esi, [ebp+KTRAP_FRAME_EIP]
1761
1762 /* Setup loop count */
1763 mov ecx, 15
1764
1765 InstLoop:
1766 /* Save loop count */
1767 push ecx
1768
1769 /* Get the instruction */
1770 lods byte ptr [esi]
1771
1772 /* Now lookup in the prefix table */
1773 mov ecx, 11
1774 mov edi, offset _KiTrapPrefixTable
1775 repnz scasb
1776
1777 /* Restore loop count */
1778 pop ecx
1779
1780 /* If it's not a prefix byte, check other instructions */
1781 jnz NotPrefixByte
1782
1783 /* FIXME */
1784 UNHANDLED_PATH
1785
1786 NotPrefixByte:
1787 /* FIXME: Check if it's a HLT */
1788
1789 /* Check if the instruction has two bytes */
1790 cmp al, 0xF
1791 jne CheckRing3Io
1792
1793 /* FIXME */
1794 UNHANDLED_PATH
1795
1796 CheckRing3Io:
1797 /* Get EFLAGS and IOPL */
1798 mov ebx, [ebp+KTRAP_FRAME_EFLAGS]
1799 and ebx, 0x3000
1800 shr ebx, 12
1801
1802 /* Check the CS's RPL mask */
1803 mov ecx, [ebp+KTRAP_FRAME_CS]
1804 and ecx, RPL_MASK
1805 cmp ebx, ecx
1806 jge NotIoViolation
1807
1808 CheckPrivilegedInstruction2:
1809 /* Check if this is a CLI or STI */
1810 cmp al, 0xFA
1811 je IsPrivInstruction
1812 cmp al, 0xFB
1813 je IsPrivInstruction
1814
1815 /* Setup I/O table lookup */
1816 mov ecx, 13
1817 mov edi, offset _KiTrapIoTable
1818
1819 /* Loopup in the table */
1820 repnz scasb
1821 jnz NotIoViolation
1822
1823 /* FIXME: Check IOPM!!! */
1824
1825 IsPrivInstruction:
1826 /* Cleanup the SEH frame */
1827 pop fs:[KPCR_EXCEPTION_LIST]
1828 add esp, 8
1829
1830 /* Setup the exception */
1831 mov ebx, [ebp+KTRAP_FRAME_EIP]
1832 mov eax, STATUS_PRIVILEGED_INSTRUCTION
1833 jmp _DispatchNoParam
1834
1835 NotIoViolation:
1836 /* Cleanup the SEH frame */
1837 pop fs:[KPCR_EXCEPTION_LIST]
1838 add esp, 8
1839
1840 SetException:
1841 /* Setup the exception */
1842 mov ebx, [ebp+KTRAP_FRAME_EIP]
1843 mov esi, -1
1844 mov eax, STATUS_ACCESS_VIOLATION
1845 jmp _DispatchTwoParam
1846
1847 DispatchV86Gpf:
1848 /* FIXME */
1849 UNHANDLED_PATH
1850 .endfunc
1851
1852 .func KiTrap14
1853 Dr_kit14: DR_TRAP_FIXUP
1854 V86_kit14: V86_TRAP_FIXUP
1855 _KiTrap14:
1856
1857 /* Enter trap */
1858 TRAP_PROLOG kit14
1859
1860 /* Check if we have a VDM alert */
1861 cmp dword ptr fs:[KPCR_VDM_ALERT], 0
1862 jnz VdmAlertGpf
1863
1864 /* Get the current thread */
1865 mov edi, fs:[KPCR_CURRENT_THREAD]
1866
1867 /* Get the stack address of the frame */
1868 lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
1869 sub eax, [edi+KTHREAD_INITIAL_STACK]
1870 jz NoFixUp
1871
1872 /* This isn't the base frame, check if it's the second */
1873 cmp eax, -KTRAP_FRAME_EFLAGS
1874 jb NoFixUp
1875
1876 /* Check if we have a TEB */
1877 mov eax, fs:[KPCR_TEB]
1878 or eax, eax
1879 jle NoFixUp
1880
1881 /* Fixup the frame */
1882 call _KiFixupFrame
1883
1884 /* Save CR2 */
1885 NoFixUp:
1886 mov edi, cr2
1887
1888 /* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
1889 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
1890 je HandlePf
1891
1892 /* Enable interrupts and check if we got here with interrupts disabled */
1893 sti
1894 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
1895 jz IllegalState
1896
1897 HandlePf:
1898 /* Send trap frame and check if this is kernel-mode or usermode */
1899 push ebp
1900 mov eax, [ebp+KTRAP_FRAME_CS]
1901 and eax, MODE_MASK
1902 push eax
1903
1904 /* Send faulting address and check if this is read or write */
1905 push edi
1906 mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
1907 and eax, 1
1908 push eax
1909
1910 /* Call the access fault handler */
1911 call _MmAccessFault@16
1912 test eax, eax
1913 jl AccessFail
1914
1915 /* Access fault handled, return to caller */
1916 jmp _Kei386EoiHelper@0
1917
1918 AccessFail:
1919 /* First check if this is a fault in the S-LIST functions */
1920 mov ecx, offset _ExpInterlockedPopEntrySListFault@0
1921 cmp [ebp+KTRAP_FRAME_EIP], ecx
1922 jz SlistFault
1923
1924 /* Check if this is a fault in the syscall handler */
1925 mov ecx, offset CopyParams
1926 cmp [ebp+KTRAP_FRAME_EIP], ecx
1927 jz SysCallCopyFault
1928 mov ecx, offset ReadBatch
1929 cmp [ebp+KTRAP_FRAME_EIP], ecx
1930 jnz CheckVdmPf
1931
1932 /* FIXME: TODO */
1933 UNHANDLED_PATH
1934 jmp _Kei386EoiHelper@0
1935
1936 SysCallCopyFault:
1937 /* FIXME: TODO */
1938 UNHANDLED_PATH
1939 jmp _Kei386EoiHelper@0
1940
1941 /* Check if the fault occured in a V86 mode */
1942 CheckVdmPf:
1943 mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
1944 and ecx, 1
1945 shr ecx, 1
1946 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
1947 jnz VdmPF
1948
1949 /* Check if the fault occured in a VDM */
1950 mov esi, fs:[KPCR_CURRENT_THREAD]
1951 mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
1952 cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
1953 jz CheckStatus
1954
1955 /* Check if we this was in kernel-mode */
1956 test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
1957 jz CheckStatus
1958 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
1959 jz CheckStatus
1960
1961 VdmPF:
1962 /* FIXME: TODO */
1963 UNHANDLED_PATH
1964
1965 /* Save EIP and check what kind of status failure we got */
1966 CheckStatus:
1967 mov esi, [ebp+KTRAP_FRAME_EIP]
1968 cmp eax, STATUS_ACCESS_VIOLATION
1969 je AccessViol
1970 cmp eax, STATUS_GUARD_PAGE_VIOLATION
1971 je SpecialCode
1972 cmp eax, STATUS_STACK_OVERFLOW
1973 je SpecialCode
1974
1975 /* Setup an in-page exception to dispatch */
1976 mov edx, ecx
1977 mov ebx, esi
1978 mov esi, edi
1979 mov ecx, 3
1980 mov edi, eax
1981 mov eax, STATUS_IN_PAGE_ERROR
1982 call _CommonDispatchException
1983
1984 AccessViol:
1985 /* Use more proper status code */
1986 mov eax, KI_EXCEPTION_ACCESS_VIOLATION
1987
1988 SpecialCode:
1989 /* Setup a normal page fault exception */
1990 mov ebx, esi
1991 mov edx, ecx
1992 mov esi, edi
1993 jmp _DispatchTwoParam
1994
1995 SlistFault:
1996 /* FIXME: TODO */
1997 UNHANDLED_PATH
1998
1999 IllegalState:
2000
2001 /* This is completely illegal, bugcheck the system */
2002 push ebp
2003 push esi
2004 push ecx
2005 push eax
2006 push edi
2007 push IRQL_NOT_LESS_OR_EQUAL
2008 call _KeBugCheckWithTf@24
2009
2010 VdmAlertGpf:
2011
2012 /* FIXME: NOT SUPPORTED */
2013 UNHANDLED_PATH
2014 .endfunc
2015
2016 .func KiTrap0F
2017 Dr_kit15: DR_TRAP_FIXUP
2018 V86_kit15: V86_TRAP_FIXUP
2019 _KiTrap0F:
2020 /* Push error code */
2021 push 0
2022
2023 /* Enter trap */
2024 TRAP_PROLOG kit15
2025 sti
2026
2027 /* Raise a fatal exception */
2028 mov eax, 15
2029 jmp _KiSystemFatalException
2030 .endfunc
2031
2032 .func KiTrap16
2033 Dr_kit16: DR_TRAP_FIXUP
2034 V86_kit16: V86_TRAP_FIXUP
2035 _KiTrap16:
2036 /* Push error code */
2037 push 0
2038
2039 /* Enter trap */
2040 TRAP_PROLOG kit16
2041
2042 /* Check if this is the NPX Thread */
2043 mov eax, fs:[KPCR_CURRENT_THREAD]
2044 cmp eax, fs:[KPCR_NPX_THREAD]
2045
2046 /* Get the initial stack and NPX frame */
2047 mov ecx, [eax+KTHREAD_INITIAL_STACK]
2048 lea ecx, [ecx-NPX_FRAME_LENGTH]
2049
2050 /* If this is a valid fault, handle it */
2051 jz HandleNpxFault
2052
2053 /* Otherwise, re-enable interrupts and set delayed error */
2054 sti
2055 or dword ptr [ecx+FN_CR0_NPX_STATE], CR0_TS
2056 jmp _Kei386EoiHelper@0
2057 .endfunc
2058
2059 .func KiTrap17
2060 Dr_kit17: DR_TRAP_FIXUP
2061 V86_kit17: V86_TRAP_FIXUP
2062 _KiTrap17:
2063 /* Push error code */
2064 push 0
2065
2066 /* Enter trap */
2067 TRAP_PROLOG kit17
2068
2069 /* FIXME: ROS Doesn't handle alignment faults yet */
2070 mov eax, 17
2071 jmp _KiSystemFatalException
2072 .endfunc
2073
2074 .func KiSystemFatalException
2075 _KiSystemFatalException:
2076
2077 /* Push the trap frame */
2078 push ebp
2079
2080 /* Push empty parameters */
2081 push 0
2082 push 0
2083 push 0
2084
2085 /* Push trap number and bugcheck code */
2086 push eax
2087 push UNEXPECTED_KERNEL_MODE_TRAP
2088 call _KeBugCheckWithTf@24
2089 ret
2090 .endfunc
2091
2092 .func KiCoprocessorError@0
2093 _KiCoprocessorError@0:
2094
2095 /* Get the NPX Thread's Initial stack */
2096 mov eax, [fs:KPCR_NPX_THREAD]
2097 mov eax, [eax+KTHREAD_INITIAL_STACK]
2098
2099 /* Make space for the FPU Save area */
2100 sub eax, SIZEOF_FX_SAVE_AREA
2101
2102 /* Set the CR0 State */
2103 mov dword ptr [eax+FN_CR0_NPX_STATE], 8
2104
2105 /* Update it */
2106 mov eax, cr0
2107 or eax, 8
2108 mov cr0, eax
2109
2110 /* Return to caller */
2111 ret
2112 .endfunc
2113
2114 .func Ki16BitStackException
2115 _Ki16BitStackException:
2116
2117 /* Save stack */
2118 push ss
2119 push esp
2120
2121 /* Go to kernel mode thread stack */
2122 mov eax, fs:[KPCR_CURRENT_THREAD]
2123 add esp, [eax+KTHREAD_INITIAL_STACK]
2124
2125 /* Switch to good stack segment */
2126 UNHANDLED_PATH
2127 .endfunc
2128
2129 /* UNEXPECTED INTERRUPT HANDLERS **********************************************/
2130
2131 .globl _KiStartUnexpectedRange@0
2132 _KiStartUnexpectedRange@0:
2133
2134 GENERATE_INT_HANDLERS
2135
2136 .globl _KiEndUnexpectedRange@0
2137 _KiEndUnexpectedRange@0:
2138 jmp _KiUnexpectedInterruptTail
2139
2140 .func KiUnexpectedInterruptTail
2141 V86_kui: V86_TRAP_FIXUP
2142 Dr_kui: DR_TRAP_FIXUP
2143 _KiUnexpectedInterruptTail:
2144
2145 /* Enter interrupt trap */
2146 INT_PROLOG kui, DoNotPushFakeErrorCode
2147
2148 /* Increase interrupt count */
2149 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
2150
2151 /* Put vector in EBX and make space for KIRQL */
2152 mov ebx, [esp]
2153 sub esp, 4
2154
2155 /* Begin interrupt */
2156 push esp
2157 push ebx
2158 push HIGH_LEVEL
2159 call _HalBeginSystemInterrupt@12
2160
2161 /* Check if it was spurious or not */
2162 or al, al
2163 jnz Handled
2164
2165 /* Spurious, ignore it */
2166 add esp, 8
2167 jmp _Kei386EoiHelper2ndEntry
2168
2169 Handled:
2170 /* Unexpected interrupt, print a message on debug builds */
2171 #if DBG
2172 push [esp+4]
2173 push offset _UnexpectedMsg
2174 call _DbgPrint
2175 add esp, 8
2176 #endif
2177
2178 /* Exit the interrupt */
2179 mov esi, $
2180 cli
2181 call _HalEndSystemInterrupt@8
2182 jmp _Kei386EoiHelper@0
2183 .endfunc
2184
2185 .globl _KiUnexpectedInterrupt
2186 _KiUnexpectedInterrupt:
2187
2188 /* Bugcheck with invalid interrupt code */
2189 push TRAP_CAUSE_UNKNOWN
2190 call _KeBugCheck@4
2191
2192 /* INTERRUPT HANDLERS ********************************************************/
2193
2194 .func KiDispatchInterrupt@0
2195 _KiDispatchInterrupt@0:
2196
2197 /* Get the PCR and disable interrupts */
2198 mov ebx, [fs:KPCR_SELF]
2199 cli
2200
2201 /* Check if we have to deliver DPCs, timers, or deferred threads */
2202 mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
2203 or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
2204 or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
2205 jz CheckQuantum
2206
2207 /* Save stack pointer and exception list, then clear it */
2208 push ebp
2209 push dword ptr [ebx+KPCR_EXCEPTION_LIST]
2210 mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
2211
2212 /* Save the stack and switch to the DPC Stack */
2213 mov edx, esp
2214 //mov esp, [ebx+KPCR_PRCB_DPC_STACK]
2215 push edx
2216
2217 /* Deliver DPCs */
2218 mov ecx, [ebx+KPCR_PRCB]
2219 call @KiRetireDpcList@4
2220
2221 /* Restore stack and exception list */
2222 pop esp
2223 pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
2224 pop ebp
2225
2226 CheckQuantum:
2227
2228 /* Re-enable interrupts */
2229 sti
2230
2231 /* Check if we have quantum end */
2232 cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
2233 jnz QuantumEnd
2234
2235 /* Check if we have a thread to swap to */
2236 cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
2237 je Return
2238
2239 /* Make space on the stack to save registers */
2240 sub esp, 3 * 4
2241 mov [esp+8], esi
2242 mov [esp+4], edi
2243 mov [esp+0], ebp
2244
2245 /* Get the current thread */
2246 mov edi, [ebx+KPCR_CURRENT_THREAD]
2247
2248 #ifdef CONFIG_SMP
2249 #error SMP Interrupt not handled!
2250 #endif
2251
2252 /* Get the next thread and clear it */
2253 mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
2254 and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
2255
2256 /* Set us as the current running thread */
2257 mov [ebx+KPCR_CURRENT_THREAD], esi
2258 mov byte ptr [esi+KTHREAD_STATE], Running
2259 mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
2260
2261 /* Put thread in ECX and get the PRCB in EDX */
2262 mov ecx, edi
2263 lea edx, [ebx+KPCR_PRCB_DATA]
2264 call @KiQueueReadyThread@8
2265
2266 /* Set APC_LEVEL and do the swap */
2267 mov cl, APC_LEVEL
2268 call @KiSwapContextInternal@0
2269
2270 /* Restore registers */
2271 mov ebp, [esp+0]
2272 mov edi, [esp+4]
2273 mov esi, [esp+8]
2274 add esp, 3*4
2275
2276 Return:
2277 /* All done */
2278 ret
2279
2280 QuantumEnd:
2281 /* Disable quantum end and process it */
2282 mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
2283 call _KiQuantumEnd@0
2284 ret
2285 .endfunc
2286
2287 .func KiInterruptTemplate
2288 V86_kit: V86_TRAP_FIXUP
2289 Dr_kit: DR_TRAP_FIXUP
2290 _KiInterruptTemplate:
2291
2292 /* Enter interrupt trap */
2293 INT_PROLOG kit, DoPushFakeErrorCode
2294 .endfunc
2295
2296 _KiInterruptTemplate2ndDispatch:
2297 /* Dummy code, will be replaced by the address of the KINTERRUPT */
2298 mov edi, 0
2299
2300 _KiInterruptTemplateObject:
2301 /* Dummy jump, will be replaced by the actual jump */
2302 jmp _KeSynchronizeExecution@12
2303
2304 _KiInterruptTemplateDispatch:
2305 /* Marks the end of the template so that the jump above can be edited */
2306
2307 .func KiChainedDispatch2ndLvl@0
2308 _KiChainedDispatch2ndLvl@0:
2309
2310 /* Not yet supported */
2311 UNHANDLED_PATH
2312 .endfunc
2313
2314 .func KiChainedDispatch@0
2315 _KiChainedDispatch@0:
2316
2317 /* Increase interrupt count */
2318 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
2319
2320 /* Save trap frame */
2321 mov ebp, esp
2322
2323 /* Save vector and IRQL */
2324 mov eax, [edi+KINTERRUPT_VECTOR]
2325 mov ecx, [edi+KINTERRUPT_IRQL]
2326
2327 /* Save old irql */
2328 push eax
2329 sub esp, 4
2330
2331 /* Begin interrupt */
2332 push esp
2333 push eax
2334 push ecx
2335 call _HalBeginSystemInterrupt@12
2336
2337 /* Check if it was handled */
2338 or al, al
2339 jz SpuriousInt
2340
2341 /* Call the 2nd-level handler */
2342 call _KiChainedDispatch2ndLvl@0
2343
2344 /* Exit the interrupt */
2345 mov esi, $
2346 cli
2347 call _HalEndSystemInterrupt@8
2348 jmp _Kei386EoiHelper@0
2349 .endfunc
2350
2351 .func KiInterruptDispatch@0
2352 _KiInterruptDispatch@0:
2353
2354 /* Increase interrupt count */
2355 inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
2356
2357 /* Save trap frame */
2358 mov ebp, esp
2359
2360 /* Save vector and IRQL */
2361 mov eax, [edi+KINTERRUPT_VECTOR]
2362 mov ecx, [edi+KINTERRUPT_SYNCHRONIZE_IRQL]
2363
2364 /* Save old irql */
2365 push eax
2366 sub esp, 4
2367
2368 /* Begin interrupt */
2369 push esp
2370 push eax
2371 push ecx
2372 call _HalBeginSystemInterrupt@12
2373
2374 /* Check if it was handled */
2375 or al, al
2376 jz SpuriousInt
2377
2378 /* Acquire the lock */
2379 GetIntLock:
2380 mov esi, [edi+KINTERRUPT_ACTUAL_LOCK]
2381 ACQUIRE_SPINLOCK(esi, IntSpin)
2382
2383 /* Call the ISR */
2384 mov eax, [edi+KINTERRUPT_SERVICE_CONTEXT]
2385 push eax
2386 push edi
2387 call [edi+KINTERRUPT_SERVICE_ROUTINE]
2388
2389 /* Release the lock */
2390 RELEASE_SPINLOCK(esi)
2391
2392 /* Exit the interrupt */
2393 cli
2394 call _HalEndSystemInterrupt@8
2395 jmp _Kei386EoiHelper@0
2396
2397 SpuriousInt:
2398 /* Exit the interrupt */
2399 add esp, 8
2400 jmp _Kei386EoiHelper@0
2401
2402 #ifdef CONFIG_SMP
2403 IntSpin:
2404 SPIN_ON_LOCK esi, GetIntLock
2405 #endif
2406 .endfunc