ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ke.h
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #ifndef __ASM__
00004 
00005 #include "intrin_i.h"
00006 
00007 //
00008 // Thread Dispatcher Header DebugActive Mask
00009 //
00010 #define DR_MASK(x)                              (1 << (x))
00011 #define DR_REG_MASK                             0x4F
00012 
00013 //
00014 // INT3 is 1 byte long
00015 //
00016 #define KD_BREAKPOINT_TYPE        UCHAR
00017 #define KD_BREAKPOINT_SIZE        sizeof(UCHAR)
00018 #define KD_BREAKPOINT_VALUE       0xCC
00019 
00020 //
00021 // Macros for getting and setting special purpose registers in portable code
00022 //
00023 #define KeGetContextPc(Context) \
00024     ((Context)->Eip)
00025 
00026 #define KeSetContextPc(Context, ProgramCounter) \
00027     ((Context)->Eip = (ProgramCounter))
00028 
00029 #define KeGetTrapFramePc(TrapFrame) \
00030     ((TrapFrame)->Eip)
00031 
00032 #define KiGetLinkedTrapFrame(x) \
00033     (PKTRAP_FRAME)((x)->Edx)
00034 
00035 #define KeGetContextReturnRegister(Context) \
00036     ((Context)->Eax)
00037 
00038 #define KeSetContextReturnRegister(Context, ReturnValue) \
00039     ((Context)->Eax = (ReturnValue))
00040 
00041 //
00042 // Macro to get trap and exception frame from a thread stack
00043 //
00044 #define KeGetTrapFrame(Thread) \
00045     (PKTRAP_FRAME)((ULONG_PTR)((Thread)->InitialStack) - \
00046                    sizeof(KTRAP_FRAME) - \
00047                    sizeof(FX_SAVE_AREA))
00048 
00049 #define KeGetExceptionFrame(Thread) \
00050     NULL
00051 
00052 //
00053 // Macro to get context switches from the PRCB
00054 // All architectures but x86 have it in the PRCB's KeContextSwitches
00055 //
00056 #define KeGetContextSwitches(Prcb)  \
00057     CONTAINING_RECORD(Prcb, KIPCR, PrcbData)->ContextSwitches
00058 
00059 //
00060 // Macro to get the second level cache size field name which differs between
00061 // CISC and RISC architectures, as the former has unified I/D cache
00062 //
00063 #define KiGetSecondLevelDCacheSize() ((PKIPCR)KeGetPcr())->SecondLevelCacheSize
00064 
00065 //
00066 // Returns the Interrupt State from a Trap Frame.
00067 // ON = TRUE, OFF = FALSE
00068 //
00069 #define KeGetTrapFrameInterruptState(TrapFrame) \
00070         BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK)
00071 
00072 //
00073 // Flags for exiting a trap
00074 //
00075 #define KTE_SKIP_PM_BIT  (((KTRAP_EXIT_SKIP_BITS) { { .SkipPreviousMode = TRUE } }).Bits)
00076 #define KTE_SKIP_SEG_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipSegments  = TRUE } }).Bits)
00077 #define KTE_SKIP_VOL_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipVolatiles = TRUE } }).Bits)
00078 
00079 typedef union _KTRAP_EXIT_SKIP_BITS
00080 {
00081     struct
00082     {
00083         UCHAR SkipPreviousMode:1;
00084         UCHAR SkipSegments:1;
00085         UCHAR SkipVolatiles:1;
00086         UCHAR Reserved:5;
00087     };
00088     UCHAR Bits;
00089 } KTRAP_EXIT_SKIP_BITS, *PKTRAP_EXIT_SKIP_BITS;
00090 
00091 
00092 //
00093 // Flags used by the VDM/V8086 emulation engine for determining instruction prefixes
00094 //
00095 #define PFX_FLAG_ES                0x00000100
00096 #define PFX_FLAG_CS                0x00000200
00097 #define PFX_FLAG_SS                0x00000400
00098 #define PFX_FLAG_DS                0x00000800
00099 #define PFX_FLAG_FS                0x00001000
00100 #define PFX_FLAG_GS                0x00002000
00101 #define PFX_FLAG_OPER32            0x00004000
00102 #define PFX_FLAG_ADDR32            0x00008000
00103 #define PFX_FLAG_LOCK              0x00010000
00104 #define PFX_FLAG_REPNE             0x00020000
00105 #define PFX_FLAG_REP               0x00040000
00106 
00107 //
00108 // VDM Helper Macros
00109 //
00110 // All VDM/V8086 opcode emulators have the same FASTCALL function definition.
00111 // We need to keep 2 parameters while the original ASM implementation uses 4:
00112 // TrapFrame, PrefixFlags, Eip, InstructionSize;
00113 //
00114 // We pass the trap frame, and prefix flags, in our two parameters.
00115 //
00116 // We then realize that since the smallest prefix flag is 0x100, this gives us
00117 // a count of up to 0xFF. So we OR in the instruction size with the prefix flags
00118 //
00119 // We further realize that we always have access to EIP from the trap frame, and
00120 // that if we want the *current instruction* EIP, we simply have to add the
00121 // instruction size *MINUS ONE*, and that gives us the EIP we should be looking
00122 // at now, so we don't need to use the stack to push this parameter.
00123 //
00124 // We actually only care about the *current instruction* EIP in one location,
00125 // so although it may be slightly more expensive to re-calculate the EIP one
00126 // more time, this way we don't redefine ALL opcode handlers to have 3 parameters,
00127 // which would be forcing stack usage in all other scenarios.
00128 //
00129 #define KiVdmSetVdmEFlags(x)        InterlockedOr((PLONG)KiNtVdmState, (x));
00130 #define KiVdmClearVdmEFlags(x)      InterlockedAnd((PLONG)KiNtVdmState, ~(x))
00131 #define KiCallVdmHandler(x)         KiVdmOpcode##x(TrapFrame, Flags)
00132 #define KiCallVdmPrefixHandler(x)   KiVdmOpcodePrefix(TrapFrame, Flags | x)
00133 #define KiVdmUnhandledOpcode(x)                     \
00134     BOOLEAN                                         \
00135     FASTCALL                                        \
00136     KiVdmOpcode##x(IN PKTRAP_FRAME TrapFrame,       \
00137                    IN ULONG Flags)                  \
00138     {                                               \
00139         /* Not yet handled */                       \
00140         UNIMPLEMENTED;                              \
00141         while (TRUE);                               \
00142         return TRUE;                                \
00143     }
00144 
00145 C_ASSERT(NPX_FRAME_LENGTH == sizeof(FX_SAVE_AREA));
00146 
00147 //
00148 // Local parameters
00149 //
00150 typedef struct _KV86_FRAME
00151 {
00152     PVOID ThreadStack;
00153     PVOID ThreadTeb;
00154     PVOID PcrTeb;
00155 } KV86_FRAME, *PKV86_FRAME;
00156 
00157 //
00158 // Virtual Stack Frame
00159 //
00160 typedef struct _KV8086_STACK_FRAME
00161 {
00162     KTRAP_FRAME TrapFrame;
00163     FX_SAVE_AREA NpxArea;
00164     KV86_FRAME V86Frame;
00165 } KV8086_STACK_FRAME, *PKV8086_STACK_FRAME;
00166 
00167 /* Diable interrupts and return whether they were enabled before */
00168 FORCEINLINE
00169 BOOLEAN
00170 KeDisableInterrupts(VOID)
00171 {
00172     ULONG Flags;
00173     BOOLEAN Return;
00174 
00175     /* Get EFLAGS and check if the interrupt bit is set */
00176     Flags = __readeflags();
00177     Return = (Flags & EFLAGS_INTERRUPT_MASK) ? TRUE: FALSE;
00178 
00179     /* Disable interrupts */
00180     _disable();
00181     return Return;
00182 }
00183 
00184 /* Restore previous interrupt state */
00185 FORCEINLINE
00186 VOID
00187 KeRestoreInterrupts(BOOLEAN WereEnabled)
00188 {
00189     if (WereEnabled) _enable();
00190 }
00191 
00192 //
00193 // Registers an interrupt handler with an IDT vector
00194 //
00195 FORCEINLINE
00196 VOID
00197 KeRegisterInterruptHandler(IN ULONG Vector,
00198                            IN PVOID Handler)
00199 {
00200     UCHAR Entry;
00201     ULONG_PTR Address;
00202     PKIPCR Pcr = (PKIPCR)KeGetPcr();
00203 
00204     //
00205     // Get the entry from the HAL
00206     //
00207     Entry = HalVectorToIDTEntry(Vector);
00208     Address = PtrToUlong(Handler);
00209 
00210     //
00211     // Now set the data
00212     //
00213     Pcr->IDT[Entry].ExtendedOffset = (USHORT)(Address >> 16);
00214     Pcr->IDT[Entry].Offset = (USHORT)Address;
00215 }
00216 
00217 //
00218 // Returns the registered interrupt handler for a given IDT vector
00219 //
00220 FORCEINLINE
00221 PVOID
00222 KeQueryInterruptHandler(IN ULONG Vector)
00223 {
00224     PKIPCR Pcr = (PKIPCR)KeGetPcr();
00225     UCHAR Entry;
00226 
00227     //
00228     // Get the entry from the HAL
00229     //
00230     Entry = HalVectorToIDTEntry(Vector);
00231 
00232     //
00233     // Read the entry from the IDT
00234     //
00235     return (PVOID)(((Pcr->IDT[Entry].ExtendedOffset << 16) & 0xFFFF0000) |
00236                     (Pcr->IDT[Entry].Offset & 0xFFFF));
00237 }
00238 
00239 //
00240 // Invalidates the TLB entry for a specified address
00241 //
00242 FORCEINLINE
00243 VOID
00244 KeInvalidateTlbEntry(IN PVOID Address)
00245 {
00246     /* Invalidate the TLB entry for this address */
00247     __invlpg(Address);
00248 }
00249 
00250 FORCEINLINE
00251 VOID
00252 KeFlushProcessTb(VOID)
00253 {
00254     /* Flush the TLB by resetting CR3 */
00255     __writecr3(__readcr3());
00256 }
00257 
00258 FORCEINLINE
00259 PRKTHREAD
00260 KeGetCurrentThread(VOID)
00261 {
00262     /* Return the current thread */
00263     return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
00264 }
00265 
00266 FORCEINLINE
00267 VOID
00268 KiRundownThread(IN PKTHREAD Thread)
00269 {
00270 #ifndef CONFIG_SMP
00271     /* Check if this is the NPX Thread */
00272     if (KeGetCurrentPrcb()->NpxThread == Thread)
00273     {
00274         /* Clear it */
00275         KeGetCurrentPrcb()->NpxThread = NULL;
00276         Ke386FnInit();
00277     }
00278 #else
00279     /* Nothing to do */
00280 #endif
00281 }
00282 
00283 VOID
00284 FASTCALL
00285 Ki386InitializeTss(
00286     IN PKTSS Tss,
00287     IN PKIDTENTRY Idt,
00288     IN PKGDTENTRY Gdt
00289 );
00290 
00291 VOID
00292 NTAPI
00293 KiSetCR0Bits(VOID);
00294 
00295 VOID
00296 NTAPI
00297 KiGetCacheInformation(VOID);
00298 
00299 BOOLEAN
00300 NTAPI
00301 KiIsNpxPresent(
00302     VOID
00303 );
00304 
00305 BOOLEAN
00306 NTAPI
00307 KiIsNpxErrataPresent(
00308     VOID
00309 );
00310 
00311 VOID
00312 NTAPI
00313 KiSetProcessorType(VOID);
00314 
00315 ULONG
00316 NTAPI
00317 KiGetFeatureBits(VOID);
00318 
00319 VOID
00320 NTAPI
00321 KiThreadStartup(VOID);
00322 
00323 NTSTATUS
00324 NTAPI
00325 Ke386GetGdtEntryThread(
00326     IN PKTHREAD Thread,
00327     IN ULONG Offset,
00328     IN PKGDTENTRY Descriptor
00329 );
00330 
00331 VOID
00332 NTAPI
00333 KiFlushNPXState(
00334     IN FLOATING_SAVE_AREA *SaveArea
00335 );
00336 
00337 VOID
00338 NTAPI
00339 Ki386AdjustEsp0(
00340     IN PKTRAP_FRAME TrapFrame
00341 );
00342 
00343 VOID
00344 NTAPI
00345 Ki386SetupAndExitToV86Mode(
00346     OUT PTEB VdmTeb
00347 );
00348 
00349 VOID
00350 NTAPI
00351 KeI386VdmInitialize(
00352     VOID
00353 );
00354 
00355 ULONG_PTR
00356 NTAPI
00357 Ki386EnableGlobalPage(
00358     IN volatile ULONG_PTR Context
00359 );
00360 
00361 VOID
00362 NTAPI
00363 KiI386PentiumLockErrataFixup(
00364     VOID
00365 );
00366 
00367 VOID
00368 NTAPI
00369 KiInitializePAT(
00370     VOID
00371 );
00372 
00373 VOID
00374 NTAPI
00375 KiInitializeMTRR(
00376     IN BOOLEAN FinalCpu
00377 );
00378 
00379 VOID
00380 NTAPI
00381 KiAmdK6InitializeMTRR(
00382     VOID
00383 );
00384 
00385 VOID
00386 NTAPI
00387 KiRestoreFastSyscallReturnState(
00388     VOID
00389 );
00390 
00391 ULONG_PTR
00392 NTAPI
00393 Ki386EnableDE(
00394     IN ULONG_PTR Context
00395 );
00396 
00397 ULONG_PTR
00398 NTAPI
00399 Ki386EnableFxsr(
00400     IN ULONG_PTR Context
00401 );
00402 
00403 ULONG_PTR
00404 NTAPI
00405 Ki386EnableXMMIExceptions(
00406     IN ULONG_PTR Context
00407 );
00408 
00409 BOOLEAN
00410 NTAPI
00411 VdmDispatchBop(
00412     IN PKTRAP_FRAME TrapFrame
00413 );
00414 
00415 BOOLEAN
00416 FASTCALL
00417 KiVdmOpcodePrefix(
00418     IN PKTRAP_FRAME TrapFrame,
00419     IN ULONG Flags
00420 );
00421 
00422 BOOLEAN
00423 FASTCALL
00424 Ki386HandleOpcodeV86(
00425     IN PKTRAP_FRAME TrapFrame
00426 );
00427 
00428 DECLSPEC_NORETURN
00429 VOID
00430 FASTCALL
00431 KiEoiHelper(
00432     IN PKTRAP_FRAME TrapFrame
00433 );
00434 
00435 VOID
00436 FASTCALL
00437 Ki386BiosCallReturnAddress(
00438     IN PKTRAP_FRAME TrapFrame
00439 );
00440 
00441 ULONG_PTR
00442 FASTCALL
00443 KiExitV86Mode(
00444     IN PKTRAP_FRAME TrapFrame
00445 );
00446 
00447 DECLSPEC_NORETURN
00448 VOID
00449 NTAPI
00450 KiDispatchExceptionFromTrapFrame(
00451     IN NTSTATUS Code,
00452     IN ULONG_PTR Address,
00453     IN ULONG ParameterCount,
00454     IN ULONG_PTR Parameter1,
00455     IN ULONG_PTR Parameter2,
00456     IN ULONG_PTR Parameter3,
00457     IN PKTRAP_FRAME TrapFrame
00458 );
00459 
00460 //
00461 // Global x86 only Kernel data
00462 //
00463 extern PVOID Ki386IopmSaveArea;
00464 extern ULONG KeI386EFlagsAndMaskV86;
00465 extern ULONG KeI386EFlagsOrMaskV86;
00466 extern BOOLEAN KeI386VirtualIntExtensions;
00467 extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR+1];
00468 extern KDESCRIPTOR KiIdtDescriptor;
00469 extern BOOLEAN KiI386PentiumLockErrataPresent;
00470 extern ULONG KeI386NpxPresent;
00471 extern ULONG KeI386XMMIPresent;
00472 extern ULONG KeI386FxsrPresent;
00473 extern ULONG KiMXCsrMask;
00474 extern ULONG KeI386CpuType;
00475 extern ULONG KeI386CpuStep;
00476 extern ULONG Ke386CacheAlignment;
00477 extern ULONG KiFastSystemCallDisable;
00478 extern UCHAR KiDebugRegisterTrapOffsets[9];
00479 extern UCHAR KiDebugRegisterContextOffsets[9];
00480 extern DECLSPEC_NORETURN VOID __cdecl KiTrap02(VOID);
00481 extern VOID __cdecl KiTrap08(VOID);
00482 extern VOID __cdecl KiTrap13(VOID);
00483 extern VOID __cdecl KiFastCallEntry(VOID);
00484 extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
00485 extern VOID NTAPI ExpInterlockedPopEntrySListResume(VOID);
00486 extern VOID __cdecl CopyParams(VOID);
00487 extern VOID __cdecl ReadBatch(VOID);
00488 extern VOID __cdecl FrRestore(VOID);
00489 extern CHAR KiSystemCallExitBranch[];
00490 extern CHAR KiSystemCallExit[];
00491 extern CHAR KiSystemCallExit2[];
00492 
00493 //
00494 // Trap Macros
00495 //
00496 #include "trap_x.h"
00497 
00498 //
00499 // Returns a thread's FPU save area
00500 //
00501 PFX_SAVE_AREA
00502 FORCEINLINE
00503 KiGetThreadNpxArea(IN PKTHREAD Thread)
00504 {
00505     return (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof(FX_SAVE_AREA));
00506 }
00507 
00508 //
00509 // Sanitizes a selector
00510 //
00511 FORCEINLINE
00512 ULONG
00513 Ke386SanitizeSeg(IN ULONG Cs,
00514                 IN KPROCESSOR_MODE Mode)
00515 {
00516     //
00517     // Check if we're in kernel-mode, and force CPL 0 if so.
00518     // Otherwise, force CPL 3.
00519     //
00520     return ((Mode == KernelMode) ?
00521             (Cs & (0xFFFF & ~RPL_MASK)) :
00522             (RPL_MASK | (Cs & 0xFFFF)));
00523 }
00524 
00525 //
00526 // Sanitizes EFLAGS
00527 //
00528 FORCEINLINE
00529 ULONG
00530 Ke386SanitizeFlags(IN ULONG Eflags,
00531                    IN KPROCESSOR_MODE Mode)
00532 {
00533     //
00534     // Check if we're in kernel-mode, and sanitize EFLAGS if so.
00535     // Otherwise, also force interrupt mask on.
00536     //
00537     return ((Mode == KernelMode) ?
00538             (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
00539             (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
00540 }
00541 
00542 //
00543 // Sanitizes a Debug Register
00544 //
00545 FORCEINLINE
00546 PVOID
00547 Ke386SanitizeDr(IN PVOID DrAddress,
00548                 IN KPROCESSOR_MODE Mode)
00549 {
00550     //
00551     // Check if we're in kernel-mode, and return the address directly if so.
00552     // Otherwise, make sure it's not inside the kernel-mode address space.
00553     // If it is, then clear the address.
00554     //
00555     return ((Mode == KernelMode) ? DrAddress :
00556             (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
00557 }
00558 
00559 //
00560 // Exception with no arguments
00561 //
00562 VOID
00563 FORCEINLINE
00564 DECLSPEC_NORETURN
00565 KiDispatchException0Args(IN NTSTATUS Code,
00566                          IN ULONG_PTR Address,
00567                          IN PKTRAP_FRAME TrapFrame)
00568 {
00569     /* Helper for exceptions with no arguments */
00570     KiDispatchExceptionFromTrapFrame(Code, Address, 0, 0, 0, 0, TrapFrame);
00571 }
00572 
00573 //
00574 // Exception with one argument
00575 //
00576 VOID
00577 FORCEINLINE
00578 DECLSPEC_NORETURN
00579 KiDispatchException1Args(IN NTSTATUS Code,
00580                          IN ULONG_PTR Address,
00581                          IN ULONG P1,
00582                          IN PKTRAP_FRAME TrapFrame)
00583 {
00584     /* Helper for exceptions with no arguments */
00585     KiDispatchExceptionFromTrapFrame(Code, Address, 1, P1, 0, 0, TrapFrame);
00586 }
00587 
00588 //
00589 // Exception with two arguments
00590 //
00591 VOID
00592 FORCEINLINE
00593 DECLSPEC_NORETURN
00594 KiDispatchException2Args(IN NTSTATUS Code,
00595                          IN ULONG_PTR Address,
00596                          IN ULONG P1,
00597                          IN ULONG P2,
00598                          IN PKTRAP_FRAME TrapFrame)
00599 {
00600     /* Helper for exceptions with no arguments */
00601     KiDispatchExceptionFromTrapFrame(Code, Address, 2, P1, P2, 0, TrapFrame);
00602 }
00603 
00604 //
00605 // Performs a system call
00606 //
00607 
00608     /*
00609      * This sequence does a RtlCopyMemory(Stack - StackBytes, Arguments, StackBytes)
00610      * and then calls the function associated with the system call.
00611      *
00612      * It's done in assembly for two reasons: we need to muck with the stack,
00613      * and the call itself restores the stack back for us. The only way to do
00614      * this in C is to do manual C handlers for every possible number of args on
00615      * the stack, and then have the handler issue a call by pointer. This is
00616      * wasteful since it'll basically push the values twice and require another
00617      * level of call indirection.
00618      *
00619      * The ARM kernel currently does this, but it should probably be changed
00620      * later to function like this as well.
00621      *
00622      */
00623 #ifdef __GNUC__
00624 NTSTATUS
00625 FORCEINLINE
00626 KiSystemCallTrampoline(IN PVOID Handler,
00627                        IN PVOID Arguments,
00628                        IN ULONG StackBytes)
00629 {
00630     NTSTATUS Result;
00631 
00632     __asm__ __volatile__
00633     (
00634         "subl %1, %%esp\n"
00635         "movl %%esp, %%edi\n"
00636         "movl %2, %%esi\n"
00637         "shrl $2, %1\n"
00638         "rep movsd\n"
00639         "call *%3\n"
00640         "movl %%eax, %0\n"
00641         : "=r"(Result)
00642         : "c"(StackBytes),
00643           "d"(Arguments),
00644           "r"(Handler)
00645         : "%esp", "%esi", "%edi"
00646     );
00647     return Result;
00648 }
00649 #elif defined(_MSC_VER)
00650 NTSTATUS
00651 FORCEINLINE
00652 KiSystemCallTrampoline(IN PVOID Handler,
00653                        IN PVOID Arguments,
00654                        IN ULONG StackBytes)
00655 {
00656     __asm
00657     {
00658         mov ecx, StackBytes
00659         mov esi, Arguments
00660         mov eax, Handler
00661         sub esp, ecx
00662         mov edi, esp
00663         shr ecx, 2
00664         rep movsd
00665         call eax
00666     }
00667     /* Return with result in EAX */
00668 }
00669 #else
00670 #error Unknown Compiler
00671 #endif
00672 
00673 
00674 //
00675 // Checks for pending APCs
00676 //
00677 VOID
00678 FORCEINLINE
00679 KiCheckForApcDelivery(IN PKTRAP_FRAME TrapFrame)
00680 {
00681     PKTHREAD Thread;
00682     KIRQL OldIrql;
00683 
00684     /* Check for V8086 or user-mode trap */
00685     if ((TrapFrame->EFlags & EFLAGS_V86_MASK) || (KiUserTrap(TrapFrame)))
00686     {
00687         /* Get the thread */
00688         Thread = KeGetCurrentThread();
00689         while (TRUE)
00690         {
00691             /* Turn off the alerted state for kernel mode */
00692             Thread->Alerted[KernelMode] = FALSE;
00693 
00694             /* Are there pending user APCs? */
00695             if (!Thread->ApcState.UserApcPending) break;
00696 
00697             /* Raise to APC level and enable interrupts */
00698             OldIrql = KfRaiseIrql(APC_LEVEL);
00699             _enable();
00700 
00701             /* Deliver APCs */
00702             KiDeliverApc(UserMode, NULL, TrapFrame);
00703 
00704             /* Restore IRQL and disable interrupts once again */
00705             KfLowerIrql(OldIrql);
00706             _disable();
00707         }
00708     }
00709 }
00710 
00711 //
00712 // Converts a base thread to a GUI thread
00713 //
00714 #ifdef __GNUC__
00715 NTSTATUS
00716 FORCEINLINE
00717 KiConvertToGuiThread(VOID)
00718 {
00719     NTSTATUS Result;
00720     PVOID StackFrame;
00721 
00722     /*
00723      * Converting to a GUI thread safely updates ESP in-place as well as the
00724      * current Thread->TrapFrame and EBP when KeSwitchKernelStack is called.
00725      *
00726      * However, PsConvertToGuiThread "helpfully" restores EBP to the original
00727      * caller's value, since it is considered a nonvolatile register. As such,
00728      * as soon as we're back after the conversion and we try to store the result
00729      * which will probably be in some stack variable (EBP-based), we'll crash as
00730      * we are touching the de-allocated non-expanded stack.
00731      *
00732      * Thus we need a way to update our EBP before EBP is touched, and the only
00733      * way to guarantee this is to do the call itself in assembly, use the EAX
00734      * register to store the result, fixup EBP, and then let the C code continue
00735      * on its merry way.
00736      *
00737      */
00738     __asm__ __volatile__
00739     (
00740         "movl %%ebp, %1\n\t"
00741         "subl %%esp, %1\n\t"
00742         "call _PsConvertToGuiThread@0\n\t"
00743         "addl %%esp, %1\n\t"
00744         "movl %1, %%ebp"
00745         : "=a"(Result), "=r"(StackFrame)
00746         :
00747         : "%esp", "%ecx", "%edx", "memory"
00748     );
00749     return Result;
00750 }
00751 #elif defined(_MSC_VER)
00752 NTSTATUS
00753 NTAPI
00754 KiConvertToGuiThread(VOID);
00755 #else
00756 #error Unknown Compiler
00757 #endif
00758 
00759 //
00760 // Switches from boot loader to initial kernel stack
00761 //
00762 VOID
00763 FORCEINLINE
00764 KiSwitchToBootStack(IN ULONG_PTR InitialStack)
00765 {
00766     /* We have to switch to a new stack before continuing kernel initialization */
00767 #ifdef __GNUC__
00768     __asm__
00769     (
00770         "movl %0, %%esp\n"
00771         "subl %1, %%esp\n"
00772         "pushl %2\n"
00773         "jmp _KiSystemStartupBootStack@0\n"
00774         :
00775         : "c"(InitialStack),
00776           "i"(NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH),
00777           "i"(CR0_EM | CR0_TS | CR0_MP)
00778         : "%esp"
00779     );
00780 #elif defined(_MSC_VER)
00781     VOID NTAPI KiSystemStartupBootStack(VOID);
00782     __asm
00783     {
00784         mov esp, InitialStack
00785         sub esp, (NPX_FRAME_LENGTH + KTRAP_FRAME_ALIGN + KTRAP_FRAME_LENGTH)
00786         push (CR0_EM | CR0_TS | CR0_MP)
00787         jmp KiSystemStartupBootStack
00788     }
00789 #else
00790 #error Unknown Compiler
00791 #endif
00792 }
00793 
00794 //
00795 // Emits the iret instruction for C code
00796 //
00797 DECLSPEC_NORETURN
00798 VOID
00799 FORCEINLINE
00800 KiIret(VOID)
00801 {
00802 #if defined(__GNUC__)
00803     __asm__ __volatile__
00804     (
00805         "iret\n"
00806     );
00807 #elif defined(_MSC_VER)
00808     __asm
00809     {
00810         iretd
00811     }
00812 #else
00813 #error Unsupported compiler
00814 #endif
00815     UNREACHABLE;
00816 }
00817 
00818 //
00819 // Normally this is done by the HAL, but on x86 as an optimization, the kernel
00820 // initiates the end by calling back into the HAL and exiting the trap here.
00821 //
00822 VOID
00823 FORCEINLINE
00824 KiEndInterrupt(IN KIRQL Irql,
00825                IN PKTRAP_FRAME TrapFrame)
00826 {
00827     /* Disable interrupts and end the interrupt */
00828     _disable();
00829     HalEndSystemInterrupt(Irql, TrapFrame);
00830 
00831     /* Exit the interrupt */
00832     KiEoiHelper(TrapFrame);
00833 }
00834 
00835 //
00836 // PERF Code
00837 //
00838 VOID
00839 FORCEINLINE
00840 Ki386PerfEnd(VOID)
00841 {
00842     extern ULONGLONG BootCyclesEnd, BootCycles;
00843     BootCyclesEnd = __rdtsc();
00844     DbgPrint("Boot took %I64d cycles!\n", BootCyclesEnd - BootCycles);
00845     DbgPrint("Interrupts: %d System Calls: %d Context Switches: %d\n",
00846              KeGetCurrentPrcb()->InterruptCount,
00847              KeGetCurrentPrcb()->KeSystemCalls,
00848              KeGetContextSwitches(KeGetCurrentPrcb()));
00849 }
00850 
00851 FORCEINLINE
00852 PULONG
00853 KiGetUserModeStackAddress(void)
00854 {
00855     return &(KeGetCurrentThread()->TrapFrame->HardwareEsp);
00856 }
00857 
00858 #endif

Generated on Sun May 27 2012 04:33:22 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.