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