1/* 2 * FILE: ntoskrnl/ke/amd64/trap.S 3 * COPYRIGHT: See COPYING in the top level directory 4 * PURPOSE: System Traps, Entrypoints and Exitpoints 5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) 6 */ 7 8/* INCLUDES ******************************************************************/ 9 10#include <asm.inc> 11#include <ksamd64.inc> 12#include <trapamd64.inc> 13 14EXTERN KiDispatchException:PROC 15EXTERN FrLdrDbgPrint:DWORD 16EXTERN KeBugCheckWithTf:PROC 17EXTERN MmAccessFault:PROC 18EXTERN KiSystemFatalException:PROC 19EXTERN KiNpxNotAvailableFaultHandler:PROC 20EXTERN KiGeneralProtectionFaultHandler:PROC 21EXTERN KiXmmExceptionHandler:PROC 22EXTERN KiDeliverApc:PROC 23EXTERN KiDpcInterruptHandler:PROC 24 25#ifdef _WINKD_ 26EXTERN KdSetOwedBreakpoints:PROC 27#endif 28 29 30/* GLOBALS *******************************************************************/ 31 32.data 33 34PUBLIC MsgUnimplemented 35MsgUnimplemented: 36.asciz "WARNING: %s at %s:%d is UNIMPLEMENTED!\n" 37 38MsgPageFault: 39.asciz "Page fault! Code = 0x%x, RIP = %p, FaultingAddress = %p\n" 40 41MsgGeneralProtFault: 42.asciz "General protection fault at %p!\n" 43 44MsgBreakpointTrap: 45.asciz "BreakpointTrap at %p\n" 46 47MsgUnexpectedInterrupt: 48.asciz "UnexpectedInterrupt Vector=0x%02lx\n" 49 50MsgInvalidOpcodeFault: 51.asciz "Invalid opcode fault at %p!\n" 52 53MsgDoubleFault: 54.asciz "Double fault at %p, rbp=%p!\n" 55 56MsgTrapInfo: 57.asciz "Trap: %s at %p\n" 58 59MACRO(TRAPINFO, func) 60LOCAL label1, label2 61#if 0 62 jmp label2 63label1: .asciz "\func" 64label2: 65 push rax 66 push rcx 67 push rdx 68 push r8 69 push r9 70 push r10 71 push r11 72 sub rsp, 32 73 lea rcx, MsgTrapInfo[rip] 74 lea rdx, 1b[rip] 75 mov r8, [rbp + KTRAP_FRAME_Rip] 76 call qword ptr FrLdrDbgPrint[rip] 77 pop r11 78 pop r10 79 pop r9 80 pop r8 81 pop rdx 82 pop rcx 83 pop rax 84 add rsp, 32 85#endif 86ENDM 87 88/* Helper Macros *************************************************************/ 89 90MACRO(DispatchException, Status, Number, P1, P2, P3) 91 mov eax, Status 92 mov edx, Number 93 mov r9, P1 94 mov r10, P2 95 mov r11, P3 96 call InternalDispatchException 97ENDM 98 99MACRO(Fatal, BugcheckCode) 100 /* Bugcheck */ 101 mov ecx, BugcheckCode 102 mov rdx, rbp 103 call KiSystemFatalException 104ENDM 105 106 107/* FUNCTIONS *****************************************************************/ 108 109.code64 110 111ALIGN 8 112 113MACRO(UnexpectedVectorStub, Vector) 114 /* This nop is to make the relative jmp address 4 bytes aligned and to 115 make the whole code 8 bytes long */ 116 nop 117 /* This is a push instruction with 8bit operand. Since the instruction 118 sign extends the value to 32 bits, we need to offset it */ 119PUBLIC KxUnexpectedInterrupt&Vector 120KxUnexpectedInterrupt&Vector: 121 push (Vector - 128) 122 jmp KiUnexpectedInterrupt 123ENDM 124 125PUBLIC KiUnexpectedRange 126KiUnexpectedRange: 127Vector = 0 128REPEAT 256 129 UnexpectedVectorStub %Vector 130 Vector = Vector+1 131ENDR 132PUBLIC KiUnexpectedRangeEnd 133KiUnexpectedRangeEnd: 134 135PUBLIC KiInterruptDispatchTemplate 136KiInterruptDispatchTemplate: 137 /* This instruction pushes the return address on the stack, which is the 138 address of the interrupt object's DispatchCode member, then jumps 139 to the address stored in the interrupt object's DispatchAddress member */ 140 call qword ptr KiInterruptDispatchTemplate[rip - KINTERRUPT_DispatchCode + KINTERRUPT_DispatchAddress] 141 142 143// rbp = TrapFrame, eax = ExceptionCode, edx = NumParams, r9,r10,r11 = params 144FUNC InternalDispatchException 145 146 /* Allocate stack space for EXCEPTION_RECORD and KEXCEPTION_FRAME */ 147 sub rsp, EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH 148 .allocstack (EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH) 149 .endprolog 150 151 /* Set up EXCEPTION_RECORD */ 152 lea rcx, [rsp + KEXCEPTION_FRAME_LENGTH] 153 mov [rcx + EXCEPTION_RECORD_ExceptionCode], eax 154 xor rax, rax 155 mov [rcx + EXCEPTION_RECORD_ExceptionFlags], eax 156 mov [rcx + EXCEPTION_RECORD_ExceptionRecord], rax 157 mov rax, [rbp + KTRAP_FRAME_Rip] 158 mov [rcx + EXCEPTION_RECORD_ExceptionAddress], rax 159 mov [rcx + EXCEPTION_RECORD_NumberParameters], edx 160 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(00)], r9 161 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(08)], r10 162 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(10)], r11 163 164 /* Set up KEXCEPTION_FRAME */ 165 mov rax, [rbp + KTRAP_FRAME_Rbp] 166 mov [rsp + KEXCEPTION_FRAME_Rbp], rax 167 mov [rsp + KEXCEPTION_FRAME_Rbx], rbx 168 mov [rsp + KEXCEPTION_FRAME_Rdi], rdi 169 mov [rsp + KEXCEPTION_FRAME_Rsi], rsi 170 mov [rsp + KEXCEPTION_FRAME_R12], r12 171 mov [rsp + KEXCEPTION_FRAME_R13], r13 172 mov [rsp + KEXCEPTION_FRAME_R14], r14 173 mov [rsp + KEXCEPTION_FRAME_R15], r15 174 movdqa [rsp + KEXCEPTION_FRAME_Xmm6], xmm6 175 movdqa [rsp + KEXCEPTION_FRAME_Xmm7], xmm7 176 movdqa [rsp + KEXCEPTION_FRAME_Xmm8], xmm8 177 movdqa [rsp + KEXCEPTION_FRAME_Xmm9], xmm9 178 movdqa [rsp + KEXCEPTION_FRAME_Xmm10], xmm10 179 movdqa [rsp + KEXCEPTION_FRAME_Xmm11], xmm11 180 movdqa [rsp + KEXCEPTION_FRAME_Xmm12], xmm12 181 movdqa [rsp + KEXCEPTION_FRAME_Xmm13], xmm13 182 movdqa [rsp + KEXCEPTION_FRAME_Xmm14], xmm14 183 movdqa [rsp + KEXCEPTION_FRAME_Xmm15], xmm15 184 mov qword ptr [rsp + KEXCEPTION_FRAME_Return], 0 185 186 /* Call KiDispatchException */ 187 // rcx already points to ExceptionRecord 188 mov rdx, rsp // ExceptionFrame 189 mov r8, rbp // TrapFrame 190 mov r9b, [r8 + KTRAP_FRAME_PreviousMode] // PreviousMode 191 mov byte ptr [rsp + KEXCEPTION_FRAME_P5], 1 // FirstChance 192 call KiDispatchException 193 194 /* Restore registers */ 195 mov r12, [rsp + KEXCEPTION_FRAME_R12] 196 mov r13, [rsp + KEXCEPTION_FRAME_R13] 197 mov r14, [rsp + KEXCEPTION_FRAME_R14] 198 mov r15, [rsp + KEXCEPTION_FRAME_R15] 199 movdqa xmm6, [rsp + KEXCEPTION_FRAME_Xmm6] 200 movdqa xmm7, [rsp + KEXCEPTION_FRAME_Xmm7] 201 movdqa xmm8, [rsp + KEXCEPTION_FRAME_Xmm8] 202 movdqa xmm9, [rsp + KEXCEPTION_FRAME_Xmm9] 203 movdqa xmm10, [rsp + KEXCEPTION_FRAME_Xmm10] 204 movdqa xmm11, [rsp + KEXCEPTION_FRAME_Xmm11] 205 movdqa xmm12, [rsp + KEXCEPTION_FRAME_Xmm12] 206 movdqa xmm13, [rsp + KEXCEPTION_FRAME_Xmm13] 207 movdqa xmm14, [rsp + KEXCEPTION_FRAME_Xmm14] 208 movdqa xmm15, [rsp + KEXCEPTION_FRAME_Xmm15] 209 210 add rsp, EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH 211 ret 212ENDFUNC 213 214 215/* CPU EXCEPTION HANDLERS ****************************************************/ 216 217PUBLIC KiDivideErrorFault 218FUNC KiDivideErrorFault 219 /* Push pseudo error code */ 220 EnterTrap TF_SAVE_ALL 221 222 /* Enable interrupts */ 223 sti 224 225 /* Dispatch the exception */ 226 DispatchException STATUS_INTEGER_DIVIDE_BY_ZERO, 0, 0, 0, 0 227 228 /* Return */ 229 ExitTrap TF_SAVE_ALL 230ENDFUNC 231 232 233PUBLIC KiDebugTrapOrFault 234FUNC KiDebugTrapOrFault 235 /* Push pseudo error code */ 236 EnterTrap TF_SAVE_ALL 237 238 TRAPINFO KiDebugTrapOrFault 239 240 /* Check if the frame was from kernelmode */ 241 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 242 jz KiDebugTrapOrFaultKMode 243 244 /* Enable interrupts for user-mode */ 245 sti 246 247KiDebugTrapOrFaultKMode: 248 /* Dispatch the exception */ 249 DispatchException STATUS_SINGLE_STEP, 0, 0, 0, 0 250 251 /* Return */ 252 ExitTrap TF_SAVE_ALL 253ENDFUNC 254 255 256PUBLIC KiNmiInterrupt 257FUNC KiNmiInterrupt 258 /* Push pseudo error code */ 259 EnterTrap TF_SAVE_ALL 260 261 UNIMPLEMENTED KiNmiInterrupt 262 int 3 263 264 /* Return */ 265 ExitTrap TF_SAVE_ALL 266ENDFUNC 267 268 269PUBLIC KiBreakpointTrap 270FUNC KiBreakpointTrap 271 /* Push pseudo error code */ 272 EnterTrap TF_SAVE_ALL 273 274 /* Check if the frame was from kernelmode */ 275 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 276 jz KiBreakpointTrapKMode 277 278 /* Enable interrupts for user-mode */ 279 sti 280 281KiBreakpointTrapKMode: 282 /* Dispatch the exception */ 283 DispatchException STATUS_BREAKPOINT, 3, BREAKPOINT_BREAK, 0, 0 284 285 /* Return */ 286 ExitTrap TF_SAVE_ALL 287ENDFUNC 288 289 290PUBLIC KiOverflowTrap 291FUNC KiOverflowTrap 292 /* Push pseudo error code */ 293 EnterTrap TF_SAVE_ALL 294 295 /* Enable interrupts */ 296 sti 297 298 /* Dispatch the exception */ 299 DispatchException STATUS_INTEGER_OVERFLOW, 3, 0, 0, 0 300 301 /* Return */ 302 ExitTrap TF_SAVE_ALL 303ENDFUNC 304 305 306PUBLIC KiBoundFault 307FUNC KiBoundFault 308 /* Push pseudo error code */ 309 EnterTrap TF_SAVE_ALL 310 311 /* Check if the frame was from kernelmode */ 312 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 313 jnz KiBoundFaultUserMode 314 315 /* Bugcheck */ 316 Fatal EXCEPTION_BOUND_CHECK 317 318KiBoundFaultUserMode: 319 /* Enable interrupts for user-mode */ 320 sti 321 322 /* Dispatch the exception */ 323 DispatchException STATUS_ARRAY_BOUNDS_EXCEEDED, 0, 0, 0, 0 324 325 /* Return */ 326 ExitTrap TF_SAVE_ALL 327ENDFUNC 328 329 330PUBLIC KiInvalidOpcodeFault 331FUNC KiInvalidOpcodeFault 332 /* Push pseudo error code */ 333 EnterTrap TF_SAVE_ALL 334 335 TRAPINFO KiInvalidOpcodeFault 336 337 mov rdx, [rbp + KTRAP_FRAME_Rip] 338 lea rcx, MsgInvalidOpcodeFault[rip] 339 call qword ptr FrLdrDbgPrint[rip] 340 341 /* Enable interrupts */ 342 sti 343 344 /* Check if the frame was from kernelmode */ 345 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 346 jz KiInvalidOpcodeKernel 347 348 // FIXME: handle STATUS_INVALID_LOCK_SEQUENCE 349 350KiInvalidOpcodeKernel: 351 /* Kernel mode fault */ 352 353 /* Dispatch the exception */ 354 DispatchException STATUS_ILLEGAL_INSTRUCTION, 3, 0, 0, 0 355 356 /* Return */ 357 ExitTrap TF_SAVE_ALL 358ENDFUNC 359 360 361PUBLIC KiNpxNotAvailableFault 362FUNC KiNpxNotAvailableFault 363 /* Push pseudo error code */ 364 EnterTrap TF_SAVE_ALL 365 366 /* Call the C handler */ 367 mov rcx, rbp 368 call KiNpxNotAvailableFaultHandler 369 370 /* Check the return status code */ 371 test eax, eax 372 jz KiNpxNotAvailableFaultExit 373 374 /* Dispatch the exception */ 375 DispatchException eax, 3, 0, 0, 0 376 377KiNpxNotAvailableFaultExit: 378 /* Return */ 379 ExitTrap TF_SAVE_ALL 380ENDFUNC 381 382 383PUBLIC KiDoubleFaultAbort 384FUNC KiDoubleFaultAbort 385 /* A zero error code is pushed */ 386 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 387 388 lea rcx, MsgDoubleFault[rip] 389 mov rdx, [rbp + KTRAP_FRAME_FaultAddress] 390 mov r8, rbp 391 call qword ptr FrLdrDbgPrint[rip] 392 393 /* Bugcheck */ 394 Fatal 8 // EXCEPTION_DOUBLE_FAULT 395 jmp $ 396ENDFUNC 397 398 399PUBLIC KiNpxSegmentOverrunAbort 400FUNC KiNpxSegmentOverrunAbort 401 /* Push pseudo error code */ 402 EnterTrap TF_SAVE_ALL 403 404 /* Bugcheck */ 405 Fatal EXCEPTION_NPX_OVERRUN 406 407 jmp $ 408ENDFUNC 409 410 411PUBLIC KiInvalidTssFault 412FUNC KiInvalidTssFault 413 /* We have an error code */ 414 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 415 416 /* Bugcheck */ 417 Fatal EXCEPTION_INVALID_TSS 418 jmp $ 419ENDFUNC 420 421 422PUBLIC KiSegmentNotPresentFault 423FUNC KiSegmentNotPresentFault 424 /* We have an error code */ 425 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 426 427 /* Bugcheck */ 428 Fatal EXCEPTION_SEGMENT_NOT_PRESENT 429 jmp $ 430ENDFUNC 431 432 433PUBLIC KiStackFault 434FUNC KiStackFault 435 /* We have an error code */ 436 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 437 438 /* Bugcheck */ 439 Fatal EXCEPTION_STACK_FAULT 440 jmp $ 441ENDFUNC 442 443 444PUBLIC KiGeneralProtectionFault 445FUNC KiGeneralProtectionFault 446 /* We have an error code */ 447 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 448 449 //TRAPINFO KiGeneralProtectionFault 450 //mov rdx, [rbp + KTRAP_FRAME_Rip] 451 //lea rcx, MsgGeneralProtFault[rip] 452 //call qword ptr FrLdrDbgPrint[rip] 453 454 /* Call the C handler */ 455 mov rcx, rbp 456 call KiGeneralProtectionFaultHandler 457 458 /* Check for success */ 459 test eax, eax 460 jge KiGpfExit 461 462 /* Dispatch the exception */ 463 DispatchException eax, 3, 0, 0, 0 464 465KiGpfFatal: 466 467 /* Bugcheck */ 468 mov ecx, UNEXPECTED_KERNEL_MODE_TRAP 469 mov rdx, HEX(000D) // EXCEPTION_GP_FAULT 470 xor r8, r8 471 mov r9, [rbp + KTRAP_FRAME_ErrorCode] // error code 472 sub rsp, 8 473 mov [rsp + KTRAP_FRAME_P5+8], rbp // trap frame 474 call KeBugCheckWithTf 475 476KiGpfExit: 477 /* Return */ 478 /* Return */ 479 ExitTrap TF_SAVE_ALL 480ENDFUNC 481 482 483PUBLIC KiPageFault 484FUNC KiPageFault 485 /* We have an error code */ 486 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 487 488 TRAPINFO KiPageFault 489 490#if 0 491 lea rcx, MsgPageFault[rip] 492 mov rdx, [rbp + KTRAP_FRAME_ErrorCode] 493 mov r8, [rbp + KTRAP_FRAME_Rip] 494 mov r9, [rbp + KTRAP_FRAME_FaultAddress] 495 call qword ptr FrLdrDbgPrint[rip] 496#endif 497 498 /* Save page fault address */ 499 mov rdx, cr2 500 mov [rbp + KTRAP_FRAME_FaultAddress], rdx 501 502 /* Enable interrupts for the page fault handler */ 503 sti 504 505 /* Call page fault handler */ 506 mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // FaultCode 507 // rdx == Address 508 mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode 509 and r8b, 1 510 mov r9, rbp // TrapInformation 511 call MmAccessFault 512 513 /* Check for success */ 514 test eax, eax 515#ifndef _WINKD_ 516 jge PageFaultReturn 517#else 518 jl PageFaultError 519 520 /* Check whether the kernel debugger has owed breakpoints to be inserted */ 521 call KdSetOwedBreakpoints 522 /* We succeeded, return */ 523 jmp PageFaultReturn 524 525PageFaultError: 526#endif 527 528 /* Disable interrupts again for the debugger */ 529 cli 530 531 /* Set parameter 1 to error code */ 532 mov r9d, [rbp + KTRAP_FRAME_ErrorCode] 533 534 /* Set parameter2 to faulting address */ 535 mov r10, cr2 // Param2 = faulting address 536 537 cmp eax, STATUS_ACCESS_VIOLATION 538 je AccessViolation 539 cmp eax, STATUS_GUARD_PAGE_VIOLATION 540 je SpecialCode 541 cmp eax, STATUS_STACK_OVERFLOW 542 je SpecialCode 543 544InPageException: 545 /* Dispatch in-page exception */ 546 mov r11d, eax // Param3 = Status 547 mov eax, STATUS_IN_PAGE_ERROR // ExceptionCode 548 mov edx, 3 // ParamCount 549 call InternalDispatchException 550 jmp PageFaultReturn 551 552AccessViolation: 553 /* Use more proper status code */ 554 mov eax, KI_EXCEPTION_ACCESS_VIOLATION 555 556SpecialCode: 557 /* Setup a normal page fault exception */ 558 mov edx, 2 // ParamCount 559 call InternalDispatchException 560 561PageFaultReturn: 562 /* Return */ 563 ExitTrap (TF_SAVE_ALL or TF_CHECKUSERAPC) 564ENDFUNC 565 566 567PUBLIC KiFloatingErrorFault 568FUNC KiFloatingErrorFault 569 /* Push pseudo error code */ 570 EnterTrap TF_SAVE_ALL 571 572 UNIMPLEMENTED KiFloatingErrorFault 573 int 3 574 575 /* Return */ 576 ExitTrap TF_SAVE_ALL 577ENDFUNC 578 579 580PUBLIC KiAlignmentFault 581FUNC KiAlignmentFault 582 /* We have an error code */ 583 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 584 585 /* Bugcheck */ 586 Fatal EXCEPTION_ALIGNMENT_CHECK 587 jmp $ 588ENDFUNC 589 590 591PUBLIC KiMcheckAbort 592FUNC KiMcheckAbort 593 /* Push pseudo error code */ 594 EnterTrap TF_SAVE_ALL 595 596 /* Bugcheck */ 597 Fatal HEX(12) 598 jmp $ 599ENDFUNC 600 601 602PUBLIC KiXmmException 603FUNC KiXmmException 604 /* Push pseudo error code */ 605 EnterTrap TF_SAVE_ALL 606 607 /* Call the C handler */ 608 mov rcx, rbp 609 call KiXmmExceptionHandler 610 611 /* Check for success */ 612 test eax, eax 613 jge KiXmmExit 614 615 /* Dispatch the exception */ 616 DispatchException eax, 3, 0, 0, 0 617 618KiXmmExit: 619 /* Return */ 620 ExitTrap TF_SAVE_ALL 621ENDFUNC 622 623 624/* SOFTWARE INTERRUPT SERVICES ***********************************************/ 625 626PUBLIC KiRaiseAssertion 627FUNC KiRaiseAssertion 628 /* We have an error code */ 629 EnterTrap (TF_SAVE_ALL) 630 631 /* Decrement RIP to point to the INT2C instruction (2 bytes, not 1 like INT3) */ 632 sub qword ptr [rbp + KTRAP_FRAME_Rip], 2 633 634 /* Dispatch the exception */ 635 DispatchException STATUS_ASSERTION_FAILURE, 0, 0, 0, 0 636 637 /* Return */ 638 ExitTrap TF_SAVE_ALL 639ENDFUNC 640 641 642PUBLIC KiDebugServiceTrap 643FUNC KiDebugServiceTrap 644 /* No error code */ 645 EnterTrap TF_SAVE_ALL 646 647 TRAPINFO KiDebugServiceTrap 648 649 /* Increase Rip to skip the int3 */ 650 inc qword ptr [rbp + KTRAP_FRAME_Rip] 651 652 /* Dispatch the exception (Params = service, buffer, legth) */ 653 DispatchException STATUS_BREAKPOINT, 3, [rbp+KTRAP_FRAME_Rax], [rbp+KTRAP_FRAME_Rcx], [rbp+KTRAP_FRAME_Rdx] 654 655 /* Return */ 656 ExitTrap TF_SAVE_ALL 657ENDFUNC 658 659 660PUBLIC KiApcInterrupt 661.PROC KiApcInterrupt 662 /* No error code */ 663 EnterTrap (TF_VOLATILES or TF_IRQL) 664 665 /* Raise to APC_LEVEL */ 666 mov rax, APC_LEVEL 667 mov cr8, rax 668 669 /* End the interrupt */ 670 mov dword ptr [APIC_EOI], 0 671 672 /* Enable interrupts */ 673 sti 674 675 /* Call the worker routine */ 676 mov cl, [rbp + KTRAP_FRAME_SegCs] // ProcessorMode 677 and cl, 1 678 mov rdx, 0 // ExceptionFrame 679 mov r8, rdx // TrapFrame 680 call KiDeliverApc 681 682 /* Disable interrupts */ 683 cli 684 685 /* Lower IRQL back to PASSIVE */ 686 mov rax, PASSIVE_LEVEL 687 mov cr8, rax 688 689 /* Return */ 690 ExitTrap (TF_VOLATILES or TF_IRQL) 691.ENDP 692 693EXTERN KiRetireDpcList:PROC 694PUBLIC KiRetireDpcListInDpcStack 695.PROC KiRetireDpcListInDpcStack 696 push rbp 697 .pushreg rbp 698 mov rbp, rsp 699 .setframe rbp, 0 700 .endprolog 701 702 /* Switch stack and call the function */ 703 mov rsp, rdx 704 sub rsp, 40 705 call KiRetireDpcList 706 707 /* Restore stack, cleanup and return */ 708 mov rsp, rbp 709 pop rbp 710 ret 711.ENDP 712 713PUBLIC KiDpcInterrupt 714.PROC KiDpcInterrupt 715 /* No error code */ 716 EnterTrap (TF_VOLATILES or TF_IRQL) 717 718 /* Call the worker routine */ 719 call KiDpcInterruptHandler 720 721 /* Return, but don't send an EOI! */ 722 ExitTrap (TF_VOLATILES or TF_IRQL) 723.ENDP 724 725 726PUBLIC KiIpiInterrupt 727.PROC KiIpiInterrupt 728 /* No error code */ 729 EnterTrap (TF_VOLATILES or TF_IRQL) 730 731 /* Raise to IPI_LEVEL */ 732 mov rax, IPI_LEVEL 733 mov cr8, rax 734 735 /* End the interrupt */ 736 mov dword ptr [APIC_EOI], 0 737 738 int 3 739 740 /* Return */ 741 ExitTrap (TF_VOLATILES or TF_IRQL) 742.ENDP 743 744 745PUBLIC KiUnexpectedInterrupt 746FUNC KiUnexpectedInterrupt 747 /* The error code is the vector */ 748 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 749 750#if 0 751 /* Set bugcheck parameters */ 752 mov ecx, TRAP_CAUSE_UNKNOWN 753 mov rdx, [rbp + KTRAP_FRAME_ErrorCode] // the vector 754 mov r8, 0 // The unknown floating-point exception 755 mov r9, 0 // The enabled and asserted status bits 756 sub rsp, 8 757 mov [rbp + KTRAP_FRAME_P5 + 8], rbp // trap frame 758 call KeBugCheckWithTf 759 jmp $ 760#endif 761 /* Return */ 762 ExitTrap TF_SAVE_ALL 763ENDFUNC 764 765PUBLIC KiInterruptDispatch 766FUNC KiInterruptDispatch 767 /* The error code is a pointer to the interrupt object's code */ 768 EnterTrap (TF_HAS_ERROR_CODE or TF_SAVE_ALL or TF_IRQL) 769 770 /* Increase interrupt count */ 771 inc dword ptr gs:[PcInterruptCount]; 772 773 /* Load the address of the interrupt object into rcx */ 774 mov rcx, [rbp + KTRAP_FRAME_ErrorCode] 775 776 /* Substract offset of the DispatchCode member plus 6 for the call instruction */ 777 sub rcx, KINTERRUPT_DispatchCode + 6 778 779 /* Raise IRQL to SynchronizeIrql */ 780 movzx rax, byte ptr [rcx + KINTERRUPT_SynchronizeIrql] 781 mov cr8, rax 782 783#ifdef CONFIG_SMP 784 /* Acquire interrupt lock */ 785 mov r8, [rcx + KINTERRUPT_ActualLock] 786 787 //KxAcquireSpinLock(Interrupt->ActualLock); 788#endif 789 790 /* Call the ISR */ 791 mov rdx, [rcx + KINTERRUPT_ServiceContext] 792 call qword ptr [rcx + KINTERRUPT_ServiceRoutine] 793 794#ifdef CONFIG_SMP 795 /* Release interrupt lock */ 796 //KxReleaseSpinLock(Interrupt->ActualLock); 797#endif 798 799 /* Go back to old irql */ 800 movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql] 801 mov cr8, rax 802 803 /* Return */ 804 ExitTrap (TF_SAVE_ALL or TF_SEND_EOI) 805ENDFUNC 806 807 808#define MAX_SYSCALL_PARAM_SIZE (16 * 8) 809#define HOME_SIZE 6*8 810#define SYSCALL_ALLOCATION (MAX_SYSCALL_PARAM_SIZE + HOME_SIZE) 811 812EXTERN KiSystemCallHandler:PROC 813 814/*! \name KiSystemCallEntry64 815 * 816 * \brief This is the entrypoint for syscalls from 64bit user mode 817 * 818 * \param rax - The system call number 819 * \param rcx - User mode return address, set by the syscall instruction 820 * \param rdx,r8,r9 - Parameters 2-4 to the service function 821 * \param r10 - Parameter 1 to the service function 822 * \param r11 - RFLAGS saved by the syscall instruction 823 *--*/ 824PUBLIC KiSystemCallEntry64 825.PROC KiSystemCallEntry64 826 827 /* Old stack pointer is in rcx, lie and say we saved it in rbp */ 828 .setframe rbp, 0 829 .endprolog 830 831 /* Swap gs to kernel, so we can access the PCR */ 832 swapgs 833 834 /* Save the user mode rsp in the PCR */ 835 mov gs:[PcUserRsp], rsp 836 837 /* Get the kernel stack from the PCR */ 838 mov rsp, gs:[PcRspBase] 839 840 /* Allocate a TRAP_FRAME and space for parameters */ 841 sub rsp, (KTRAP_FRAME_LENGTH + MAX_SYSCALL_PARAM_SIZE + HOME_SIZE) 842#if DBG 843 /* Save rbp and load it with the old stack pointer */ 844 mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + HOME_SIZE + KTRAP_FRAME_Rbp], rbp 845 mov rbp, gs:[PcUserRsp] 846#endif 847 848 /* Save important volatiles in the trap frame */ 849 mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rax], rax 850 mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx], rcx 851 mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R10], r10 852 mov [rsp + HOME_SIZE + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R11], r11 853 854 /* Set sane segments */ 855 mov ax, (KGDT64_R3_DATA or RPL_MASK) 856 mov ds, ax 857 mov es, ax 858 859 /* Call the C-handler (will enable interrupts) */ 860 lea rcx, [rsp + SYSCALL_ALLOCATION] 861 call KiSystemCallHandler 862 863 /* Deallocate the handlers home stack frame */ 864 add rsp, HOME_SIZE 865 866 /* The return value is the address of the Nt-function */ 867 mov rcx, [rsp + 0] 868 mov rdx, [rsp + 8] 869 mov r8, [rsp + 16] 870 mov r9, [rsp + 24] 871 call rax 872 873#if DBG 874 /* Restore rbp */ 875 mov rbp, [rsp + SYSCALL_ALLOCATION + KTRAP_FRAME_Rbp] 876#endif 877 878 /* Disable interrupts for return */ 879 cli 880 881 /* Restore old trap frame */ 882 mov rcx, gs:[PcCurrentThread] 883 mov rdx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_TrapFrame] 884 mov [rcx + KTHREAD_TrapFrame], rdx 885 886 /* Prepare user mode return address (rcx) and eflags (r11) for sysret */ 887 mov rcx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx] 888 mov r11, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R11] 889 890 /* Load user mode stack (It was copied to the trap frame) */ 891 mov rsp, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rsp] 892 893 /* Swap gs back to user */ 894 swapgs 895 896 /* return to user mode */ 897 .byte HEX(48) // REX prefix to return to long mode 898 sysret 899.ENDP 900 901 902PUBLIC KiSystemCallEntry32 903KiSystemCallEntry32: 904 swapgs 905 int 3 906 907 908PUBLIC KiZwSystemService 909FUNC KiZwSystemService 910 push rbp 911 .pushreg rbp 912 sub rsp, KTRAP_FRAME_LENGTH 913 .allocstack KTRAP_FRAME_LENGTH 914 mov [rsp + KTRAP_FRAME_Rsi], rsi 915 .savereg rsi, KTRAP_FRAME_Rsi 916 mov [rsp + KTRAP_FRAME_Rdi], rdi 917 .savereg rdi, KTRAP_FRAME_Rdi 918 mov rbp, rsp 919 .setframe rbp, 0 920 .endprolog 921 922 /* Get current thread */ 923 mov r11, gs:[PcCurrentThread] 924 925 /* Save the old trap frame in TrapFrame.Rdx */ 926 mov rdi, [r11 + KTHREAD_TrapFrame] 927 mov [rbp + KTRAP_FRAME_Rdx], rdi 928 929 /* Set the new trap frame and previous mode */ 930 mov [r11 + ThTrapFrame], rbp 931 mov byte ptr [r11 + KTHREAD_PreviousMode], 0 932 933 /* allocate space for parameters */ 934 sub rsp, r10 935 and rsp, HEX(0fffffffffffffff0) 936 937 /* Save rcx */ 938 mov [rbp + KTRAP_FRAME_Rcx], rcx 939 940 /* copy parameters to the new location */ 941 lea rsi, [rbp + KTRAP_FRAME_LENGTH + 16] 942 lea rdi, [rsp] 943 mov rcx, r10 944 shr rcx, 3 945 rep movsq 946 947 /* Restore rcx */ 948 mov rcx, [rbp + KTRAP_FRAME_Rcx] 949 950 /* Call the service function */ 951 call rax 952 953 /* Restore the old trap frame */ 954 mov r11, gs:[PcCurrentThread] 955 mov rsi, [rsp + KTRAP_FRAME_Rdx] 956 mov [r11 + KTHREAD_TrapFrame], rsi 957 958 /* Restore rdi and rsi */ 959 mov rsi, [rbp + KTRAP_FRAME_Rsi] 960 mov rdi, [rbp + KTRAP_FRAME_Rdi] 961 962 /* Cleanup the stack and return */ 963 lea rsp, [rbp + KTRAP_FRAME_LENGTH] 964 pop rbp 965 ret 966 967ENDFUNC 968 969 970KiExitToUserApc: 971 int 3 972 973/*! 974 * VOID 975 * DECLSPEC_NORETURN 976 * KiServiceExit(IN PKTRAP_FRAME TrapFrame, IN NTSTATUS Status)); 977 */ 978PUBLIC KiServiceExit 979KiServiceExit: 980 mov [rcx + KTRAP_FRAME_Rax], rdx 981 mov rbp, rcx 982 mov rsp, rcx 983 984 /* Return */ 985 //ExitTrap TF_SAVE_ALL 986 987/*! 988 * VOID 989 * DECLSPEC_NORETURN 990 * KiServiceExit2(IN PKTRAP_FRAME TrapFrame); 991 */ 992PUBLIC KiServiceExit2 993.PROC KiServiceExit2 994 .ENDPROLOG 995 996 mov rbp, rcx 997 mov rsp, rcx 998 999 /* Return */ 1000 ExitTrap TF_SAVE_ALL 1001.ENDP 1002 1003PUBLIC KiInitializeSegments 1004KiInitializeSegments: 1005 mov ax, KGDT64_R3_DATA or RPL_MASK 1006 mov gs, ax 1007 swapgs 1008 mov gs, ax 1009 ret 1010 1011 1012#ifdef _MSC_VER 1013#undef lgdt 1014#undef lidt 1015 1016//void __lgdt(void *Source); 1017PUBLIC __lgdt 1018__lgdt: 1019 lgdt fword ptr [rcx] 1020 ret 1021 1022//void __sgdt(void *Destination); 1023PUBLIC __sgdt 1024__sgdt: 1025 sgdt fword ptr [rcx] 1026 ret 1027 1028// void __lldt(unsigned short Value) 1029PUBLIC __lldt 1030__lldt: 1031 lldt cx 1032 ret 1033 1034//void __sldt(void *Destination); 1035PUBLIC __sldt 1036__sldt: 1037 sldt word ptr [rcx] 1038 ret 1039 1040//void __ltr(unsigned short Source); 1041PUBLIC __ltr 1042__ltr: 1043 ltr cx 1044 ret 1045 1046//void __str(unsigned short *Destination); 1047PUBLIC __str 1048__str: 1049 str word ptr [rcx] 1050 ret 1051 1052PUBLIC __swapgs 1053__swapgs: 1054 swapgs 1055 ret 1056 1057#endif 1058 1059END 1060