#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
VOID
);
+BOOLEAN
+NTAPI
+KiIsNpxErrataPresent(
+ VOID
+);
+
VOID
NTAPI
KiSetProcessorType(VOID);
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 */