1 #pragma once 2 3 #ifndef __ASM__ 4 5 #include "intrin_i.h" 6 7 #ifdef __cplusplus 8 extern "C" 9 { 10 #endif 11 12 // 13 // Thread Dispatcher Header DebugActive Mask 14 // 15 #define DR_MASK(x) (1 << (x)) 16 #define DR_REG_MASK 0x4F 17 18 // 19 // INT3 is 1 byte long 20 // 21 #define KD_BREAKPOINT_TYPE UCHAR 22 #define KD_BREAKPOINT_SIZE sizeof(UCHAR) 23 #define KD_BREAKPOINT_VALUE 0xCC 24 25 // 26 // One-liners for getting and setting special purpose registers in portable code 27 // 28 FORCEINLINE 29 ULONG_PTR 30 KeGetContextPc(PCONTEXT Context) 31 { 32 return Context->Eip; 33 } 34 35 FORCEINLINE 36 VOID 37 KeSetContextPc(PCONTEXT Context, ULONG_PTR ProgramCounter) 38 { 39 Context->Eip = ProgramCounter; 40 } 41 42 FORCEINLINE 43 ULONG_PTR 44 KeGetContextReturnRegister(PCONTEXT Context) 45 { 46 return Context->Eax; 47 } 48 49 FORCEINLINE 50 VOID 51 KeSetContextReturnRegister(PCONTEXT Context, ULONG_PTR ReturnValue) 52 { 53 Context->Eax = ReturnValue; 54 } 55 56 FORCEINLINE 57 ULONG_PTR 58 KeGetContextFrameRegister(PCONTEXT Context) 59 { 60 return Context->Ebp; 61 } 62 63 FORCEINLINE 64 VOID 65 KeSetContextFrameRegister(PCONTEXT Context, ULONG_PTR Frame) 66 { 67 Context->Ebp = Frame; 68 } 69 70 FORCEINLINE 71 ULONG_PTR 72 KeGetTrapFramePc(PKTRAP_FRAME TrapFrame) 73 { 74 return TrapFrame->Eip; 75 } 76 77 FORCEINLINE 78 PKTRAP_FRAME 79 KiGetLinkedTrapFrame(PKTRAP_FRAME TrapFrame) 80 { 81 return (PKTRAP_FRAME)TrapFrame->Edx; 82 } 83 84 85 FORCEINLINE 86 ULONG_PTR 87 KeGetTrapFrameStackRegister(PKTRAP_FRAME TrapFrame) 88 { 89 if (TrapFrame->PreviousPreviousMode == KernelMode) 90 return TrapFrame->TempEsp; 91 return TrapFrame->HardwareEsp; 92 } 93 94 FORCEINLINE 95 ULONG_PTR 96 KeGetTrapFrameFrameRegister(PKTRAP_FRAME TrapFrame) 97 { 98 return TrapFrame->Ebp; 99 } 100 101 // 102 // Macro to get trap and exception frame from a thread stack 103 // 104 #define KeGetTrapFrame(Thread) \ 105 (PKTRAP_FRAME)((ULONG_PTR)((Thread)->InitialStack) - \ 106 sizeof(KTRAP_FRAME) - \ 107 sizeof(FX_SAVE_AREA)) 108 109 #define KeGetExceptionFrame(Thread) \ 110 NULL 111 112 // 113 // Macro to get context switches from the PRCB 114 // All architectures but x86 have it in the PRCB's KeContextSwitches 115 // 116 #define KeGetContextSwitches(Prcb) \ 117 CONTAINING_RECORD(Prcb, KIPCR, PrcbData)->ContextSwitches 118 119 // 120 // Macro to get the second level cache size field name which differs between 121 // CISC and RISC architectures, as the former has unified I/D cache 122 // 123 #define KiGetSecondLevelDCacheSize() ((PKIPCR)KeGetPcr())->SecondLevelCacheSize 124 125 // 126 // Returns the Interrupt State from a Trap Frame. 127 // ON = TRUE, OFF = FALSE 128 // 129 #define KeGetTrapFrameInterruptState(TrapFrame) \ 130 BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK) 131 132 // 133 // Flags for exiting a trap 134 // 135 #define KTE_SKIP_PM_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipPreviousMode = TRUE } }).Bits) 136 #define KTE_SKIP_SEG_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipSegments = TRUE } }).Bits) 137 #define KTE_SKIP_VOL_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipVolatiles = TRUE } }).Bits) 138 139 typedef union _KTRAP_EXIT_SKIP_BITS 140 { 141 struct 142 { 143 UCHAR SkipPreviousMode:1; 144 UCHAR SkipSegments:1; 145 UCHAR SkipVolatiles:1; 146 UCHAR Reserved:5; 147 }; 148 UCHAR Bits; 149 } KTRAP_EXIT_SKIP_BITS, *PKTRAP_EXIT_SKIP_BITS; 150 151 152 // 153 // Flags used by the VDM/V8086 emulation engine for determining instruction prefixes 154 // 155 #define PFX_FLAG_ES 0x00000100 156 #define PFX_FLAG_CS 0x00000200 157 #define PFX_FLAG_SS 0x00000400 158 #define PFX_FLAG_DS 0x00000800 159 #define PFX_FLAG_FS 0x00001000 160 #define PFX_FLAG_GS 0x00002000 161 #define PFX_FLAG_OPER32 0x00004000 162 #define PFX_FLAG_ADDR32 0x00008000 163 #define PFX_FLAG_LOCK 0x00010000 164 #define PFX_FLAG_REPNE 0x00020000 165 #define PFX_FLAG_REP 0x00040000 166 167 // 168 // VDM Helper Macros 169 // 170 // All VDM/V8086 opcode emulators have the same FASTCALL function definition. 171 // We need to keep 2 parameters while the original ASM implementation uses 4: 172 // TrapFrame, PrefixFlags, Eip, InstructionSize; 173 // 174 // We pass the trap frame, and prefix flags, in our two parameters. 175 // 176 // We then realize that since the smallest prefix flag is 0x100, this gives us 177 // a count of up to 0xFF. So we OR in the instruction size with the prefix flags 178 // 179 // We further realize that we always have access to EIP from the trap frame, and 180 // that if we want the *current instruction* EIP, we simply have to add the 181 // instruction size *MINUS ONE*, and that gives us the EIP we should be looking 182 // at now, so we don't need to use the stack to push this parameter. 183 // 184 // We actually only care about the *current instruction* EIP in one location, 185 // so although it may be slightly more expensive to re-calculate the EIP one 186 // more time, this way we don't redefine ALL opcode handlers to have 3 parameters, 187 // which would be forcing stack usage in all other scenarios. 188 // 189 #define KiVdmSetVdmEFlags(x) InterlockedOr((PLONG)KiNtVdmState, (x)); 190 #define KiVdmClearVdmEFlags(x) InterlockedAnd((PLONG)KiNtVdmState, ~(x)) 191 #define KiCallVdmHandler(x) KiVdmOpcode##x(TrapFrame, Flags) 192 #define KiCallVdmPrefixHandler(x) KiVdmOpcodePrefix(TrapFrame, Flags | x) 193 #define KiVdmUnhandledOpcode(x) \ 194 BOOLEAN \ 195 FASTCALL \ 196 KiVdmOpcode##x(IN PKTRAP_FRAME TrapFrame, \ 197 IN ULONG Flags) \ 198 { \ 199 /* Not yet handled */ \ 200 UNIMPLEMENTED_DBGBREAK(); \ 201 return FALSE; \ 202 } 203 204 C_ASSERT(NPX_FRAME_LENGTH == sizeof(FX_SAVE_AREA)); 205 206 // 207 // Local parameters 208 // 209 typedef struct _KV86_FRAME 210 { 211 PVOID ThreadStack; 212 PVOID ThreadTeb; 213 PVOID PcrTeb; 214 } KV86_FRAME, *PKV86_FRAME; 215 216 // 217 // Virtual Stack Frame 218 // 219 typedef struct _KV8086_STACK_FRAME 220 { 221 KTRAP_FRAME TrapFrame; 222 FX_SAVE_AREA NpxArea; 223 KV86_FRAME V86Frame; 224 } KV8086_STACK_FRAME, *PKV8086_STACK_FRAME; 225 226 // 227 // Large Pages Support 228 // 229 typedef struct _LARGE_IDENTITY_MAP 230 { 231 PHARDWARE_PTE TopLevelDirectory; 232 ULONG Cr3; 233 ULONG_PTR StartAddress; 234 ULONG PagesCount; 235 PVOID PagesList[30]; 236 } LARGE_IDENTITY_MAP, *PLARGE_IDENTITY_MAP; 237 238 // 239 // Floating Point Internal Context Structure 240 // 241 typedef struct _FLOATING_SAVE_CONTEXT 242 { 243 PKTHREAD CurrentThread; 244 KIRQL OldNpxIrql; 245 PFX_SAVE_AREA Buffer; 246 PFX_SAVE_AREA PfxSaveArea; 247 } FLOATING_SAVE_CONTEXT, *PFLOATING_SAVE_CONTEXT; 248 249 /* Diable interrupts and return whether they were enabled before */ 250 FORCEINLINE 251 BOOLEAN 252 KeDisableInterrupts(VOID) 253 { 254 ULONG Flags; 255 BOOLEAN Return; 256 257 /* Get EFLAGS and check if the interrupt bit is set */ 258 Flags = __readeflags(); 259 Return = (Flags & EFLAGS_INTERRUPT_MASK) ? TRUE: FALSE; 260 261 /* Disable interrupts */ 262 _disable(); 263 return Return; 264 } 265 266 /* Restore previous interrupt state */ 267 FORCEINLINE 268 VOID 269 KeRestoreInterrupts(BOOLEAN WereEnabled) 270 { 271 if (WereEnabled) _enable(); 272 } 273 274 // 275 // Registers an interrupt handler with an IDT vector 276 // 277 FORCEINLINE 278 VOID 279 KeRegisterInterruptHandler(IN ULONG Vector, 280 IN PVOID Handler) 281 { 282 UCHAR Entry; 283 ULONG_PTR Address; 284 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 285 286 // 287 // Get the entry from the HAL 288 // 289 Entry = HalVectorToIDTEntry(Vector); 290 Address = PtrToUlong(Handler); 291 292 // 293 // Now set the data 294 // 295 Pcr->IDT[Entry].ExtendedOffset = (USHORT)(Address >> 16); 296 Pcr->IDT[Entry].Offset = (USHORT)Address; 297 } 298 299 // 300 // Returns the registered interrupt handler for a given IDT vector 301 // 302 FORCEINLINE 303 PVOID 304 KeQueryInterruptHandler(IN ULONG Vector) 305 { 306 PKIPCR Pcr = (PKIPCR)KeGetPcr(); 307 UCHAR Entry; 308 309 // 310 // Get the entry from the HAL 311 // 312 Entry = HalVectorToIDTEntry(Vector); 313 314 // 315 // Read the entry from the IDT 316 // 317 return (PVOID)(((Pcr->IDT[Entry].ExtendedOffset << 16) & 0xFFFF0000) | 318 (Pcr->IDT[Entry].Offset & 0xFFFF)); 319 } 320 321 // 322 // Invalidates the TLB entry for a specified address 323 // 324 FORCEINLINE 325 VOID 326 KeInvalidateTlbEntry(IN PVOID Address) 327 { 328 /* Invalidate the TLB entry for this address */ 329 __invlpg(Address); 330 } 331 332 FORCEINLINE 333 VOID 334 KeFlushProcessTb(VOID) 335 { 336 /* Flush the TLB by resetting CR3 */ 337 __writecr3(__readcr3()); 338 } 339 340 FORCEINLINE 341 VOID 342 KeSweepICache(IN PVOID BaseAddress, 343 IN SIZE_T FlushSize) 344 { 345 // 346 // Always sweep the whole cache 347 // 348 UNREFERENCED_PARAMETER(BaseAddress); 349 UNREFERENCED_PARAMETER(FlushSize); 350 __wbinvd(); 351 } 352 353 FORCEINLINE 354 PRKTHREAD 355 KeGetCurrentThread(VOID) 356 { 357 /* Return the current thread */ 358 return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread; 359 } 360 361 FORCEINLINE 362 VOID 363 KiRundownThread(IN PKTHREAD Thread) 364 { 365 #ifndef CONFIG_SMP 366 /* Check if this is the NPX Thread */ 367 if (KeGetCurrentPrcb()->NpxThread == Thread) 368 { 369 /* Clear it */ 370 KeGetCurrentPrcb()->NpxThread = NULL; 371 Ke386FnInit(); 372 } 373 #else 374 /* Nothing to do */ 375 #endif 376 } 377 378 FORCEINLINE 379 VOID 380 Ke386SetGdtEntryBase(PKGDTENTRY GdtEntry, PVOID BaseAddress) 381 { 382 GdtEntry->BaseLow = (USHORT)((ULONG_PTR)BaseAddress & 0xFFFF); 383 GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)BaseAddress >> 16); 384 GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)BaseAddress >> 24); 385 } 386 387 FORCEINLINE 388 VOID 389 KiSetTebBase(PKPCR Pcr, PNT_TIB TebAddress) 390 { 391 Pcr->NtTib.Self = TebAddress; 392 Ke386SetGdtEntryBase(&Pcr->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)], TebAddress); 393 } 394 395 CODE_SEG("INIT") 396 VOID 397 FASTCALL 398 Ki386InitializeTss( 399 IN PKTSS Tss, 400 IN PKIDTENTRY Idt, 401 IN PKGDTENTRY Gdt 402 ); 403 404 CODE_SEG("INIT") 405 VOID 406 NTAPI 407 KiSetCR0Bits(VOID); 408 409 CODE_SEG("INIT") 410 VOID 411 NTAPI 412 KiGetCacheInformation(VOID); 413 414 CODE_SEG("INIT") 415 BOOLEAN 416 NTAPI 417 KiIsNpxPresent( 418 VOID 419 ); 420 421 CODE_SEG("INIT") 422 BOOLEAN 423 NTAPI 424 KiIsNpxErrataPresent( 425 VOID 426 ); 427 428 CODE_SEG("INIT") 429 VOID 430 NTAPI 431 KiSetProcessorType(VOID); 432 433 CODE_SEG("INIT") 434 ULONG 435 NTAPI 436 KiGetFeatureBits(VOID); 437 438 VOID 439 NTAPI 440 KiThreadStartup(VOID); 441 442 NTSTATUS 443 NTAPI 444 Ke386GetGdtEntryThread( 445 IN PKTHREAD Thread, 446 IN ULONG Offset, 447 IN PKGDTENTRY Descriptor 448 ); 449 450 VOID 451 NTAPI 452 KiFlushNPXState( 453 IN FLOATING_SAVE_AREA *SaveArea 454 ); 455 456 VOID 457 NTAPI 458 Ki386AdjustEsp0( 459 IN PKTRAP_FRAME TrapFrame 460 ); 461 462 VOID 463 NTAPI 464 Ki386SetupAndExitToV86Mode( 465 OUT PTEB VdmTeb 466 ); 467 468 CODE_SEG("INIT") 469 VOID 470 NTAPI 471 KeI386VdmInitialize( 472 VOID 473 ); 474 475 CODE_SEG("INIT") 476 ULONG_PTR 477 NTAPI 478 Ki386EnableGlobalPage( 479 IN ULONG_PTR Context 480 ); 481 482 CODE_SEG("INIT") 483 ULONG_PTR 484 NTAPI 485 Ki386EnableTargetLargePage( 486 IN ULONG_PTR Context 487 ); 488 489 BOOLEAN 490 NTAPI 491 Ki386CreateIdentityMap( 492 IN PLARGE_IDENTITY_MAP IdentityMap, 493 IN PVOID StartPtr, 494 IN ULONG Length 495 ); 496 497 VOID 498 NTAPI 499 Ki386FreeIdentityMap( 500 IN PLARGE_IDENTITY_MAP IdentityMap 501 ); 502 503 VOID 504 NTAPI 505 Ki386EnableCurrentLargePage( 506 IN ULONG_PTR StartAddress, 507 IN ULONG Cr3 508 ); 509 510 CODE_SEG("INIT") 511 VOID 512 NTAPI 513 KiI386PentiumLockErrataFixup( 514 VOID 515 ); 516 517 CODE_SEG("INIT") 518 VOID 519 NTAPI 520 KiInitializePAT( 521 VOID 522 ); 523 524 CODE_SEG("INIT") 525 VOID 526 NTAPI 527 KiInitializeMTRR( 528 IN BOOLEAN FinalCpu 529 ); 530 531 CODE_SEG("INIT") 532 VOID 533 NTAPI 534 KiAmdK6InitializeMTRR( 535 VOID 536 ); 537 538 CODE_SEG("INIT") 539 VOID 540 NTAPI 541 KiRestoreFastSyscallReturnState( 542 VOID 543 ); 544 545 CODE_SEG("INIT") 546 ULONG_PTR 547 NTAPI 548 Ki386EnableDE( 549 IN ULONG_PTR Context 550 ); 551 552 CODE_SEG("INIT") 553 ULONG_PTR 554 NTAPI 555 Ki386EnableFxsr( 556 IN ULONG_PTR Context 557 ); 558 559 CODE_SEG("INIT") 560 ULONG_PTR 561 NTAPI 562 Ki386EnableXMMIExceptions( 563 IN ULONG_PTR Context 564 ); 565 566 BOOLEAN 567 NTAPI 568 VdmDispatchBop( 569 IN PKTRAP_FRAME TrapFrame 570 ); 571 572 BOOLEAN 573 NTAPI 574 VdmDispatchPageFault( 575 _In_ PKTRAP_FRAME TrapFrame 576 ); 577 578 BOOLEAN 579 FASTCALL 580 KiVdmOpcodePrefix( 581 IN PKTRAP_FRAME TrapFrame, 582 IN ULONG Flags 583 ); 584 585 BOOLEAN 586 FASTCALL 587 Ki386HandleOpcodeV86( 588 IN PKTRAP_FRAME TrapFrame 589 ); 590 591 DECLSPEC_NORETURN 592 VOID 593 FASTCALL 594 KiEoiHelper( 595 IN PKTRAP_FRAME TrapFrame 596 ); 597 598 VOID 599 FASTCALL 600 Ki386BiosCallReturnAddress( 601 IN PKTRAP_FRAME TrapFrame 602 ); 603 604 ULONG_PTR 605 FASTCALL 606 KiExitV86Mode( 607 IN PKTRAP_FRAME TrapFrame 608 ); 609 610 DECLSPEC_NORETURN 611 VOID 612 NTAPI 613 KiDispatchExceptionFromTrapFrame( 614 IN NTSTATUS Code, 615 IN ULONG Flags, 616 IN ULONG_PTR Address, 617 IN ULONG ParameterCount, 618 IN ULONG_PTR Parameter1, 619 IN ULONG_PTR Parameter2, 620 IN ULONG_PTR Parameter3, 621 IN PKTRAP_FRAME TrapFrame 622 ); 623 624 NTSTATUS 625 NTAPI 626 KiConvertToGuiThread( 627 VOID 628 ); 629 630 // 631 // Global x86 only Kernel data 632 // 633 extern PVOID Ki386IopmSaveArea; 634 extern ULONG KeI386EFlagsAndMaskV86; 635 extern ULONG KeI386EFlagsOrMaskV86; 636 extern BOOLEAN KeI386VirtualIntExtensions; 637 extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR+1]; 638 extern KDESCRIPTOR KiIdtDescriptor; 639 extern BOOLEAN KiI386PentiumLockErrataPresent; 640 extern ULONG KeI386NpxPresent; 641 extern ULONG KeI386XMMIPresent; 642 extern ULONG KeI386FxsrPresent; 643 extern ULONG KiMXCsrMask; 644 extern ULONG KeI386CpuType; 645 extern ULONG KeI386CpuStep; 646 extern ULONG KiFastSystemCallDisable; 647 extern UCHAR KiDebugRegisterTrapOffsets[9]; 648 extern UCHAR KiDebugRegisterContextOffsets[9]; 649 extern VOID __cdecl KiTrap02(VOID); 650 extern VOID __cdecl KiTrap08(VOID); 651 extern VOID __cdecl KiTrap13(VOID); 652 extern VOID __cdecl KiFastCallEntry(VOID); 653 extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID); 654 extern VOID NTAPI ExpInterlockedPopEntrySListResume(VOID); 655 extern VOID __cdecl CopyParams(VOID); 656 extern VOID __cdecl ReadBatch(VOID); 657 extern CHAR KiSystemCallExitBranch[]; 658 extern CHAR KiSystemCallExit[]; 659 extern CHAR KiSystemCallExit2[]; 660 661 // 662 // Trap Macros 663 // 664 #include "trap_x.h" 665 666 // 667 // Returns a thread's FPU save area 668 // 669 FORCEINLINE 670 PFX_SAVE_AREA 671 KiGetThreadNpxArea(IN PKTHREAD Thread) 672 { 673 ASSERT((ULONG_PTR)Thread->InitialStack % 16 == 0); 674 return (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof(FX_SAVE_AREA)); 675 } 676 677 // 678 // Sanitizes a selector 679 // 680 FORCEINLINE 681 ULONG 682 Ke386SanitizeSeg(IN ULONG Cs, 683 IN KPROCESSOR_MODE Mode) 684 { 685 // 686 // Check if we're in kernel-mode, and force CPL 0 if so. 687 // Otherwise, force CPL 3. 688 // 689 return ((Mode == KernelMode) ? 690 (Cs & (0xFFFF & ~RPL_MASK)) : 691 (RPL_MASK | (Cs & 0xFFFF))); 692 } 693 694 // 695 // Sanitizes EFLAGS 696 // 697 FORCEINLINE 698 ULONG 699 Ke386SanitizeFlags(IN ULONG Eflags, 700 IN KPROCESSOR_MODE Mode) 701 { 702 // 703 // Check if we're in kernel-mode, and sanitize EFLAGS if so. 704 // Otherwise, also force interrupt mask on. 705 // 706 return ((Mode == KernelMode) ? 707 (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) : 708 (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE))); 709 } 710 711 // 712 // Sanitizes a Debug Register 713 // 714 FORCEINLINE 715 PVOID 716 Ke386SanitizeDr(IN PVOID DrAddress, 717 IN KPROCESSOR_MODE Mode) 718 { 719 // 720 // Check if we're in kernel-mode, and return the address directly if so. 721 // Otherwise, make sure it's not inside the kernel-mode address space. 722 // If it is, then clear the address. 723 // 724 return ((Mode == KernelMode) ? DrAddress : 725 (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0); 726 } 727 728 // 729 // Exception with no arguments 730 // 731 FORCEINLINE 732 DECLSPEC_NORETURN 733 VOID 734 KiDispatchException0Args(IN NTSTATUS Code, 735 IN ULONG_PTR Address, 736 IN PKTRAP_FRAME TrapFrame) 737 { 738 /* Helper for exceptions with no arguments */ 739 KiDispatchExceptionFromTrapFrame(Code, 0, Address, 0, 0, 0, 0, TrapFrame); 740 } 741 742 // 743 // Exception with one argument 744 // 745 FORCEINLINE 746 DECLSPEC_NORETURN 747 VOID 748 KiDispatchException1Args(IN NTSTATUS Code, 749 IN ULONG_PTR Address, 750 IN ULONG P1, 751 IN PKTRAP_FRAME TrapFrame) 752 { 753 /* Helper for exceptions with no arguments */ 754 KiDispatchExceptionFromTrapFrame(Code, 0, Address, 1, P1, 0, 0, TrapFrame); 755 } 756 757 // 758 // Exception with two arguments 759 // 760 FORCEINLINE 761 DECLSPEC_NORETURN 762 VOID 763 KiDispatchException2Args(IN NTSTATUS Code, 764 IN ULONG_PTR Address, 765 IN ULONG P1, 766 IN ULONG P2, 767 IN PKTRAP_FRAME TrapFrame) 768 { 769 /* Helper for exceptions with no arguments */ 770 KiDispatchExceptionFromTrapFrame(Code, 0, Address, 2, P1, P2, 0, TrapFrame); 771 } 772 773 // 774 // Performs a system call 775 // 776 NTSTATUS 777 NTAPI 778 KiSystemCallTrampoline(_In_ PVOID Handler, 779 _In_ PVOID Arguments, 780 _In_ ULONG StackBytes); 781 782 783 // 784 // Checks for pending APCs 785 // 786 FORCEINLINE 787 VOID 788 KiCheckForApcDelivery(IN PKTRAP_FRAME TrapFrame) 789 { 790 PKTHREAD Thread; 791 KIRQL OldIrql; 792 793 /* Check for V8086 or user-mode trap */ 794 if ((TrapFrame->EFlags & EFLAGS_V86_MASK) || (KiUserTrap(TrapFrame))) 795 { 796 /* Get the thread */ 797 Thread = KeGetCurrentThread(); 798 while (TRUE) 799 { 800 /* Turn off the alerted state for kernel mode */ 801 Thread->Alerted[KernelMode] = FALSE; 802 803 /* Are there pending user APCs? */ 804 if (!Thread->ApcState.UserApcPending) break; 805 806 /* Raise to APC level and enable interrupts */ 807 OldIrql = KfRaiseIrql(APC_LEVEL); 808 _enable(); 809 810 /* Deliver APCs */ 811 KiDeliverApc(UserMode, NULL, TrapFrame); 812 813 /* Restore IRQL and disable interrupts once again */ 814 KfLowerIrql(OldIrql); 815 _disable(); 816 } 817 } 818 } 819 820 // 821 // Switches from boot loader to initial kernel stack 822 // 823 CODE_SEG("INIT") 824 FORCEINLINE 825 DECLSPEC_NORETURN 826 VOID 827 KiSwitchToBootStack(IN ULONG_PTR InitialStack) 828 { 829 CODE_SEG("INIT") DECLSPEC_NORETURN VOID NTAPI KiSystemStartupBootStack(VOID); 830 831 /* We have to switch to a new stack before continuing kernel initialization */ 832 #ifdef __GNUC__ 833 __asm__ 834 ( 835 "movl %0, %%esp\n\t" 836 "subl %1, %%esp\n\t" 837 "pushl %2\n\t" 838 "jmp _KiSystemStartupBootStack@0" 839 : 840 : "c"(InitialStack), 841 "i"(NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH), 842 "i"(CR0_EM | CR0_TS | CR0_MP), 843 "p"(KiSystemStartupBootStack) 844 : "%esp" 845 ); 846 #elif defined(_MSC_VER) 847 __asm 848 { 849 mov esp, InitialStack 850 sub esp, (NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH) 851 push (CR0_EM | CR0_TS | CR0_MP) 852 jmp KiSystemStartupBootStack 853 } 854 #else 855 #error Unknown Compiler 856 #endif 857 858 UNREACHABLE; 859 } 860 861 // 862 // Emits the iret instruction for C code 863 // 864 FORCEINLINE 865 DECLSPEC_NORETURN 866 VOID 867 KiIret(VOID) 868 { 869 #if defined(__GNUC__) 870 __asm__ __volatile__ 871 ( 872 "iret" 873 ); 874 #elif defined(_MSC_VER) 875 __asm 876 { 877 iretd 878 } 879 #else 880 #error Unsupported compiler 881 #endif 882 UNREACHABLE; 883 } 884 885 // 886 // Normally this is done by the HAL, but on x86 as an optimization, the kernel 887 // initiates the end by calling back into the HAL and exiting the trap here. 888 // 889 FORCEINLINE 890 VOID 891 KiEndInterrupt(IN KIRQL Irql, 892 IN PKTRAP_FRAME TrapFrame) 893 { 894 /* Disable interrupts and end the interrupt */ 895 _disable(); 896 HalEndSystemInterrupt(Irql, TrapFrame); 897 898 /* Exit the interrupt */ 899 KiEoiHelper(TrapFrame); 900 } 901 902 // 903 // PERF Code 904 // 905 FORCEINLINE 906 VOID 907 Ki386PerfEnd(VOID) 908 { 909 extern ULONGLONG BootCyclesEnd, BootCycles; 910 BootCyclesEnd = __rdtsc(); 911 DbgPrint("Boot took %I64u cycles!\n", BootCyclesEnd - BootCycles); 912 DbgPrint("Interrupts: %u System Calls: %u Context Switches: %u\n", 913 KeGetCurrentPrcb()->InterruptCount, 914 KeGetCurrentPrcb()->KeSystemCalls, 915 KeGetContextSwitches(KeGetCurrentPrcb())); 916 } 917 918 FORCEINLINE 919 PULONG 920 KiGetUserModeStackAddress(void) 921 { 922 return &(KeGetCurrentThread()->TrapFrame->HardwareEsp); 923 } 924 925 #ifdef __cplusplus 926 } // extern "C" 927 #endif 928 929 #endif 930