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 KeBugCheckWithTf:PROC 16EXTERN MmAccessFault:PROC 17EXTERN KiSystemFatalException:PROC 18EXTERN KiNpxNotAvailableFaultHandler:PROC 19EXTERN KiGeneralProtectionFaultHandler:PROC 20EXTERN KiXmmExceptionHandler:PROC 21EXTERN KiDeliverApc:PROC 22EXTERN KiDpcInterruptHandler:PROC 23EXTERN PsConvertToGuiThread:PROC 24EXTERN MmCreateKernelStack:PROC 25EXTERN MmDeleteKernelStack:PROC 26EXTERN KdSetOwedBreakpoints:PROC 27EXTERN KeAcquireSpinLockAtDpcLevel:PROC 28EXTERN KeReleaseSpinLockFromDpcLevel:PROC 29 30 31/* Helper Macros *************************************************************/ 32 33MACRO(DispatchException, Status, Number, P1, P2, P3) 34 mov eax, Status 35 mov edx, Number 36 mov r9, P1 37 mov r10, P2 38 mov r11, P3 39 call InternalDispatchException 40ENDM 41 42MACRO(Fatal, BugcheckCode) 43 /* Bugcheck */ 44 mov ecx, BugcheckCode 45 mov rdx, rbp 46 call KiSystemFatalException 47ENDM 48 49 50/* FUNCTIONS *****************************************************************/ 51 52.code64 53 54ALIGN 8 55 56MACRO(UnexpectedVectorStub, Vector) 57 /* This nop is to make the relative jmp address 4 bytes aligned and to 58 make the whole code 8 bytes long */ 59 nop 60 /* This is a push instruction with 8bit operand. Since the instruction 61 sign extends the value to 32 bits, we need to offset it */ 62PUBLIC KxUnexpectedInterrupt&Vector 63KxUnexpectedInterrupt&Vector: 64 push (Vector - 128) 65 jmp KiUnexpectedInterrupt 66ENDM 67 68PUBLIC KiUnexpectedRange 69KiUnexpectedRange: 70Vector = 0 71REPEAT 256 72 UnexpectedVectorStub %Vector 73 Vector = Vector+1 74ENDR 75PUBLIC KiUnexpectedRangeEnd 76KiUnexpectedRangeEnd: 77 78PUBLIC KiInterruptDispatchTemplate 79KiInterruptDispatchTemplate: 80 /* This instruction pushes the return address on the stack, which is the 81 address of the interrupt object's DispatchCode member, then jumps 82 to the address stored in the interrupt object's DispatchAddress member */ 83 call qword ptr KiInterruptDispatchTemplate[rip - KINTERRUPT_DispatchCode + KINTERRUPT_DispatchAddress] 84 85 86// rbp = TrapFrame, eax = ExceptionCode, edx = NumParams, r9,r10,r11 = params 87FUNC InternalDispatchException 88 89 /* Allocate stack space for EXCEPTION_RECORD and KEXCEPTION_FRAME */ 90 sub rsp, EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH 91 .allocstack (EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH) 92 .endprolog 93 94 /* Set up EXCEPTION_RECORD */ 95 lea rcx, [rsp + KEXCEPTION_FRAME_LENGTH] 96 mov [rcx + EXCEPTION_RECORD_ExceptionCode], eax 97 xor rax, rax 98 mov [rcx + EXCEPTION_RECORD_ExceptionFlags], eax 99 mov [rcx + EXCEPTION_RECORD_ExceptionRecord], rax 100 mov rax, [rbp + KTRAP_FRAME_Rip] 101 mov [rcx + EXCEPTION_RECORD_ExceptionAddress], rax 102 mov [rcx + EXCEPTION_RECORD_NumberParameters], edx 103 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(00)], r9 104 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(08)], r10 105 mov [rcx + EXCEPTION_RECORD_ExceptionInformation + HEX(10)], r11 106 107 /* Set up KEXCEPTION_FRAME */ 108 mov rax, [rbp + KTRAP_FRAME_Rbp] 109 mov [rsp + KEXCEPTION_FRAME_Rbp], rax 110 mov [rsp + KEXCEPTION_FRAME_Rbx], rbx 111 mov [rsp + KEXCEPTION_FRAME_Rdi], rdi 112 mov [rsp + KEXCEPTION_FRAME_Rsi], rsi 113 mov [rsp + KEXCEPTION_FRAME_R12], r12 114 mov [rsp + KEXCEPTION_FRAME_R13], r13 115 mov [rsp + KEXCEPTION_FRAME_R14], r14 116 mov [rsp + KEXCEPTION_FRAME_R15], r15 117 movdqa [rsp + KEXCEPTION_FRAME_Xmm6], xmm6 118 movdqa [rsp + KEXCEPTION_FRAME_Xmm7], xmm7 119 movdqa [rsp + KEXCEPTION_FRAME_Xmm8], xmm8 120 movdqa [rsp + KEXCEPTION_FRAME_Xmm9], xmm9 121 movdqa [rsp + KEXCEPTION_FRAME_Xmm10], xmm10 122 movdqa [rsp + KEXCEPTION_FRAME_Xmm11], xmm11 123 movdqa [rsp + KEXCEPTION_FRAME_Xmm12], xmm12 124 movdqa [rsp + KEXCEPTION_FRAME_Xmm13], xmm13 125 movdqa [rsp + KEXCEPTION_FRAME_Xmm14], xmm14 126 movdqa [rsp + KEXCEPTION_FRAME_Xmm15], xmm15 127 mov qword ptr [rsp + KEXCEPTION_FRAME_Return], 0 128 129 /* Call KiDispatchException */ 130 // rcx already points to ExceptionRecord 131 mov rdx, rsp // ExceptionFrame 132 mov r8, rbp // TrapFrame 133 mov r9b, [r8 + KTRAP_FRAME_PreviousMode] // PreviousMode 134 mov byte ptr [rsp + KEXCEPTION_FRAME_P5], 1 // FirstChance 135 call KiDispatchException 136 137 /* Restore registers */ 138 mov r12, [rsp + KEXCEPTION_FRAME_R12] 139 mov r13, [rsp + KEXCEPTION_FRAME_R13] 140 mov r14, [rsp + KEXCEPTION_FRAME_R14] 141 mov r15, [rsp + KEXCEPTION_FRAME_R15] 142 movdqa xmm6, [rsp + KEXCEPTION_FRAME_Xmm6] 143 movdqa xmm7, [rsp + KEXCEPTION_FRAME_Xmm7] 144 movdqa xmm8, [rsp + KEXCEPTION_FRAME_Xmm8] 145 movdqa xmm9, [rsp + KEXCEPTION_FRAME_Xmm9] 146 movdqa xmm10, [rsp + KEXCEPTION_FRAME_Xmm10] 147 movdqa xmm11, [rsp + KEXCEPTION_FRAME_Xmm11] 148 movdqa xmm12, [rsp + KEXCEPTION_FRAME_Xmm12] 149 movdqa xmm13, [rsp + KEXCEPTION_FRAME_Xmm13] 150 movdqa xmm14, [rsp + KEXCEPTION_FRAME_Xmm14] 151 movdqa xmm15, [rsp + KEXCEPTION_FRAME_Xmm15] 152 153 add rsp, EXCEPTION_RECORD_LENGTH + KEXCEPTION_FRAME_LENGTH 154 ret 155ENDFUNC 156 157 158/* CPU EXCEPTION HANDLERS ****************************************************/ 159 160PUBLIC KiDivideErrorFault 161FUNC KiDivideErrorFault 162 /* Push pseudo error code */ 163 EnterTrap TF_SAVE_ALL 164 165 /* Enable interrupts */ 166 sti 167 168 /* Dispatch the exception */ 169 DispatchException STATUS_INTEGER_DIVIDE_BY_ZERO, 0, 0, 0, 0 170 171 /* Return */ 172 ExitTrap TF_SAVE_ALL 173ENDFUNC 174 175 176PUBLIC KiDebugTrapOrFault 177FUNC KiDebugTrapOrFault 178 /* Push pseudo error code */ 179 EnterTrap TF_SAVE_ALL 180 181 /* Check if the frame was from kernelmode */ 182 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 183 jz KiDebugTrapOrFaultKMode 184 185 /* Enable interrupts for user-mode */ 186 sti 187 188KiDebugTrapOrFaultKMode: 189 /* Dispatch the exception */ 190 DispatchException STATUS_SINGLE_STEP, 0, 0, 0, 0 191 192 /* Return */ 193 ExitTrap TF_SAVE_ALL 194ENDFUNC 195 196EXTERN KiNmiInterruptHandler:PROC 197 198FUNC KiNmiInterruptWithEf 199 /* Generate a KEXCEPTION_FRAME on the stack */ 200 GENERATE_EXCEPTION_FRAME 201 202 /* Call the C handler */ 203 lea rcx, [rsp + KEXCEPTION_FRAME_LENGTH] 204 lea rdx, [rsp] 205 call KiNmiInterruptHandler 206 207 /* Restore the registers from the KEXCEPTION_FRAME */ 208 RESTORE_EXCEPTION_STATE 209 210 /* Return */ 211 ret 212ENDFUNC 213 214PUBLIC KiNmiInterrupt 215FUNC KiNmiInterrupt 216 /* Push pseudo error code */ 217 EnterTrap TF_SAVE_ALL 218 219 call KiNmiInterruptWithEf 220 221 /* Return */ 222 ExitTrap TF_SAVE_ALL 223ENDFUNC 224 225 226PUBLIC KiBreakpointTrap 227FUNC KiBreakpointTrap 228 /* Push pseudo error code */ 229 EnterTrap TF_SAVE_ALL 230 231 /* Check if the frame was from kernelmode */ 232 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 233 jz KiBreakpointTrapKMode 234 235 /* Enable interrupts for user-mode */ 236 sti 237 238KiBreakpointTrapKMode: 239 /* Dispatch the exception */ 240 DispatchException STATUS_BREAKPOINT, 3, BREAKPOINT_BREAK, 0, 0 241 242 /* Return */ 243 ExitTrap TF_SAVE_ALL 244ENDFUNC 245 246 247PUBLIC KiOverflowTrap 248FUNC KiOverflowTrap 249 /* Push pseudo error code */ 250 EnterTrap TF_SAVE_ALL 251 252 /* Enable interrupts */ 253 sti 254 255 /* Dispatch the exception */ 256 DispatchException STATUS_INTEGER_OVERFLOW, 3, 0, 0, 0 257 258 /* Return */ 259 ExitTrap TF_SAVE_ALL 260ENDFUNC 261 262 263PUBLIC KiBoundFault 264FUNC KiBoundFault 265 /* Push pseudo error code */ 266 EnterTrap TF_SAVE_ALL 267 268 /* Check if the frame was from kernelmode */ 269 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 270 jnz KiBoundFaultUserMode 271 272 /* Bugcheck */ 273 Fatal EXCEPTION_BOUND_CHECK 274 275KiBoundFaultUserMode: 276 /* Enable interrupts for user-mode */ 277 sti 278 279 /* Dispatch the exception */ 280 DispatchException STATUS_ARRAY_BOUNDS_EXCEEDED, 0, 0, 0, 0 281 282 /* Return */ 283 ExitTrap TF_SAVE_ALL 284ENDFUNC 285 286 287PUBLIC KiInvalidOpcodeFault 288FUNC KiInvalidOpcodeFault 289 /* Push pseudo error code */ 290 EnterTrap TF_SAVE_ALL 291 292 /* Enable interrupts */ 293 sti 294 295 /* Check if the frame was from kernelmode */ 296 test word ptr [rbp + KTRAP_FRAME_SegCs], 3 297 jz KiInvalidOpcodeKernel 298 299 // FIXME: handle STATUS_INVALID_LOCK_SEQUENCE 300 301KiInvalidOpcodeKernel: 302 /* Kernel mode fault */ 303 304 /* Dispatch the exception */ 305 DispatchException STATUS_ILLEGAL_INSTRUCTION, 0, 0, 0, 0 306 307 /* Return */ 308 ExitTrap TF_SAVE_ALL 309ENDFUNC 310 311 312PUBLIC KiNpxNotAvailableFault 313FUNC KiNpxNotAvailableFault 314 /* Push pseudo error code */ 315 EnterTrap TF_SAVE_ALL 316 317 /* Call the C handler */ 318 mov rcx, rbp 319 call KiNpxNotAvailableFaultHandler 320 321 /* Check the return status code */ 322 test eax, eax 323 jz KiNpxNotAvailableFaultExit 324 325 /* Dispatch the exception */ 326 DispatchException eax, 3, 0, 0, 0 327 328KiNpxNotAvailableFaultExit: 329 /* Return */ 330 ExitTrap TF_SAVE_ALL 331ENDFUNC 332 333 334PUBLIC KiDoubleFaultAbort 335FUNC KiDoubleFaultAbort 336 337 /* Hack for VBox, which "forgets" to push an error code on the stack! */ 338 and rsp, HEX(FFFFFFFFFFFFFFF0) 339 340 /* A zero error code is pushed */ 341 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 342 343 int 3 344 345 /* Bugcheck */ 346 Fatal 8 // EXCEPTION_DOUBLE_FAULT 347 jmp $ 348ENDFUNC 349 350 351PUBLIC KiNpxSegmentOverrunAbort 352FUNC KiNpxSegmentOverrunAbort 353 /* Push pseudo error code */ 354 EnterTrap TF_SAVE_ALL 355 356 /* Bugcheck */ 357 Fatal EXCEPTION_NPX_OVERRUN 358 359 jmp $ 360ENDFUNC 361 362 363PUBLIC KiInvalidTssFault 364FUNC KiInvalidTssFault 365 /* We have an error code */ 366 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 367 368 /* Bugcheck */ 369 Fatal EXCEPTION_INVALID_TSS 370 jmp $ 371ENDFUNC 372 373 374PUBLIC KiSegmentNotPresentFault 375FUNC KiSegmentNotPresentFault 376 /* We have an error code */ 377 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 378 379 /* Bugcheck */ 380 Fatal EXCEPTION_SEGMENT_NOT_PRESENT 381 jmp $ 382ENDFUNC 383 384 385PUBLIC KiStackFault 386FUNC KiStackFault 387 /* We have an error code */ 388 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 389 390 /* Bugcheck */ 391 Fatal EXCEPTION_STACK_FAULT 392 jmp $ 393ENDFUNC 394 395 396PUBLIC KiGeneralProtectionFault 397FUNC KiGeneralProtectionFault 398 /* We have an error code */ 399 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 400 401 /* Call the C handler */ 402 mov rcx, rbp 403 call KiGeneralProtectionFaultHandler 404 405 /* Check for success */ 406 test eax, eax 407 jge KiGpfExit 408 409 /* Check for access violation */ 410 cmp eax, STATUS_ACCESS_VIOLATION 411 je DispatchAccessViolation 412 413 /* Dispatch privileged instruction fault */ 414 DispatchException eax, 0, 0, 0, 0 415 jmp KiGpfExit 416 417DispatchAccessViolation: 418 419 /* Dispatch access violation */ 420 DispatchException eax, 2, 0, -1, 0 421 422KiGpfExit: 423 /* Return */ 424 ExitTrap TF_SAVE_ALL 425ENDFUNC 426 427 428PUBLIC KiPageFault 429FUNC KiPageFault 430 /* We have an error code */ 431 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 432 433 /* Save page fault address */ 434 mov rdx, cr2 435 mov [rbp + KTRAP_FRAME_FaultAddress], rdx 436 437 /* If interrupts are off, do not enable them */ 438 test dword ptr [rbp + KTRAP_FRAME_EFlags], EFLAGS_IF_MASK 439 jz IntsDisabled 440 441 /* Enable interrupts for the page fault handler */ 442 sti 443 444IntsDisabled: 445 446 /* Call page fault handler */ 447 mov ecx, [rbp + KTRAP_FRAME_ErrorCode] // FaultCode 448 // rdx == Address 449 mov r8b, [rbp + KTRAP_FRAME_SegCs] // Mode 450 and r8b, 1 451 mov r9, rbp // TrapInformation 452 call MmAccessFault 453 454 /* Check for success */ 455 test eax, eax 456 jl PageFaultError 457 458 /* Check whether the kernel debugger has owed breakpoints to be inserted */ 459 call KdSetOwedBreakpoints 460 /* We succeeded, return */ 461 jmp PageFaultReturn 462 463PageFaultError: 464 465 /* Set parameter 1 to write/execute flag. 466 See https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record */ 467 mov r9d, [rbp + KTRAP_FRAME_ErrorCode] 468 shr r9d, 1 469 and r9d, 9 470 471 /* Set parameter 2 to faulting address */ 472 mov r10, cr2 // Param2 = faulting address 473 474 cmp eax, STATUS_ACCESS_VIOLATION 475 je AccessViolation 476 cmp eax, STATUS_GUARD_PAGE_VIOLATION 477 je SpecialCode 478 cmp eax, STATUS_STACK_OVERFLOW 479 je SpecialCode 480 481InPageException: 482 /* Dispatch in-page exception */ 483 mov r11d, eax // Param3 = Status 484 mov eax, STATUS_IN_PAGE_ERROR // ExceptionCode 485 mov edx, 3 // ParamCount 486 call InternalDispatchException 487 jmp PageFaultReturn 488 489AccessViolation: 490 /* Use more proper status code */ 491 mov eax, KI_EXCEPTION_ACCESS_VIOLATION 492 493SpecialCode: 494 /* Setup a normal page fault exception */ 495 mov edx, 2 // ParamCount 496 call InternalDispatchException 497 498PageFaultReturn: 499 500 /* Disable interrupts for the return */ 501 cli 502 503 /* Return */ 504 ExitTrap (TF_SAVE_ALL or TF_CHECKUSERAPC) 505ENDFUNC 506 507 508PUBLIC KiFloatingErrorFault 509FUNC KiFloatingErrorFault 510 /* Push pseudo error code */ 511 EnterTrap TF_SAVE_ALL 512 513 UNIMPLEMENTED KiFloatingErrorFault 514 int 3 515 516 /* Return */ 517 ExitTrap TF_SAVE_ALL 518ENDFUNC 519 520 521PUBLIC KiAlignmentFault 522FUNC KiAlignmentFault 523 /* We have an error code */ 524 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 525 526 /* Bugcheck */ 527 Fatal EXCEPTION_ALIGNMENT_CHECK 528 jmp $ 529ENDFUNC 530 531 532PUBLIC KiMcheckAbort 533FUNC KiMcheckAbort 534 /* Push pseudo error code */ 535 EnterTrap TF_SAVE_ALL 536 537 /* Bugcheck */ 538 Fatal HEX(12) 539 jmp $ 540ENDFUNC 541 542 543PUBLIC KiXmmException 544FUNC KiXmmException 545 /* Push pseudo error code */ 546 EnterTrap TF_SAVE_ALL 547 548 /* Call the C handler */ 549 mov rcx, rbp 550 call KiXmmExceptionHandler 551 552 /* Check for success */ 553 test eax, eax 554 jge KiXmmExit 555 556 /* Dispatch the exception */ 557 DispatchException eax, 2, 0, [rbp+KTRAP_FRAME_MxCsr], 0 558 559 // FIXME: STATUS_FLOAT_MULTIPLE_TRAPS / STATUS_FLOAT_MULTIPLE_FAULTS 560 561KiXmmExit: 562 /* Return */ 563 ExitTrap TF_SAVE_ALL 564ENDFUNC 565 566 567/* SOFTWARE INTERRUPT SERVICES ***********************************************/ 568 569PUBLIC KiRaiseAssertion 570FUNC KiRaiseAssertion 571 /* We have an error code */ 572 EnterTrap (TF_SAVE_ALL) 573 574 /* Decrement RIP to point to the INT2C instruction (2 bytes, not 1 like INT3) */ 575 sub qword ptr [rbp + KTRAP_FRAME_Rip], 2 576 577 /* Dispatch the exception */ 578 DispatchException STATUS_ASSERTION_FAILURE, 0, 0, 0, 0 579 580 /* Return */ 581 ExitTrap TF_SAVE_ALL 582ENDFUNC 583 584 585PUBLIC KiDebugServiceTrap 586FUNC KiDebugServiceTrap 587 /* No error code */ 588 EnterTrap TF_SAVE_ALL 589 590 /* Increase Rip to skip the int3 */ 591 inc qword ptr [rbp + KTRAP_FRAME_Rip] 592 593 /* Dispatch the exception (Params = service, buffer, legth) */ 594 DispatchException STATUS_BREAKPOINT, 3, [rbp+KTRAP_FRAME_Rax], [rbp+KTRAP_FRAME_Rcx], [rbp+KTRAP_FRAME_Rdx] 595 596 /* Return */ 597 ExitTrap TF_SAVE_ALL 598ENDFUNC 599 600 601PUBLIC KiApcInterrupt 602.PROC KiApcInterrupt 603 /* No error code */ 604 EnterTrap (TF_SAVE_ALL or TF_IRQL) 605 606 /* Raise to APC_LEVEL */ 607 mov rax, APC_LEVEL 608 mov cr8, rax 609 610 /* End the interrupt */ 611 mov dword ptr [APIC_EOI], 0 612 613 /* Enable interrupts */ 614 sti 615 616 /* Call the worker routine */ 617 mov cl, [rbp + KTRAP_FRAME_SegCs] // ProcessorMode 618 and cl, 1 619 mov rdx, 0 // ExceptionFrame 620 mov r8, rbp // TrapFrame 621 call KiDeliverApc 622 623 /* Disable interrupts */ 624 cli 625 626 /* Lower IRQL back to PASSIVE */ 627 mov rax, PASSIVE_LEVEL 628 mov cr8, rax 629 630 /* Return */ 631 ExitTrap (TF_SAVE_ALL or TF_IRQL) 632.ENDP 633 634/* 635 * VOID 636 * KiRetireDpcList( 637 * PKPRCB Prcb); 638 */ 639EXTERN KiRetireDpcList:PROC 640 641/* 642 * VOID 643 * KiRetireDpcListInDpcStack( 644 * PKPRCB Prcb, 645 * PVOID DpcStack); 646 */ 647PUBLIC KiRetireDpcListInDpcStack 648.PROC KiRetireDpcListInDpcStack 649 push rbp 650 .pushreg rbp 651 mov rbp, rsp 652 .setframe rbp, 0 653 .endprolog 654 655 /* Switch to the DpcStack */ 656 mov rsp, rdx 657 658 /* The stack is 16 byte aligned, allocate 32 bytes home space */ 659 sub rsp, 32 660 661 /* Call KiRetireDpcList on the given stack */ 662 call KiRetireDpcList 663 664 /* Restore stack, cleanup and return */ 665 mov rsp, rbp 666 pop rbp 667 ret 668.ENDP 669 670PUBLIC KiDpcInterrupt 671.PROC KiDpcInterrupt 672 /* No error code */ 673 EnterTrap (TF_SAVE_ALL or TF_IRQL) 674 675 /* Call the worker routine */ 676 call KiDpcInterruptHandler 677 678 /* Return, but don't send an EOI! */ 679 ExitTrap (TF_SAVE_ALL or TF_IRQL) 680.ENDP 681 682 683PUBLIC KiIpiInterrupt 684.PROC KiIpiInterrupt 685 /* No error code */ 686 EnterTrap (TF_SAVE_ALL or TF_IRQL) 687 688 /* Raise to IPI_LEVEL */ 689 mov rax, IPI_LEVEL 690 mov cr8, rax 691 692 /* End the interrupt */ 693 mov dword ptr [APIC_EOI], 0 694 695 int 3 696 697 /* Return */ 698 ExitTrap (TF_SAVE_ALL or TF_IRQL) 699.ENDP 700 701 702PUBLIC KiUnexpectedInterrupt 703FUNC KiUnexpectedInterrupt 704 /* The error code is the vector */ 705 EnterTrap (TF_HAS_ERROR_CODE OR TF_SAVE_ALL) 706 707#if 0 708 /* Set bugcheck parameters */ 709 mov ecx, TRAP_CAUSE_UNKNOWN 710 mov rdx, [rbp + KTRAP_FRAME_ErrorCode] // the vector 711 mov r8, 0 // The unknown floating-point exception 712 mov r9, 0 // The enabled and asserted status bits 713 sub rsp, 8 714 mov [rbp + KTRAP_FRAME_P5 + 8], rbp // trap frame 715 call KeBugCheckWithTf 716 jmp $ 717#endif 718 /* Return */ 719 ExitTrap TF_SAVE_ALL 720ENDFUNC 721 722PUBLIC KiInterruptDispatch 723FUNC KiInterruptDispatch 724 /* The error code is a pointer to the interrupt object's code */ 725 EnterTrap (TF_HAS_ERROR_CODE or TF_SAVE_ALL or TF_IRQL) 726 727 /* Increase interrupt count */ 728 inc dword ptr gs:[PcInterruptCount]; 729 730 /* Save rbx and rsi in the trap frame */ 731 mov [rbp + KTRAP_FRAME_Rbx], rbx 732 mov [rbp + KTRAP_FRAME_Rsi], rsi 733 734 /* Load the address of the dispatch code into rbx */ 735 mov rbx, [rbp + KTRAP_FRAME_ErrorCode] 736 737 /* Substract offset of the DispatchCode member plus 6 for the call instruction */ 738 sub rbx, KINTERRUPT_DispatchCode + 6 739 740 /* Save the address of the InterruptListEntry in rsi */ 741 lea rsi, [rbx + KINTERRUPT_InterruptListEntry] 742 743.DoDispatchInterrupt: 744 /* Raise IRQL to SynchronizeIrql */ 745 movzx rax, byte ptr [rbx + KINTERRUPT_SynchronizeIrql] 746 mov cr8, rax 747 748 /* Enable interrupts */ 749 sti 750 751#ifdef CONFIG_SMP 752 /* Acquire interrupt lock */ 753 mov rcx, [rbx + KINTERRUPT_ActualLock] 754 call KeAcquireSpinLockAtDpcLevel 755#endif 756 757 /* Call the ISR */ 758 mov rcx, rbx 759 mov rdx, [rbx + KINTERRUPT_ServiceContext] 760 call qword ptr [rbx + KINTERRUPT_ServiceRoutine] 761 762#ifdef CONFIG_SMP 763 /* Release interrupt lock */ 764 mov rcx, [rbx + KINTERRUPT_ActualLock] 765 call KeReleaseSpinLockFromDpcLevel 766#endif 767 768 /* Disable interrupts and go back to old irql */ 769 cli 770 movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql] 771 mov cr8, rax 772 773 /* Check for chained interrupts */ 774 mov rax, [rbx + KINTERRUPT_InterruptListEntry] 775 cmp rax, rsi 776 je .Done 777 778 /* Load the next interrupt object into rbx and repeat */ 779 lea rbx, [rax - KINTERRUPT_InterruptListEntry] 780 jmp .DoDispatchInterrupt 781 782.Done: 783 /* Restore rbx and rsi */ 784 mov rbx, [rbp + KTRAP_FRAME_Rbx] 785 mov rsi, [rbp + KTRAP_FRAME_Rsi] 786 787 /* Return */ 788 ExitTrap (TF_SAVE_ALL or TF_SEND_EOI) 789ENDFUNC 790 791EXTERN KiSystemCallHandler:PROC 792 793/*! \name KiSystemCallEntry64 794 * 795 * \brief This is the entrypoint for syscalls from 64bit user mode 796 * 797 * \param rax - The system call number 798 * \param rcx - User mode return address, set by the syscall instruction 799 * \param rdx,r8,r9 - Parameters 2-4 to the service function 800 * \param r10 - Parameter 1 to the service function 801 * \param r11 - RFLAGS saved by the syscall instruction 802 *--*/ 803PUBLIC KiSystemCallEntry64 804.PROC KiSystemCallEntry64 805 /* The unwind info pretends we have a machine frame */ 806 .PUSHFRAME 807 .ALLOCSTACK (KTRAP_FRAME_LENGTH + MAX_SYSCALL_PARAM_SIZE - MachineFrameLength) 808 .SAVEREG rbp, MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rbp 809 .ENDPROLOG 810 811 /* Swap gs to kernel, so we can access the PCR */ 812 swapgs 813 814 /* Save the user mode rsp in the PCR */ 815 mov gs:[PcUserRsp], rsp 816 817 /* Get the kernel stack from the PCR */ 818 mov rsp, gs:[PcRspBase] 819 820 /* Allocate a TRAP_FRAME and space for parameters */ 821 sub rsp, (KTRAP_FRAME_LENGTH + MAX_SYSCALL_PARAM_SIZE) 822 823 /* Save volatile registers and rbp in the trap frame */ 824 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rax], rax 825 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rip], rcx 826 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rdx], rdx 827 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R8], r8 828 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R9], r9 829 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx], r10 830 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_EFlags], r11 831 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rbp], rbp 832 833 /* Store user stack pointer in the trap frame */ 834 mov rax, gs:[PcUserRsp] 835 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rsp], rax 836 837 /* Set sane segments */ 838 mov ax, (KGDT64_R3_DATA or RPL_MASK) 839 mov ds, ax 840 mov es, ax 841 842 /* Save MCXSR and set kernel value */ 843 stmxcsr [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_MxCsr] 844 ldmxcsr gs:[PcMxCsr] 845 846 /* Get the current thread and the trap frame */ 847 mov rax, gs:[PcCurrentThread] 848 mov rcx, [rax + ThTrapFrame] 849 850 /* Save the old trap frame */ 851 lea rdx, [rsp + MAX_SYSCALL_PARAM_SIZE] 852 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_TrapFrame], rcx 853 mov [rax + ThTrapFrame], rdx 854 855#if DBG 856 /* Check IRQL */ 857 mov rax, cr8 858 test eax, eax 859 jz KiSystemCall64Again 860 int HEX(2C) 861#endif 862 863GLOBAL_LABEL KiSystemCall64Again 864 865 /* Call the C-handler (will enable interrupts) */ 866 call KiSystemCallHandler 867 868 /* The return value from KiSystemCallHandler is the address of the Nt-function */ 869 mov rcx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx] 870 mov rdx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rdx] 871 mov r8, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R8] 872 mov r9, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R9] 873 call rax 874 875GLOBAL_LABEL KiSystemServiceExit 876 877 ASSERT_TRAP_FRAME_INTS_ENABLED rsp + MAX_SYSCALL_PARAM_SIZE 878 879 /* Check for pending user APCs */ 880 mov rcx, gs:[PcCurrentThread] 881 cmp byte ptr [rcx + ThApcState + AsUserApcPending], 0 882 jz NoUserApcPending 883 884 /* Save missing regs in the trap frame */ 885 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rax], rax 886 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rbp], rbp 887 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R9], rbp 888 mov rax, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rsp] 889 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R8], rax 890 mov rax, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rip] 891 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rcx], rax 892 mov rax, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_EFlags] 893 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R11], rax 894 xor rax, rax 895 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rdx], rax 896 mov [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R10], rax 897 pxor xmm0, xmm0 898 movdqa [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Xmm0], xmm0 899 movdqa [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Xmm1], xmm0 900 movdqa [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Xmm2], xmm0 901 movdqa [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Xmm3], xmm0 902 movdqa [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Xmm4], xmm0 903 movdqa [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Xmm5], xmm0 904 905 lea rcx, [rsp + MAX_SYSCALL_PARAM_SIZE] 906 call KiInitiateUserApc 907 908NoUserApcPending: 909 /* Disable interrupts for return */ 910 cli 911 912 /* Restore MCXSR */ 913 ldmxcsr [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_MxCsr] 914 915 /* Restore old trap frame */ 916 mov rcx, gs:[PcCurrentThread] 917 mov rdx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_TrapFrame] 918 mov [rcx + KTHREAD_TrapFrame], rdx 919 920 /* Prepare user mode return address (rcx) and eflags (r11) for sysret */ 921 mov rcx, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rip] 922 mov r11, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_EFlags] 923 924 /* Load user mode stack (It was copied to the trap frame) */ 925 mov rsp, [rsp + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rsp] 926 927 /* r8 points to the user stack */ 928 mov r8, rsp 929 930 /* r9 matches rbp */ 931 mov r9, rbp 932 933 /* Swap gs back to user */ 934 swapgs 935 936 /* Zero out volatiles */ 937 pxor xmm0, xmm0 938 pxor xmm1, xmm1 939 pxor xmm2, xmm2 940 pxor xmm3, xmm3 941 pxor xmm4, xmm4 942 pxor xmm5, xmm5 943 xor rdx, rdx 944 xor r10, r10 945 946 /* return to user mode */ 947 sysretq 948 949.ENDP 950 951 952/*! 953 * VOID 954 * DECLSPEC_NORETURN 955 * KiExceptionExit( 956 * _In_ PKTRAP_FRAME TrapFrame@<rcx>, 957 * _In_ PKEXCEPTION_FRAME ExceptionFrame@<rdx>); 958 */ 959PUBLIC KiExceptionExit 960KiExceptionExit: 961 962 /* Restore registers from exception frame */ 963 movaps xmm6, [rdx + ExXmm6] 964 movaps xmm7, [rdx + ExXmm7] 965 movaps xmm8, [rdx + ExXmm8] 966 movaps xmm9, [rdx + ExXmm9] 967 movaps xmm10, [rdx + ExXmm10] 968 movaps xmm11, [rdx + ExXmm11] 969 movaps xmm12, [rdx + ExXmm12] 970 movaps xmm13, [rdx + ExXmm13] 971 movaps xmm14, [rdx + ExXmm14] 972 movaps xmm15, [rdx + ExXmm15] 973 mov rbx, [rdx + ExRbx] 974 mov rdi, [rdx + ExRdi] 975 mov rsi, [rdx + ExRsi] 976 mov r12, [rdx + ExR12] 977 mov r13, [rdx + ExR13] 978 mov r14, [rdx + ExR14] 979 mov r15, [rdx + ExR15] 980 981 /* Point rsp at the trap frame */ 982 mov rsp, rcx 983 /* Fall through */ 984 985/* 986 * Internal function. Exits to user-mode with rsp pointing to the trap frame. 987 * All non-volatile register context must be set up already. 988 * Used by KiInitializeContextThread to set up the init path for a new thread. 989 */ 990PUBLIC KiServiceExit3 991.PROC KiServiceExit3 992 .PUSHFRAME 993 .ALLOCSTACK (KTRAP_FRAME_LENGTH - MachineFrameLength) 994 .ENDPROLOG 995 996 /* Return */ 997 mov rbp, rsp 998 ExitTrap (TF_SEGMENTS or TF_CHECKUSERAPC) 999.ENDP 1000 1001 1002PUBLIC KiSystemCallEntry32 1003KiSystemCallEntry32: 1004 swapgs 1005 int 3 1006 1007 1008PUBLIC KiZwSystemService 1009FUNC KiZwSystemService 1010 push rbp 1011 .pushreg rbp 1012 sub rsp, KTRAP_FRAME_LENGTH 1013 .allocstack KTRAP_FRAME_LENGTH 1014 mov [rsp + KTRAP_FRAME_Rsi], rsi 1015 .savereg rsi, KTRAP_FRAME_Rsi 1016 mov [rsp + KTRAP_FRAME_Rdi], rdi 1017 .savereg rdi, KTRAP_FRAME_Rdi 1018 mov rbp, rsp 1019 .setframe rbp, 0 1020 .endprolog 1021 1022 /* Get current thread */ 1023 mov r11, gs:[PcCurrentThread] 1024 1025 /* Save PreviousMode in the trap frame */ 1026 mov dil, byte ptr [r11 + KTHREAD_PreviousMode] 1027 mov byte ptr [rbp + KTRAP_FRAME_PreviousMode], dil 1028 1029 /* Save the old trap frame in TrapFrame.Rdx */ 1030 mov rdi, [r11 + KTHREAD_TrapFrame] 1031 mov [rbp + KTRAP_FRAME_Rdx], rdi 1032 1033 /* Set the new trap frame and previous mode */ 1034 mov [r11 + ThTrapFrame], rbp 1035 mov byte ptr [r11 + KTHREAD_PreviousMode], 0 1036 1037 /* allocate space for parameters */ 1038 sub rsp, r10 1039 and rsp, HEX(0fffffffffffffff0) 1040 1041 /* Save rcx */ 1042 mov [rbp + KTRAP_FRAME_Rcx], rcx 1043 1044 /* copy parameters to the new location */ 1045 lea rsi, [rbp + KTRAP_FRAME_LENGTH + 16] 1046 lea rdi, [rsp] 1047 mov rcx, r10 1048 shr rcx, 3 1049 rep movsq 1050 1051 /* Restore rcx */ 1052 mov rcx, [rbp + KTRAP_FRAME_Rcx] 1053 1054 /* Call the service function */ 1055 call rax 1056 1057 /* Restore the old trap frame */ 1058 mov r11, gs:[PcCurrentThread] 1059 mov rsi, [rbp + KTRAP_FRAME_Rdx] 1060 mov [r11 + KTHREAD_TrapFrame], rsi 1061 1062 /* Restore PreviousMode from the trap frame */ 1063 mov dil, byte ptr [rbp + KTRAP_FRAME_PreviousMode] 1064 mov byte ptr [r11 + KTHREAD_PreviousMode], dil 1065 1066 /* Restore rdi and rsi */ 1067 mov rsi, [rbp + KTRAP_FRAME_Rsi] 1068 mov rdi, [rbp + KTRAP_FRAME_Rdi] 1069 1070 /* Cleanup the stack and return */ 1071 lea rsp, [rbp + KTRAP_FRAME_LENGTH] 1072 pop rbp 1073 ret 1074 1075ENDFUNC 1076 1077PUBLIC KiConvertToGuiThread 1078FUNC KiConvertToGuiThread 1079 1080 sub rsp, 40 1081 .allocstack 40 1082 .endprolog 1083 1084 /* Check if we already have a large stack */ 1085 mov rax, gs:[PcCurrentThread] 1086 cmp byte ptr [rax + KTHREAD_LargeStack], 0 1087 jnz AlreadyLargeStack 1088 1089 // NewStack = (ULONG_PTR)MmCreateKernelStack(TRUE, 0); 1090 mov cl, 1 1091 xor rdx, rdx 1092 call MmCreateKernelStack 1093 1094 /* Check for failure */ 1095 test rax, rax 1096 jz KiConvertToGuiThreadFailed 1097 1098 /* OldStack = KeSwitchKernelStack((PVOID)NewStack, (PVOID)(NewStack - KERNEL_LARGE_STACK_COMMIT )); */ 1099 mov rcx, rax 1100 mov rdx, rax 1101 sub rdx, KERNEL_LARGE_STACK_COMMIT 1102 call KeSwitchKernelStack 1103 1104 // MmDeleteKernelStack(OldStack, FALSE); 1105 mov rcx, rax 1106 xor rdx, rdx 1107 call MmDeleteKernelStack 1108 1109AlreadyLargeStack: 1110 1111 /* Call the worker function */ 1112 call PsConvertToGuiThread 1113 1114 /* Check for failure */ 1115 test eax, eax 1116 js KiConvertToGuiThreadFailed 1117 1118 /* Disable interrupts for return */ 1119 cli 1120 1121 // Restore register parameters 1122 mov rcx, [rsp + 48 + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rip] 1123 mov rdx, [rsp + 48 + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_Rdx] 1124 mov r8, [rsp + 48 + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R8] 1125 mov r9, [rsp + 48 + MAX_SYSCALL_PARAM_SIZE + KTRAP_FRAME_R9] 1126 1127 /* Run KiSystemCallHandler again */ 1128 add rsp, 48 1129 jmp KiSystemCall64Again 1130 1131KiConvertToGuiThreadFailed: 1132 1133 /* Clean up the stack and return failure */ 1134 add rsp, 40 1135 mov eax, HEX(C0000017) // STATUS_NO_MEMORY 1136 ret 1137 1138ENDFUNC 1139 1140 1141EXTERN KiSetTrapContextInternal:PROC 1142 1143/* 1144 * VOID 1145 * KiSetTrapContext( 1146 * _Out_ PKTRAP_FRAME TrapFrame, 1147 * _In_ PCONTEXT Context, 1148 * _In_ KPROCESSOR_MODE RequestorMode); 1149 */ 1150PUBLIC KiSetTrapContext 1151.PROC KiSetTrapContext 1152 1153 /* Generate a KEXCEPTION_FRAME on the stack */ 1154 GENERATE_EXCEPTION_FRAME 1155 1156 call KiSetTrapContextInternal 1157 1158 /* Restore the registers from the KEXCEPTION_FRAME */ 1159 RESTORE_EXCEPTION_STATE 1160 1161 /* Return */ 1162 ret 1163 1164.ENDP 1165 1166 1167/* 1168 * VOID 1169 * KiDeliverApc( 1170 * _In_ KPROCESSOR_MODE DeliveryMode, 1171 * _In_ PKEXCEPTION_FRAME ExceptionFrame, 1172 * _In_ PKTRAP_FRAME TrapFrame); 1173 * 1174 */ 1175EXTERN KiDeliverApc:PROC 1176 1177/* 1178 * VOID 1179 * KiInitiateUserApc( 1180 * _In_ PKTRAP_FRAME TrapFrame@<rcx>); 1181 * 1182 * This function is called to deliver user mode APCs. 1183 * It clobbers all non-volatile registers, except rax. 1184 */ 1185PUBLIC KiInitiateUserApc 1186.PROC KiInitiateUserApc 1187 1188 /* Generate a KEXCEPTION_FRAME on the stack */ 1189 GENERATE_EXCEPTION_FRAME 1190 1191 /* Raise IRQL to APC_LEVEL */ 1192 mov rax, APC_LEVEL 1193 mov cr8, rax 1194 1195 /* Get the current thread */ 1196 mov rbp, gs:[PcCurrentThread] 1197 1198 /* Save the trap frame in rsi */ 1199 mov rsi, rcx 1200 1201 /* Enable interrupts */ 1202 sti 1203 1204 /* Call the C function */ 1205 mov ecx, 1 1206 mov rdx, rsp 1207 mov r8, rsi 1208 call KiDeliverApc 1209 1210 /* Disable interrupts again */ 1211 cli 1212 1213 /* Go back to PASSIVE_LEVEL */ 1214 mov rax, PASSIVE_LEVEL 1215 mov cr8, rax 1216 1217 /* Restore the registers from the KEXCEPTION_FRAME */ 1218 RESTORE_EXCEPTION_STATE 1219 1220 /* Return */ 1221 ret 1222 1223.ENDP 1224 1225 1226PUBLIC KiInitializeSegments 1227KiInitializeSegments: 1228 mov ax, KGDT64_R3_DATA or RPL_MASK 1229 mov gs, ax 1230 swapgs 1231 mov gs, ax 1232 ret 1233 1234/*! 1235 * VOID 1236 * KiSwitchKernelStackHelper( 1237 * LONG_PTR StackOffset, 1238 * PVOID OldStackBase); 1239 */ 1240PUBLIC KiSwitchKernelStackHelper 1241KiSwitchKernelStackHelper: 1242 1243 /* Pop return address from the current stack */ 1244 pop rax 1245 1246 /* Switch to new stack */ 1247 lea rsp, [rsp + rcx] 1248 1249 /* Push return address on the new stack */ 1250 push rax 1251 1252 /* Return on new stack */ 1253 mov rax, rdx 1254 ret 1255 1256EXTERN KiSwitchKernelStack:PROC 1257 1258PUBLIC KeSwitchKernelStack 1259FUNC KeSwitchKernelStack 1260 1261 /* Save rcx and allocate callee home space */ 1262 mov [rsp + P1Home], rcx 1263 .savereg rcx, P1Home 1264 sub rsp, 40 1265 .allocstack 40 1266 .endprolog 1267 1268 /* Call the C handler, which returns the old stack in rax */ 1269 call KiSwitchKernelStack 1270 1271 /* Restore rcx (StackBase) */ 1272 mov rcx, [rsp + 40 + P1Home] 1273 1274 /* Switch to new stack: RSP += (StackBase - OldStackBase) */ 1275 sub rcx, rax 1276 add rsp, rcx 1277 1278 /* Deallocate the home frame */ 1279 add rsp, 40 1280 ret 1281 1282ENDFUNC 1283 1284 1285 1286 1287#ifdef _MSC_VER 1288#undef lgdt 1289#undef lidt 1290 1291//void __lgdt(void *Source); 1292PUBLIC __lgdt 1293__lgdt: 1294 lgdt fword ptr [rcx] 1295 ret 1296 1297//void __sgdt(void *Destination); 1298PUBLIC __sgdt 1299__sgdt: 1300 sgdt fword ptr [rcx] 1301 ret 1302 1303// void __lldt(unsigned short Value) 1304PUBLIC __lldt 1305__lldt: 1306 lldt cx 1307 ret 1308 1309//void __sldt(void *Destination); 1310PUBLIC __sldt 1311__sldt: 1312 sldt word ptr [rcx] 1313 ret 1314 1315//void __ltr(unsigned short Source); 1316PUBLIC __ltr 1317__ltr: 1318 ltr cx 1319 ret 1320 1321//void __str(unsigned short *Destination); 1322PUBLIC __str 1323__str: 1324 str word ptr [rcx] 1325 ret 1326 1327PUBLIC __swapgs 1328__swapgs: 1329 swapgs 1330 ret 1331 1332#endif 1333 1334END 1335