3005 lines
64 KiB
C
3005 lines
64 KiB
C
/*++ BUILD Version: 0014 // Increment this if a change has global effects
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
i386.h
|
||
|
||
Abstract:
|
||
|
||
This module contains the i386 hardware specific header file.
|
||
|
||
Author:
|
||
|
||
David N. Cutler (davec) 2-Aug-1989
|
||
|
||
Revision History:
|
||
|
||
25-Jan-1990 shielint
|
||
|
||
Added definitions for 8259 ports and commands and
|
||
macros for 8259 irq# and system irql conversion.
|
||
|
||
--*/
|
||
|
||
#ifndef _i386_
|
||
#define _i386_
|
||
|
||
|
||
// begin_ntddk begin_wdm begin_nthal begin_ntndis begin_ntosp
|
||
|
||
#if defined(_X86_)
|
||
|
||
//
|
||
// Types to use to contain PFNs and their counts.
|
||
//
|
||
|
||
typedef ULONG PFN_COUNT;
|
||
|
||
typedef LONG SPFN_NUMBER, *PSPFN_NUMBER;
|
||
typedef ULONG PFN_NUMBER, *PPFN_NUMBER;
|
||
|
||
//
|
||
// Define maximum size of flush multiple TB request.
|
||
//
|
||
|
||
#define FLUSH_MULTIPLE_MAXIMUM 16
|
||
|
||
//
|
||
// Indicate that the i386 compiler supports the pragma textout construct.
|
||
//
|
||
|
||
#define ALLOC_PRAGMA 1
|
||
//
|
||
// Indicate that the i386 compiler supports the DATA_SEG("INIT") and
|
||
// DATA_SEG("PAGE") pragmas
|
||
//
|
||
|
||
#define ALLOC_DATA_PRAGMA 1
|
||
|
||
// end_ntddk end_nthal end_ntndis end_wdm end_ntosp
|
||
|
||
|
||
// NOTE - KiPcr is only useful for PCR references where we know we
|
||
// won't get context switched between the call to it and the
|
||
// variable reference, OR, were we don't care, (ie TEB pointer)
|
||
|
||
// NOTE - bryanwi 11 june 90 - we must not macro out things we export
|
||
// Things like KeFlushIcache and KeFlushDcache cannot be macroed
|
||
// out because external code (like drivers) will want to import
|
||
// them by name. Therefore, the defines below that turn them into
|
||
// nothing are inappropriate. But this isn't going to hurt us right
|
||
// now.
|
||
|
||
|
||
//
|
||
// 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
|
||
|
||
|
||
//
|
||
// Define constants to access the bits in CR0.
|
||
//
|
||
|
||
#define CR0_PG 0x80000000 // paging
|
||
#define CR0_ET 0x00000010 // extension type (80387)
|
||
#define CR0_TS 0x00000008 // task switched
|
||
#define CR0_EM 0x00000004 // emulate math coprocessor
|
||
#define CR0_MP 0x00000002 // math present
|
||
#define CR0_PE 0x00000001 // protection enable
|
||
|
||
//
|
||
// More CR0 bits; these only apply to the 80486.
|
||
//
|
||
|
||
#define CR0_CD 0x40000000 // cache disable
|
||
#define CR0_NW 0x20000000 // not write-through
|
||
#define CR0_AM 0x00040000 // alignment mask
|
||
#define CR0_WP 0x00010000 // write protect
|
||
#define CR0_NE 0x00000020 // numeric error
|
||
|
||
//
|
||
// CR4 bits; These only apply to Pentium
|
||
//
|
||
#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
|
||
|
||
// end_nthal
|
||
|
||
//
|
||
// Define constants to access ThNpxState
|
||
//
|
||
|
||
#define NPX_STATE_NOT_LOADED (CR0_TS | CR0_MP)
|
||
#define NPX_STATE_LOADED 0
|
||
|
||
//
|
||
// External references to the labels defined in int.asm
|
||
//
|
||
|
||
extern ULONG KiInterruptTemplate[NORMAL_DISPATCH_LENGTH];
|
||
extern PULONG KiInterruptTemplateObject;
|
||
extern PULONG KiInterruptTemplateDispatch;
|
||
extern PULONG KiInterruptTemplate2ndDispatch;
|
||
|
||
// 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 PROFILE_LEVEL 27 // timer used for profiling.
|
||
#define CLOCK1_LEVEL 28 // Interval clock 1 level - Not used on x86
|
||
#define CLOCK2_LEVEL 28 // Interval clock 2 level
|
||
#define IPI_LEVEL 29 // Interprocessor interrupt level
|
||
#define POWER_LEVEL 30 // Power failure level
|
||
#define HIGH_LEVEL 31 // Highest interrupt level
|
||
|
||
#if defined(NT_UP)
|
||
|
||
#define SYNCH_LEVEL DISPATCH_LEVEL // synchronization level - UP system
|
||
|
||
#else
|
||
|
||
#define SYNCH_LEVEL (IPI_LEVEL-1) // synchronization level - MP system
|
||
|
||
#endif
|
||
|
||
// 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 are or'ed into KeI386MachineType.
|
||
//
|
||
|
||
extern ULONG KeI386MachineType;
|
||
|
||
// begin_nthal
|
||
//
|
||
// Define constants used in selector tests.
|
||
//
|
||
// RPL_MASK is the real value for extracting RPL values. IT IS THE WRONG
|
||
// CONSTANT TO USE FOR MODE TESTING.
|
||
//
|
||
// MODE_MASK is the value for deciding the current mode.
|
||
// WARNING: MODE_MASK assumes that all code runs at either ring-0
|
||
// or ring-3. Ring-1 or Ring-2 support will require changing
|
||
// this value and all of the code that refers to it.
|
||
|
||
#define MODE_MASK 1 // ntosp
|
||
#define RPL_MASK 3
|
||
|
||
//
|
||
// SEGMENT_MASK is used to throw away trash part of segment. Part always
|
||
// pushes or pops 32 bits to/from stack, but if it's a segment value,
|
||
// high order 16 bits are trash.
|
||
//
|
||
|
||
#define SEGMENT_MASK 0xffff
|
||
|
||
//
|
||
// 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.
|
||
//
|
||
// These have to be actual functions on the 386, because we need
|
||
// to use assembler, but cannot return a value if we inline it.
|
||
//
|
||
// The READ/WRITE_REGISTER_* calls manipulate I/O registers in MEMORY space.
|
||
// (Use x86 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 x86 in/out instructions.)
|
||
//
|
||
|
||
NTKERNELAPI
|
||
UCHAR
|
||
NTAPI
|
||
READ_REGISTER_UCHAR(
|
||
PUCHAR Register
|
||
);
|
||
|
||
NTKERNELAPI
|
||
USHORT
|
||
NTAPI
|
||
READ_REGISTER_USHORT(
|
||
PUSHORT Register
|
||
);
|
||
|
||
NTKERNELAPI
|
||
ULONG
|
||
NTAPI
|
||
READ_REGISTER_ULONG(
|
||
PULONG Register
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
READ_REGISTER_BUFFER_UCHAR(
|
||
PUCHAR Register,
|
||
PUCHAR Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
READ_REGISTER_BUFFER_USHORT(
|
||
PUSHORT Register,
|
||
PUSHORT Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
READ_REGISTER_BUFFER_ULONG(
|
||
PULONG Register,
|
||
PULONG Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_REGISTER_UCHAR(
|
||
PUCHAR Register,
|
||
UCHAR Value
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_REGISTER_USHORT(
|
||
PUSHORT Register,
|
||
USHORT Value
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_REGISTER_ULONG(
|
||
PULONG Register,
|
||
ULONG Value
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_REGISTER_BUFFER_UCHAR(
|
||
PUCHAR Register,
|
||
PUCHAR Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_REGISTER_BUFFER_USHORT(
|
||
PUSHORT Register,
|
||
PUSHORT Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_REGISTER_BUFFER_ULONG(
|
||
PULONG Register,
|
||
PULONG Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTHALAPI
|
||
UCHAR
|
||
NTAPI
|
||
READ_PORT_UCHAR(
|
||
PUCHAR Port
|
||
);
|
||
|
||
NTHALAPI
|
||
USHORT
|
||
NTAPI
|
||
READ_PORT_USHORT(
|
||
PUSHORT Port
|
||
);
|
||
|
||
NTHALAPI
|
||
ULONG
|
||
NTAPI
|
||
READ_PORT_ULONG(
|
||
PULONG Port
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
READ_PORT_BUFFER_UCHAR(
|
||
PUCHAR Port,
|
||
PUCHAR Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
READ_PORT_BUFFER_USHORT(
|
||
PUSHORT Port,
|
||
PUSHORT Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
READ_PORT_BUFFER_ULONG(
|
||
PULONG Port,
|
||
PULONG Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_PORT_UCHAR(
|
||
PUCHAR Port,
|
||
UCHAR Value
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_PORT_USHORT(
|
||
PUSHORT Port,
|
||
USHORT Value
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_PORT_ULONG(
|
||
PULONG Port,
|
||
ULONG Value
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_PORT_BUFFER_UCHAR(
|
||
PUCHAR Port,
|
||
PUCHAR Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_PORT_BUFFER_USHORT(
|
||
PUSHORT Port,
|
||
PUSHORT Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
NTHALAPI
|
||
VOID
|
||
NTAPI
|
||
WRITE_PORT_BUFFER_ULONG(
|
||
PULONG Port,
|
||
PULONG Buffer,
|
||
ULONG Count
|
||
);
|
||
|
||
// 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.
|
||
//
|
||
|
||
#define KeFillEntryTb(Pte, Virtual, Invalid) \
|
||
if (Invalid != FALSE) { \
|
||
Ke386InvalidateTb (Virtual); \
|
||
}
|
||
|
||
#if !defined(MIDL_PASS) && defined(_M_IX86) && !defined(_CROSS_PLATFORM_)
|
||
|
||
FORCEINLINE
|
||
VOID
|
||
NTAPI
|
||
Ke386InvalidateTb (
|
||
IN PVOID Virtual
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Virtual
|
||
invlpg [eax]
|
||
}
|
||
}
|
||
|
||
#endif
|
||
|
||
NTKERNELAPI // nthal
|
||
VOID // nthal
|
||
KeFlushCurrentTb ( // nthal
|
||
VOID // nthal
|
||
); // nthal
|
||
// nthal
|
||
//
|
||
// Data cache, instruction cache, I/O buffer, and write buffer flush routine
|
||
// prototypes.
|
||
//
|
||
|
||
// 386 and 486 have 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() __asm { rep nop }
|
||
|
||
// 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.
|
||
//
|
||
// KeRaiseIrql is one instruction longer than KeAcquireSpinLock on x86 UP.
|
||
// KeLowerIrql and KeReleaseSpinLock are the same.
|
||
//
|
||
|
||
#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
|
||
|
||
//
|
||
// 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_IX86) && !defined(USER_MODE_CODE)
|
||
|
||
#pragma warning(disable:4164)
|
||
#pragma intrinsic(_disable)
|
||
#pragma intrinsic(_enable)
|
||
#pragma warning(default:4164)
|
||
|
||
#endif
|
||
|
||
#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
|
||
|
||
VOID
|
||
FASTCALL
|
||
KiAcquireSpinLock (
|
||
IN PKSPIN_LOCK SpinLock
|
||
);
|
||
|
||
VOID
|
||
FASTCALL
|
||
KiReleaseSpinLock (
|
||
IN PKSPIN_LOCK SpinLock
|
||
);
|
||
|
||
// end_nthal
|
||
|
||
//
|
||
// 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
|
||
FASTCALL
|
||
KeTestSpinLock (
|
||
IN PKSPIN_LOCK SpinLock
|
||
);
|
||
|
||
#endif
|
||
|
||
//
|
||
// Define query tick count macro.
|
||
//
|
||
// begin_ntddk begin_nthal begin_ntosp
|
||
|
||
#if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
|
||
|
||
// begin_wdm
|
||
|
||
#define KeQueryTickCount(CurrentCount ) { \
|
||
volatile PKSYSTEM_TIME _TickCount = *((PKSYSTEM_TIME *)(&KeTickCount)); \
|
||
while (TRUE) { \
|
||
(CurrentCount)->HighPart = _TickCount->High1Time; \
|
||
(CurrentCount)->LowPart = _TickCount->LowPart; \
|
||
if ((CurrentCount)->HighPart == _TickCount->High2Time) break; \
|
||
_asm { rep nop } \
|
||
} \
|
||
}
|
||
|
||
// end_wdm
|
||
|
||
#else
|
||
|
||
// end_ntddk end_nthal end_ntosp
|
||
|
||
#define KiQueryTickCount(CurrentCount) \
|
||
while (TRUE) { \
|
||
(CurrentCount)->HighPart = KeTickCount.High1Time; \
|
||
(CurrentCount)->LowPart = KeTickCount.LowPart; \
|
||
if ((CurrentCount)->HighPart == KeTickCount.High2Time) break; \
|
||
_asm { rep nop } \
|
||
}
|
||
|
||
// begin_ntddk begin_nthal begin_ntosp
|
||
|
||
VOID
|
||
NTAPI
|
||
KeQueryTickCount (
|
||
OUT PLARGE_INTEGER CurrentCount
|
||
);
|
||
|
||
#endif // defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
|
||
|
||
// end_ntddk end_nthal end_ntosp
|
||
|
||
|
||
// begin_nthal begin_ntosp
|
||
//
|
||
// 386 hardware structures
|
||
//
|
||
|
||
//
|
||
// A Page Table Entry on an Intel 386/486 has the following definition.
|
||
//
|
||
// **** NOTE A PRIVATE COPY OF THIS EXISTS IN THE MM\I386 DIRECTORY! ****
|
||
// **** ANY CHANGES NEED TO BE MADE TO BOTH HEADER FILES. ****
|
||
//
|
||
|
||
|
||
typedef struct _HARDWARE_PTE_X86 {
|
||
ULONG Valid : 1;
|
||
ULONG Write : 1;
|
||
ULONG Owner : 1;
|
||
ULONG WriteThrough : 1;
|
||
ULONG CacheDisable : 1;
|
||
ULONG Accessed : 1;
|
||
ULONG Dirty : 1;
|
||
ULONG LargePage : 1;
|
||
ULONG Global : 1;
|
||
ULONG CopyOnWrite : 1; // software field
|
||
ULONG Prototype : 1; // software field
|
||
ULONG reserved : 1; // software field
|
||
ULONG PageFrameNumber : 20;
|
||
} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86;
|
||
|
||
typedef struct _HARDWARE_PTE_X86PAE {
|
||
union {
|
||
struct {
|
||
ULONGLONG Valid : 1;
|
||
ULONGLONG Write : 1;
|
||
ULONGLONG Owner : 1;
|
||
ULONGLONG WriteThrough : 1;
|
||
ULONGLONG CacheDisable : 1;
|
||
ULONGLONG Accessed : 1;
|
||
ULONGLONG Dirty : 1;
|
||
ULONGLONG LargePage : 1;
|
||
ULONGLONG Global : 1;
|
||
ULONGLONG CopyOnWrite : 1; // software field
|
||
ULONGLONG Prototype : 1; // software field
|
||
ULONGLONG reserved0 : 1; // software field
|
||
ULONGLONG PageFrameNumber : 26;
|
||
ULONGLONG reserved1 : 26; // software field
|
||
};
|
||
struct {
|
||
ULONG LowPart;
|
||
ULONG HighPart;
|
||
};
|
||
};
|
||
} HARDWARE_PTE_X86PAE, *PHARDWARE_PTE_X86PAE;
|
||
|
||
//
|
||
// Special check to work around mspdb limitation
|
||
//
|
||
#if defined (_NTSYM_HARDWARE_PTE_SYMBOL_)
|
||
#if !defined (_X86PAE_)
|
||
typedef struct _HARDWARE_PTE {
|
||
ULONG Valid : 1;
|
||
ULONG Write : 1;
|
||
ULONG Owner : 1;
|
||
ULONG WriteThrough : 1;
|
||
ULONG CacheDisable : 1;
|
||
ULONG Accessed : 1;
|
||
ULONG Dirty : 1;
|
||
ULONG LargePage : 1;
|
||
ULONG Global : 1;
|
||
ULONG CopyOnWrite : 1; // software field
|
||
ULONG Prototype : 1; // software field
|
||
ULONG reserved : 1; // software field
|
||
ULONG PageFrameNumber : 20;
|
||
} HARDWARE_PTE, *PHARDWARE_PTE;
|
||
|
||
#else
|
||
typedef struct _HARDWARE_PTE {
|
||
union {
|
||
struct {
|
||
ULONGLONG Valid : 1;
|
||
ULONGLONG Write : 1;
|
||
ULONGLONG Owner : 1;
|
||
ULONGLONG WriteThrough : 1;
|
||
ULONGLONG CacheDisable : 1;
|
||
ULONGLONG Accessed : 1;
|
||
ULONGLONG Dirty : 1;
|
||
ULONGLONG LargePage : 1;
|
||
ULONGLONG Global : 1;
|
||
ULONGLONG CopyOnWrite : 1; // software field
|
||
ULONGLONG Prototype : 1; // software field
|
||
ULONGLONG reserved0 : 1; // software field
|
||
ULONGLONG PageFrameNumber : 26;
|
||
ULONGLONG reserved1 : 26; // software field
|
||
};
|
||
struct {
|
||
ULONG LowPart;
|
||
ULONG HighPart;
|
||
};
|
||
};
|
||
} HARDWARE_PTE, *PHARDWARE_PTE;
|
||
#endif
|
||
|
||
#else
|
||
|
||
#if !defined (_X86PAE_)
|
||
typedef HARDWARE_PTE_X86 HARDWARE_PTE;
|
||
typedef PHARDWARE_PTE_X86 PHARDWARE_PTE;
|
||
#else
|
||
typedef HARDWARE_PTE_X86PAE HARDWARE_PTE;
|
||
typedef PHARDWARE_PTE_X86PAE PHARDWARE_PTE;
|
||
#endif
|
||
#endif
|
||
|
||
//
|
||
// GDT Entry
|
||
//
|
||
|
||
typedef struct _KGDTENTRY {
|
||
USHORT LimitLow;
|
||
USHORT BaseLow;
|
||
union {
|
||
struct {
|
||
UCHAR BaseMid;
|
||
UCHAR Flags1; // Declare as bytes to avoid alignment
|
||
UCHAR Flags2; // Problems.
|
||
UCHAR BaseHi;
|
||
} Bytes;
|
||
struct {
|
||
ULONG BaseMid : 8;
|
||
ULONG Type : 5;
|
||
ULONG Dpl : 2;
|
||
ULONG Pres : 1;
|
||
ULONG LimitHi : 4;
|
||
ULONG Sys : 1;
|
||
ULONG Reserved_0 : 1;
|
||
ULONG Default_Big : 1;
|
||
ULONG Granularity : 1;
|
||
ULONG BaseHi : 8;
|
||
} Bits;
|
||
} HighWord;
|
||
} KGDTENTRY, *PKGDTENTRY;
|
||
|
||
#define TYPE_CODE 0x10 // 11010 = Code, Readable, NOT Conforming, Accessed
|
||
#define TYPE_DATA 0x12 // 10010 = Data, ReadWrite, NOT Expanddown, Accessed
|
||
#define TYPE_TSS 0x01 // 01001 = NonBusy TSS
|
||
#define TYPE_LDT 0x02 // 00010 = LDT
|
||
|
||
#define DPL_USER 3
|
||
#define DPL_SYSTEM 0
|
||
|
||
#define GRAN_BYTE 0
|
||
#define GRAN_PAGE 1
|
||
|
||
#define SELECTOR_TABLE_INDEX 0x04
|
||
|
||
//
|
||
// Entry of Interrupt Descriptor Table (IDTENTRY)
|
||
//
|
||
|
||
typedef struct _KIDTENTRY {
|
||
USHORT Offset;
|
||
USHORT Selector;
|
||
USHORT Access;
|
||
USHORT ExtendedOffset;
|
||
} KIDTENTRY;
|
||
|
||
typedef KIDTENTRY *PKIDTENTRY;
|
||
|
||
|
||
//
|
||
// TSS (Task switch segment) NT only uses to control stack switches.
|
||
//
|
||
// The only fields we actually care about are Esp0, Ss0, the IoMapBase
|
||
// and the IoAccessMaps themselves.
|
||
//
|
||
//
|
||
// N.B. Size of TSS must be <= 0xDFFF
|
||
//
|
||
|
||
//
|
||
// The interrupt direction bitmap is used on Pentium to allow
|
||
// the processor to emulate V86 mode software interrupts for us.
|
||
// There is one for each IOPM. It is located by subtracting
|
||
// 32 from the IOPM base in the Tss.
|
||
//
|
||
#define INT_DIRECTION_MAP_SIZE 32
|
||
typedef UCHAR KINT_DIRECTION_MAP[INT_DIRECTION_MAP_SIZE];
|
||
|
||
#define IOPM_COUNT 1 // Number of i/o access maps that
|
||
// exist (in addition to
|
||
// IO_ACCESS_MAP_NONE)
|
||
|
||
#define IO_ACCESS_MAP_NONE 0
|
||
|
||
#define IOPM_SIZE 8192 // Size of map callers can set.
|
||
|
||
#define PIOPM_SIZE 8196 // Size of structure we must allocate
|
||
// to hold it.
|
||
|
||
typedef UCHAR KIO_ACCESS_MAP[IOPM_SIZE];
|
||
|
||
typedef KIO_ACCESS_MAP *PKIO_ACCESS_MAP;
|
||
|
||
typedef struct _KiIoAccessMap {
|
||
KINT_DIRECTION_MAP DirectionMap;
|
||
UCHAR IoMap[PIOPM_SIZE];
|
||
} KIIO_ACCESS_MAP;
|
||
|
||
|
||
typedef struct _KTSS {
|
||
|
||
USHORT Backlink;
|
||
USHORT Reserved0;
|
||
|
||
ULONG Esp0;
|
||
USHORT Ss0;
|
||
USHORT Reserved1;
|
||
|
||
ULONG NotUsed1[4];
|
||
|
||
ULONG CR3;
|
||
ULONG Eip;
|
||
ULONG EFlags;
|
||
ULONG Eax;
|
||
ULONG Ecx;
|
||
ULONG Edx;
|
||
ULONG Ebx;
|
||
ULONG Esp;
|
||
ULONG Ebp;
|
||
ULONG Esi;
|
||
ULONG Edi;
|
||
|
||
|
||
USHORT Es;
|
||
USHORT Reserved2;
|
||
|
||
USHORT Cs;
|
||
USHORT Reserved3;
|
||
|
||
USHORT Ss;
|
||
USHORT Reserved4;
|
||
|
||
USHORT Ds;
|
||
USHORT Reserved5;
|
||
|
||
USHORT Fs;
|
||
USHORT Reserved6;
|
||
|
||
USHORT Gs;
|
||
USHORT Reserved7;
|
||
|
||
USHORT LDT;
|
||
USHORT Reserved8;
|
||
|
||
USHORT Flags;
|
||
|
||
USHORT IoMapBase;
|
||
|
||
KIIO_ACCESS_MAP IoMaps[IOPM_COUNT];
|
||
|
||
//
|
||
// This is the Software interrupt direction bitmap associated with
|
||
// IO_ACCESS_MAP_NONE
|
||
//
|
||
KINT_DIRECTION_MAP IntDirectionMap;
|
||
} KTSS, *PKTSS;
|
||
|
||
|
||
#define KiComputeIopmOffset(MapNumber) \
|
||
(MapNumber == IO_ACCESS_MAP_NONE) ? \
|
||
(USHORT)(sizeof(KTSS)) : \
|
||
(USHORT)(FIELD_OFFSET(KTSS, IoMaps[MapNumber-1].IoMap))
|
||
|
||
// begin_windbgkd
|
||
|
||
//
|
||
// Special Registers for i386
|
||
//
|
||
|
||
#ifdef _X86_
|
||
|
||
typedef struct _DESCRIPTOR {
|
||
USHORT Pad;
|
||
USHORT Limit;
|
||
ULONG Base;
|
||
} KDESCRIPTOR, *PKDESCRIPTOR;
|
||
|
||
typedef struct _KSPECIAL_REGISTERS {
|
||
ULONG Cr0;
|
||
ULONG Cr2;
|
||
ULONG Cr3;
|
||
ULONG Cr4;
|
||
ULONG KernelDr0;
|
||
ULONG KernelDr1;
|
||
ULONG KernelDr2;
|
||
ULONG KernelDr3;
|
||
ULONG KernelDr6;
|
||
ULONG KernelDr7;
|
||
KDESCRIPTOR Gdtr;
|
||
KDESCRIPTOR Idtr;
|
||
USHORT Tr;
|
||
USHORT Ldtr;
|
||
ULONG Reserved[6];
|
||
} KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS;
|
||
|
||
//
|
||
// Processor State frame: Before a processor freezes itself, it
|
||
// dumps the processor state to the processor state frame for
|
||
// debugger to examine.
|
||
//
|
||
|
||
typedef struct _KPROCESSOR_STATE {
|
||
struct _CONTEXT ContextFrame;
|
||
struct _KSPECIAL_REGISTERS SpecialRegisters;
|
||
} KPROCESSOR_STATE, *PKPROCESSOR_STATE;
|
||
|
||
#endif // _X86_
|
||
|
||
// end_windbgkd
|
||
|
||
//
|
||
// Processor Control Block (PRCB)
|
||
//
|
||
|
||
#define PRCB_MAJOR_VERSION 1
|
||
#define PRCB_MINOR_VERSION 1
|
||
#define PRCB_BUILD_DEBUG 0x0001
|
||
#define PRCB_BUILD_UNIPROCESSOR 0x0002
|
||
|
||
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;
|
||
|
||
struct _KTHREAD *CurrentThread;
|
||
struct _KTHREAD *NextThread;
|
||
struct _KTHREAD *IdleThread;
|
||
|
||
CCHAR Number;
|
||
CCHAR Reserved;
|
||
USHORT BuildType;
|
||
KAFFINITY SetMember;
|
||
|
||
CCHAR CpuType;
|
||
CCHAR CpuID;
|
||
USHORT CpuStep;
|
||
|
||
struct _KPROCESSOR_STATE ProcessorState;
|
||
|
||
ULONG KernelReserved[16]; // For use by the kernel
|
||
ULONG HalReserved[16]; // For use by Hal
|
||
|
||
//
|
||
// Per processor lock queue entries.
|
||
//
|
||
// N.B. The following padding is such that the first lock entry falls in the
|
||
// last eight bytes of a cache line. This makes the dispatcher lock and
|
||
// the context swap lock lie in separate cache lines.
|
||
//
|
||
|
||
UCHAR PrcbPad0[28 + 64];
|
||
KSPIN_LOCK_QUEUE LockQueue[16];
|
||
UCHAR PrcbPad1[8];
|
||
|
||
// End of the architecturally defined section of the PRCB.
|
||
// end_nthal end_ntosp
|
||
|
||
//
|
||
// Micellaneous counters - 64-byte aligned.
|
||
//
|
||
|
||
struct _KTHREAD *NpxThread;
|
||
ULONG InterruptCount;
|
||
ULONG KernelTime;
|
||
ULONG UserTime;
|
||
ULONG DpcTime;
|
||
ULONG DebugDpcTime;
|
||
ULONG InterruptTime;
|
||
ULONG AdjustDpcThreshold;
|
||
ULONG PageColor;
|
||
LOGICAL SkipTick;
|
||
|
||
//
|
||
// MultiThreadSetBusy is TRUE is all the processors in the set are
|
||
// not idle. This field is only updated in the PRCB of the first
|
||
// member of the SMT set and only by members of the same set.
|
||
//
|
||
|
||
BOOLEAN MultiThreadSetBusy;
|
||
UCHAR Spare2[3];
|
||
struct _KNODE * ParentNode; // Node this processor is a member of
|
||
KAFFINITY MultiThreadProcessorSet; // Processors in SMT set
|
||
struct _KPRCB * MultiThreadSetMaster;// Pointer to first proc in SMT set
|
||
ULONG ThreadStartCount[2]; // perf data
|
||
|
||
//
|
||
// Performance counters - 64-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];
|
||
|
||
//
|
||
// Nonpaged per processor lookaside lists - 64-byte aligned.
|
||
//
|
||
|
||
PP_LOOKASIDE_LIST PPLookasideList[16];
|
||
|
||
//
|
||
// Nonpaged per processor small pool lookaside lists - 64-byte aligned.
|
||
//
|
||
|
||
PP_LOOKASIDE_LIST PPNPagedLookasideList[POOL_SMALL_LISTS];
|
||
|
||
//
|
||
// Paged per processor small pool lookaside lists - 64-byte aligned.
|
||
//
|
||
|
||
PP_LOOKASIDE_LIST PPPagedLookasideList[POOL_SMALL_LISTS];
|
||
|
||
//
|
||
// MP interprocessor request packet barrier - 64-byte aligned.
|
||
//
|
||
|
||
volatile ULONG PacketBarrier;
|
||
volatile ULONG ReverseStall;
|
||
PVOID IpiFrame;
|
||
UCHAR PrcbPad2[52];
|
||
|
||
//
|
||
// MP interprocessor request packet and summary - 64-byte aligned.
|
||
//
|
||
|
||
volatile PVOID CurrentPacket[3];
|
||
volatile KAFFINITY TargetSet;
|
||
volatile PKIPI_WORKER WorkerRoutine;
|
||
volatile ULONG IpiFrozen;
|
||
UCHAR PrcbPad3[40];
|
||
|
||
//
|
||
// MP interprocessor request summary and packet address - 64-byte aligned.
|
||
//
|
||
|
||
volatile ULONG RequestSummary;
|
||
volatile struct _KPRCB *SignalDone;
|
||
UCHAR PrcbPad4[56];
|
||
|
||
//
|
||
// DPC listhead, counts, and batching parameters - 64-byte aligned.
|
||
//
|
||
|
||
LIST_ENTRY DpcListHead;
|
||
PVOID DpcStack;
|
||
ULONG DpcCount;
|
||
volatile ULONG DpcQueueDepth;
|
||
volatile ULONG DpcRoutineActive;
|
||
volatile ULONG DpcInterruptRequested;
|
||
ULONG DpcLastCount;
|
||
ULONG DpcRequestRate;
|
||
ULONG MaximumDpcQueueDepth;
|
||
ULONG MinimumDpcRate;
|
||
ULONG QuantumEnd;
|
||
UCHAR PrcbPad5[16];
|
||
|
||
//
|
||
// DPC list lock - 64-byte aligned.
|
||
//
|
||
|
||
KSPIN_LOCK DpcLock;
|
||
UCHAR PrcbPad6[60];
|
||
|
||
//
|
||
// Per processor chained interrupt list.
|
||
//
|
||
|
||
PVOID ChainedInterruptList;
|
||
|
||
//
|
||
// I/O IRP float.
|
||
//
|
||
|
||
LONG LookasideIrpFloat;
|
||
|
||
//
|
||
// Spare fields.
|
||
//
|
||
|
||
ULONG SpareFields0[6];
|
||
|
||
//
|
||
// Processor information.
|
||
//
|
||
|
||
UCHAR VendorString[13];
|
||
UCHAR InitialApicId;
|
||
UCHAR LogicalProcessorsPerPhysicalProcessor;
|
||
ULONG MHz;
|
||
ULONG FeatureBits;
|
||
LARGE_INTEGER UpdateSignature;
|
||
|
||
//
|
||
// Npx save area - 16-byte aligned.
|
||
//
|
||
|
||
FX_SAVE_AREA NpxSaveArea;
|
||
|
||
//
|
||
// Processors power state
|
||
//
|
||
|
||
PROCESSOR_POWER_STATE PowerState;
|
||
|
||
// begin_nthal begin_ntosp
|
||
|
||
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
|
||
|
||
// end_nthal end_ntosp
|
||
|
||
//
|
||
// The offset of the PRCB in the PCR is 32 mod 64.
|
||
//
|
||
// The offset of the following structure must be 0 mod 64 except for the
|
||
// lock queue array which straddles two cache lines.
|
||
//
|
||
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, LockQueue) + sizeof(KSPIN_LOCK_QUEUE) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, NpxThread) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, CcFastReadNoWait) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, PPLookasideList) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, PPNPagedLookasideList) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, PPPagedLookasideList) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, PacketBarrier) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, CurrentPacket) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, DpcListHead) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, DpcLock) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, ChainedInterruptList) + 32) & (64 - 1)) == 0);
|
||
C_ASSERT(((FIELD_OFFSET(KPRCB, NpxSaveArea) + 32) & (16 - 1)) == 0);
|
||
|
||
// begin_nthal begin_ntddk begin_ntosp
|
||
|
||
//
|
||
// 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 _KPCR *SelfPcr; // flat address of this PCR
|
||
struct _KPRCB *Prcb; // pointer to Prcb
|
||
KIRQL Irql;
|
||
ULONG IRR;
|
||
ULONG IrrActive;
|
||
ULONG IDR;
|
||
PVOID KdVersionBlock;
|
||
|
||
struct _KIDTENTRY *IDT;
|
||
struct _KGDTENTRY *GDT;
|
||
struct _KTSS *TSS;
|
||
USHORT MajorVersion;
|
||
USHORT MinorVersion;
|
||
KAFFINITY SetMember;
|
||
ULONG StallScaleFactor;
|
||
UCHAR DebugActive;
|
||
UCHAR Number;
|
||
|
||
// end_ntddk end_ntosp
|
||
|
||
UCHAR Spare0;
|
||
UCHAR SecondLevelCacheAssociativity;
|
||
ULONG VdmAlert;
|
||
ULONG KernelReserved[14]; // For use by the kernel
|
||
ULONG SecondLevelCacheSize;
|
||
ULONG HalReserved[16]; // For use by Hal
|
||
|
||
// End of the architecturally defined section of the PCR.
|
||
// end_nthal
|
||
|
||
ULONG InterruptMode;
|
||
UCHAR Spare1;
|
||
ULONG KernelReserved2[17];
|
||
struct _KPRCB PrcbData;
|
||
|
||
// begin_nthal begin_ntddk begin_ntosp
|
||
|
||
} KPCR, *PKPCR;
|
||
|
||
// end_nthal end_ntddk end_ntosp
|
||
|
||
C_ASSERT((FIELD_OFFSET(KPCR, PrcbData) & (64 - 1)) == 32);
|
||
|
||
// begin_nthal begin_ntosp
|
||
|
||
#define EFLAGS_TF 0x00000100L
|
||
#define EFLAGS_INTERRUPT_MASK 0x00000200L
|
||
#define EFLAGS_DF_MASK 0x00000400L
|
||
#define EFLAGS_V86_MASK 0x00020000L
|
||
#define EFLAGS_ALIGN_CHECK 0x00040000L
|
||
#define EFLAGS_IOPL_MASK 0x00003000L
|
||
#define EFLAGS_VIF 0x00080000L
|
||
#define EFLAGS_VIP 0x00100000L
|
||
#define EFLAGS_USER_SANITIZE 0x003e0dd7L
|
||
|
||
// end_nthal
|
||
|
||
//
|
||
// Sanitize segCS and eFlags based on a processor mode.
|
||
//
|
||
// If kernel mode,
|
||
// force CPL == 0
|
||
//
|
||
// If user mode,
|
||
// force CPL == 3
|
||
//
|
||
|
||
#define SANITIZE_SEG(segCS, mode) (\
|
||
((mode) == KernelMode ? \
|
||
((0x00000000L) | ((segCS) & 0xfffc)) : \
|
||
((0x00000003L) | ((segCS) & 0xffff))))
|
||
|
||
//
|
||
// If kernel mode, then
|
||
// let caller specify Carry, Parity, AuxCarry, Zero, Sign, Trap,
|
||
// Direction, Overflow, Interrupt, AlignCheck.
|
||
//
|
||
// If user mode, then
|
||
// let caller specify Carry, Parity, AuxCarry, Zero, Sign, Trap,
|
||
// Direction, Overflow, AlignCheck.
|
||
// force Interrupts on.
|
||
//
|
||
|
||
|
||
#define SANITIZE_FLAGS(eFlags, mode) (\
|
||
((mode) == KernelMode ? \
|
||
((0x00000000L) | ((eFlags) & 0x003e0fd7)) : \
|
||
((((eFlags) & EFLAGS_V86_MASK) && KeI386VdmIoplAllowed) ? \
|
||
(((eFlags) & KeI386EFlagsAndMaskV86) | KeI386EFlagsOrMaskV86) : \
|
||
((EFLAGS_INTERRUPT_MASK) | ((eFlags) & EFLAGS_USER_SANITIZE)))))
|
||
|
||
//
|
||
// Masks for Dr7 and sanitize macros for various Dr registers.
|
||
//
|
||
|
||
#define DR6_LEGAL 0x0000e00f
|
||
|
||
#define DR7_LEGAL 0xffff0155 // R/W, LEN for Dr0-Dr4,
|
||
// Local enable for Dr0-Dr4,
|
||
// Le for "perfect" trapping
|
||
|
||
#define DR7_ACTIVE 0x00000055 // If any of these bits are set, a Dr is active
|
||
|
||
#define SANITIZE_DR6(Dr6, mode) ((Dr6 & DR6_LEGAL));
|
||
|
||
#define SANITIZE_DR7(Dr7, mode) ((Dr7 & DR7_LEGAL));
|
||
|
||
#define SANITIZE_DRADDR(DrReg, mode) ( \
|
||
(mode) == KernelMode ? \
|
||
(DrReg) : \
|
||
(((PVOID)DrReg <= MM_HIGHEST_USER_ADDRESS) ? \
|
||
(DrReg) : \
|
||
(0) \
|
||
) \
|
||
)
|
||
|
||
//
|
||
// Define macro to clear reserved bits from MXCSR so that we don't
|
||
// GP fault when doing an FRSTOR
|
||
//
|
||
|
||
extern ULONG KiMXCsrMask;
|
||
|
||
#define SANITIZE_MXCSR(_mxcsr_) ((_mxcsr_) & KiMXCsrMask)
|
||
|
||
//
|
||
// Nonvolatile context pointers
|
||
//
|
||
// bryanwi 21 feb 90 - This is bogus. The 386 doesn't have
|
||
// enough nonvolatile context to make this
|
||
// structure worthwhile. Can't declare a
|
||
// field to be void, so declare a Junk structure
|
||
// instead.
|
||
|
||
typedef struct _KNONVOLATILE_CONTEXT_POINTERS {
|
||
ULONG Junk;
|
||
} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS;
|
||
|
||
// begin_nthal
|
||
//
|
||
// Trap frame
|
||
//
|
||
// NOTE - We deal only with 32bit registers, so the assembler equivalents
|
||
// are always the extended forms.
|
||
//
|
||
// NOTE - Unless you want to run like slow molasses everywhere in the
|
||
// the system, this structure must be of DWORD length, DWORD
|
||
// aligned, and its elements must all be DWORD aligned.
|
||
//
|
||
// NOTE WELL -
|
||
//
|
||
// The i386 does not build stack frames in a consistent format, the
|
||
// frames vary depending on whether or not a privilege transition
|
||
// was involved.
|
||
//
|
||
// In order to make NtContinue work for both user mode and kernel
|
||
// mode callers, we must force a canonical stack.
|
||
//
|
||
// If we're called from kernel mode, this structure is 8 bytes longer
|
||
// than the actual frame!
|
||
//
|
||
// WARNING:
|
||
//
|
||
// KTRAP_FRAME_LENGTH needs to be 16byte integral (at present.)
|
||
//
|
||
|
||
typedef struct _KTRAP_FRAME {
|
||
|
||
|
||
//
|
||
// Following 4 values are only used and defined for DBG systems,
|
||
// but are always allocated to make switching from DBG to non-DBG
|
||
// and back quicker. They are not DEVL because they have a non-0
|
||
// performance impact.
|
||
//
|
||
|
||
ULONG DbgEbp; // Copy of User EBP set up so KB will work.
|
||
ULONG DbgEip; // EIP of caller to system call, again, for KB.
|
||
ULONG DbgArgMark; // Marker to show no args here.
|
||
ULONG DbgArgPointer; // Pointer to the actual args
|
||
|
||
//
|
||
// Temporary values used when frames are edited.
|
||
//
|
||
//
|
||
// NOTE: Any code that want's ESP must materialize it, since it
|
||
// is not stored in the frame for kernel mode callers.
|
||
//
|
||
// And code that sets ESP in a KERNEL mode frame, must put
|
||
// the new value in TempEsp, make sure that TempSegCs holds
|
||
// the real SegCs value, and put a special marker value into SegCs.
|
||
//
|
||
|
||
ULONG TempSegCs;
|
||
ULONG TempEsp;
|
||
|
||
//
|
||
// Debug registers.
|
||
//
|
||
|
||
ULONG Dr0;
|
||
ULONG Dr1;
|
||
ULONG Dr2;
|
||
ULONG Dr3;
|
||
ULONG Dr6;
|
||
ULONG Dr7;
|
||
|
||
//
|
||
// Segment registers
|
||
//
|
||
|
||
ULONG SegGs;
|
||
ULONG SegEs;
|
||
ULONG SegDs;
|
||
|
||
//
|
||
// Volatile registers
|
||
//
|
||
|
||
ULONG Edx;
|
||
ULONG Ecx;
|
||
ULONG Eax;
|
||
|
||
//
|
||
// Nesting state, not part of context record
|
||
//
|
||
|
||
ULONG PreviousPreviousMode;
|
||
|
||
PEXCEPTION_REGISTRATION_RECORD ExceptionList;
|
||
// Trash if caller was user mode.
|
||
// Saved exception list if caller
|
||
// was kernel mode or we're in
|
||
// an interrupt.
|
||
|
||
//
|
||
// FS is TIB/PCR pointer, is here to make save sequence easy
|
||
//
|
||
|
||
ULONG SegFs;
|
||
|
||
//
|
||
// Non-volatile registers
|
||
//
|
||
|
||
ULONG Edi;
|
||
ULONG Esi;
|
||
ULONG Ebx;
|
||
ULONG Ebp;
|
||
|
||
//
|
||
// Control registers
|
||
//
|
||
|
||
ULONG ErrCode;
|
||
ULONG Eip;
|
||
ULONG SegCs;
|
||
ULONG EFlags;
|
||
|
||
ULONG HardwareEsp; // WARNING - segSS:esp are only here for stacks
|
||
ULONG HardwareSegSs; // that involve a ring transition.
|
||
|
||
ULONG V86Es; // these will be present for all transitions from
|
||
ULONG V86Ds; // V86 mode
|
||
ULONG V86Fs;
|
||
ULONG V86Gs;
|
||
} KTRAP_FRAME;
|
||
|
||
|
||
typedef KTRAP_FRAME *PKTRAP_FRAME;
|
||
typedef KTRAP_FRAME *PKEXCEPTION_FRAME;
|
||
|
||
#define KTRAP_FRAME_LENGTH (sizeof(KTRAP_FRAME))
|
||
#define KTRAP_FRAME_ALIGN (sizeof(ULONG))
|
||
#define KTRAP_FRAME_ROUND (KTRAP_FRAME_ALIGN-1)
|
||
|
||
//
|
||
// Bits forced to 0 in SegCs if Esp has been edited.
|
||
//
|
||
|
||
#define FRAME_EDITED 0xfff8
|
||
|
||
// end_nthal
|
||
|
||
//
|
||
// The frame saved by KiCallUserMode is defined here to allow
|
||
// the kernel debugger to trace the entire kernel stack
|
||
// when usermode callouts are pending.
|
||
//
|
||
|
||
typedef struct _KCALLOUT_FRAME {
|
||
ULONG InStk; // saved initial stack address
|
||
ULONG TrFr; // saved callback trap frame
|
||
ULONG CbStk; // saved callback stack address
|
||
ULONG Edi; // saved nonvolatile registers
|
||
ULONG Esi; //
|
||
ULONG Ebx; //
|
||
ULONG Ebp; //
|
||
ULONG Ret; // saved return address
|
||
ULONG OutBf; // address to store output buffer
|
||
ULONG OutLn; // address to store output length
|
||
} KCALLOUT_FRAME;
|
||
|
||
typedef KCALLOUT_FRAME *PKCALLOUT_FRAME;
|
||
|
||
|
||
//
|
||
// Switch Frame
|
||
//
|
||
// 386 doesn't have an "exception frame", and doesn't normally make
|
||
// any use of nonvolatile context register structures.
|
||
//
|
||
// However, swapcontext in ctxswap.c and KeInitializeThread in
|
||
// thredini.c need to share common stack structure used at thread
|
||
// startup and switch time.
|
||
//
|
||
// This is that structure.
|
||
//
|
||
|
||
typedef struct _KSWITCHFRAME {
|
||
ULONG ExceptionList;
|
||
ULONG Eflags;
|
||
ULONG RetAddr;
|
||
} KSWITCHFRAME, *PKSWITCHFRAME;
|
||
|
||
|
||
//
|
||
// Various 387 defines
|
||
//
|
||
|
||
#define I386_80387_NP_VECTOR 0x07 // trap 7 when hardware not present
|
||
|
||
// begin_ntddk begin_wdm
|
||
//
|
||
// The non-volatile 387 state
|
||
//
|
||
|
||
typedef struct _KFLOATING_SAVE {
|
||
ULONG ControlWord;
|
||
ULONG StatusWord;
|
||
ULONG ErrorOffset;
|
||
ULONG ErrorSelector;
|
||
ULONG DataOffset; // Not used in wdm
|
||
ULONG DataSelector;
|
||
ULONG Cr0NpxState;
|
||
ULONG Spare1; // Not used in wdm
|
||
} KFLOATING_SAVE, *PKFLOATING_SAVE;
|
||
|
||
// end_ntddk end_wdm end_ntosp
|
||
|
||
//
|
||
// i386 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
|
||
//
|
||
// i386 Specific portions of mm component
|
||
//
|
||
|
||
//
|
||
// Define the page size for the Intel 386 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 the number of bits to shift to right justify the Page Directory Index
|
||
// field of a PTE.
|
||
//
|
||
|
||
#define PDI_SHIFT_X86 22
|
||
#define PDI_SHIFT_X86PAE 21
|
||
|
||
#if !defined (_X86PAE_)
|
||
#define PDI_SHIFT PDI_SHIFT_X86
|
||
#else
|
||
#define PDI_SHIFT PDI_SHIFT_X86PAE
|
||
#define PPI_SHIFT 30
|
||
#endif
|
||
|
||
//
|
||
// Define the number of bits to shift to right justify the Page Table Index
|
||
// field of a PTE.
|
||
//
|
||
|
||
#define PTI_SHIFT 12
|
||
|
||
//
|
||
// 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 ULONG *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 ULONG MmUserProbeAddress;
|
||
|
||
#define MM_HIGHEST_USER_ADDRESS MmHighestUserAddress
|
||
#define MM_SYSTEM_RANGE_START MmSystemRangeStart
|
||
#define MM_USER_PROBE_ADDRESS MmUserProbeAddress
|
||
|
||
#endif
|
||
|
||
// 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.
|
||
//
|
||
|
||
#if !defined (_X86PAE_)
|
||
#define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0800000
|
||
#else
|
||
#define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0C00000
|
||
#endif
|
||
|
||
// begin_wdm
|
||
|
||
#define MmGetProcedureAddress(Address) (Address)
|
||
#define MmLockPagableCodeSection(Address) MmLockPagableDataSection(Address)
|
||
|
||
// end_ntddk end_wdm
|
||
|
||
//
|
||
// Define the number of bits to shift to right justify the Page Directory Index
|
||
// field of a PTE.
|
||
//
|
||
|
||
#define PDI_SHIFT_X86 22
|
||
#define PDI_SHIFT_X86PAE 21
|
||
|
||
#if !defined (_X86PAE_)
|
||
#define PDI_SHIFT PDI_SHIFT_X86
|
||
#else
|
||
#define PDI_SHIFT PDI_SHIFT_X86PAE
|
||
#define PPI_SHIFT 30
|
||
#endif
|
||
|
||
//
|
||
// Define the number of bits to shift to right justify the Page Table Index
|
||
// field of a PTE.
|
||
//
|
||
|
||
#define PTI_SHIFT 12
|
||
|
||
//
|
||
// Define page directory and page base addresses.
|
||
//
|
||
|
||
#define PDE_BASE_X86 0xc0300000
|
||
#define PDE_BASE_X86PAE 0xc0600000
|
||
|
||
#define PTE_TOP_X86 0xC03FFFFF
|
||
#define PDE_TOP_X86 0xC0300FFF
|
||
|
||
#define PTE_TOP_X86PAE 0xC07FFFFF
|
||
#define PDE_TOP_X86PAE 0xC0603FFF
|
||
|
||
|
||
#if !defined (_X86PAE_)
|
||
#define PDE_BASE PDE_BASE_X86
|
||
#define PTE_TOP PTE_TOP_X86
|
||
#define PDE_TOP PDE_TOP_X86
|
||
#else
|
||
#define PDE_BASE PDE_BASE_X86PAE
|
||
#define PTE_TOP PTE_TOP_X86PAE
|
||
#define PDE_TOP PDE_TOP_X86PAE
|
||
#endif
|
||
#define PTE_BASE 0xc0000000
|
||
|
||
// end_nthal end_ntosp
|
||
|
||
//
|
||
// Define virtual base and alternate virtual base of kernel.
|
||
//
|
||
|
||
#define KSEG0_BASE 0x80000000
|
||
#define ALTERNATE_BASE (0xe1000000 - 16 * 1024 * 1024)
|
||
|
||
//
|
||
// Define macro to initialize directory table base.
|
||
//
|
||
|
||
#define INITIALIZE_DIRECTORY_TABLE_BASE(dirbase,pfn) \
|
||
*((PULONG)(dirbase)) = ((pfn) << PAGE_SHIFT)
|
||
|
||
|
||
// begin_nthal
|
||
//
|
||
// Location of primary PCR (used only for UP kernel & hal code)
|
||
//
|
||
|
||
// addressed from 0xffdf0000 - 0xffdfffff are reserved for the system
|
||
// (ie, not for use by the hal)
|
||
|
||
#define KI_BEGIN_KERNEL_RESERVED 0xffdf0000
|
||
#define KIP0PCRADDRESS 0xffdff000 // ntddk wdm ntosp
|
||
|
||
// begin_ntddk begin_ntosp
|
||
|
||
#define KI_USER_SHARED_DATA 0xffdf0000
|
||
#define SharedUserData ((KUSER_SHARED_DATA * const) KI_USER_SHARED_DATA)
|
||
|
||
//
|
||
// Result type definition for i386. (Machine specific enumerate type
|
||
// which is return type for portable exinterlockedincrement/decrement
|
||
// procedures.) In general, you should use the enumerated type defined
|
||
// in ex.h instead of directly referencing these constants.
|
||
//
|
||
|
||
// Flags loaded into AH by LAHF instruction
|
||
|
||
#define EFLAG_SIGN 0x8000
|
||
#define EFLAG_ZERO 0x4000
|
||
#define EFLAG_SELECT (EFLAG_SIGN | EFLAG_ZERO)
|
||
|
||
#define RESULT_NEGATIVE ((EFLAG_SIGN & ~EFLAG_ZERO) & EFLAG_SELECT)
|
||
#define RESULT_ZERO ((~EFLAG_SIGN & EFLAG_ZERO) & EFLAG_SELECT)
|
||
#define RESULT_POSITIVE ((~EFLAG_SIGN & ~EFLAG_ZERO) & EFLAG_SELECT)
|
||
|
||
//
|
||
// Convert various portable ExInterlock APIs into their architectural
|
||
// equivalents.
|
||
//
|
||
|
||
#if PRAGMA_DEPRECATED_DDK
|
||
#pragma deprecated(ExInterlockedIncrementLong) // Use InterlockedIncrement
|
||
#pragma deprecated(ExInterlockedDecrementLong) // Use InterlockedDecrement
|
||
#pragma deprecated(ExInterlockedExchangeUlong) // Use InterlockedExchange
|
||
#endif
|
||
|
||
#define ExInterlockedIncrementLong(Addend,Lock) \
|
||
Exfi386InterlockedIncrementLong(Addend)
|
||
|
||
#define ExInterlockedDecrementLong(Addend,Lock) \
|
||
Exfi386InterlockedDecrementLong(Addend)
|
||
|
||
#define ExInterlockedExchangeUlong(Target,Value,Lock) \
|
||
Exfi386InterlockedExchangeUlong(Target,Value)
|
||
|
||
// begin_wdm
|
||
|
||
#define ExInterlockedAddUlong ExfInterlockedAddUlong
|
||
#define ExInterlockedInsertHeadList ExfInterlockedInsertHeadList
|
||
#define ExInterlockedInsertTailList ExfInterlockedInsertTailList
|
||
#define ExInterlockedRemoveHeadList ExfInterlockedRemoveHeadList
|
||
#define ExInterlockedPopEntryList ExfInterlockedPopEntryList
|
||
#define ExInterlockedPushEntryList ExfInterlockedPushEntryList
|
||
|
||
// end_wdm
|
||
|
||
//
|
||
// Prototypes for architectural specific versions of Exi386 Api
|
||
//
|
||
|
||
//
|
||
// Interlocked result type is portable, but its values are machine specific.
|
||
// Constants for value are in i386.h, mips.h, etc.
|
||
//
|
||
|
||
typedef enum _INTERLOCKED_RESULT {
|
||
ResultNegative = RESULT_NEGATIVE,
|
||
ResultZero = RESULT_ZERO,
|
||
ResultPositive = RESULT_POSITIVE
|
||
} INTERLOCKED_RESULT;
|
||
|
||
NTKERNELAPI
|
||
INTERLOCKED_RESULT
|
||
FASTCALL
|
||
Exfi386InterlockedIncrementLong (
|
||
IN PLONG Addend
|
||
);
|
||
|
||
NTKERNELAPI
|
||
INTERLOCKED_RESULT
|
||
FASTCALL
|
||
Exfi386InterlockedDecrementLong (
|
||
IN PLONG Addend
|
||
);
|
||
|
||
NTKERNELAPI
|
||
ULONG
|
||
FASTCALL
|
||
Exfi386InterlockedExchangeUlong (
|
||
IN PULONG Target,
|
||
IN ULONG Value
|
||
);
|
||
|
||
// end_ntddk end_nthal end_ntosp
|
||
|
||
//
|
||
// UP/MP versions of interlocked intrinsics
|
||
//
|
||
// N.B. FASTCALL does NOT work with inline functions.
|
||
//
|
||
|
||
#if !defined(_WINBASE_) && !defined(NONTOSPINTERLOCK) // ntosp ntddk nthal
|
||
#if defined(_M_IX86)
|
||
|
||
#pragma warning(disable:4035) // wdm re-enable below
|
||
|
||
// begin_ntddk begin_nthal begin_ntosp
|
||
#if !defined(MIDL_PASS) // wdm
|
||
#if defined(NO_INTERLOCKED_INTRINSICS) || defined(_CROSS_PLATFORM_)
|
||
// begin_wdm
|
||
|
||
NTKERNELAPI
|
||
LONG
|
||
FASTCALL
|
||
InterlockedIncrement(
|
||
IN LONG volatile *Addend
|
||
);
|
||
|
||
NTKERNELAPI
|
||
LONG
|
||
FASTCALL
|
||
InterlockedDecrement(
|
||
IN LONG volatile *Addend
|
||
);
|
||
|
||
NTKERNELAPI
|
||
LONG
|
||
FASTCALL
|
||
InterlockedExchange(
|
||
IN OUT LONG volatile *Target,
|
||
IN LONG Value
|
||
);
|
||
|
||
#define InterlockedExchangePointer(Target, Value) \
|
||
(PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
|
||
|
||
LONG
|
||
FASTCALL
|
||
InterlockedExchangeAdd(
|
||
IN OUT LONG volatile *Addend,
|
||
IN LONG Increment
|
||
);
|
||
|
||
NTKERNELAPI
|
||
LONG
|
||
FASTCALL
|
||
InterlockedCompareExchange(
|
||
IN OUT LONG volatile *Destination,
|
||
IN LONG ExChange,
|
||
IN LONG Comperand
|
||
);
|
||
|
||
#define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \
|
||
(PVOID)InterlockedCompareExchange((PLONG)Destination, (LONG)ExChange, (LONG)Comperand)
|
||
|
||
#define InterlockedCompareExchange64(Destination, ExChange, Comperand) \
|
||
ExfInterlockedCompareExchange64(Destination, &(ExChange), &(Comperand))
|
||
|
||
NTKERNELAPI
|
||
LONGLONG
|
||
FASTCALL
|
||
ExfInterlockedCompareExchange64(
|
||
IN OUT LONGLONG volatile *Destination,
|
||
IN PLONGLONG ExChange,
|
||
IN PLONGLONG Comperand
|
||
);
|
||
|
||
// end_wdm
|
||
|
||
#else // NO_INTERLOCKED_INCREMENTS || _CROSS_PLATFORM_
|
||
|
||
#define InterlockedExchangePointer(Target, Value) \
|
||
(PVOID)InterlockedExchange((PLONG)Target, (LONG)Value)
|
||
|
||
// end_ntddk end_nthal end_ntosp
|
||
|
||
#if defined(NT_UP) && !defined (_NTDDK_) && !defined(_NTIFS_)
|
||
|
||
#define InterlockedIncrement(Addend) (InterlockedExchangeAdd (Addend, 1)+1)
|
||
#define InterlockedDecrement(Addend) (InterlockedExchangeAdd (Addend, -1)-1)
|
||
|
||
//FORCEINLINE
|
||
//LONG
|
||
//FASTCALL
|
||
//InterlockedIncrement(
|
||
// IN PLONG Addend
|
||
// )
|
||
//{
|
||
// __asm {
|
||
// mov eax, 1
|
||
// mov ecx, Addend
|
||
// xadd [ecx], eax
|
||
// inc eax
|
||
// }
|
||
//}
|
||
|
||
//FORCEINLINE
|
||
//LONG
|
||
//FASTCALL
|
||
//InterlockedDecrement(
|
||
// IN PLONG Addend
|
||
// )
|
||
//{
|
||
// __asm {
|
||
// mov eax, -1
|
||
// mov ecx, Addend
|
||
// xadd [ecx], eax
|
||
// dec eax
|
||
// }
|
||
//}
|
||
|
||
FORCEINLINE
|
||
LONG
|
||
FASTCALL
|
||
InterlockedExchange(
|
||
IN OUT LONG volatile *Target,
|
||
IN LONG Value
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Value
|
||
mov ecx, Target
|
||
xchg [ecx], eax
|
||
}
|
||
}
|
||
|
||
FORCEINLINE
|
||
LONG
|
||
FASTCALL
|
||
InterlockedExchangeAdd(
|
||
IN OUT LONG volatile *Addend,
|
||
IN LONG Increment
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Increment
|
||
mov ecx, Addend
|
||
xadd [ecx], eax
|
||
}
|
||
}
|
||
|
||
FORCEINLINE
|
||
LONG
|
||
FASTCALL
|
||
InterlockedCompareExchange(
|
||
IN OUT LONG volatile *Destination,
|
||
IN LONG Exchange,
|
||
IN LONG Comperand
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Comperand
|
||
mov ecx, Destination
|
||
mov edx, Exchange
|
||
cmpxchg [ecx], edx
|
||
}
|
||
}
|
||
|
||
#define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \
|
||
(PVOID)InterlockedCompareExchange((PLONG)Destination, (LONG)ExChange, (LONG)Comperand)
|
||
|
||
#define InterlockedCompareExchange64(Destination, ExChange, Comperand) \
|
||
ExfInterlockedCompareExchange64(Destination, &(ExChange), &(Comperand))
|
||
|
||
LONGLONG
|
||
FASTCALL
|
||
ExfInterlockedCompareExchange64(
|
||
IN OUT LONGLONG volatile *Destination,
|
||
IN PLONGLONG ExChange,
|
||
IN PLONGLONG Comperand
|
||
);
|
||
|
||
#else // NT_UP
|
||
|
||
// begin_ntosp begin_ntddk begin_nthal
|
||
|
||
#if (_MSC_FULL_VER > 13009037)
|
||
LONG
|
||
__cdecl
|
||
_InterlockedExchange(
|
||
IN OUT LONG volatile *Target,
|
||
IN LONG Value
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedExchange)
|
||
#define InterlockedExchange _InterlockedExchange
|
||
#else
|
||
FORCEINLINE
|
||
LONG
|
||
FASTCALL
|
||
InterlockedExchange(
|
||
IN OUT LONG volatile *Target,
|
||
IN LONG Value
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Value
|
||
mov ecx, Target
|
||
xchg [ecx], eax
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#if (_MSC_FULL_VER > 13009037)
|
||
LONG
|
||
__cdecl
|
||
_InterlockedIncrement(
|
||
IN LONG volatile *Addend
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedIncrement)
|
||
#define InterlockedIncrement _InterlockedIncrement
|
||
#else
|
||
#define InterlockedIncrement(Addend) (InterlockedExchangeAdd (Addend, 1)+1)
|
||
#endif
|
||
|
||
#if (_MSC_FULL_VER > 13009037)
|
||
LONG
|
||
__cdecl
|
||
_InterlockedDecrement(
|
||
IN LONG volatile *Addend
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedDecrement)
|
||
#define InterlockedDecrement _InterlockedDecrement
|
||
#else
|
||
#define InterlockedDecrement(Addend) (InterlockedExchangeAdd (Addend, -1)-1)
|
||
#endif
|
||
|
||
#if (_MSC_FULL_VER > 13009037)
|
||
LONG
|
||
__cdecl
|
||
_InterlockedExchangeAdd(
|
||
IN OUT LONG volatile *Addend,
|
||
IN LONG Increment
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedExchangeAdd)
|
||
#define InterlockedExchangeAdd _InterlockedExchangeAdd
|
||
#else
|
||
// begin_wdm
|
||
FORCEINLINE
|
||
LONG
|
||
FASTCALL
|
||
InterlockedExchangeAdd(
|
||
IN OUT LONG volatile *Addend,
|
||
IN LONG Increment
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Increment
|
||
mov ecx, Addend
|
||
lock xadd [ecx], eax
|
||
}
|
||
}
|
||
// end_wdm
|
||
#endif
|
||
|
||
#if (_MSC_FULL_VER > 13009037)
|
||
LONG
|
||
__cdecl
|
||
_InterlockedCompareExchange (
|
||
IN OUT LONG volatile *Destination,
|
||
IN LONG ExChange,
|
||
IN LONG Comperand
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedCompareExchange)
|
||
#define InterlockedCompareExchange (LONG)_InterlockedCompareExchange
|
||
#else
|
||
FORCEINLINE
|
||
LONG
|
||
FASTCALL
|
||
InterlockedCompareExchange(
|
||
IN OUT LONG volatile *Destination,
|
||
IN LONG Exchange,
|
||
IN LONG Comperand
|
||
)
|
||
{
|
||
__asm {
|
||
mov eax, Comperand
|
||
mov ecx, Destination
|
||
mov edx, Exchange
|
||
lock cmpxchg [ecx], edx
|
||
}
|
||
}
|
||
#endif
|
||
|
||
#define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \
|
||
(PVOID)InterlockedCompareExchange((PLONG)Destination, (LONG)ExChange, (LONG)Comperand)
|
||
|
||
#define InterlockedCompareExchange64(Destination, ExChange, Comperand) \
|
||
ExfInterlockedCompareExchange64(Destination, &(ExChange), &(Comperand))
|
||
|
||
NTKERNELAPI
|
||
LONGLONG
|
||
FASTCALL
|
||
ExfInterlockedCompareExchange64(
|
||
IN OUT LONGLONG volatile *Destination,
|
||
IN PLONGLONG ExChange,
|
||
IN PLONGLONG Comperand
|
||
);
|
||
|
||
// end_ntosp end_ntddk end_nthal
|
||
#endif // NT_UP
|
||
// begin_ntddk begin_nthal begin_ntosp
|
||
#endif // INTERLOCKED_INTRINSICS || _CROSS_PLATFORM_
|
||
// begin_wdm
|
||
#endif // MIDL_PASS
|
||
// end_ntosp end_ntddk end_nthal
|
||
#pragma warning(default:4035)
|
||
// end_wdm
|
||
#endif // _M_IX86 && !CROSS_PLATFORM
|
||
// begin_ntddk begin_nthal begin_ntosp
|
||
#endif // __WINBASE__ && !NONTOSPINTERLOCK
|
||
// end_ntosp end_ntddk end_nthal
|
||
|
||
// begin_nthal begin_ntddk
|
||
|
||
//
|
||
// Turn these instrinsics off until the compiler can handle them
|
||
//
|
||
#if (_MSC_FULL_VER > 13009037)
|
||
|
||
LONG
|
||
_InterlockedOr (
|
||
IN OUT PLONG Target,
|
||
IN LONG Set
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedOr)
|
||
|
||
#define InterlockedOr _InterlockedOr
|
||
|
||
LONG
|
||
_InterlockedAnd (
|
||
IN OUT LONG volatile *Target,
|
||
IN LONG Set
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedAnd)
|
||
|
||
#define InterlockedAnd _InterlockedAnd
|
||
|
||
LONG
|
||
_InterlockedXor (
|
||
IN OUT LONG volatile Target,
|
||
IN LONG Set
|
||
);
|
||
|
||
#pragma intrinsic (_InterlockedXor)
|
||
|
||
#define InterlockedXor _InterlockedXor
|
||
|
||
#else // compiler version
|
||
|
||
FORCEINLINE
|
||
LONG
|
||
InterlockedAnd (
|
||
IN OUT LONG volatile *Target,
|
||
LONG Set
|
||
)
|
||
{
|
||
LONG i;
|
||
LONG j;
|
||
|
||
j = *Target;
|
||
do {
|
||
i = j;
|
||
j = InterlockedCompareExchange(Target,
|
||
i & Set,
|
||
i);
|
||
|
||
} while (i != j);
|
||
|
||
return j;
|
||
}
|
||
|
||
FORCEINLINE
|
||
LONG
|
||
InterlockedOr (
|
||
IN OUT LONG volatile *Target,
|
||
IN LONG Set
|
||
)
|
||
{
|
||
LONG i;
|
||
LONG j;
|
||
|
||
j = *Target;
|
||
do {
|
||
i = j;
|
||
j = InterlockedCompareExchange(Target,
|
||
i | Set,
|
||
i);
|
||
|
||
} while (i != j);
|
||
|
||
return j;
|
||
}
|
||
|
||
#endif // compiler version
|
||
|
||
// end_nthal end_ntddk
|
||
|
||
//
|
||
// Structure for Ldt information in x86 processes
|
||
//
|
||
typedef struct _LDTINFORMATION {
|
||
ULONG Size;
|
||
ULONG AllocatedSize;
|
||
PLDT_ENTRY Ldt;
|
||
} LDTINFORMATION, *PLDTINFORMATION;
|
||
|
||
//
|
||
// SetProcessInformation Structure for ProcessSetIoHandlers info class
|
||
//
|
||
|
||
// begin_ntosp
|
||
|
||
typedef struct _PROCESS_IO_PORT_HANDLER_INFORMATION {
|
||
BOOLEAN Install; // true if handlers to be installed
|
||
ULONG NumEntries;
|
||
ULONG Context;
|
||
PEMULATOR_ACCESS_ENTRY EmulatorAccessEntries;
|
||
} PROCESS_IO_PORT_HANDLER_INFORMATION, *PPROCESS_IO_PORT_HANDLER_INFORMATION;
|
||
|
||
|
||
//
|
||
// Vdm Objects and Io handling structure
|
||
//
|
||
|
||
typedef struct _VDM_IO_HANDLER_FUNCTIONS {
|
||
PDRIVER_IO_PORT_ULONG UlongIo;
|
||
PDRIVER_IO_PORT_ULONG_STRING UlongStringIo;
|
||
PDRIVER_IO_PORT_USHORT UshortIo[2];
|
||
PDRIVER_IO_PORT_USHORT_STRING UshortStringIo[2];
|
||
PDRIVER_IO_PORT_UCHAR UcharIo[4];
|
||
PDRIVER_IO_PORT_UCHAR_STRING UcharStringIo[4];
|
||
} VDM_IO_HANDLER_FUNCTIONS, *PVDM_IO_HANDLER_FUNCTIONS;
|
||
|
||
typedef struct _VDM_IO_HANDLER {
|
||
struct _VDM_IO_HANDLER *Next;
|
||
ULONG PortNumber;
|
||
VDM_IO_HANDLER_FUNCTIONS IoFunctions[2];
|
||
} VDM_IO_HANDLER, *PVDM_IO_HANDLER;
|
||
|
||
|
||
|
||
// begin_nthal begin_ntddk begin_wdm
|
||
|
||
|
||
#if !defined(MIDL_PASS) && defined(_M_IX86)
|
||
|
||
//
|
||
// i386 function definitions
|
||
//
|
||
|
||
#pragma warning(disable:4035) // re-enable below
|
||
|
||
// end_wdm
|
||
|
||
#if NT_UP
|
||
#define _PCR ds:[KIP0PCRADDRESS]
|
||
#else
|
||
#define _PCR fs:[0]
|
||
#endif
|
||
|
||
// end_ntddk end_ntosp
|
||
|
||
//
|
||
// Get address of current processor block.
|
||
//
|
||
// WARNING: This inline macro can only be used by the kernel or hal
|
||
//
|
||
#define KiPcr() KeGetPcr()
|
||
FORCEINLINE
|
||
PKPCR
|
||
NTAPI
|
||
KeGetPcr(VOID)
|
||
{
|
||
#if NT_UP
|
||
__asm { mov eax, KIP0PCRADDRESS }
|
||
#else
|
||
__asm { mov eax, _PCR KPCR.SelfPcr }
|
||
#endif
|
||
}
|
||
|
||
// begin_ntosp
|
||
|
||
//
|
||
// Get address of current processor block.
|
||
//
|
||
// WARNING: This inline macro can only be used by the kernel or hal
|
||
//
|
||
FORCEINLINE
|
||
PKPRCB
|
||
NTAPI
|
||
KeGetCurrentPrcb (VOID)
|
||
{
|
||
__asm { mov eax, _PCR KPCR.Prcb }
|
||
}
|
||
|
||
// begin_ntddk begin_wdm
|
||
|
||
//
|
||
// Get current IRQL.
|
||
//
|
||
// On x86 this function resides in the HAL
|
||
//
|
||
|
||
NTHALAPI
|
||
KIRQL
|
||
NTAPI
|
||
KeGetCurrentIrql();
|
||
|
||
// end_wdm
|
||
//
|
||
// Get the current processor number
|
||
//
|
||
|
||
FORCEINLINE
|
||
ULONG
|
||
NTAPI
|
||
KeGetCurrentProcessorNumber(VOID)
|
||
{
|
||
__asm { movzx eax, _PCR 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.
|
||
// WARNING: This inline macro is always MP enabled because filesystems
|
||
// utilize it
|
||
//
|
||
//
|
||
FORCEINLINE
|
||
struct _KTHREAD *
|
||
NTAPI KeGetCurrentThread (VOID)
|
||
{
|
||
__asm { mov eax, fs:[0] KPCR.PrcbData.CurrentThread }
|
||
}
|
||
|
||
//
|
||
// If processor executing DPC?
|
||
// WARNING: This inline macro is always MP enabled because filesystems
|
||
// utilize it
|
||
//
|
||
FORCEINLINE
|
||
ULONG
|
||
NTAPI
|
||
KeIsExecutingDpc(VOID)
|
||
{
|
||
__asm { mov eax, fs:[0] KPCR.PrcbData.DpcRoutineActive }
|
||
}
|
||
|
||
// begin_nthal begin_ntddk begin_ntosp
|
||
|
||
#pragma warning(default:4035)
|
||
|
||
// begin_wdm
|
||
#endif // !defined(MIDL_PASS) && defined(_M_IX86)
|
||
|
||
// 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 x86.
|
||
//
|
||
//
|
||
// Arguments:
|
||
//
|
||
// None.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//--
|
||
|
||
#define KeMemoryBarrier()
|
||
|
||
// begin_nthal
|
||
//
|
||
// Macro to set address of a trap/interrupt handler to IDT
|
||
//
|
||
#define KiSetHandlerAddressToIDT(Vector, HandlerAddress) {\
|
||
UCHAR IDTEntry = HalVectorToIDTEntry(Vector); \
|
||
ULONG Ha = (ULONG)HandlerAddress; \
|
||
KeGetPcr()->IDT[IDTEntry].ExtendedOffset = HIGHWORD(Ha); \
|
||
KeGetPcr()->IDT[IDTEntry].Offset = LOWWORD(Ha); \
|
||
}
|
||
|
||
//
|
||
// Macro to return address of a trap/interrupt handler in IDT
|
||
//
|
||
#define KiReturnHandlerAddressFromIDT(Vector) \
|
||
MAKEULONG(KiPcr()->IDT[HalVectorToIDTEntry(Vector)].ExtendedOffset, KiPcr()->IDT[HalVectorToIDTEntry(Vector)].Offset)
|
||
|
||
// end_nthal
|
||
|
||
//++
|
||
//
|
||
// BOOLEAN
|
||
// KiIsThreadNumericStateSaved(
|
||
// IN PKTHREAD Address
|
||
// )
|
||
//
|
||
//--
|
||
#define KiIsThreadNumericStateSaved(a) \
|
||
(a->NpxState != NPX_STATE_LOADED)
|
||
|
||
//++
|
||
//
|
||
// VOID
|
||
// KiRundownThread(
|
||
// IN PKTHREAD Address
|
||
// )
|
||
//
|
||
//--
|
||
|
||
#if defined(NT_UP)
|
||
|
||
//
|
||
// On UP x86 systems, FP state is lazy saved and loaded. If this
|
||
// thread owns the current FP context, clear the ownership field
|
||
// so we will not try to save to this thread after it has been
|
||
// terminated.
|
||
//
|
||
|
||
#define KiRundownThread(a) \
|
||
if (KeGetCurrentPrcb()->NpxThread == (a)) { \
|
||
KeGetCurrentPrcb()->NpxThread = NULL; \
|
||
}
|
||
|
||
#else
|
||
|
||
#define KiRundownThread(a)
|
||
|
||
#endif
|
||
|
||
//
|
||
// functions specific to 386 structure
|
||
//
|
||
|
||
VOID
|
||
NTAPI
|
||
KiSetIRR (
|
||
IN ULONG SWInterruptMask
|
||
);
|
||
|
||
//
|
||
// Procedures to support frame manipulation
|
||
//
|
||
|
||
ULONG
|
||
NTAPI
|
||
KiEspFromTrapFrame(
|
||
IN PKTRAP_FRAME TrapFrame
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KiEspToTrapFrame(
|
||
IN PKTRAP_FRAME TrapFrame,
|
||
IN ULONG Esp
|
||
);
|
||
|
||
ULONG
|
||
NTAPI
|
||
KiSegSsFromTrapFrame(
|
||
IN PKTRAP_FRAME TrapFrame
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KiSegSsToTrapFrame(
|
||
IN PKTRAP_FRAME TrapFrame,
|
||
IN ULONG SegSs
|
||
);
|
||
|
||
//
|
||
// Define prototypes for i386 specific clock and profile interrupt routines.
|
||
//
|
||
|
||
VOID
|
||
NTAPI
|
||
KiUpdateRunTime (
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KiUpdateSystemTime (
|
||
VOID
|
||
);
|
||
|
||
// begin_ntddk begin_wdm begin_ntosp
|
||
|
||
NTKERNELAPI
|
||
NTSTATUS
|
||
NTAPI
|
||
KeSaveFloatingPointState (
|
||
OUT PKFLOATING_SAVE FloatSave
|
||
);
|
||
|
||
NTKERNELAPI
|
||
NTSTATUS
|
||
NTAPI
|
||
KeRestoreFloatingPointState (
|
||
IN PKFLOATING_SAVE FloatSave
|
||
);
|
||
|
||
// end_ntddk end_wdm
|
||
// begin_nthal
|
||
|
||
NTKERNELAPI
|
||
VOID
|
||
NTAPI
|
||
KeProfileInterruptWithSource (
|
||
IN struct _KTRAP_FRAME *TrapFrame,
|
||
IN KPROFILE_SOURCE ProfileSource
|
||
);
|
||
|
||
// end_ntosp
|
||
|
||
VOID
|
||
NTAPI
|
||
KeProfileInterrupt (
|
||
IN KIRQL OldIrql,
|
||
IN KTRAP_FRAME TrapFrame
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KeUpdateRuntime (
|
||
IN KIRQL OldIrql,
|
||
IN KTRAP_FRAME TrapFrame
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KeUpdateSystemTime (
|
||
IN KIRQL OldIrql,
|
||
IN KTRAP_FRAME TrapFrame
|
||
);
|
||
|
||
// begin_ntddk begin_wdm begin_ntndis begin_ntosp
|
||
|
||
#endif // defined(_X86_)
|
||
|
||
// end_nthal end_ntddk end_wdm end_ntndis end_ntosp
|
||
|
||
// begin_nthal begin_ntddk
|
||
|
||
// Use the following for kernel mode runtime checks of X86 system architecture
|
||
|
||
#ifdef _X86_
|
||
|
||
#ifdef IsNEC_98
|
||
#undef IsNEC_98
|
||
#endif
|
||
|
||
#ifdef IsNotNEC_98
|
||
#undef IsNotNEC_98
|
||
#endif
|
||
|
||
#ifdef SetNEC_98
|
||
#undef SetNEC_98
|
||
#endif
|
||
|
||
#ifdef SetNotNEC_98
|
||
#undef SetNotNEC_98
|
||
#endif
|
||
|
||
#define IsNEC_98 (SharedUserData->AlternativeArchitecture == NEC98x86)
|
||
#define IsNotNEC_98 (SharedUserData->AlternativeArchitecture != NEC98x86)
|
||
#define SetNEC_98 SharedUserData->AlternativeArchitecture = NEC98x86
|
||
#define SetNotNEC_98 SharedUserData->AlternativeArchitecture = StandardDesign
|
||
|
||
#endif
|
||
|
||
// end_nthal end_ntddk
|
||
|
||
//
|
||
// i386 arch. specific kernel functions.
|
||
//
|
||
|
||
// begin_ntosp
|
||
#ifdef _X86_
|
||
VOID
|
||
NTAPI
|
||
Ke386SetLdtProcess (
|
||
struct _KPROCESS *Process,
|
||
PLDT_ENTRY Ldt,
|
||
ULONG Limit
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
Ke386SetDescriptorProcess (
|
||
struct _KPROCESS *Process,
|
||
ULONG Offset,
|
||
LDT_ENTRY LdtEntry
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
Ke386GetGdtEntryThread (
|
||
struct _KTHREAD *Thread,
|
||
ULONG Offset,
|
||
PKGDTENTRY Descriptor
|
||
);
|
||
|
||
BOOLEAN
|
||
NTAPI
|
||
Ke386SetIoAccessMap (
|
||
ULONG MapNumber,
|
||
PKIO_ACCESS_MAP IoAccessMap
|
||
);
|
||
|
||
BOOLEAN
|
||
NTAPI
|
||
Ke386QueryIoAccessMap (
|
||
ULONG MapNumber,
|
||
PKIO_ACCESS_MAP IoAccessMap
|
||
);
|
||
|
||
BOOLEAN
|
||
NTAPI
|
||
Ke386IoSetAccessProcess (
|
||
struct _KPROCESS *Process,
|
||
ULONG MapNumber
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
Ke386SetIOPL(
|
||
struct _KPROCESS *Process
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
Ke386CallBios (
|
||
IN ULONG BiosCommand,
|
||
IN OUT PCONTEXT BiosArguments
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KiEditIopmDpc (
|
||
IN struct _KDPC *Dpc,
|
||
IN PVOID DeferredContext,
|
||
IN PVOID SystemArgument1,
|
||
IN PVOID SystemArgument2
|
||
);
|
||
|
||
BOOLEAN
|
||
NTAPI
|
||
Ki386GetSelectorParameters(
|
||
IN USHORT Selector,
|
||
OUT PULONG Flags,
|
||
OUT PULONG Base,
|
||
OUT PULONG Limit
|
||
);
|
||
|
||
ULONG
|
||
Ki386DispatchOpcodeV86 (
|
||
IN PKTRAP_FRAME TrapFrame
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
Ke386SetVdmInterruptHandler (
|
||
IN struct _KPROCESS *Process,
|
||
IN ULONG Interrupt,
|
||
IN USHORT Selector,
|
||
IN ULONG Offset,
|
||
IN BOOLEAN Gate32
|
||
);
|
||
#endif //_X86_
|
||
// end_ntosp
|
||
//
|
||
// i386 ABIOS specific routines.
|
||
//
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386GetLid(
|
||
IN USHORT DeviceId,
|
||
IN USHORT RelativeLid,
|
||
IN BOOLEAN SharedLid,
|
||
IN struct _DRIVER_OBJECT *DeviceObject,
|
||
OUT PUSHORT LogicalId
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386ReleaseLid(
|
||
IN USHORT LogicalId,
|
||
IN struct _DRIVER_OBJECT *DeviceObject
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386AbiosCall(
|
||
IN USHORT LogicalId,
|
||
IN struct _DRIVER_OBJECT *DriverObject,
|
||
IN PUCHAR RequestBlock,
|
||
IN USHORT EntryPoint
|
||
);
|
||
|
||
//
|
||
// i386 misc routines
|
||
//
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386AllocateGdtSelectors(
|
||
OUT PUSHORT SelectorArray,
|
||
IN USHORT NumberOfSelectors
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
KeI386Call16BitFunction (
|
||
IN OUT PCONTEXT Regs
|
||
);
|
||
|
||
USHORT
|
||
NTAPI
|
||
KeI386Call16BitCStyleFunction (
|
||
IN ULONG EntryOffset,
|
||
IN ULONG EntrySelector,
|
||
IN PUCHAR Parameters,
|
||
IN ULONG Size
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386FlatToGdtSelector(
|
||
IN ULONG SelectorBase,
|
||
IN USHORT Length,
|
||
IN USHORT Selector
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386ReleaseGdtSelectors(
|
||
OUT PUSHORT SelectorArray,
|
||
IN USHORT NumberOfSelectors
|
||
);
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
KeI386SetGdtSelector (
|
||
ULONG Selector,
|
||
PKGDTENTRY GdtValue
|
||
);
|
||
|
||
|
||
VOID
|
||
NTAPI
|
||
KeOptimizeProcessorControlState (
|
||
VOID
|
||
);
|
||
|
||
//
|
||
// Vdm specific functions.
|
||
//
|
||
|
||
BOOLEAN
|
||
NTAPI
|
||
KeVdmInsertQueueApc (
|
||
IN PKAPC Apc,
|
||
IN struct _KTHREAD *Thread,
|
||
IN KPROCESSOR_MODE ApcMode,
|
||
IN PKKERNEL_ROUTINE KernelRoutine,
|
||
IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
|
||
IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,
|
||
IN PVOID NormalContext OPTIONAL,
|
||
IN KPRIORITY Increment
|
||
);
|
||
|
||
FORCEINLINE
|
||
VOID
|
||
NTAPI
|
||
KeVdmClearApcThreadAddress (
|
||
IN PKAPC Apc
|
||
)
|
||
|
||
{
|
||
if (Apc->Inserted == FALSE) {
|
||
Apc->Thread = NULL;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
NTAPI
|
||
KeI386VdmInitialize (
|
||
VOID
|
||
);
|
||
|
||
//
|
||
// x86 functions for special instructions
|
||
//
|
||
|
||
VOID
|
||
NTAPI
|
||
CPUID (
|
||
ULONG InEax,
|
||
PULONG OutEax,
|
||
PULONG OutEbx,
|
||
PULONG OutEcx,
|
||
PULONG OutEdx
|
||
);
|
||
|
||
LONGLONG
|
||
NTAPI
|
||
RDTSC (
|
||
VOID
|
||
);
|
||
|
||
ULONGLONG
|
||
FASTCALL
|
||
RDMSR (
|
||
IN ULONG MsrRegister
|
||
);
|
||
|
||
VOID
|
||
NTAPI
|
||
WRMSR (
|
||
IN ULONG MsrRegister,
|
||
IN ULONGLONG MsrValue
|
||
);
|
||
|
||
//
|
||
// i386 Vdm specific data
|
||
//
|
||
extern ULONG KeI386EFlagsAndMaskV86;
|
||
extern ULONG KeI386EFlagsOrMaskV86;
|
||
extern BOOLEAN KeI386VdmIoplAllowed;
|
||
extern ULONG KeI386VirtualIntExtensions;
|
||
|
||
|
||
extern ULONG KeI386CpuType;
|
||
extern ULONG KeI386CpuStep;
|
||
extern BOOLEAN KeI386NpxPresent;
|
||
extern BOOLEAN KeI386FxsrPresent;
|
||
|
||
|
||
//
|
||
// i386 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 macro to test if x86 feature is present.
|
||
//
|
||
|
||
extern ULONG KiBootFeatureBits;
|
||
|
||
#define Isx86FeaturePresent(_f_) ((KiBootFeatureBits & (_f_)) != 0)
|
||
|
||
#endif // _i386_
|