unbreak build
[reactos.git] / reactos / ntoskrnl / include / internal / i386 / ke.h
index d2c0f8c..abcaba7 100644 (file)
@@ -8,6 +8,229 @@
 
 extern ULONG Ke386CacheAlignment;
 
+//
+// Thread Dispatcher Header DebugActive Mask
+//
+#define DR_MASK(x)                              (1 << (x))
+#define DR_REG_MASK                             0x4F
+
+#define IMAGE_FILE_MACHINE_ARCHITECTURE IMAGE_FILE_MACHINE_I386
+
+//
+// INT3 is 1 byte long
+//
+#define KD_BREAKPOINT_TYPE        UCHAR
+#define KD_BREAKPOINT_SIZE        sizeof(UCHAR)
+#define KD_BREAKPOINT_VALUE       0xCC
+
+//
+// Macros for getting and setting special purpose registers in portable code
+//
+#define KeGetContextPc(Context) \
+    ((Context)->Eip)
+
+#define KeSetContextPc(Context, ProgramCounter) \
+    ((Context)->Eip = (ProgramCounter))
+
+#define KeGetTrapFramePc(TrapFrame) \
+    ((TrapFrame)->Eip)
+
+#define KeGetContextReturnRegister(Context) \
+    ((Context)->Eax)
+
+#define KeSetContextReturnRegister(Context, ReturnValue) \
+    ((Context)->Eax = (ReturnValue))
+
+//
+// Macro to get trap and exception frame from a thread stack
+//
+#define KeGetTrapFrame(Thread) \
+    (PKTRAP_FRAME)((ULONG_PTR)((Thread)->InitialStack) - \
+                   sizeof(KTRAP_FRAME) - \
+                   sizeof(FX_SAVE_AREA))
+
+#define KeGetExceptionFrame(Thread) \
+    NULL
+
+//
+// Macro to get context switches from the PRCB
+// All architectures but x86 have it in the PRCB's KeContextSwitches
+//
+#define KeGetContextSwitches(Prcb)  \
+    CONTAINING_RECORD(Prcb, KIPCR, PrcbData)->ContextSwitches
+
+//
+// Returns the Interrupt State from a Trap Frame.
+// ON = TRUE, OFF = FALSE
+//
+#define KeGetTrapFrameInterruptState(TrapFrame) \
+        BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK)
+
+//
+// Flags for exiting a trap
+//
+#define KTE_SKIP_PM_BIT  (((KTRAP_EXIT_SKIP_BITS) { { .SkipPreviousMode = TRUE } }).Bits)
+#define KTE_SKIP_SEG_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipSegments  = TRUE } }).Bits)
+#define KTE_SKIP_VOL_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipVolatiles = TRUE } }).Bits)
+typedef union _KTRAP_EXIT_SKIP_BITS
+{
+    struct
+    {
+        UCHAR SkipPreviousMode:1;
+        UCHAR SkipSegments:1;
+        UCHAR SkipVolatiles:1;
+        UCHAR Reserved:5;
+    };
+    UCHAR Bits;
+} KTRAP_EXIT_SKIP_BITS, *PKTRAP_EXIT_SKIP_BITS;
+
+
+//
+// Flags used by the VDM/V8086 emulation engine for determining instruction prefixes
+//
+#define PFX_FLAG_ES                0x00000100
+#define PFX_FLAG_CS                0x00000200
+#define PFX_FLAG_SS                0x00000400
+#define PFX_FLAG_DS                0x00000800
+#define PFX_FLAG_FS                0x00001000
+#define PFX_FLAG_GS                0x00002000
+#define PFX_FLAG_OPER32            0x00004000
+#define PFX_FLAG_ADDR32            0x00008000
+#define PFX_FLAG_LOCK              0x00010000
+#define PFX_FLAG_REPNE             0x00020000
+#define PFX_FLAG_REP               0x00040000
+
+//
+// VDM Helper Macros
+//
+// All VDM/V8086 opcode emulators have the same FASTCALL function definition.
+// We need to keep 2 parameters while the original ASM implementation uses 4:
+// TrapFrame, PrefixFlags, Eip, InstructionSize;
+//
+// We pass the trap frame, and prefix flags, in our two parameters.
+//
+// We then realize that since the smallest prefix flag is 0x100, this gives us
+// a count of up to 0xFF. So we OR in the instruction size with the prefix flags
+//
+// We further realize that we always have access to EIP from the trap frame, and
+// that if we want the *current instruction* EIP, we simply have to add the
+// instruction size *MINUS ONE*, and that gives us the EIP we should be looking
+// at now, so we don't need to use the stack to push this parameter.
+//
+// We actually only care about the *current instruction* EIP in one location,
+// so although it may be slightly more expensive to re-calculate the EIP one
+// more time, this way we don't redefine ALL opcode handlers to have 3 parameters,
+// which would be forcing stack usage in all other scenarios.
+//
+#define KiVdmSetVdmEFlags(x)        InterlockedOr((PLONG)KiNtVdmState, (x));
+#define KiVdmClearVdmEFlags(x)      InterlockedAnd((PLONG)KiNtVdmState, ~(x))
+#define KiCallVdmHandler(x)         KiVdmOpcode##x(TrapFrame, Flags)
+#define KiCallVdmPrefixHandler(x)   KiVdmOpcodePrefix(TrapFrame, Flags | x)
+#define KiVdmUnhandledOpcode(x)                     \
+    BOOLEAN                                         \
+    FASTCALL                                        \
+    KiVdmOpcode##x(IN PKTRAP_FRAME TrapFrame,       \
+                   IN ULONG Flags)                  \
+    {                                               \
+        /* Not yet handled */                       \
+        UNIMPLEMENTED;                              \
+        while (TRUE);                               \
+        return TRUE;                                \
+    }
+
+              
+//
+// Registers an interrupt handler with an IDT vector
+//
+FORCEINLINE
+VOID
+KeRegisterInterruptHandler(IN ULONG Vector,
+                           IN PVOID Handler)
+{                           
+    UCHAR Entry;
+    ULONG_PTR Address;
+    PKIPCR Pcr = (PKIPCR)KeGetPcr();
+
+    //
+    // Get the entry from the HAL
+    //
+    Entry = HalVectorToIDTEntry(Vector);
+    Address = PtrToUlong(Handler);
+
+    //
+    // Now set the data
+    //
+    Pcr->IDT[Entry].ExtendedOffset = (USHORT)(Address >> 16);
+    Pcr->IDT[Entry].Offset = (USHORT)Address;
+}
+
+//
+// Returns the registered interrupt handler for a given IDT vector
+//
+FORCEINLINE
+PVOID
+KeQueryInterruptHandler(IN ULONG Vector)
+{
+    PKIPCR Pcr = (PKIPCR)KeGetPcr();
+    UCHAR Entry;
+
+    //
+    // Get the entry from the HAL
+    //
+    Entry = HalVectorToIDTEntry(Vector);
+
+    //
+    // Read the entry from the IDT
+    //
+    return (PVOID)(((Pcr->IDT[Entry].ExtendedOffset << 16) & 0xFFFF0000) |
+                    (Pcr->IDT[Entry].Offset & 0xFFFF));
+}
+
+//
+// Invalidates the TLB entry for a specified address
+//
+FORCEINLINE
+VOID
+KeInvalidateTlbEntry(IN PVOID Address)
+{
+    /* Invalidate the TLB entry for this address */
+    __invlpg(Address);
+}
+
+FORCEINLINE
+VOID
+KeFlushProcessTb(VOID)
+{
+    /* Flush the TLB by resetting CR3 */
+    __writecr3(__readcr3());
+}
+
+FORCEINLINE
+PRKTHREAD
+KeGetCurrentThread(VOID)
+{
+    /* Return the current thread */
+    return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
+}
+
+FORCEINLINE
+VOID
+KiRundownThread(IN PKTHREAD Thread)
+{
+#ifndef CONFIG_SMP
+    /* Check if this is the NPX Thread */
+    if (KeGetCurrentPrcb()->NpxThread == Thread)
+    {
+        /* Clear it */
+        KeGetCurrentPrcb()->NpxThread = NULL;
+        Ke386FnInit();
+    }
+#else
+    /* Nothing to do */
+#endif
+}
+
 VOID
 FASTCALL
 Ki386InitializeTss(
@@ -54,7 +277,211 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
                 KTRAP_FRAME TrapFrame);
 #endif
 
+NTSTATUS
+NTAPI
+Ke386GetGdtEntryThread(
+    IN PKTHREAD Thread,
+    IN ULONG Offset,
+    IN PKGDTENTRY Descriptor
+);
+
+VOID
+NTAPI
+KiFlushNPXState(
+    IN FLOATING_SAVE_AREA *SaveArea
+);
+
+VOID
+NTAPI
+Ki386AdjustEsp0(
+    IN PKTRAP_FRAME TrapFrame
+);
+
+VOID
+NTAPI
+Ki386SetupAndExitToV86Mode(
+    OUT PTEB VdmTeb
+);
+
+VOID
+NTAPI
+KeI386VdmInitialize(
+    VOID
+);
+
+ULONG_PTR
+NTAPI
+Ki386EnableGlobalPage(
+    IN volatile ULONG_PTR Context
+);
+
+VOID
+NTAPI
+KiI386PentiumLockErrataFixup(
+    VOID
+);
+
+VOID
+NTAPI
+KiInitializePAT(
+    VOID
+);
+
+VOID
+NTAPI
+KiInitializeMTRR(
+    IN BOOLEAN FinalCpu
+);
+
+VOID
+NTAPI
+KiAmdK6InitializeMTRR(
+    VOID
+);
+
+VOID
+NTAPI
+KiRestoreFastSyscallReturnState(
+    VOID
+);
+
+ULONG_PTR
+NTAPI
+Ki386EnableDE(
+    IN ULONG_PTR Context
+);
+
+ULONG_PTR
+NTAPI
+Ki386EnableFxsr(
+    IN ULONG_PTR Context
+);
+
+ULONG_PTR
+NTAPI
+Ki386EnableXMMIExceptions(
+    IN ULONG_PTR Context
+);
+
+BOOLEAN
+NTAPI
+VdmDispatchBop(
+    IN PKTRAP_FRAME TrapFrame
+);
+BOOLEAN
+FASTCALL
+KiVdmOpcodePrefix(
+    IN PKTRAP_FRAME TrapFrame,
+    IN ULONG Flags
+);
+
+BOOLEAN
+FASTCALL
+Ki386HandleOpcodeV86(
+    IN PKTRAP_FRAME TrapFrame
+);
+
+//
+// Global x86 only Kernel data
+//
+extern PVOID Ki386IopmSaveArea;
+extern ULONG KeI386EFlagsAndMaskV86;
+extern ULONG KeI386EFlagsOrMaskV86;
+extern BOOLEAN KeI386VirtualIntExtensions;
+extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR];
+extern KDESCRIPTOR KiIdtDescriptor;
+extern ULONG Ke386GlobalPagesEnabled;
+extern BOOLEAN KiI386PentiumLockErrataPresent;
+extern ULONG KeI386NpxPresent;
+extern ULONG KeI386XMMIPresent;
+extern ULONG KeI386FxsrPresent;
+extern ULONG KiMXCsrMask;
+extern ULONG KeI386CpuType;
+extern ULONG KeI386CpuStep;
+extern UCHAR KiDebugRegisterTrapOffsets[9];
+extern UCHAR KiDebugRegisterContextOffsets[9];
+extern VOID __cdecl KiTrap2(VOID);
+extern VOID __cdecl KiTrap8(VOID);
+extern VOID __cdecl KiTrap19(VOID);
+extern VOID __cdecl KiFastCallEntry(VOID);
+extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
+extern VOID __cdecl CopyParams(VOID);
+extern VOID __cdecl ReadBatch(VOID);
+extern VOID __cdecl FrRestore(VOID);
+
+//
+// Sanitizes a selector
+//
+FORCEINLINE
+ULONG
+Ke386SanitizeSeg(IN ULONG Cs,
+                IN KPROCESSOR_MODE Mode)
+{
+    //
+    // Check if we're in kernel-mode, and force CPL 0 if so.
+    // Otherwise, force CPL 3.
+    //
+    return ((Mode == KernelMode) ?
+            (Cs & (0xFFFF & ~RPL_MASK)) :
+            (RPL_MASK | (Cs & 0xFFFF)));
+}
+
+//
+// Sanitizes EFLAGS
+//
+FORCEINLINE
+ULONG
+Ke386SanitizeFlags(IN ULONG Eflags,
+                   IN KPROCESSOR_MODE Mode)
+{
+    //
+    // Check if we're in kernel-mode, and sanitize EFLAGS if so.
+    // Otherwise, also force interrupt mask on.
+    //
+    return ((Mode == KernelMode) ?
+            (Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
+            (EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
+}
+
+//
+// Gets a DR register from a CONTEXT structure
+//
+FORCEINLINE
+PVOID
+KiDrFromContext(IN ULONG Dr,
+                IN PCONTEXT Context)
+{
+    return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
+}
+
+//
+// Gets a DR register from a KTRAP_FRAME structure
+//
+FORCEINLINE
+PVOID*
+KiDrFromTrapFrame(IN ULONG Dr,
+                  IN PKTRAP_FRAME TrapFrame)
+{
+    return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
+}
+
+//
+// Sanitizes a Debug Register
+//
+FORCEINLINE
+PVOID
+Ke386SanitizeDr(IN PVOID DrAddress,
+                IN KPROCESSOR_MODE Mode)
+{
+    //
+    // Check if we're in kernel-mode, and return the address directly if so.
+    // Otherwise, make sure it's not inside the kernel-mode address space.
+    // If it is, then clear the address.
+    //
+    return ((Mode == KernelMode) ? DrAddress :
+            (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
+}
+
 #endif
 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H */
-
-/* EOF */