windows-nt/Source/XPSP1/NT/base/ntos/inc/amd64.h

3187 lines
63 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
amd64.h
Abstract:
This module contains the AMD64 hardware specific header file.
Author:
David N. Cutler (davec) 3-May-2000
Revision History:
--*/
#ifndef __amd64_
#define __amd64_
#if !(defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(_NTOSP_)) && !defined(_BLDR_)
#define ExRaiseException RtlRaiseException
#define ExRaiseStatus RtlRaiseStatus
#endif
// begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
#if defined(_M_AMD64) && !defined(RC_INVOKED) && !defined(MIDL_PASS)
//
// Define intrinsic function to do in's and out's.
//
#ifdef __cplusplus
extern "C" {
#endif
UCHAR
__inbyte (
IN USHORT Port
);
USHORT
__inword (
IN USHORT Port
);
ULONG
__indword (
IN USHORT Port
);
VOID
__outbyte (
IN USHORT Port,
IN UCHAR Data
);
VOID
__outword (
IN USHORT Port,
IN USHORT Data
);
VOID
__outdword (
IN USHORT Port,
IN ULONG Data
);
VOID
__inbytestring (
IN USHORT Port,
IN PUCHAR Buffer,
IN ULONG Count
);
VOID
__inwordstring (
IN USHORT Port,
IN PUSHORT Buffer,
IN ULONG Count
);
VOID
__indwordstring (
IN USHORT Port,
IN PULONG Buffer,
IN ULONG Count
);
VOID
__outbytestring (
IN USHORT Port,
IN PUCHAR Buffer,
IN ULONG Count
);
VOID
__outwordstring (
IN USHORT Port,
IN PUSHORT Buffer,
IN ULONG Count
);
VOID
__outdwordstring (
IN USHORT Port,
IN PULONG Buffer,
IN ULONG Count
);
#ifdef __cplusplus
}
#endif
#pragma intrinsic(__inbyte)
#pragma intrinsic(__inword)
#pragma intrinsic(__indword)
#pragma intrinsic(__outbyte)
#pragma intrinsic(__outword)
#pragma intrinsic(__outdword)
#pragma intrinsic(__inbytestring)
#pragma intrinsic(__inwordstring)
#pragma intrinsic(__indwordstring)
#pragma intrinsic(__outbytestring)
#pragma intrinsic(__outwordstring)
#pragma intrinsic(__outdwordstring)
//
// Interlocked intrinsic functions.
//
#define InterlockedAnd _InterlockedAnd
#define InterlockedOr _InterlockedOr
#define InterlockedXor _InterlockedXor
#define InterlockedIncrement _InterlockedIncrement
#define InterlockedDecrement _InterlockedDecrement
#define InterlockedAdd _InterlockedAdd
#define InterlockedExchange _InterlockedExchange
#define InterlockedExchangeAdd _InterlockedExchangeAdd
#define InterlockedCompareExchange _InterlockedCompareExchange
#define InterlockedAnd64 _InterlockedAnd64
#define InterlockedOr64 _InterlockedOr64
#define InterlockedXor64 _InterlockedXor64
#define InterlockedIncrement64 _InterlockedIncrement64
#define InterlockedDecrement64 _InterlockedDecrement64
#define InterlockedAdd64 _InterlockedAdd64
#define InterlockedExchange64 _InterlockedExchange64
#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64
#define InterlockedCompareExchange64 _InterlockedCompareExchange64
#define InterlockedExchangePointer _InterlockedExchangePointer
#define InterlockedCompareExchangePointer _InterlockedCompareExchangePointer
#ifdef __cplusplus
extern "C" {
#endif
LONG
InterlockedAnd (
IN OUT LONG volatile *Destination,
IN LONG Value
);
LONG
InterlockedOr (
IN OUT LONG volatile *Destination,
IN LONG Value
);
LONG
InterlockedXor (
IN OUT LONG volatile *Destination,
IN LONG Value
);
LONG64
InterlockedAnd64 (
IN OUT LONG64 volatile *Destination,
IN LONG64 Value
);
LONG64
InterlockedOr64 (
IN OUT LONG64 volatile *Destination,
IN LONG64 Value
);
LONG64
InterlockedXor64 (
IN OUT LONG64 volatile *Destination,
IN LONG64 Value
);
LONG
InterlockedIncrement(
IN OUT LONG volatile *Addend
);
LONG
InterlockedDecrement(
IN OUT LONG volatile *Addend
);
LONG
InterlockedExchange(
IN OUT LONG volatile *Target,
IN LONG Value
);
LONG
InterlockedExchangeAdd(
IN OUT LONG volatile *Addend,
IN LONG Value
);
#if !defined(_X86AMD64_)
__forceinline
LONG
InterlockedAdd(
IN OUT LONG volatile *Addend,
IN LONG Value
)
{
return InterlockedExchangeAdd(Addend, Value) + Value;
}
#endif
LONG
InterlockedCompareExchange (
IN OUT LONG volatile *Destination,
IN LONG ExChange,
IN LONG Comperand
);
LONG64
InterlockedIncrement64(
IN OUT LONG64 volatile *Addend
);
LONG64
InterlockedDecrement64(
IN OUT LONG64 volatile *Addend
);
LONG64
InterlockedExchange64(
IN OUT LONG64 volatile *Target,
IN LONG64 Value
);
LONG64
InterlockedExchangeAdd64(
IN OUT LONG64 volatile *Addend,
IN LONG64 Value
);
#if !defined(_X86AMD64_)
__forceinline
LONG64
InterlockedAdd64(
IN OUT LONG64 volatile *Addend,
IN LONG64 Value
)
{
return InterlockedExchangeAdd64(Addend, Value) + Value;
}
#endif
LONG64
InterlockedCompareExchange64 (
IN OUT LONG64 volatile *Destination,
IN LONG64 ExChange,
IN LONG64 Comperand
);
PVOID
InterlockedCompareExchangePointer (
IN OUT PVOID volatile *Destination,
IN PVOID Exchange,
IN PVOID Comperand
);
PVOID
InterlockedExchangePointer(
IN OUT PVOID volatile *Target,
IN PVOID Value
);
#pragma intrinsic(_InterlockedAnd)
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedXor)
#pragma intrinsic(_InterlockedIncrement)
#pragma intrinsic(_InterlockedDecrement)
#pragma intrinsic(_InterlockedExchange)
#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedCompareExchange)
#pragma intrinsic(_InterlockedAnd64)
#pragma intrinsic(_InterlockedOr64)
#pragma intrinsic(_InterlockedXor64)
#pragma intrinsic(_InterlockedIncrement64)
#pragma intrinsic(_InterlockedDecrement64)
#pragma intrinsic(_InterlockedExchange64)
#pragma intrinsic(_InterlockedExchangeAdd64)
#pragma intrinsic(_InterlockedCompareExchange64)
#pragma intrinsic(_InterlockedExchangePointer)
#pragma intrinsic(_InterlockedCompareExchangePointer)
#ifdef __cplusplus
}
#endif
#endif // defined(_M_AMD64) && !defined(RC_INVOKED) && !defined(MIDL_PASS)
#if defined(_AMD64_)
//
// Types to use to contain PFNs and their counts.
//
typedef ULONG PFN_COUNT;
typedef LONG64 SPFN_NUMBER, *PSPFN_NUMBER;
typedef ULONG64 PFN_NUMBER, *PPFN_NUMBER;
//
// Define maximum size of flush multiple TB request.
//
#define FLUSH_MULTIPLE_MAXIMUM 16
//
// Indicate that the AMD64 compiler supports the allocate pragmas.
//
#define ALLOC_PRAGMA 1
#define ALLOC_DATA_PRAGMA 1
// end_ntddk end_nthal end_ntndis end_wdm end_ntosp
//
// Length on interrupt object dispatch code in longwords.
// (shielint) Reserve 9*4 space for ABIOS stack mapping. If NO
// ABIOS support the size of DISPATCH_LENGTH should be 74.
//
// begin_nthal
#define NORMAL_DISPATCH_LENGTH 106 // ntddk wdm
#define DISPATCH_LENGTH NORMAL_DISPATCH_LENGTH // ntddk wdm
// ntddk wdm
// begin_ntosp
//
// Define constants for bits in CR0.
//
#define CR0_PE 0x00000001 // protection enable
#define CR0_MP 0x00000002 // math present
#define CR0_EM 0x00000004 // emulate math coprocessor
#define CR0_TS 0x00000008 // task switched
#define CR0_ET 0x00000010 // extension type (80387)
#define CR0_NE 0x00000020 // numeric error
#define CR0_WP 0x00010000 // write protect
#define CR0_AM 0x00040000 // alignment mask
#define CR0_NW 0x20000000 // not write-through
#define CR0_CD 0x40000000 // cache disable
#define CR0_PG 0x80000000 // paging
//
// Define functions to read and write CR0.
//
#ifdef __cplusplus
extern "C" {
#endif
#define ReadCR0() __readcr0()
ULONG64
__readcr0 (
VOID
);
#define WriteCR0(Data) __writecr0(Data)
VOID
__writecr0 (
IN ULONG64 Data
);
#pragma intrinsic(__readcr0)
#pragma intrinsic(__writecr0)
//
// Define functions to read and write CR3.
//
#define ReadCR3() __readcr3()
ULONG64
__readcr3 (
VOID
);
#define WriteCR3(Data) __writecr3(Data)
VOID
__writecr3 (
IN ULONG64 Data
);
#pragma intrinsic(__readcr3)
#pragma intrinsic(__writecr3)
//
// Define constants for bits in CR4.
//
#define CR4_VME 0x00000001 // V86 mode extensions
#define CR4_PVI 0x00000002 // Protected mode virtual interrupts
#define CR4_TSD 0x00000004 // Time stamp disable
#define CR4_DE 0x00000008 // Debugging Extensions
#define CR4_PSE 0x00000010 // Page size extensions
#define CR4_PAE 0x00000020 // Physical address extensions
#define CR4_MCE 0x00000040 // Machine check enable
#define CR4_PGE 0x00000080 // Page global enable
#define CR4_FXSR 0x00000200 // FXSR used by OS
#define CR4_XMMEXCPT 0x00000400 // XMMI used by OS
//
// Define functions to read and write CR4.
//
#define ReadCR4() __readcr4()
ULONG64
__readcr4 (
VOID
);
#define WriteCR4(Data) __writecr4(Data)
VOID
__writecr4 (
IN ULONG64 Data
);
#pragma intrinsic(__readcr4)
#pragma intrinsic(__writecr4)
//
// Define functions to read and write CR8.
//
// CR8 is the APIC TPR register.
//
#define ReadCR8() __readcr8()
ULONG64
__readcr8 (
VOID
);
#define WriteCR8(Data) __writecr8(Data)
VOID
__writecr8 (
IN ULONG64 Data
);
#pragma intrinsic(__readcr8)
#pragma intrinsic(__writecr8)
#ifdef __cplusplus
}
#endif
// end_nthal end_ntosp
//
// External references to the code labels.
//
extern ULONG KiInterruptTemplate[NORMAL_DISPATCH_LENGTH];
// begin_ntddk begin_wdm begin_nthal begin_ntosp
//
// Interrupt Request Level definitions
//
#define PASSIVE_LEVEL 0 // Passive release level
#define LOW_LEVEL 0 // Lowest interrupt level
#define APC_LEVEL 1 // APC interrupt level
#define DISPATCH_LEVEL 2 // Dispatcher level
#define CLOCK_LEVEL 13 // Interval clock level
#define IPI_LEVEL 14 // Interprocessor interrupt level
#define POWER_LEVEL 14 // Power failure level
#define PROFILE_LEVEL 15 // timer used for profiling.
#define HIGH_LEVEL 15 // Highest interrupt level
#if defined(NT_UP)
#define SYNCH_LEVEL DISPATCH_LEVEL // synchronization level
#else
#define SYNCH_LEVEL (IPI_LEVEL - 1) // synchronization level
#endif
#define IRQL_VECTOR_OFFSET 2 // offset from IRQL to vector / 16
// end_ntddk end_wdm end_ntosp
#define KiSynchIrql SYNCH_LEVEL // enable portable code
//
// Machine type definitions
//
#define MACHINE_TYPE_ISA 0
#define MACHINE_TYPE_EISA 1
#define MACHINE_TYPE_MCA 2
// end_nthal
//
// The previous values and the following are or'ed in KeI386MachineType.
//
#define MACHINE_TYPE_PC_AT_COMPATIBLE 0x00000000
#define MACHINE_TYPE_PC_9800_COMPATIBLE 0x00000100
#define MACHINE_TYPE_FMR_COMPATIBLE 0x00000200
extern ULONG KeI386MachineType;
// begin_nthal
//
// Define constants used in selector tests.
//
// N.B. MODE_MASK and MODE_BIT assumes that all code runs at either ring-0
// or ring-3 and is used to test the mode. RPL_MASK is used for merging
// or extracting RPL values.
//
#define MODE_BIT 0
#define MODE_MASK 1 // ntosp
#define RPL_MASK 3
//
// Startup count value for KeStallExecution. This value is used
// until KiInitializeStallExecution can compute the real one.
// Pick a value long enough for very fast processors.
//
#define INITIAL_STALL_COUNT 100
// end_nthal
//
// begin_nthal
//
// Macro to extract the high word of a long offset
//
#define HIGHWORD(l) \
((USHORT)(((ULONG)(l)>>16) & 0xffff))
//
// Macro to extract the low word of a long offset
//
#define LOWWORD(l) \
((USHORT)((ULONG)l & 0x0000ffff))
//
// Macro to combine two USHORT offsets into a long offset
//
#if !defined(MAKEULONG)
#define MAKEULONG(x, y) \
(((((ULONG)(x))<<16) & 0xffff0000) | \
((ULONG)(y) & 0xffff))
#endif
// end_nthal
//
// Request a software interrupt.
//
#define KiRequestSoftwareInterrupt(RequestIrql) \
HalRequestSoftwareInterrupt( RequestIrql )
// begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
//
// I/O space read and write macros.
//
// The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space.
// (Use move instructions, with LOCK prefix to force correct behavior
// w.r.t. caches and write buffers.)
//
// The READ/WRITE_PORT_* calls manipulate I/O registers in PORT space.
// (Use in/out instructions.)
//
__forceinline
UCHAR
READ_REGISTER_UCHAR (
volatile UCHAR *Register
)
{
return *Register;
}
__forceinline
USHORT
READ_REGISTER_USHORT (
volatile USHORT *Register
)
{
return *Register;
}
__forceinline
ULONG
READ_REGISTER_ULONG (
volatile ULONG *Register
)
{
return *Register;
}
__forceinline
VOID
READ_REGISTER_BUFFER_UCHAR (
PUCHAR Register,
PUCHAR Buffer,
ULONG Count
)
{
__movsb(Register, Buffer, Count);
return;
}
__forceinline
VOID
READ_REGISTER_BUFFER_USHORT (
PUSHORT Register,
PUSHORT Buffer,
ULONG Count
)
{
__movsw(Register, Buffer, Count);
return;
}
__forceinline
VOID
READ_REGISTER_BUFFER_ULONG (
PULONG Register,
PULONG Buffer,
ULONG Count
)
{
__movsd(Register, Buffer, Count);
return;
}
__forceinline
VOID
WRITE_REGISTER_UCHAR (
PUCHAR Register,
UCHAR Value
)
{
LONG Synch;
*Register = Value;
InterlockedOr(&Synch, 1);
return;
}
__forceinline
VOID
WRITE_REGISTER_USHORT (
PUSHORT Register,
USHORT Value
)
{
LONG Synch;
*Register = Value;
InterlockedOr(&Synch, 1);
return;
}
__forceinline
VOID
WRITE_REGISTER_ULONG (
PULONG Register,
ULONG Value
)
{
LONG Synch;
*Register = Value;
InterlockedOr(&Synch, 1);
return;
}
__forceinline
VOID
WRITE_REGISTER_BUFFER_UCHAR (
PUCHAR Register,
PUCHAR Buffer,
ULONG Count
)
{
LONG Synch;
__movsb(Register, Buffer, Count);
InterlockedOr(&Synch, 1);
return;
}
__forceinline
VOID
WRITE_REGISTER_BUFFER_USHORT (
PUSHORT Register,
PUSHORT Buffer,
ULONG Count
)
{
LONG Synch;
__movsw(Register, Buffer, Count);
InterlockedOr(&Synch, 1);
return;
}
__forceinline
VOID
WRITE_REGISTER_BUFFER_ULONG (
PULONG Register,
PULONG Buffer,
ULONG Count
)
{
LONG Synch;
__movsd(Register, Buffer, Count);
InterlockedOr(&Synch, 1);
return;
}
__forceinline
UCHAR
READ_PORT_UCHAR (
PUCHAR Port
)
{
return __inbyte((USHORT)((ULONG64)Port));
}
__forceinline
USHORT
READ_PORT_USHORT (
PUSHORT Port
)
{
return __inword((USHORT)((ULONG64)Port));
}
__forceinline
ULONG
READ_PORT_ULONG (
PULONG Port
)
{
return __indword((USHORT)((ULONG64)Port));
}
__forceinline
VOID
READ_PORT_BUFFER_UCHAR (
PUCHAR Port,
PUCHAR Buffer,
ULONG Count
)
{
__inbytestring((USHORT)((ULONG64)Port), Buffer, Count);
return;
}
__forceinline
VOID
READ_PORT_BUFFER_USHORT (
PUSHORT Port,
PUSHORT Buffer,
ULONG Count
)
{
__inwordstring((USHORT)((ULONG64)Port), Buffer, Count);
return;
}
__forceinline
VOID
READ_PORT_BUFFER_ULONG (
PULONG Port,
PULONG Buffer,
ULONG Count
)
{
__indwordstring((USHORT)((ULONG64)Port), Buffer, Count);
return;
}
__forceinline
VOID
WRITE_PORT_UCHAR (
PUCHAR Port,
UCHAR Value
)
{
__outbyte((USHORT)((ULONG64)Port), Value);
return;
}
__forceinline
VOID
WRITE_PORT_USHORT (
PUSHORT Port,
USHORT Value
)
{
__outword((USHORT)((ULONG64)Port), Value);
return;
}
__forceinline
VOID
WRITE_PORT_ULONG (
PULONG Port,
ULONG Value
)
{
__outdword((USHORT)((ULONG64)Port), Value);
return;
}
__forceinline
VOID
WRITE_PORT_BUFFER_UCHAR (
PUCHAR Port,
PUCHAR Buffer,
ULONG Count
)
{
__outbytestring((USHORT)((ULONG64)Port), Buffer, Count);
return;
}
__forceinline
VOID
WRITE_PORT_BUFFER_USHORT (
PUSHORT Port,
PUSHORT Buffer,
ULONG Count
)
{
__outwordstring((USHORT)((ULONG64)Port), Buffer, Count);
return;
}
__forceinline
VOID
WRITE_PORT_BUFFER_ULONG (
PULONG Port,
PULONG Buffer,
ULONG Count
)
{
__outdwordstring((USHORT)((ULONG64)Port), Buffer, Count);
return;
}
// end_ntndis
//
// Get data cache fill size.
//
#if PRAGMA_DEPRECATED_DDK
#pragma deprecated(KeGetDcacheFillSize) // Use GetDmaAlignment
#endif
#define KeGetDcacheFillSize() 1L
// end_ntddk end_wdm end_nthal end_ntosp
//
// Fill TB entry and flush single TB entry.
//
#define KeFillEntryTb(Pte, Virtual, Invalid) \
if (Invalid != FALSE) { \
InvalidatePage(Virtual); \
}
// begin_nthal
#if !defined(_NTHAL_) && !defined(RC_INVOKED) && !defined(MIDL_PASS)
__forceinline
VOID
KeFlushCurrentTb (
VOID
)
{
ULONG64 Cr4;
Cr4 = ReadCR4();
WriteCR4(Cr4 & ~CR4_PGE);
WriteCR4(Cr4 | CR4_PGE);
return;
}
#else
NTKERNELAPI
VOID
KeFlushCurrentTb (
VOID
);
#endif
// end_nthal
#define KiFlushSingleTb(Invalid, Virtual) InvalidatePage(Virtual)
//
// Data cache, instruction cache, I/O buffer, and write buffer flush routine
// prototypes.
//
// AMD64 has transparent caches, so these are noops.
#define KeSweepDcache(AllProcessors)
#define KeSweepCurrentDcache()
#define KeSweepIcache(AllProcessors)
#define KeSweepCurrentIcache()
#define KeSweepIcacheRange(AllProcessors, BaseAddress, Length)
// begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
// end_ntddk end_wdm end_ntndis end_ntosp
#define KeYieldProcessor()
// end_nthal
//
// Define executive macros for acquiring and releasing executive spinlocks.
// These macros can ONLY be used by executive components and NOT by drivers.
// Drivers MUST use the kernel interfaces since they must be MP enabled on
// all systems.
//
#if defined(NT_UP) && !DBG && !defined(_NTDDK_) && !defined(_NTIFS_)
#if !defined(_NTDRIVER_)
#define ExAcquireSpinLock(Lock, OldIrql) (*OldIrql) = KeRaiseIrqlToDpcLevel();
#define ExReleaseSpinLock(Lock, OldIrql) KeLowerIrql((OldIrql))
#else
#define ExAcquireSpinLock(Lock, OldIrql) KeAcquireSpinLock((Lock), (OldIrql))
#define ExReleaseSpinLock(Lock, OldIrql) KeReleaseSpinLock((Lock), (OldIrql))
#endif
#define ExAcquireSpinLockAtDpcLevel(Lock)
#define ExReleaseSpinLockFromDpcLevel(Lock)
#else
// begin_wdm begin_ntddk begin_ntosp
#define ExAcquireSpinLock(Lock, OldIrql) KeAcquireSpinLock((Lock), (OldIrql))
#define ExReleaseSpinLock(Lock, OldIrql) KeReleaseSpinLock((Lock), (OldIrql))
#define ExAcquireSpinLockAtDpcLevel(Lock) KeAcquireSpinLockAtDpcLevel(Lock)
#define ExReleaseSpinLockFromDpcLevel(Lock) KeReleaseSpinLockFromDpcLevel(Lock)
// end_wdm end_ntddk end_ntosp
#endif
// begin_nthal
//
// The acquire and release fast lock macros disable and enable interrupts
// on UP nondebug systems. On MP or debug systems, the spinlock routines
// are used.
//
// N.B. Extreme caution should be observed when using these routines.
//
#if defined(_M_AMD64) && !defined(USER_MODE_CODE)
VOID
_disable (
VOID
);
VOID
_enable (
VOID
);
#pragma warning(push)
#pragma warning(disable:4164)
#pragma intrinsic(_disable)
#pragma intrinsic(_enable)
#pragma warning(pop)
#endif
// end_nthal
#if defined(NT_UP) && !DBG && !defined(USER_MODE_CODE)
#define ExAcquireFastLock(Lock, OldIrql) _disable()
#else
#define ExAcquireFastLock(Lock, OldIrql) \
ExAcquireSpinLock(Lock, OldIrql)
#endif
#if defined(NT_UP) && !DBG && !defined(USER_MODE_CODE)
#define ExReleaseFastLock(Lock, OldIrql) _enable()
#else
#define ExReleaseFastLock(Lock, OldIrql) \
ExReleaseSpinLock(Lock, OldIrql)
#endif
//
// The following function prototypes must be in this module so that the
// above macros can call them directly.
//
// begin_nthal
#if defined(NT_UP)
#define KiAcquireSpinLock(SpinLock)
#define KiReleaseSpinLock(SpinLock)
#else
#define KiAcquireSpinLock(SpinLock) KeAcquireSpinLockAtDpcLevel(SpinLock)
#define KiReleaseSpinLock(SpinLock) KeReleaseSpinLockFromDpcLevel(SpinLock)
#endif // defined(NT_UP)
//
// KeTestSpinLock may be used to spin at low IRQL until the lock is
// available. The IRQL must then be raised and the lock acquired with
// KeTryToAcquireSpinLock. If that fails, lower the IRQL and start again.
//
#if defined(NT_UP)
#define KeTestSpinLock(SpinLock) (TRUE)
#else
BOOLEAN
KeTestSpinLock (
IN PKSPIN_LOCK SpinLock
);
#endif
// end_nthal
//
// Define query tick count macro.
//
// begin_ntddk begin_nthal begin_ntosp
#if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
// begin_wdm
#define KeQueryTickCount(CurrentCount ) \
*(PULONG64)(CurrentCount) = **((volatile ULONG64 **)(&KeTickCount));
// end_wdm
#else
// end_ntddk end_nthal end_ntosp
#define KiQueryTickCount(CurrentCount) \
*(PULONG64)(CurrentCount) = KeTickCount.QuadPart;
// begin_ntddk begin_nthal begin_ntosp
VOID
KeQueryTickCount (
OUT PLARGE_INTEGER CurrentCount
);
#endif // defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
// end_ntddk end_nthal end_ntosp
BOOLEAN
KiEmulateReference (
IN OUT PEXCEPTION_RECORD ExceptionRecord,
IN OUT struct _KEXCEPTION_FRAME *ExceptionFrame,
IN OUT struct _KTRAP_FRAME *TrapFrame
);
// begin_nthal begin_ntosp
//
// AMD64 hardware structures
//
// A Page Table Entry on an AMD64 has the following definition.
//
#define _HARDWARE_PTE_WORKING_SET_BITS 11
typedef struct _HARDWARE_PTE {
ULONG64 Valid : 1;
ULONG64 Write : 1; // UP version
ULONG64 Owner : 1;
ULONG64 WriteThrough : 1;
ULONG64 CacheDisable : 1;
ULONG64 Accessed : 1;
ULONG64 Dirty : 1;
ULONG64 LargePage : 1;
ULONG64 Global : 1;
ULONG64 CopyOnWrite : 1; // software field
ULONG64 Prototype : 1; // software field
ULONG64 reserved0 : 1; // software field
ULONG64 PageFrameNumber : 28;
ULONG64 reserved1 : 24 - (_HARDWARE_PTE_WORKING_SET_BITS+1);
ULONG64 SoftwareWsIndex : _HARDWARE_PTE_WORKING_SET_BITS;
ULONG64 NoExecute : 1;
} HARDWARE_PTE, *PHARDWARE_PTE;
//
// Define macro to initialize directory table base.
//
#define INITIALIZE_DIRECTORY_TABLE_BASE(dirbase,pfn) \
*((PULONG64)(dirbase)) = (((ULONG64)(pfn)) << PAGE_SHIFT)
//
// Define Global Descriptor Table (GDT) entry structure and constants.
//
// Define descriptor type codes.
//
#define TYPE_CODE 0x1A // 11010 = code, read only
#define TYPE_DATA 0x12 // 10010 = data, read and write
#define TYPE_TSS64 0x09 // 01001 = task state segment
//
// Define descriptor privilege levels for user and system.
//
#define DPL_USER 3
#define DPL_SYSTEM 0
//
// Define limit granularity.
//
#define GRANULARITY_BYTE 0
#define GRANULARITY_PAGE 1
#define SELECTOR_TABLE_INDEX 0x04
typedef union _KGDTENTRY64 {
struct {
USHORT LimitLow;
USHORT BaseLow;
union {
struct {
UCHAR BaseMiddle;
UCHAR Flags1;
UCHAR Flags2;
UCHAR BaseHigh;
} Bytes;
struct {
ULONG BaseMiddle : 8;
ULONG Type : 5;
ULONG Dpl : 2;
ULONG Present : 1;
ULONG LimitHigh : 4;
ULONG System : 1;
ULONG LongMode : 1;
ULONG DefaultBig : 1;
ULONG Granularity : 1;
ULONG BaseHigh : 8;
} Bits;
};
ULONG BaseUpper;
ULONG MustBeZero;
};
ULONG64 Alignment;
} KGDTENTRY64, *PKGDTENTRY64;
//
// Define Interrupt Descriptor Table (IDT) entry structure and constants.
//
typedef union _KIDTENTRY64 {
struct {
USHORT OffsetLow;
USHORT Selector;
USHORT IstIndex : 3;
USHORT Reserved0 : 5;
USHORT Type : 5;
USHORT Dpl : 2;
USHORT Present : 1;
USHORT OffsetMiddle;
ULONG OffsetHigh;
ULONG Reserved1;
};
ULONG64 Alignment;
} KIDTENTRY64, *PKIDTENTRY64;
//
// Define two union definitions used for parsing addresses into the
// component fields required by a GDT.
//
typedef union _KGDT_BASE {
struct {
USHORT BaseLow;
UCHAR BaseMiddle;
UCHAR BaseHigh;
ULONG BaseUpper;
};
ULONG64 Base;
} KGDT_BASE, *PKGDT_BASE;
C_ASSERT(sizeof(KGDT_BASE) == sizeof(ULONG64));
typedef union _KGDT_LIMIT {
struct {
USHORT LimitLow;
USHORT LimitHigh : 4;
USHORT MustBeZero : 12;
};
ULONG Limit;
} KGDT_LIMIT, *PKGDT_LIMIT;
C_ASSERT(sizeof(KGDT_LIMIT) == sizeof(ULONG));
//
// Define Task State Segment (TSS) structure and constants.
//
// Task switches are not supported by the AMD64, but a task state segment
// must be present to define the kernel stack pointer and I/O map base.
//
// N.B. This structure is misaligned as per the AMD64 specification.
//
// N.B. The size of TSS must be <= 0xDFFF.
//
#define IOPM_SIZE 8192
typedef UCHAR KIO_ACCESS_MAP[IOPM_SIZE];
typedef KIO_ACCESS_MAP *PKIO_ACCESS_MAP;
#pragma pack(push, 4)
typedef struct _KTSS64 {
ULONG Reserved0;
ULONG64 Rsp0;
ULONG64 Rsp1;
ULONG64 Rsp2;
//
// Element 0 of the Ist is reserved
//
ULONG64 Ist[8];
ULONG64 Reserved1;
USHORT IoMapBase;
KIO_ACCESS_MAP IoMap;
ULONG IoMapEnd;
ULONG Reserved2;
} KTSS64, *PKTSS64;
#pragma pack(pop)
C_ASSERT((sizeof(KTSS64) % sizeof(PVOID)) == 0);
#define TSS_IST_RESERVED 0
#define TSS_IST_PANIC 1
#define TSS_IST_MCA 2
#define IO_ACCESS_MAP_NONE FALSE
#define KiComputeIopmOffset(Enable) \
((Enable == FALSE) ? \
(USHORT)(sizeof(KTSS64)) : (USHORT)(FIELD_OFFSET(KTSS64, IoMap[0])))
// begin_windbgkd
#if defined(_AMD64_)
//
// Define pseudo descriptor structures for both 64- and 32-bit mode.
//
typedef struct _KDESCRIPTOR {
USHORT Pad[3];
USHORT Limit;
PVOID Base;
} KDESCRIPTOR, *PKDESCRIPTOR;
typedef struct _KDESCRIPTOR32 {
USHORT Pad[3];
USHORT Limit;
ULONG Base;
} KDESCRIPTOR32, *PKDESCRIPTOR32;
//
// Define special kernel registers and the initial MXCSR value.
//
typedef struct _KSPECIAL_REGISTERS {
ULONG64 Cr0;
ULONG64 Cr2;
ULONG64 Cr3;
ULONG64 Cr4;
ULONG64 KernelDr0;
ULONG64 KernelDr1;
ULONG64 KernelDr2;
ULONG64 KernelDr3;
ULONG64 KernelDr6;
ULONG64 KernelDr7;
KDESCRIPTOR Gdtr;
KDESCRIPTOR Idtr;
USHORT Tr;
USHORT Ldtr;
ULONG MxCsr;
} KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS;
//
// Define processor state structure.
//
typedef struct _KPROCESSOR_STATE {
KSPECIAL_REGISTERS SpecialRegisters;
CONTEXT ContextFrame;
} KPROCESSOR_STATE, *PKPROCESSOR_STATE;
#endif // _AMD64_
// end_windbgkd
//
// Processor Control Block (PRCB)
//
#define PRCB_MAJOR_VERSION 1
#define PRCB_MINOR_VERSION 1
#define PRCB_BUILD_DEBUG 0x1
#define PRCB_BUILD_UNIPROCESSOR 0x2
typedef struct _KPRCB {
//
// Start of the architecturally defined section of the PRCB. This section
// may be directly addressed by vendor/platform specific HAL code and will
// not change from version to version of NT.
//
USHORT MinorVersion;
USHORT MajorVersion;
CCHAR Number;
CCHAR Reserved;
USHORT BuildType;
struct _KTHREAD *CurrentThread;
struct _KTHREAD *NextThread;
struct _KTHREAD *IdleThread;
KAFFINITY SetMember;
KAFFINITY NotSetMember;
KPROCESSOR_STATE ProcessorState;
CCHAR CpuType;
CCHAR CpuID;
USHORT CpuStep;
ULONG KernelReserved[16];
ULONG HalReserved[16];
UCHAR PrcbPad0[88 + 112];
//
// End of the architecturally defined section of the PRCB.
//
// end_nthal end_ntosp
//
// Numbered queued spin locks - 128-byte aligned.
//
KSPIN_LOCK_QUEUE LockQueue[16];
UCHAR PrcbPad1[16];
//
// Nonpaged per processor lookaside lists - 128-byte aligned.
//
PP_LOOKASIDE_LIST PPLookasideList[16];
//
// Nonpaged per processor small pool lookaside lists - 128-byte aligned.
//
PP_LOOKASIDE_LIST PPNPagedLookasideList[POOL_SMALL_LISTS];
//
// Paged per processor small pool lookaside lists.
//
PP_LOOKASIDE_LIST PPPagedLookasideList[POOL_SMALL_LISTS];
//
// MP interprocessor request packet barrier - 128-byte aligned.
//
volatile ULONG PacketBarrier;
UCHAR PrcbPad2[124];
//
// MP interprocessor request packet and summary - 128-byte aligned.
//
volatile PVOID CurrentPacket[3];
volatile KAFFINITY TargetSet;
volatile PKIPI_WORKER WorkerRoutine;
volatile ULONG IpiFrozen;
UCHAR PrcbPad3[84];
//
// MP interprocessor request summary and packet address - 128-byte aligned.
//
// N.B. Request summary includes the request summary mask as well as the
// request packet. The address occupies the upper 48-bits and the mask
// the lower 16-bits
//
#define IPI_PACKET_SHIFT 16
volatile LONG64 RequestSummary;
UCHAR PrcbPad4[120];
//
// DPC listhead, counts, and batching parameters - 128-byte aligned.
//
LIST_ENTRY DpcListHead;
PVOID DpcStack;
PVOID SavedRsp;
ULONG DpcCount;
volatile ULONG DpcQueueDepth;
volatile LOGICAL DpcRoutineActive;
volatile LOGICAL DpcInterruptRequested;
ULONG DpcLastCount;
ULONG DpcRequestRate;
ULONG MaximumDpcQueueDepth;
ULONG MinimumDpcRate;
ULONG QuantumEnd;
UCHAR PrcbPad5[60];
//
// DPC list lock - 128-byte aligned.
//
KSPIN_LOCK DpcLock;
UCHAR PrcbPad6[120];
//
// Miscellaneous counters - 128-byte aligned.
//
ULONG InterruptCount;
ULONG KernelTime;
ULONG UserTime;
ULONG DpcTime;
ULONG InterruptTime;
ULONG AdjustDpcThreshold;
ULONG PageColor;
LOGICAL SkipTick;
ULONG TimerHand;
struct _KNODE * ParentNode;
KAFFINITY MultiThreadProcessorSet;
ULONG ThreadStartCount[2];
UCHAR PrcbPad7[64];
//
// Performacne counters - 128-byte aligned.
//
// Cache manager performance counters.
//
ULONG CcFastReadNoWait;
ULONG CcFastReadWait;
ULONG CcFastReadNotPossible;
ULONG CcCopyReadNoWait;
ULONG CcCopyReadWait;
ULONG CcCopyReadNoWaitMiss;
//
// Kernel performance counters.
//
ULONG KeAlignmentFixupCount;
ULONG KeContextSwitches;
ULONG KeDcacheFlushCount;
ULONG KeExceptionDispatchCount;
ULONG KeFirstLevelTbFills;
ULONG KeFloatingEmulationCount;
ULONG KeIcacheFlushCount;
ULONG KeSecondLevelTbFills;
ULONG KeSystemCalls;
ULONG SpareCounter0[1];
//
// I/O IRP float.
//
LONG LookasideIrpFloat;
//
// Processor information.
//
UCHAR VendorString[13];
UCHAR InitialApicId;
UCHAR LogicalProcessorsPerPhysicalProcessor;
ULONG MHz;
ULONG FeatureBits;
LARGE_INTEGER UpdateSignature;
//
// Processors power state
//
PROCESSOR_POWER_STATE PowerState;
// begin_nthal begin_ntosp
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
// end_nthal end_ntosp
#if !defined(_X86AMD64_)
C_ASSERT(((FIELD_OFFSET(KPRCB, LockQueue) + 16) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, PPLookasideList) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, PPNPagedLookasideList) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, PacketBarrier) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, RequestSummary) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, DpcListHead) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, DpcLock) & (128 - 1)) == 0);
C_ASSERT((FIELD_OFFSET(KPRCB, InterruptCount) & (128 - 1)) == 0);
#endif
// begin_nthal begin_ntosp begin_ntddk
//
// Processor Control Region Structure Definition
//
#define PCR_MINOR_VERSION 1
#define PCR_MAJOR_VERSION 1
typedef struct _KPCR {
//
// Start of the architecturally defined section of the PCR. This section
// may be directly addressed by vendor/platform specific HAL code and will
// not change from version to version of NT.
//
NT_TIB NtTib;
struct _KPRCB *CurrentPrcb;
ULONG64 SavedRcx;
ULONG64 SavedR11;
KIRQL Irql;
UCHAR SecondLevelCacheAssociativity;
UCHAR Number;
UCHAR Fill0;
ULONG Irr;
ULONG IrrActive;
ULONG Idr;
USHORT MajorVersion;
USHORT MinorVersion;
ULONG StallScaleFactor;
union _KIDTENTRY64 *IdtBase;
union _KGDTENTRY64 *GdtBase;
struct _KTSS64 *TssBase;
// end_ntddk end_ntosp
ULONG KernelReserved[15];
ULONG SecondLevelCacheSize;
ULONG HalReserved[16];
ULONG MxCsr;
PVOID KdVersionBlock;
struct _KPCR *Self;
//
// End of the architecturally defined section of the PCR.
//
// end_nthal
//
ULONG PcrAlign1[24];
KPRCB Prcb;
// begin_nthal begin_ntddk begin_ntosp
} KPCR, *PKPCR;
// end_nthal end_ntddk end_ntosp
#if !defined (_X86AMD64_)
C_ASSERT((FIELD_OFFSET(KPCR, Prcb) & (128 - 1)) == 0);
//
// The offset of the DebuggerDataBlock must not change.
//
C_ASSERT(FIELD_OFFSET(KPCR, KdVersionBlock) == 0x108);
#endif
// begin_nthal begin_ntosp
//
// Define legacy floating status word bit masks.
//
#define FSW_INVALID_OPERATION 0x1
#define FSW_DENORMAL 0x2
#define FSW_ZERO_DIVIDE 0x4
#define FSW_OVERFLOW 0x8
#define FSW_UNDERFLOW 0x10
#define FSW_PRECISION 0x20
#define FSW_STACK_FAULT 0x40
#define FSW_CONDITION_CODE_0 0x100
#define FSW_CONDITION_CODE_1 0x200
#define FSW_CONDITION_CODE_2 0x400
#define FSW_CONDITION_CODE_3 0x4000
#define FSW_ERROR_MASK (FSW_INVALID_OPERATION | FSW_DENORMAL | \
FSW_ZERO_DIVIDE | FSW_OVERFLOW | FSW_UNDERFLOW | \
FSW_PRECISION | FSW_STACK_FAULT)
//
// Define MxCsr floating control/status word bit masks.
//
// No flush to zero, round to nearest, and all exception masked.
//
#define INITIAL_MXCSR 0x1f80 // initial MXCSR vlaue
#define XSW_INVALID_OPERATION 0x1
#define XSW_DENORMAL 0x2
#define XSW_ZERO_DIVIDE 0x4
#define XSW_OVERFLOW 0x8
#define XSW_UNDERFLOW 0x10
#define XSW_PRECISION 0x20
#define XSW_ERROR_MASK (XSW_INVALID_OPERATION | XSW_DENORMAL | \
XSW_ZERO_DIVIDE | XSW_OVERFLOW | XSW_UNDERFLOW | \
XSW_PRECISION)
#define XSW_ERROR_SHIFT 7
#define XCW_INVALID_OPERATION 0x80
#define XCW_DENORMAL 0x100
#define XCW_ZERO_DIVIDE 0x200
#define XCW_OVERFLOW 0x400
#define XCW_UNDERFLOW 0x800
#define XCW_PRECISION 0x1000
#define XCW_ROUND_CONTROL 0x6000
#define XCW_FLUSH_ZERO 0x8000
//
// Define EFLAG bit masks and shift offsets.
//
#define EFLAGS_CF_MASK 0x00000001 // carry flag
#define EFLAGS_PF_MASK 0x00000004 // parity flag
#define EFALGS_AF_MASK 0x00000010 // auxiliary carry flag
#define EFLAGS_ZF_MASK 0x00000040 // zero flag
#define EFLAGS_SF_MASK 0x00000080 // sign flag
#define EFLAGS_TF_MASK 0x00000100 // trap flag
#define EFLAGS_IF_MASK 0x00000200 // interrupt flag
#define EFLAGS_DF_MASK 0x00000400 // direction flag
#define EFLAGS_OF_MASK 0x00000800 // overflow flag
#define EFLAGS_IOPL_MASK 0x00003000 // I/O privilege level
#define EFLAGS_NT_MASK 0x00004000 // nested task
#define EFLAGS_RF_MASK 0x00010000 // resume flag
#define EFLAGS_VM_MASK 0x00020000 // virtual 8086 mode
#define EFLAGS_AC_MASK 0x00040000 // alignment check
#define EFLAGS_VIF_MASK 0x00080000 // virtual interrupt flag
#define EFLAGS_VIP_MASK 0x00100000 // virtual interrupt pending
#define EFLAGS_ID_MASK 0x00200000 // identification flag
#define EFLAGS_TF_SHIFT 8 // trap
#define EFLAGS_IF_SHIFT 9 // interrupt enable
// end_nthal
//
// Define sanitize EFLAGS macro.
//
// If kernel mode, then
// caller can specify Carry, Parity, AuxCarry, Zero, Sign, Trap,
// Interrupt, Direction, Overflow, Align Check, identification.
//
// If user mode, then
// caller can specify Carry, Parity, AuxCarry, Zero, Sign, Trap,
// Direction, Overflow, Align Check, and force Interrupt on.
//
#define EFLAGS_KERNEL_SANITIZE 0x00240fd5L
#define EFLAGS_USER_SANITIZE 0x00040dd5L
#define SANITIZE_EFLAGS(eFlags, mode) ( \
((mode) == KernelMode ? \
((eFlags) & EFLAGS_KERNEL_SANITIZE) : \
(((eFlags) & EFLAGS_USER_SANITIZE) | EFLAGS_IF_MASK)))
//
// Define sanitize debug register macros.
//
// Define control register settable bits and active mask.
//
#define DR7_LEGAL 0xffff0155
#define DR7_ACTIVE 0x00000055
//
// Define macro to sanitize the debug control register.
//
#define SANITIZE_DR7(Dr7, mode) ((Dr7 & DR7_LEGAL));
//
// Define macro to santitize debug address registers.
//
#define SANITIZE_DRADDR(DrReg, mode) \
((mode) == KernelMode ? \
(DrReg) : \
(((PVOID)(DrReg) <= MM_HIGHEST_USER_ADDRESS) ? (DrReg) : 0)) \
//
// Define macro to clear reserved bits from MXCSR.
//
#define SANITIZE_MXCSR(_mxcsr_) ((_mxcsr_) & 0xffbf)
//
// Define macro to clear reserved bits for legacy FP control word.
//
#define SANITIZE_FCW(_fcw_) ((_fcw_) & 0x1f37)
// begin_nthal
//
// Exception frame
//
// This frame is established when handling an exception. It provides a place
// to save all nonvolatile registers. The volatile registers will already
// have been saved in a trap frame.
//
typedef struct _KEXCEPTION_FRAME {
//
// Home address for the parameter registers.
//
ULONG64 P1Home;
ULONG64 P2Home;
ULONG64 P3Home;
ULONG64 P4Home;
ULONG64 P5;
//
// Kernel callout initial stack value.
//
ULONG64 InitialStack;
//
// Saved nonvolatile floating registers.
//
M128 Xmm6;
M128 Xmm7;
M128 Xmm8;
M128 Xmm9;
M128 Xmm10;
M128 Xmm11;
M128 Xmm12;
M128 Xmm13;
M128 Xmm14;
M128 Xmm15;
//
// Kernel callout frame variables.
//
ULONG64 TrapFrame;
ULONG64 CallbackStack;
ULONG64 OutputBuffer;
ULONG64 OutputLength;
//
// Saved nonvolatile register - not always saved.
//
ULONG64 Fill1;
ULONG64 Rbp;
//
// Saved nonvolatile registers.
//
ULONG64 Rbx;
ULONG64 Rdi;
ULONG64 Rsi;
ULONG64 R12;
ULONG64 R13;
ULONG64 R14;
ULONG64 R15;
//
// EFLAGS and return address.
//
ULONG64 Return;
} KEXCEPTION_FRAME, *PKEXCEPTION_FRAME;
#define KEXCEPTION_FRAME_LENGTH sizeof(KEXCEPTION_FRAME)
C_ASSERT((sizeof(KEXCEPTION_FRAME) & STACK_ROUND) == 0);
#define EXCEPTION_RECORD_LENGTH \
((sizeof(EXCEPTION_RECORD) + STACK_ROUND) & ~STACK_ROUND)
//
// Machine Frame
//
// This frame is established by code that trampolines to user mode (e.g. user
// APC, user callback, dispatch user exception, etc.). The purpose of this
// frame is to allow unwinding through these callbacks if an exception occurs.
//
// N.B. This frame is identical to the frame that is pushed for a trap without
// an error code and is identical to the hardware part of a trap frame.
//
typedef struct _MACHINE_FRAME {
ULONG64 Rip;
USHORT SegCs;
USHORT Fill1[3];
ULONG EFlags;
ULONG Fill2;
ULONG64 Rsp;
USHORT SegSs;
USHORT Fill3[3];
} MACHINE_FRAME, *PMACHINE_FRAME;
#define MACHINE_FRAME_LENGTH sizeof(MACHINE_FRAME)
C_ASSERT((sizeof(MACHINE_FRAME) & STACK_ROUND) == 8);
//
// Switch Frame
//
// This frame is established by the code that switches context from one
// thread to the next and is used by the thread initialization code to
// construct a stack that will start the execution of a thread in the
// thread start up code.
//
typedef struct _KSWITCH_FRAME {
ULONG64 Fill0;
ULONG MxCsr;
KIRQL ApcBypass;
BOOLEAN NpxSave;
UCHAR Fill1[2];
ULONG64 Rbp;
ULONG64 Return;
} KSWITCH_FRAME, *PKSWITCH_FRAME;
#define KSWITCH_FRAME_LENGTH sizeof(KSWITCH_FRAME)
C_ASSERT((sizeof(KSWITCH_FRAME) & STACK_ROUND) == 0);
//
// Trap frame
//
// This frame is established when handling a trap. It provides a place to
// save all volatile registers. The nonvolatile registers are saved in an
// exception frame or through the normal C calling conventions for saved
// registers.
//
typedef struct _KTRAP_FRAME {
//
// Home address for the parameter registers.
//
ULONG64 P1Home;
ULONG64 P2Home;
ULONG64 P3Home;
ULONG64 P4Home;
ULONG64 P5;
//
// Previous processor mode (system services only) and previous IRQL
// (interrupts only).
//
KPROCESSOR_MODE PreviousMode;
KIRQL PreviousIrql;
UCHAR Fill0[2];
//
// Floating point state.
//
ULONG MxCsr;
//
// Volatile registers.
//
// N.B. These registers are only saved on exceptions and interrupts. They
// are not saved for system calls.
//
ULONG64 Rax;
ULONG64 Rcx;
ULONG64 Rdx;
ULONG64 R8;
ULONG64 R9;
ULONG64 R10;
ULONG64 R11;
ULONG64 Spare0;
//
// Volatile floating registers.
//
// N.B. These registers are only saved on exceptions and interrupts. They
// are not saved for system calls.
//
M128 Xmm0;
M128 Xmm1;
M128 Xmm2;
M128 Xmm3;
M128 Xmm4;
M128 Xmm5;
//
// Debug registers.
//
ULONG64 Dr0;
ULONG64 Dr1;
ULONG64 Dr2;
ULONG64 Dr3;
ULONG64 Dr6;
ULONG64 Dr7;
//
// Segment registers
//
USHORT SegDs;
USHORT SegEs;
USHORT SegFs;
USHORT SegGs;
//
// Previous trap frame address.
//
ULONG64 TrapFrame;
//
// Exception record for exceptions.
//
UCHAR ExceptionRecord[(sizeof(EXCEPTION_RECORD) + 15) & (~15)];
//
// Saved nonvolatile registers RBX, RDI and RSI. These registers are only
// saved in system service trap frames.
//
ULONG64 Rbx;
ULONG64 Rdi;
ULONG64 Rsi;
//
// Saved nonvolatile register RBP. This register is used as a frame
// pointer during trap processing and is saved in all trap frames.
//
ULONG64 Rbp;
//
// Information pushed by hardware.
//
// N.B. The error code is not always pushed by hardware. For those cases
// where it is not pushed by hardware a dummy error code is allocated
// on the stack.
//
ULONG64 ErrorCode;
ULONG64 Rip;
USHORT SegCs;
USHORT Fill1[3];
ULONG EFlags;
ULONG Fill2;
ULONG64 Rsp;
USHORT SegSs;
USHORT Fill3[3];
} KTRAP_FRAME, *PKTRAP_FRAME;
#define KTRAP_FRAME_LENGTH sizeof(KTRAP_FRAME)
C_ASSERT((sizeof(KTRAP_FRAME) & STACK_ROUND) == 0);
//
// IPI, profile, update run time, and update system time interrupt routines.
//
NTKERNELAPI
VOID
KeIpiInterrupt (
IN PKTRAP_FRAME TrapFrame
);
NTKERNELAPI
VOID
KeProfileInterruptWithSource (
IN PKTRAP_FRAME TrapFrame,
IN KPROFILE_SOURCE ProfileSource
);
NTKERNELAPI
VOID
KeUpdateRunTime (
IN PKTRAP_FRAME TrapFrame
);
NTKERNELAPI
VOID
KeUpdateSystemTime (
IN PKTRAP_FRAME TrapFrame,
IN ULONG64 Increment
);
// end_nthal
//
// The frame saved by the call out to user mode code is defined here to allow
// the kernel debugger to trace the entire kernel stack when user mode callouts
// are active.
//
// N.B. The kernel callout frame is the same as an exception frame.
//
typedef KEXCEPTION_FRAME KCALLOUT_FRAME;
typedef PKEXCEPTION_FRAME PKCALLOUT_FRAME;
typedef struct _UCALLOUT_FRAME {
ULONG64 P1Home;
ULONG64 P2Home;
ULONG64 P3Home;
ULONG64 P4Home;
PVOID Buffer;
ULONG Length;
ULONG ApiNumber;
MACHINE_FRAME MachineFrame;
} UCALLOUT_FRAME, *PUCALLOUT_FRAME;
#define UCALLOUT_FRAME_LENGTH sizeof(UCALLOUT_FRAME)
C_ASSERT((sizeof(UCALLOUT_FRAME) & STACK_ROUND) == 8);
// begin_ntddk begin_wdm
//
// The nonvolatile floating state
//
typedef struct _KFLOATING_SAVE {
ULONG MxCsr;
} KFLOATING_SAVE, *PKFLOATING_SAVE;
// end_ntddk end_wdm end_ntosp
//
// Define profile values.
//
#define DEFAULT_PROFILE_INTERVAL 39063
//
// The minimum acceptable profiling interval is set to 1221 which is the
// fast RTC clock rate we can get. If this
// value is too small, the system will run very slowly.
//
#define MINIMUM_PROFILE_INTERVAL 1221
// begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
//
// AMD64 Specific portions of mm component.
//
// Define the page size for the AMD64 as 4096 (0x1000).
//
#define PAGE_SIZE 0x1000
//
// Define the number of trailing zeroes in a page aligned virtual address.
// This is used as the shift count when shifting virtual addresses to
// virtual page numbers.
//
#define PAGE_SHIFT 12L
// end_ntndis end_wdm
#define PXE_BASE 0xFFFFF6FB7DBED000UI64
#define PXE_SELFMAP 0xFFFFF6FB7DBEDF68UI64
#define PPE_BASE 0xFFFFF6FB7DA00000UI64
#define PDE_BASE 0xFFFFF6FB40000000UI64
#define PTE_BASE 0xFFFFF68000000000UI64
#define PXE_TOP 0xFFFFF6FB7DBEDFFFUI64
#define PPE_TOP 0xFFFFF6FB7DBFFFFFUI64
#define PDE_TOP 0xFFFFF6FB7FFFFFFFUI64
#define PTE_TOP 0xFFFFF6FFFFFFFFFFUI64
#define PDE_KTBASE_AMD64 PPE_BASE
#define PTI_SHIFT 12
#define PDI_SHIFT 21
#define PPI_SHIFT 30
#define PXI_SHIFT 39
#define PTE_PER_PAGE 512
#define PDE_PER_PAGE 512
#define PPE_PER_PAGE 512
#define PXE_PER_PAGE 512
#define PTI_MASK_AMD64 (PTE_PER_PAGE - 1)
#define PDI_MASK_AMD64 (PDE_PER_PAGE - 1)
#define PPI_MASK (PPE_PER_PAGE - 1)
#define PXI_MASK (PXE_PER_PAGE - 1)
//
// Define the highest user address and user probe address.
//
// end_ntddk end_nthal end_ntosp
#if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_)
// begin_ntddk begin_nthal begin_ntosp
extern PVOID *MmHighestUserAddress;
extern PVOID *MmSystemRangeStart;
extern ULONG64 *MmUserProbeAddress;
#define MM_HIGHEST_USER_ADDRESS *MmHighestUserAddress
#define MM_SYSTEM_RANGE_START *MmSystemRangeStart
#define MM_USER_PROBE_ADDRESS *MmUserProbeAddress
// end_ntddk end_nthal end_ntosp
#else
extern PVOID MmHighestUserAddress;
extern PVOID MmSystemRangeStart;
extern ULONG64 MmUserProbeAddress;
#define MM_HIGHEST_USER_ADDRESS MmHighestUserAddress
#define MM_SYSTEM_RANGE_START MmSystemRangeStart
#define MM_USER_PROBE_ADDRESS MmUserProbeAddress
#define MI_HIGHEST_USER_ADDRESS (PVOID) (ULONG_PTR)((0x80000000000 - 0x10000 - 1)) // highest user address
#define MI_SYSTEM_RANGE_START (PVOID)(0xFFFF080000000000) // start of system space
#define MI_USER_PROBE_ADDRESS ((ULONG_PTR)(0x80000000000UI64 - 0x10000)) // starting address of guard page
#endif
// begin_nthal
//
// 4MB at the top of VA space is reserved for the HAL's use.
//
#define HAL_VA_START 0xFFFFFFFFFFC00000UI64
#define HAL_VA_SIZE (4 * 1024 * 1024)
// end_nthal
// begin_ntddk begin_nthal begin_ntosp
//
// The lowest user address reserves the low 64k.
//
#define MM_LOWEST_USER_ADDRESS (PVOID)0x10000
//
// The lowest address for system space.
//
#define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xFFFF080000000000
// begin_wdm
#define MmGetProcedureAddress(Address) (Address)
#define MmLockPagableCodeSection(Address) MmLockPagableDataSection(Address)
// end_ntddk end_wdm end_ntosp
//
// Define virtual base and alternate virtual base of kernel.
//
#define KSEG0_BASE 0xFFFFF80000000000UI64
//
// Generate kernel segment physical address.
//
#define KSEG_ADDRESS(PAGE) ((PVOID)(KSEG0_BASE | ((ULONG_PTR)(PAGE) << PAGE_SHIFT)))
// begin_ntddk begin_ntosp
#define KI_USER_SHARED_DATA 0xFFFFF78000000000UI64
#define SharedUserData ((KUSER_SHARED_DATA * const) KI_USER_SHARED_DATA)
//
// Intrinsic functions
//
// begin_wdm
#if defined(_M_AMD64) && !defined(RC_INVOKED) && !defined(MIDL_PASS)
// end_wdm
//
// The following routines are provided for backward compatibility with old
// code. They are no longer the preferred way to accomplish these functions.
//
#if PRAGMA_DEPRECATED_DDK
#pragma deprecated(ExInterlockedIncrementLong) // Use InterlockedIncrement
#pragma deprecated(ExInterlockedDecrementLong) // Use InterlockedDecrement
#pragma deprecated(ExInterlockedExchangeUlong) // Use InterlockedExchange
#endif
#define RESULT_ZERO 0
#define RESULT_NEGATIVE 1
#define RESULT_POSITIVE 2
typedef enum _INTERLOCKED_RESULT {
ResultNegative = RESULT_NEGATIVE,
ResultZero = RESULT_ZERO,
ResultPositive = RESULT_POSITIVE
} INTERLOCKED_RESULT;
#define ExInterlockedDecrementLong(Addend, Lock) \
_ExInterlockedDecrementLong(Addend)
__forceinline
LONG
_ExInterlockedDecrementLong (
IN OUT PLONG Addend
)
{
LONG Result;
Result = InterlockedDecrement(Addend);
if (Result < 0) {
return ResultNegative;
} else if (Result > 0) {
return ResultPositive;
} else {
return ResultZero;
}
}
#define ExInterlockedIncrementLong(Addend, Lock) \
_ExInterlockedIncrementLong(Addend)
__forceinline
LONG
_ExInterlockedIncrementLong (
IN OUT PLONG Addend
)
{
LONG Result;
Result = InterlockedIncrement(Addend);
if (Result < 0) {
return ResultNegative;
} else if (Result > 0) {
return ResultPositive;
} else {
return ResultZero;
}
}
#define ExInterlockedExchangeUlong(Target, Value, Lock) \
_ExInterlockedExchangeUlong(Target, Value)
__forceinline
_ExInterlockedExchangeUlong (
IN OUT PULONG Target,
IN ULONG Value
)
{
return (ULONG)InterlockedExchange((PLONG)Target, (LONG)Value);
}
// begin_wdm
#endif // defined(_M_AMD64) && !defined(RC_INVOKED) && !defined(MIDL_PASS)
// end_wdm end_ntddk end_nthal end_ntosp
// begin_ntosp begin_nthal begin_ntddk begin_wdm
#if !defined(MIDL_PASS) && defined(_M_AMD64)
//
// AMD646 function prototype definitions
//
// end_wdm
// end_ntddk end_ntosp
//
// Get address of current processor block.
//
__forceinline
PKPCR
KeGetPcr (
VOID
)
{
return (PKPCR)__readgsqword(FIELD_OFFSET(KPCR, Self));
}
// begin_ntosp
//
// Get address of current processor block.
//
__forceinline
PKPRCB
KeGetCurrentPrcb (
VOID
)
{
return (PKPRCB)__readgsqword(FIELD_OFFSET(KPCR, CurrentPrcb));
}
// begin_ntddk
//
// Get the current processor number
//
__forceinline
ULONG
KeGetCurrentProcessorNumber (
VOID
)
{
return (ULONG)__readgsbyte(FIELD_OFFSET(KPCR, Number));
}
// end_nthal end_ntddk end_ntosp
//
// Get address of current kernel thread object.
//
// WARNING: This inline macro can not be used for device drivers or HALs
// they must call the kernel function KeGetCurrentThread.
//
__forceinline
struct _KTHREAD *
KeGetCurrentThread (
VOID
)
{
return (struct _KTHREAD *)__readgsqword(FIELD_OFFSET(KPCR, Prcb.CurrentThread));
}
//
// If processor executing a DPC.
//
// WARNING: This inline macro is always MP enabled because filesystems
// utilize it
//
__forceinline
ULONG
KeIsExecutingDpc (
VOID
)
{
return (__readgsdword(FIELD_OFFSET(KPCR, Prcb.DpcRoutineActive)) != 0);
}
// begin_nthal begin_ntddk begin_ntosp
// begin_wdm
#endif // !defined(MIDL_PASS) && defined(_M_AMD64)
// end_nthal end_ntddk end_wdm end_ntosp
//++
//
//
// VOID
// KeMemoryBarrier (
// VOID
// )
//
//
// Routine Description:
//
// This function cases ordering of memory acceses as seen by other processors.
// Memory ordering isn't an issue on amd64.
//
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//--
#define KeMemoryBarrier()
// begin_nthal
//
// Define inline functions to get and set the handler address in and IDT
// entry.
//
typedef union _KIDT_HANDLER_ADDRESS {
struct {
USHORT OffsetLow;
USHORT OffsetMiddle;
ULONG OffsetHigh;
};
ULONG64 Address;
} KIDT_HANDLER_ADDRESS, *PKIDT_HANDLER_ADDRESS;
#define KiGetIdtFromVector(Vector) \
&KeGetPcr()->IdtBase[HalVectorToIDTEntry(Vector)]
#define KeGetIdtHandlerAddress(Vector,Addr) { \
KIDT_HANDLER_ADDRESS Handler; \
PKIDTENTRY64 Idt; \
\
Idt = KiGetIdtFromVector(Vector); \
Handler.OffsetLow = Idt->OffsetLow; \
Handler.OffsetMiddle = Idt->OffsetMiddle; \
Handler.OffsetHigh = Idt->OffsetHigh; \
*(Addr) = (PVOID)(Handler.Address); \
}
#define KeSetIdtHandlerAddress(Vector,Addr) { \
KIDT_HANDLER_ADDRESS Handler; \
PKIDTENTRY64 Idt; \
\
Idt = KiGetIdtFromVector(Vector); \
Handler.Address = (ULONG64)(Addr); \
Idt->OffsetLow = Handler.OffsetLow; \
Idt->OffsetMiddle = Handler.OffsetMiddle; \
Idt->OffsetHigh = Handler.OffsetHigh; \
}
// end_nthal
//++
//
// BOOLEAN
// KiIsThreadNumericStateSaved(
// IN PKTHREAD Address
// )
//
//--
#define KiIsThreadNumericStateSaved(a) TRUE
//++
//
// VOID
// KiRundownThread(
// IN PKTHREAD Address
// )
//
//--
#define KiRundownThread(a)
//
// functions specific to structure
//
VOID
KiSetIRR (
IN ULONG SWInterruptMask
);
// begin_ntddk begin_wdm begin_ntosp
NTKERNELAPI
NTSTATUS
KeSaveFloatingPointState (
OUT PKFLOATING_SAVE SaveArea
);
NTKERNELAPI
NTSTATUS
KeRestoreFloatingPointState (
IN PKFLOATING_SAVE SaveArea
);
// end_ntddk end_wdm end_ntosp
// begin_nthal begin_ntddk begin_wdm begin_ntndis begin_ntosp
#endif // defined(_AMD64_)
// end_nthal end_ntddk end_wdm end_ntndis end_ntosp
//
// Architecture specific kernel functions.
//
// begin_ntosp
#ifdef _AMD64_
VOID
KeSetIoAccessMap (
PKIO_ACCESS_MAP IoAccessMap
);
VOID
KeQueryIoAccessMap (
PKIO_ACCESS_MAP IoAccessMap
);
VOID
KeSetIoAccessProcess (
struct _KPROCESS *Process,
BOOLEAN Enable
);
VOID
KiEditIopmDpc (
IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
#endif //_AMD64_
//
// Platform specific kernel fucntions to raise and lower IRQL.
//
// These functions are imported for ntddk, ntifs, and wdm. They are
// inlined for nthal, ntosp, and the system.
//
#if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_WDMDDK_)
// begin_ntddk begin_wdm
#if defined(_AMD64_)
NTKERNELAPI
KIRQL
KeGetCurrentIrql (
VOID
);
NTKERNELAPI
VOID
KeLowerIrql (
IN KIRQL NewIrql
);
#define KeRaiseIrql(a,b) *(b) = KfRaiseIrql(a)
NTKERNELAPI
KIRQL
KfRaiseIrql (
IN KIRQL NewIrql
);
// end_wdm
NTKERNELAPI
KIRQL
KeRaiseIrqlToDpcLevel (
VOID
);
NTKERNELAPI
KIRQL
KeRaiseIrqlToSynchLevel (
VOID
);
// begin_wdm
#endif // defined(_AMD64_)
// end_ntddk end_wdm
#else
// begin_nthal
#if defined(_AMD64_) && !defined(MIDL_PASS)
__forceinline
KIRQL
KeGetCurrentIrql (
VOID
)
/*++
Routine Description:
This function return the current IRQL.
Arguments:
None.
Return Value:
The current IRQL is returned as the function value.
--*/
{
return (KIRQL)ReadCR8();
}
__forceinline
VOID
KeLowerIrql (
IN KIRQL NewIrql
)
/*++
Routine Description:
This function lowers the IRQL to the specified value.
Arguments:
NewIrql - Supplies the new IRQL value.
Return Value:
None.
--*/
{
ASSERT(KeGetCurrentIrql() >= NewIrql);
WriteCR8(NewIrql);
return;
}
#define KeRaiseIrql(a,b) *(b) = KfRaiseIrql(a)
__forceinline
KIRQL
KfRaiseIrql (
IN KIRQL NewIrql
)
/*++
Routine Description:
This function raises the current IRQL to the specified value and returns
the previous IRQL.
Arguments:
NewIrql (cl) - Supplies the new IRQL value.
Return Value:
The previous IRQL is retured as the function value.
--*/
{
KIRQL OldIrql;
OldIrql = KeGetCurrentIrql();
ASSERT(OldIrql <= NewIrql);
WriteCR8(NewIrql);
return OldIrql;
}
__forceinline
KIRQL
KeRaiseIrqlToDpcLevel (
VOID
)
/*++
Routine Description:
This function raises the current IRQL to DPC_LEVEL and returns the
previous IRQL.
Arguments:
None.
Return Value:
The previous IRQL is retured as the function value.
--*/
{
KIRQL OldIrql;
OldIrql = KeGetCurrentIrql();
ASSERT(OldIrql <= DISPATCH_LEVEL);
WriteCR8(DISPATCH_LEVEL);
return OldIrql;
}
__forceinline
KIRQL
KeRaiseIrqlToSynchLevel (
VOID
)
/*++
Routine Description:
This function raises the current IRQL to SYNCH_LEVEL and returns the
previous IRQL.
Arguments:
Return Value:
The previous IRQL is retured as the function value.
--*/
{
KIRQL OldIrql;
OldIrql = KeGetCurrentIrql();
ASSERT(OldIrql <= SYNCH_LEVEL);
WriteCR8(SYNCH_LEVEL);
return OldIrql;
}
#endif // defined(_AMD64_) && !defined(MIDL_PASS)
// end_nthal
#endif // defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_WDMDDK_)
// end_ntosp
//
// misc routines
//
VOID
KeOptimizeProcessorControlState (
VOID
);
// begin_nthal
#if defined(_AMD64_)
//
// Structure to aid in booting secondary processors
//
#pragma pack(push,1)
typedef struct _FAR_JMP_16 {
UCHAR OpCode; // = 0xe9
USHORT Offset;
} FAR_JMP_16;
typedef struct _FAR_TARGET_32 {
USHORT Selector;
ULONG Offset;
} FAR_TARGET_32;
typedef struct _FAR_TARGET_64 {
USHORT Selector;
ULONG64 Offset;
} FAR_TARGET_64;
typedef struct _PSEUDO_DESCRIPTOR_32 {
USHORT Limit;
ULONG Base;
} PSEUDO_DESCRIPTOR_32;
#pragma pack(pop)
#define PSB_GDT32_NULL 0 * 16
#define PSB_GDT32_CODE64 1 * 16
#define PSB_GDT32_DATA32 2 * 16
#define PSB_GDT32_CODE32 3 * 16
#define PSB_GDT32_MAX 3
typedef struct _PROCESSOR_START_BLOCK *PPROCESSOR_START_BLOCK;
typedef struct _PROCESSOR_START_BLOCK {
//
// The block starts with a jmp instruction to the end of the block
//
FAR_JMP_16 Jmp;
//
// Completion flag is set to non-zero when the target processor has
// started
//
ULONG CompletionFlag;
//
// Pseudo descriptors for GDT and IDT.
//
PSEUDO_DESCRIPTOR_32 Gdt32;
PSEUDO_DESCRIPTOR_32 Idt32;
//
// The temporary 32-bit GDT itself resides here.
//
KGDTENTRY64 Gdt[PSB_GDT32_MAX + 1];
//
// Physical address of the 64-bit top-level identity-mapped page table.
//
ULONG64 TiledCr3;
//
// Far jump target from Rm to Pm code
//
FAR_TARGET_32 PmTarget;
//
// Far jump target from Pm to Lm code
//
FAR_TARGET_64 LmTarget;
//
// Linear address of this structure
//
PPROCESSOR_START_BLOCK SelfMap;
//
// Initial processor state for the processor to be started
//
KPROCESSOR_STATE ProcessorState;
} PROCESSOR_START_BLOCK;
//
// AMD64 functions for special instructions
//
typedef struct _CPU_INFO {
ULONG Eax;
ULONG Ebx;
ULONG Ecx;
ULONG Edx;
} CPU_INFO, *PCPU_INFO;
VOID
KiCpuId (
ULONG Function,
PCPU_INFO CpuInfo
);
//
// Define read/write MSR fucntions and register definitions.
//
#define MSR_TSC 0x10 // time stamp counter
#define MSR_PAT 0x277 // page attributes table
#define MSR_EFER 0xc0000080 // extended function enable register
#define MSR_STAR 0xc0000081 // system call selectors
#define MSR_LSTAR 0xc0000082 // system call 64-bit entry
#define MSR_CSTAR 0xc0000083 // system call 32-bit entry
#define MSR_SYSCALL_MASK 0xc0000084 // system call flags mask
#define MSR_FS_BASE 0xc0000100 // fs long mode base address register
#define MSR_GS_BASE 0xc0000101 // gs long mode base address register
#define MSR_GS_SWAP 0xc0000102 // gs long mode swap GS base register
//
// Flags within MSR_EFER
//
#define MSR_SCE 0x00000001 // system call enable
#define MSR_LME 0x00000100 // long mode enable
#define MSR_LMA 0x00000400 // long mode active
//
// Page attributes table.
//
#define PAT_TYPE_STRONG_UC 0 // uncacheable/strongly ordered
#define PAT_TYPE_USWC 1 // write combining/weakly ordered
#define PAT_TYPE_WT 4 // write through
#define PAT_TYPE_WP 5 // write protected
#define PAT_TYPE_WB 6 // write back
#define PAT_TYPE_WEAK_UC 7 // uncacheable/weakly ordered
//
// Page attributes table structure.
//
typedef union _PAT_ATTRIBUTES {
struct {
UCHAR Pat[8];
} hw;
ULONG64 QuadPart;
} PAT_ATTRIBUTES, *PPAT_ATTRIBUTES;
#define ReadMSR(Msr) __readmsr(Msr)
ULONG64
__readmsr (
IN ULONG Msr
);
#define WriteMSR(Msr, Data) __writemsr(Msr, Data)
VOID
__writemsr (
IN ULONG Msr,
IN ULONG64 Value
);
#define InvalidatePage(Page) __invlpg(Page)
VOID
__invlpg (
IN PVOID Page
);
#define WritebackInvalidate() __wbinvd()
VOID
__wbinvd (
VOID
);
#pragma intrinsic(__readmsr)
#pragma intrinsic(__writemsr)
#pragma intrinsic(__invlpg)
#pragma intrinsic(__wbinvd)
#endif // _AMD64_
// end_nthal
//
// Define software feature bit definitions.
//
#define KF_V86_VIS 0x00000001
#define KF_RDTSC 0x00000002
#define KF_CR4 0x00000004
#define KF_CMOV 0x00000008
#define KF_GLOBAL_PAGE 0x00000010
#define KF_LARGE_PAGE 0x00000020
#define KF_MTRR 0x00000040
#define KF_CMPXCHG8B 0x00000080
#define KF_MMX 0x00000100
#define KF_WORKING_PTE 0x00000200
#define KF_PAT 0x00000400
#define KF_FXSR 0x00000800
#define KF_FAST_SYSCALL 0x00001000
#define KF_XMMI 0x00002000
#define KF_3DNOW 0x00004000
#define KF_AMDK6MTRR 0x00008000
#define KF_XMMI64 0x00010000
#define KF_DTS 0x00020000
#define KF_SMT 0x00040000
//
// Define required software feature bits.
//
#define KF_REQUIRED (KF_RDTSC | KF_CR4 | KF_CMOV | KF_GLOBAL_PAGE | \
KF_LARGE_PAGE | KF_CMPXCHG8B | KF_MMX | KF_WORKING_PTE | \
KF_PAT | KF_FXSR | KF_FAST_SYSCALL | KF_XMMI | KF_XMMI64)
//
// Define hardware feature bits definitions.
//
#define HF_FPU 0x00000001 // FPU is on chip
#define HF_VME 0x00000002 // virtual 8086 mode enhancement
#define HF_DE 0x00000004 // debugging extension
#define HF_PSE 0x00000008 // page size extension
#define HF_TSC 0x00000010 // time stamp counter
#define HF_MSR 0x00000020 // rdmsr and wrmsr support
#define HF_PAE 0x00000040 // physical address extension
#define HF_MCE 0x00000080 // machine check exception
#define HF_CXS 0x00000100 // cmpxchg8b instruction supported
#define HF_APIC 0x00000200 // APIC on chip
#define HF_UNUSED0 0x00000400 // unused bit
#define HF_SYSCALL 0x00000800 // fast system call
#define HF_MTRR 0x00001000 // memory type range registers
#define HF_PGE 0x00002000 // global page TB support
#define HF_MCA 0x00004000 // machine check architecture
#define HF_CMOV 0x00008000 // cmov instruction supported
#define HF_PAT 0x00010000 // physical attributes table
#define HF_UNUSED1 0x00020000 // unused bit
#define HF_UNUSED2 0x00040000 // unused bit
#define HF_UNUSED3 0x00080000 // unused bit
#define HF_UNUSED4 0x00100000 // unused bit
#define HF_UNUSED5 0x00200000 // unused bit
#define HF_UNUSED6 0x00400000 // unused bit
#define HF_MMX 0x00800000 // MMX technology supported
#define HF_FXSR 0x01000000 // fxsr instruction supported
#define HF_XMMI 0x02000000 // xmm (SSE) registers supported
#define HF_XMMI64 0x04000000 // xmm (SSE2) registers supported
//
// Define required hardware feature bits.
//
#define HF_REQUIRED (HF_FPU | HF_DE | HF_PSE | HF_TSC | HF_MSR | \
HF_PAE | HF_MCE | HF_CXS | HF_APIC | HF_SYSCALL | \
HF_PGE | HF_MCA | HF_CMOV | HF_PAT | HF_MMX | \
HF_FXSR | HF_XMMI | HF_XMMI64)
//
// Define extended hardware feature bit definitions.
//
#define XHF_3DNOW 0x80000000 // 3DNOW supported
#endif // __amd64_