unbreak build
[reactos.git] / reactos / ntoskrnl / include / internal / i386 / ke.h
index 9925e96..abcaba7 100644 (file)
 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H
 #define __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H
 
-#if __GNUC__ >=3
-#pragma GCC system_header
-#endif
-
-#define X86_EFLAGS_TF           0x00000100 /* Trap flag */
-#define X86_EFLAGS_IF           0x00000200 /* Interrupt Enable flag */
-#define X86_EFLAGS_IOPL         0x00003000 /* I/O Privilege Level bits */
-#define X86_EFLAGS_NT           0x00004000 /* Nested Task flag */
-#define X86_EFLAGS_RF           0x00010000 /* Resume flag */
-#define X86_EFLAGS_VM           0x00020000 /* Virtual Mode */
-#define X86_EFLAGS_ID           0x00200000 /* CPUID detection flag */
-
-#define X86_CR0_PE              0x00000001 /* enable Protected Mode */
-#define X86_CR0_NE              0x00000020 /* enable native FPU error reporting */
-#define X86_CR0_TS              0x00000008 /* enable exception on FPU instruction for task switch */
-#define X86_CR0_EM              0x00000004 /* enable FPU emulation (disable FPU) */
-#define X86_CR0_MP              0x00000002 /* enable FPU monitoring */
-#define X86_CR0_WP              0x00010000 /* enable Write Protect (copy on write) */
-#define X86_CR0_PG              0x80000000 /* enable Paging */
-
-#define X86_CR4_PAE             0x00000020 /* enable physical address extensions */
-#define X86_CR4_PGE             0x00000080 /* enable global pages */
-#define X86_CR4_OSFXSR          0x00000200 /* enable FXSAVE/FXRSTOR instructions */
-#define X86_CR4_OSXMMEXCPT      0x00000400 /* enable #XF exception */
-
-#define X86_FEATURE_VME         0x00000002 /* Virtual 8086 Extensions are present */
-#define X86_FEATURE_TSC         0x00000010 /* time stamp counters are present */
-#define X86_FEATURE_PAE         0x00000040 /* physical address extension is present */
-#define X86_FEATURE_CX8         0x00000100 /* CMPXCHG8B instruction present */
-#define X86_FEATURE_SYSCALL     0x00000800 /* SYSCALL/SYSRET support present */
-#define X86_FEATURE_PGE         0x00002000 /* Page Global Enable */
-#define X86_FEATURE_MMX         0x00800000 /* MMX extension present */
-#define X86_FEATURE_FXSR        0x01000000 /* FXSAVE/FXRSTOR instructions present */
-#define X86_FEATURE_SSE         0x02000000 /* SSE extension present */
-#define X86_FEATURE_SSE2        0x04000000 /* SSE2 extension present */
-#define X86_FEATURE_HT          0x10000000 /* Hyper-Threading present */
-
-#define X86_EXT_FEATURE_SSE3    0x00000001 /* SSE3 extension present */
-#define X86_EXT_FEATURE_3DNOW   0x40000000 /* 3DNOW! extension present */
-
-#define DR7_ACTIVE              0x00000055  /* If any of these bits are set, a Dr is active */
-
-#define FRAME_EDITED        0xFFF8
-
-#define WE_DO_NOT_SPEAK_ABOUT_THE_V86_HACK 1
-
 #ifndef __ASM__
 
+#include "intrin_i.h"
+#include "v86m.h"
+
 extern ULONG Ke386CacheAlignment;
 
-struct _KPCR;
-VOID
-KiInitializeGdt(struct _KPCR* Pcr);
+//
+// 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
-Ki386ApplicationProcessorInitializeTSS(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
-NTAPI
-Ki386InitializeTss(VOID);
+KeInvalidateTlbEntry(IN PVOID Address)
+{
+    /* Invalidate the TLB entry for this address */
+    __invlpg(Address);
+}
+
+FORCEINLINE
 VOID
-KiGdtPrepareForApplicationProcessorInit(ULONG Id);
+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
-Ki386InitializeLdt(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
-Ki386SetProcessorFeatures(VOID);
+FASTCALL
+Ki386InitializeTss(
+    IN PKTSS Tss,
+    IN PKIDTENTRY Idt,
+    IN PKGDTENTRY Gdt
+);
 
 VOID
 NTAPI
@@ -80,6 +253,12 @@ KiIsNpxPresent(
     VOID
 );
 
+BOOLEAN
+NTAPI
+KiIsNpxErrataPresent(
+    VOID
+);
+
 VOID
 NTAPI
 KiSetProcessorType(VOID);
@@ -88,190 +267,221 @@ ULONG
 NTAPI
 KiGetFeatureBits(VOID);
 
-ULONG KeAllocateGdtSelector(ULONG Desc[2]);
-VOID KeFreeGdtSelector(ULONG Entry);
+#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
 VOID
-NtEarlyInitVdm(VOID);
+NTAPI
+KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
+                PKSTART_ROUTINE StartRoutine,
+                PVOID StartContext,
+                BOOLEAN UserThread,
+                KTRAP_FRAME TrapFrame);
+#endif
+
+NTSTATUS
+NTAPI
+Ke386GetGdtEntryThread(
+    IN PKTHREAD Thread,
+    IN ULONG Offset,
+    IN PKGDTENTRY Descriptor
+);
+
 VOID
-KeApplicationProcessorInitDispatcher(VOID);
+NTAPI
+KiFlushNPXState(
+    IN FLOATING_SAVE_AREA *SaveArea
+);
+
 VOID
-KeCreateApplicationProcessorIdleThread(ULONG Id);
+NTAPI
+Ki386AdjustEsp0(
+    IN PKTRAP_FRAME TrapFrame
+);
 
-typedef
 VOID
-(STDCALL*PKSYSTEM_ROUTINE)(PKSTART_ROUTINE StartRoutine,
-                    PVOID StartContext);
+NTAPI
+Ki386SetupAndExitToV86Mode(
+    OUT PTEB VdmTeb
+);
 
 VOID
-STDCALL
-Ke386InitThreadWithContext(PKTHREAD Thread,
-                           PKSYSTEM_ROUTINE SystemRoutine,
-                           PKSTART_ROUTINE StartRoutine,
-                           PVOID StartContext,
-                           PCONTEXT Context);
+NTAPI
+KeI386VdmInitialize(
+    VOID
+);
+
+ULONG_PTR
+NTAPI
+Ki386EnableGlobalPage(
+    IN volatile ULONG_PTR Context
+);
 
-#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
 VOID
-STDCALL
-KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
-                PKSTART_ROUTINE StartRoutine,
-                PVOID StartContext,
-                BOOLEAN UserThread,
-                KTRAP_FRAME TrapFrame);
-#endif
+NTAPI
+KiI386PentiumLockErrataFixup(
+    VOID
+);
 
-#ifdef CONFIG_SMP
-#define LOCK "lock ; "
-#else
-#define LOCK ""
-#define KeGetCurrentIrql() (((PKPCR)KPCR_BASE)->Irql)
-#endif
+VOID
+NTAPI
+KiInitializePAT(
+    VOID
+);
 
-#if defined(__GNUC__)
-#define Ke386DisableInterrupts() __asm__("cli\n\t");
-#define Ke386EnableInterrupts()  __asm__("sti\n\t");
-#define Ke386HaltProcessor()     __asm__("hlt\n\t");
-#define Ke386GetPageTableDirectory(X) \
-                                 __asm__("movl %%cr3,%0\n\t" : "=d" (X));
-#define Ke386SetPageTableDirectory(X) \
-                                 __asm__("movl %0,%%cr3\n\t" \
-                                     : /* no outputs */ \
-                                     : "r" (X));
-#define Ke386SetFileSelector(X) \
-                                 __asm__("movl %0,%%cr3\n\t" \
-                                     : /* no outputs */ \
-                                     : "r" (X));
-#define Ke386SetLocalDescriptorTable(X) \
-                                 __asm__("lldt %0\n\t" \
-                                     : /* no outputs */ \
-                                     : "m" (X));
-#define Ke386SetInterruptDescriptorTable(X) \
-                                 __asm__("lidt %0\n\t" \
-                                     : /* no outputs */ \
-                                     : "m" (X));
-#define Ke386SetGlobalDescriptorTable(X) \
-                                 __asm__("lgdt %0\n\t" \
-                                     : /* no outputs */ \
-                                     : "m" (X));
-#define Ke386SaveFlags(x)        __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
-#define Ke386RestoreFlags(x)     __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
-
-#define _Ke386GetSeg(N)           ({ \
-                                     unsigned int __d; \
-                                     __asm__("movl %%" #N ",%0\n\t" :"=r" (__d)); \
-                                     __d; \
-                                 })
-
-#define _Ke386GetCr(N)           ({ \
-                                     unsigned int __d; \
-                                     __asm__("movl %%cr" #N ",%0\n\t" :"=r" (__d)); \
-                                     __d; \
-                                 })
-#define _Ke386SetCr(N,X)         __asm__ __volatile__("movl %0,%%cr" #N : :"r" (X));
-#define Ke386SetTr(X)         __asm__ __volatile__("ltr %%ax" : :"a" (X));
-
-#define _Ke386SetSeg(N,X)         __asm__ __volatile__("movl %0,%%" #N : :"r" (X));
-
-#define Ke386GetCr0()            _Ke386GetCr(0)
-#define Ke386SetCr0(X)           _Ke386SetCr(0,X)
-#define Ke386GetCr2()            _Ke386GetCr(2)
-#define Ke386SetCr2(X)           _Ke386SetCr(2,X)
-#define Ke386GetCr4()            _Ke386GetCr(4)
-#define Ke386SetCr4(X)           _Ke386SetCr(4,X)
-#define Ke386GetSs()             _Ke386GetSeg(ss)
-#define Ke386SetFs(X)            _Ke386SetSeg(fs, X)
-#define Ke386SetDs(X)            _Ke386SetSeg(ds, X)
-#define Ke386SetEs(X)            _Ke386SetSeg(es, X)
-
-static inline LONG Ke386TestAndClearBit(ULONG BitPos, volatile PULONG Addr)
-{
-       LONG OldBit;
-
-       __asm__ __volatile__(LOCK
-                            "btrl %2,%1\n\t"
-                            "sbbl %0,%0\n\t"
-                            :"=r" (OldBit),"=m" (*Addr)
-                            :"Ir" (BitPos)
-                            : "memory");
-       return OldBit;
-}
+VOID
+NTAPI
+KiInitializeMTRR(
+    IN BOOLEAN FinalCpu
+);
 
-static inline LONG Ke386TestAndSetBit(ULONG BitPos, volatile PULONG Addr)
-{
-       LONG OldBit;
-
-       __asm__ __volatile__(LOCK
-                            "btsl %2,%1\n\t"
-                            "sbbl %0,%0\n\t"
-                            :"=r" (OldBit),"=m" (*Addr)
-                            :"Ir" (BitPos)
-                            : "memory");
-       return OldBit;
-}
+VOID
+NTAPI
+KiAmdK6InitializeMTRR(
+    VOID
+);
+
+VOID
+NTAPI
+KiRestoreFastSyscallReturnState(
+    VOID
+);
 
+ULONG_PTR
+NTAPI
+Ki386EnableDE(
+    IN ULONG_PTR Context
+);
 
-static inline void Ki386Cpuid(ULONG Op, PULONG Eax, PULONG Ebx, PULONG Ecx, PULONG Edx)
-{
-    __asm__("cpuid"
-           : "=a" (*Eax), "=b" (*Ebx), "=c" (*Ecx), "=d" (*Edx)
-           : "0" (Op));
-}
+ULONG_PTR
+NTAPI
+Ki386EnableFxsr(
+    IN ULONG_PTR Context
+);
 
-#define Ke386Rdmsr(msr,val1,val2) __asm__ __volatile__("rdmsr" : "=a" (val1), "=d" (val2) : "c" (msr))
+ULONG_PTR
+NTAPI
+Ki386EnableXMMIExceptions(
+    IN ULONG_PTR Context
+);
 
-#define Ke386Wrmsr(msr,val1,val2) __asm__ __volatile__("wrmsr" : /* no outputs */ : "c" (msr), "a" (val1), "d" (val2))
+BOOLEAN
+NTAPI
+VdmDispatchBop(
+    IN PKTRAP_FRAME TrapFrame
+);
+BOOLEAN
+FASTCALL
+KiVdmOpcodePrefix(
+    IN PKTRAP_FRAME TrapFrame,
+    IN ULONG Flags
+);
 
+BOOLEAN
+FASTCALL
+Ki386HandleOpcodeV86(
+    IN PKTRAP_FRAME TrapFrame
+);
 
-#elif defined(_MSC_VER)
+//
+// 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)));
+}
 
-#define Ke386DisableInterrupts() __asm cli
-#define Ke386EnableInterrupts()  __asm sti
-#define Ke386HaltProcessor()     __asm hlt
-#define Ke386GetPageTableDirectory(X) \
-                                __asm mov eax, cr3; \
-                                __asm mov X, eax;
-static __forceinline void Ke386SetPageTableDirectory(ULONG X)
+//
+// Sanitizes EFLAGS
+//
+FORCEINLINE
+ULONG
+Ke386SanitizeFlags(IN ULONG Eflags,
+                   IN KPROCESSOR_MODE Mode)
 {
-    __asm mov eax, X
-    __asm mov cr3, eax
+    //
+    // 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)));
 }
-#else
-#error Unknown compiler for inline assembler
-#endif
 
-static __inline struct _KPCR * KeGetCurrentKPCR(
-  VOID)
+//
+// Gets a DR register from a CONTEXT structure
+//
+FORCEINLINE
+PVOID
+KiDrFromContext(IN ULONG Dr,
+                IN PCONTEXT Context)
 {
-  ULONG Value;
-#if defined(__GNUC__)
-  __asm__ __volatile__ ("movl %%fs:0x1C, %0\n\t"
-         : "=r" (Value)
-    : /* no inputs */
-  );
-#elif defined(_MSC_VER)
-  __asm mov eax, fs:[1Ch]
-  __asm mov [Value], eax
-#endif
-  return (struct _KPCR *) Value;
+    return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
 }
 
-static __inline struct _KPRCB * KeGetCurrentPrcb(
-  VOID)
+//
+// Gets a DR register from a KTRAP_FRAME structure
+//
+FORCEINLINE
+PVOID*
+KiDrFromTrapFrame(IN ULONG Dr,
+                  IN PKTRAP_FRAME TrapFrame)
 {
-  ULONG Value;
-#if defined(__GNUC__)
-  __asm__ __volatile__ ("movl %%fs:0x20, %0\n\t"
-         : "=r" (Value)
-    : /* no inputs */
-  );
-#elif defined(_MSC_VER)
-  __asm mov eax, fs:[20h]
-  __asm mov [Value], eax
-#endif
-  return (struct _KPRCB *) Value;
+    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 */