Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2429 lines
51 KiB

/*++ 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_nthal begin_ntndis
#if defined(_X86_)
//
// Define maximum size of flush multple 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
//
// Define function decoration depending on whether a driver, a file system,
// or a kernel component is being built.
//
#if (defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_)) && !defined (_BLDR_)
#define NTKERNELAPI DECLSPEC_IMPORT
#else
#define NTKERNELAPI
#endif
//
// Define function decoration depending on whether the HAL or other kernel
// component is being build.
//
#if !defined(_NTHAL_) && !defined(_BLDR_)
#define NTHALAPI DECLSPEC_IMPORT
#else
#define NTHALAPI
#endif
// end_ntddk end_nthal end_ntndis
// 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)
// BUGBUG 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.
// BUGBUG kenr - remove this PIC stuff from i386.h!
//
// Interrupt controller register addresses.
//
#define PIC1_PORT0 0x20 // master PIC
#define PIC1_PORT1 0x21
#define PIC2_PORT0 0x0A0 // slave PIC
#define PIC2_PORT1 0x0A1
//
// Commands for Interrupt Controller
//
#define PIC1_EOI_MASK 0x60
#define PIC2_EOI 0x62
#define OCW2_NON_SPECIFIC_EOI 0x20
#define OCW3_READ_ISR 0xb
#define OCW3_READ_IRR 0xa
//
// Length on interupt object dispatch code in longwords.
// BUGBUG 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
#define DISPATCH_LENGTH NORMAL_DISPATCH_LENGTH // ntddk
//
// 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
// begin_ntddk
//
// STATUS register for each MCA bank.
//
typedef union _MCI_STATS {
struct {
USHORT McaCod;
USHORT MsCod;
ULONG OtherInfo : 25;
ULONG Damage : 1;
ULONG AddressValid : 1;
ULONG MiscValid : 1;
ULONG Enabled : 1;
ULONG UnCorrected : 1;
ULONG OverFlow : 1;
ULONG Valid : 1;
} MciStats;
ULONGLONG QuadPart;
} MCI_STATS, *PMCI_STATS;
// end_ntddk
// 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_nthal
//
// 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
#define SYNCH_LEVEL (IPI_LEVEL-1) // synchronization level
// end_ntddk
#define KiSynchIrql SYNCH_LEVEL // enable portable code
//
// Machine type definitions
// BUGBUG shielint This is temporary definitions.
//
#define MACHINE_TYPE_ISA 0
#define MACHINE_TYPE_EISA 1
#define MACHINE_TYPE_MCA 2
// end_nthal
//
// The previous values and the follwing are or'ed in KeI386MachineType.
// The latter section can be removed onced PC/AT style computers become
// dominant in Japan. (DavidGoe)
//
#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.
//
// 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
#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)(l))
//
// Macro to combine two USHORT offsets into a long offset
//
#define MAKEULONG(x, y) \
(((((ULONG)(x))<<16) & 0xffff0000) | \
((ULONG)(y) & 0xffff))
// end_nthal
//
// Request a software interrupt.
//
#define KiRequestSoftwareInterrupt(RequestIrql) \
HalRequestSoftwareInterrupt( RequestIrql )
// begin_ntddk begin_nthal begin_ntndis
//
// 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
READ_REGISTER_UCHAR(
PUCHAR Register
);
NTKERNELAPI
USHORT
READ_REGISTER_USHORT(
PUSHORT Register
);
NTKERNELAPI
ULONG
READ_REGISTER_ULONG(
PULONG Register
);
NTKERNELAPI
VOID
READ_REGISTER_BUFFER_UCHAR(
PUCHAR Register,
PUCHAR Buffer,
ULONG Count
);
NTKERNELAPI
VOID
READ_REGISTER_BUFFER_USHORT(
PUSHORT Register,
PUSHORT Buffer,
ULONG Count
);
NTKERNELAPI
VOID
READ_REGISTER_BUFFER_ULONG(
PULONG Register,
PULONG Buffer,
ULONG Count
);
NTKERNELAPI
VOID
WRITE_REGISTER_UCHAR(
PUCHAR Register,
UCHAR Value
);
NTKERNELAPI
VOID
WRITE_REGISTER_USHORT(
PUSHORT Register,
USHORT Value
);
NTKERNELAPI
VOID
WRITE_REGISTER_ULONG(
PULONG Register,
ULONG Value
);
NTKERNELAPI
VOID
WRITE_REGISTER_BUFFER_UCHAR(
PUCHAR Register,
PUCHAR Buffer,
ULONG Count
);
NTKERNELAPI
VOID
WRITE_REGISTER_BUFFER_USHORT(
PUSHORT Register,
PUSHORT Buffer,
ULONG Count
);
NTKERNELAPI
VOID
WRITE_REGISTER_BUFFER_ULONG(
PULONG Register,
PULONG Buffer,
ULONG Count
);
NTKERNELAPI
UCHAR
READ_PORT_UCHAR(
PUCHAR Port
);
NTKERNELAPI
USHORT
READ_PORT_USHORT(
PUSHORT Port
);
NTKERNELAPI
ULONG
READ_PORT_ULONG(
PULONG Port
);
NTKERNELAPI
VOID
READ_PORT_BUFFER_UCHAR(
PUCHAR Port,
PUCHAR Buffer,
ULONG Count
);
NTKERNELAPI
VOID
READ_PORT_BUFFER_USHORT(
PUSHORT Port,
PUSHORT Buffer,
ULONG Count
);
NTKERNELAPI
VOID
READ_PORT_BUFFER_ULONG(
PULONG Port,
PULONG Buffer,
ULONG Count
);
NTKERNELAPI
VOID
WRITE_PORT_UCHAR(
PUCHAR Port,
UCHAR Value
);
NTKERNELAPI
VOID
WRITE_PORT_USHORT(
PUSHORT Port,
USHORT Value
);
NTKERNELAPI
VOID
WRITE_PORT_ULONG(
PULONG Port,
ULONG Value
);
NTKERNELAPI
VOID
WRITE_PORT_BUFFER_UCHAR(
PUCHAR Port,
PUCHAR Buffer,
ULONG Count
);
NTKERNELAPI
VOID
WRITE_PORT_BUFFER_USHORT(
PUSHORT Port,
PUSHORT Buffer,
ULONG Count
);
NTKERNELAPI
VOID
WRITE_PORT_BUFFER_ULONG(
PULONG Port,
PULONG Buffer,
ULONG Count
);
// end_ntndis
//
// Get data cache fill size.
//
#define KeGetDcacheFillSize() 1L
// end_ntddk end_nthal
//
// Fill TB entry.
//
#define KeFillEntryTb(Pte, Virtual, Invalid) \
if (Invalid != FALSE) { \
Ke386InvalidateTb (Virtual); \
}
#if !defined(MIDL_PASS) && defined(_M_IX86) && !defined(_CROSS_PLATFORM_)
__inline
VOID
Ke386InvalidateTb (
IN PVOID Virtual
)
{
__asm {
mov eax, Virtual
invlpg [eax]
}
}
#endif
//
// 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_nthal begin_ntndis
#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation)
// end_ntddk end_nthal end_ntndis
//
// 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.
//
// begin_ntddk begin_ntifs
#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
#define ExAcquireSpinLock(Lock, OldIrql) KeAcquireSpinLock((Lock), (OldIrql))
#define ExReleaseSpinLock(Lock, OldIrql) KeReleaseSpinLock((Lock), (OldIrql))
#define ExAcquireSpinLockAtDpcLevel(Lock) KeAcquireSpinLockAtDpcLevel(Lock)
#define ExReleaseSpinLockFromDpcLevel(Lock) KeReleaseSpinLockFromDpcLevel(Lock)
#endif
// end_ntddk end_ntifs
//
// 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
//
// Define query system time macro.
//
#define KiQuerySystemTime(CurrentTime) \
do { \
(CurrentTime)->HighPart = SharedUserData->SystemTime.High1Time; \
(CurrentTime)->LowPart = SharedUserData->SystemTime.LowPart; \
} while ((CurrentTime)->HighPart != SharedUserData->SystemTime.High2Time)
//
// Define query tick count macro.
//
// begin_ntddk begin_nthal
#if defined(_NTDRIVER_) || defined(_NTDDK_) || defined(_NTIFS_)
#define KeQueryTickCount(CurrentCount ) { \
PKSYSTEM_TIME _TickCount = *((PKSYSTEM_TIME *)(&KeTickCount)); \
do { \
(CurrentCount)->HighPart = _TickCount->High1Time; \
(CurrentCount)->LowPart = _TickCount->LowPart; \
} while ((CurrentCount)->HighPart != _TickCount->High2Time); \
}
#else
#define KiQueryTickCount(CurrentCount) \
do { \
(CurrentCount)->HighPart = KeTickCount.High1Time; \
(CurrentCount)->LowPart = KeTickCount.LowPart; \
} while ((CurrentCount)->HighPart != KeTickCount.High2Time)
VOID
KeQueryTickCount (
OUT PLARGE_INTEGER CurrentCount
);
#endif
// end_ntddk end_nthal
#define KiQueryLowTickCount() KeTickCount.LowPart
//
// Define query interrupt time macro.
//
#define KiQueryInterruptTime(CurrentTime) \
do { \
(CurrentTime)->HighPart = SharedUserData->InterruptTime.High1Time; \
(CurrentTime)->LowPart = SharedUserData->InterruptTime.LowPart; \
} while ((CurrentTime)->HighPart != SharedUserData->InterruptTime.High2Time)
// begin_nthal
//
// 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 {
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;
//
// 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 NotUsed2[9];
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) + 1) : \
(USHORT)(FIELD_OFFSET(KTSS, IoMaps[MapNumber-1].IoMap))
// begin_windbgkd
#ifdef _X86_
//
// Special Registers for i386
//
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
// End of the architecturally defined section of the PRCB.
// end_nthal
struct _KTHREAD *NpxThread;
ULONG InterruptCount; // per precessor counts
ULONG KernelTime;
ULONG UserTime;
ULONG DpcTime;
ULONG InterruptTime;
ULONG ApcBypassCount;
ULONG DpcBypassCount;
ULONG AdjustDpcThreshold;
ULONG Spare2[5];
ULONG ThreadStartCount[2]; // perf data
// MP tuning..
//
// Per-processor data for various hot code which resides in the
// kernel image. We give each processor it's own copy of the data
// to lessen the caching impact of sharing the data between multiple
// processors.
//
//
// File system runtime variables.
//
SINGLE_LIST_ENTRY FsRtlFreeSharedLockList;
SINGLE_LIST_ENTRY FsRtlFreeExclusiveLockList;
//
// 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;
//
// More filesystem runtime
//
SINGLE_LIST_ENTRY FsRtlFreeWaitingLockList;
SINGLE_LIST_ENTRY FsRtlFreeLockTreeNodeList;
//
// Reserved for future counters.
//
ULONG ReservedCounter[6];
//
// I/O system per processor single entry lookaside lists.
//
PVOID SmallIrpFreeEntry;
PVOID LargeIrpFreeEntry;
PVOID MdlFreeEntry;
//
// Object manager per processor single entry lookaside lists.
//
PVOID CreateInfoFreeEntry;
PVOID NameBufferFreeEntry;
//
// Cache manager per processor single entry lookaside lists.
//
PVOID SharedCacheMapEntry;
//
// Cache pad.
//
ULONG CachePad0[2];
//
// Reserved pad.
//
ULONG ReservedPad[16 * 8];
//
// MP interprocessor request packet and summary.
//
// N.B. This is carefully aligned to be on a cache line boundary.
//
volatile PVOID CurrentPacket[3];
volatile KAFFINITY TargetSet;
volatile PKIPI_WORKER WorkerRoutine;
volatile ULONG IpiFrozen;
ULONG CachePad1[2];
//
// MP interprocessor request summary and packet address.
//
volatile ULONG RequestSummary;
volatile struct _KPRCB *SignalDone;
volatile ULONG ReverseStall;
PVOID IpiFrame;
ULONG CachePad2[4];
//
// DPC interrupt requested.
//
ULONG DpcInterruptRequested;
ULONG CachePad3[3];
//
// DPC batching parameters.
//
ULONG MaximumDpcQueueDepth;
ULONG MinimumDpcRate;
ULONG CachePad4[2];
//
// DPC list head, spinlock, and count.
//
LIST_ENTRY DpcListHead;
ULONG DpcQueueDepth;
ULONG DpcRoutineActive;
ULONG DpcCount;
ULONG DpcLastCount;
ULONG DpcRequestRate;
ULONG KernelReserved2[11];
KSPIN_LOCK DpcLock;
//
// Debug & processor information
//
BOOLEAN SkipTick;
UCHAR VendorString[13];
ULONG MHz;
ULONG FeatureBits;
LARGE_INTEGER UpdateSignature;
//
// QuantumEnd indicator
//
ULONG QuantumEnd;
// begin_nthal
} KPRCB, *PKPRCB, *RESTRICTED_POINTER PRKPRCB;
// 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 _KPCR *SelfPcr; // flat address of this PCR
struct _KPRCB *Prcb; // pointer to Prcb
KIRQL Irql;
ULONG IRR;
ULONG IrrActive;
ULONG IDR;
ULONG Reserved2;
struct _KIDTENTRY *IDT;
struct _KGDTENTRY *GDT;
struct _KTSS *TSS;
USHORT MajorVersion;
USHORT MinorVersion;
KAFFINITY SetMember;
ULONG StallScaleFactor;
UCHAR DebugActive;
UCHAR Number;
// end_ntddk
UCHAR VdmAlert;
UCHAR Reserved[1]; // dword align
ULONG KernelReserved[16]; // For use by the kernel
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
} KPCR;
typedef KPCR *PKPCR;
// end_nthal end_ntddk
//
// 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 EFLAGS_DF_MASK 0x00000400L
#define EFLAGS_INTERRUPT_MASK 0x00000200L
#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 0x001e0dd7L
#define SANITIZE_FLAGS(eFlags, mode) (\
((mode) == KernelMode ? \
((0x00000000L) | ((eFlags) & 0x001e0fd7)) : \
((((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) \
) \
)
//
// Nonvolatile context pointers
//
// BUGBUG 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 privledge transition
// was involved.
//
// In order to make NtContinue work for both user mode and kernel
// mode callers, we must force a cononical 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;
//
// BUGBUG shielint The second level vectors have not been defined.
//
// #define MAXIMUM_VECTOR 0x20 // Maximum Interrupt Vector
//
// 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;
//
// Varous 387 defines
//
#define I386_80387_NP_VECTOR 0x07 // trap 7 when hardware not present
//
// The non-volatile 387 state
//
typedef struct _KFLOATING_SAVE {
ULONG ControlWord;
ULONG StatusWord;
ULONG ErrorOffset;
ULONG ErrorSelector;
ULONG DataOffset;
ULONG DataSelector;
ULONG Cr0NpxState;
ULONG Spare1;
} KFLOATING_SAVE, *PKFLOATING_SAVE;
//
// 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_nthal begin_ntndis
//
// i386 Specific portions of mm component
//
//
// Define the page size for the Intel 386 as 4096 (0x1000).
//
#define PAGE_SIZE (ULONG)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
//
// The highest user address reserves 64K bytes for a guard
// page. This allows the probing of address from kernel mode to
// only have to check the starting address for strucutures of 64k bytes
// or less.
//
#define MM_HIGHEST_USER_ADDRESS (PVOID)0x7FFEFFFF // temp should be 0xBFFEFFFF
#define MM_USER_PROBE_ADDRESS 0x7FFF0000 // starting address of guard page
//
// The lowest user address reserves the low 64k.
//
#define MM_LOWEST_USER_ADDRESS (PVOID)0x00010000
//
// The lowest address for system space.
//
#define MM_LOWEST_SYSTEM_ADDRESS (PVOID)0xC0800000
#define MmGetProcedureAddress(Address) (Address)
#define MmLockPagableCodeSection(Address) MmLockPagableDataSection(Address)
// end_ntddk end_nthal
//
// 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 KI_USER_SHARED_DATA 0xffdf0000
#define KIP0PCRADDRESS 0xffdff000
#define SharedUserData ((KUSER_SHARED_DATA * const) KI_USER_SHARED_DATA)
// begin_ntddk
//
// 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 architecural
// equivalents.
//
#define ExInterlockedIncrementLong(Addend,Lock) \
Exfi386InterlockedIncrementLong(Addend)
#define ExInterlockedDecrementLong(Addend,Lock) \
Exfi386InterlockedDecrementLong(Addend)
#define ExInterlockedExchangeUlong(Target,Value,Lock) \
Exfi386InterlockedExchangeUlong(Target,Value)
#define ExInterlockedAddUlong ExfInterlockedAddUlong
#define ExInterlockedInsertHeadList ExfInterlockedInsertHeadList
#define ExInterlockedInsertTailList ExfInterlockedInsertTailList
#define ExInterlockedRemoveHeadList ExfInterlockedRemoveHeadList
#define ExInterlockedPopEntryList ExfInterlockedPopEntryList
#define ExInterlockedPushEntryList ExfInterlockedPushEntryList
//
// Prototypes for architecural 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
LARGE_INTEGER
ExInterlockedExchangeAddLargeInteger (
IN PLARGE_INTEGER Addend,
IN LARGE_INTEGER Increment,
IN PKSPIN_LOCK Lock
);
NTKERNELAPI
ULONG
FASTCALL
Exfi386InterlockedExchangeUlong (
IN PULONG Target,
IN ULONG Value
);
//
// Intrinsic interlocked functions
//
#if (defined(_NTDDK_) || defined(_NTIFS_) || defined(_NTHAL_) || defined(NO_INTERLOCKED_INTRINSICS)) && !defined(_WINBASE_)
LONG
FASTCALL
InterlockedIncrement(
IN PLONG Addend
);
LONG
FASTCALL
InterlockedDecrement(
IN PLONG Addend
);
LONG
FASTCALL
InterlockedExchange(
IN OUT PLONG Target,
IN LONG Value
);
LONG
FASTCALL
InterlockedExchangeAdd(
IN OUT PLONG Addend,
IN LONG Increment
);
PVOID
FASTCALL
InterlockedCompareExchange(
IN OUT PVOID *Destination,
IN PVOID ExChange,
IN PVOID Comperand
);
#endif
// end_ntddk end_nthal
//
// UP/MP versions of interlocked intrinsics for use within ntoskrnl.exe.
//
// N.B. FASTCALL does NOT work with inline functions.
//
#if !defined(_NTDDK_) && !defined(_NTIFS_) && !defined(_NTHAL_) && !defined(_WINBASE_)
#if !defined(MIDL_PASS) && defined(_M_IX86) && !defined(_CROSS_PLATFORM_)
#pragma warning(disable:4035) // re-enable below
#if !defined(NO_INTERLOCKED_INTRINSICS)
#if defined(NT_UP)
__inline
LONG
FASTCALL
InterlockedIncrement(
IN PLONG Addend
)
{
__asm {
mov eax, 1
mov ecx, Addend
xadd [ecx], eax
inc eax
}
}
__inline
LONG
FASTCALL
InterlockedDecrement(
IN PLONG Addend
)
{
__asm {
mov eax, -1
mov ecx, Addend
xadd [ecx], eax
dec eax
}
}
__inline
LONG
FASTCALL
InterlockedExchange(
IN OUT PLONG Target,
IN LONG Value
)
{
__asm {
mov edx, Value
mov ecx, Target
mov eax, [ecx]
ie: cmpxchg [ecx], edx
jnz short ie
}
}
__inline
LONG
FASTCALL
InterlockedExchangeAdd(
IN OUT PLONG Addend,
IN LONG Increment
)
{
__asm {
mov eax, Increment
mov ecx, Addend
xadd [ecx], eax
}
}
__inline
PVOID
FASTCALL
InterlockedCompareExchange(
IN OUT PVOID *Destination,
IN PVOID Exchange,
IN PVOID Comperand
)
{
__asm {
mov eax, Comperand
mov ecx, Destination
mov edx, Exchange
cmpxchg [ecx], edx
}
}
#else
__inline
LONG
FASTCALL
InterlockedIncrement(
IN PLONG Addend
)
{
__asm {
mov eax, 1
mov ecx, Addend
lock xadd [ecx], eax
inc eax
}
}
__inline
LONG
FASTCALL
InterlockedDecrement(
IN PLONG Addend
)
{
__asm {
mov eax, -1
mov ecx, Addend
lock xadd [ecx], eax
dec eax
}
}
__inline
LONG
FASTCALL
InterlockedExchange(
IN OUT PLONG Target,
IN LONG Value
)
{
__asm {
mov eax, Value
mov ecx, Target
xchg [ecx], eax
}
}
__inline
LONG
FASTCALL
InterlockedExchangeAdd(
IN OUT PLONG Addend,
IN LONG Increment
)
{
__asm {
mov eax, Increment
mov ecx, Addend
lock xadd [ecx], eax
}
}
__inline
PVOID
FASTCALL
InterlockedCompareExchange(
IN OUT PVOID *Destination,
IN PVOID Exchange,
IN PVOID Comperand
)
{
__asm {
mov eax, Comperand
mov ecx, Destination
mov edx, Exchange
lock cmpxchg [ecx], edx
}
}
#endif
#endif
#pragma warning(default:4035)
#endif
#endif
//
// 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
//
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
#if !defined(MIDL_PASS) && defined(_M_IX86)
//
// i386 function definitions
//
#pragma warning(disable:4035) // re-enable below
// end_ntddk
#if NT_UP
#define _PCR ds:[KIP0PCRADDRESS]
#else
#define _PCR fs:[0] // ntddk
#endif
//
// Get address of current processor block.
//
// WARNING: This inline macro can only be used by the kernel or hal
//
#define KiPcr() KeGetPcr()
__inline PKPCR KeGetPcr(VOID)
{
#if NT_UP
__asm { mov eax, KIP0PCRADDRESS }
#else
__asm { mov eax, _PCR KPCR.SelfPcr }
#endif
}
//
// Get address of current processor block.
//
// WARNING: This inline macro can only be used by the kernel or hal
//
__inline PKPRCB KeGetCurrentPrcb (VOID)
{
__asm { mov eax, _PCR KPCR.Prcb }
}
// begin_ntddk
//
// Get current IRQL.
//
// On x86 this function resides in the HAL
//
KIRQL
KeGetCurrentIrql();
//
// Get the current processor number
//
__inline ULONG KeGetCurrentProcessorNumber(VOID)
{
__asm { movzx eax, _PCR KPCR.Number }
}
// end_nthal end_ntddk
//
// 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
//
__inline struct _KTHREAD *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
//
__inline ULONG KeIsExecutingDpc(VOID)
{
__asm { mov eax, fs:[0] KPCR.PrcbData.DpcRoutineActive }
}
// begin_nthal begin_ntddk
#endif // !defined(MIDL_PASS) && defined(_M_IX86)
// end_nthal end_ntddk
//
// Get previous processor mode.
//
// WARNING: This inline macro can not be used for device drivers or hals
//
// KPROCESSOR_MODE
// KeGetPreviousMode();
#define KeGetPreviousMode() (KeGetCurrentThread()->PreviousMode)
// begin_nthal
//
// Macro to set address of a trap/interrupt handler to IDT
//
#define KiSetHandlerAddressToIDT(Vector, HandlerAddress) \
KeGetPcr()->IDT[Vector].ExtendedOffset = HIGHWORD(HandlerAddress); \
KeGetPcr()->IDT[Vector].Offset = LOWWORD(HandlerAddress);
//
// Macro to return address of a trap/interrupt handler in IDT
//
#define KiReturnHandlerAddressFromIDT(Vector) \
MAKEULONG(KiPcr()->IDT[Vector].ExtendedOffset, KiPcr()->IDT[Vector].Offset)
#pragma warning(default:4035)
// end_nthal
//++
//
// BOOLEAN
// KiIsThreadNumericStateSaved(
// IN PKTHREAD Address
// )
//
//--
#define KiIsThreadNumericStateSaved(a) \
(a->NpxState != NPX_STATE_LOADED)
//++
//
// VOID
// KiRundownThread(
// IN PKTHREAD Address
// )
//
//--
#define KiRundownThread(a) KiFlushNPXState()
//
// functions specific to 386 structure
//
VOID
KiSetIRR (
IN ULONG SWInterruptMask
);
VOID
KiInitializeGDT (
IN OUT PKGDTENTRY Gdt,
IN USHORT GdtLimit,
IN PKPCR Pcr,
IN USHORT PcrLimit,
IN PKTSS Tss,
IN USHORT TssLimit,
IN USHORT TebLimit
);
VOID
KiInitializeGdtEntry (
OUT PKGDTENTRY GdtEntry,
IN ULONG Base,
IN ULONG Limit,
IN USHORT Type,
IN USHORT Dpl,
IN USHORT Granularity
);
//
// Procedures to support frame manipulation
//
ULONG
KiEspFromTrapFrame(
IN PKTRAP_FRAME TrapFrame
);
VOID
KiEspToTrapFrame(
IN PKTRAP_FRAME TrapFrame,
IN ULONG Esp
);
ULONG
KiSegSsFromTrapFrame(
IN PKTRAP_FRAME TrapFrame
);
VOID
KiSegSsToTrapFrame(
IN PKTRAP_FRAME TrapFrame,
IN ULONG SegSs
);
//
// Define prototypes for i386 specific clock and profile interrupt routines.
//
VOID
KiUpdateRunTime (
VOID
);
VOID
KiUpdateSystemTime (
VOID
);
// begin_nthal
VOID
KeProfileInterrupt (
IN KIRQL OldIrql,
IN KTRAP_FRAME TrapFrame
);
NTKERNELAPI
VOID
KeProfileInterruptWithSource (
IN struct _KTRAP_FRAME *TrapFrame,
IN KPROFILE_SOURCE ProfileSource
);
VOID
KeUpdateRuntime (
IN KIRQL OldIrql,
IN KTRAP_FRAME TrapFrame
);
VOID
KeUpdateSystemTime (
IN KIRQL OldIrql,
IN KTRAP_FRAME TrapFrame
);
// begin_ntddk begin_ntndis
#endif // defined(_X86_)
// end_nthal end_ntddk end_ntndis
//
// i386 arch. specific kernel functions.
//
VOID
Ke386SetLdtProcess (
struct _KPROCESS *Process,
PLDT_ENTRY Ldt,
ULONG Limit
);
VOID
Ke386SetDescriptorProcess (
struct _KPROCESS *Process,
ULONG Offset,
LDT_ENTRY LdtEntry
);
VOID
Ke386GetGdtEntryThread (
struct _KTHREAD *Thread,
ULONG Offset,
PKGDTENTRY Descriptor
);
BOOLEAN
Ke386SetIoAccessMap (
ULONG MapNumber,
PKIO_ACCESS_MAP IoAccessMap
);
BOOLEAN
Ke386QueryIoAccessMap (
ULONG MapNumber,
PKIO_ACCESS_MAP IoAccessMap
);
BOOLEAN
Ke386IoSetAccessProcess (
struct _KPROCESS *Process,
ULONG MapNumber
);
VOID
Ke386SetIOPL(
struct _KPROCESS *Process
);
NTSTATUS
Ke386CallBios (
IN ULONG BiosCommand,
IN OUT PCONTEXT BiosArguments
);
VOID
KiEditIopmDpc (
IN struct _KDPC *Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
BOOLEAN
Ki386GetSelectorParameters(
IN USHORT Selector,
OUT PULONG Flags,
OUT PULONG Base,
OUT PULONG Limit
);
NTSTATUS
Ke386SetVdmInterruptHandler (
IN struct _KPROCESS *Process,
IN ULONG Interrupt,
IN USHORT Selector,
IN ULONG Offset,
IN BOOLEAN Gate32
);
//
// i386 ABIOS specific routines.
//
NTSTATUS
KeI386GetLid(
IN USHORT DeviceId,
IN USHORT RelativeLid,
IN BOOLEAN SharedLid,
IN struct _DRIVER_OBJECT *DeviceObject,
OUT PUSHORT LogicalId
);
NTSTATUS
KeI386ReleaseLid(
IN USHORT LogicalId,
IN struct _DRIVER_OBJECT *DeviceObject
);
NTSTATUS
KeI386AbiosCall(
IN USHORT LogicalId,
IN struct _DRIVER_OBJECT *DriverObject,
IN PUCHAR RequestBlock,
IN USHORT EntryPoint
);
//
// i386 misc routines
//
NTSTATUS
KeI386AllocateGdtSelectors(
OUT PUSHORT SelectorArray,
IN USHORT NumberOfSelectors
);
VOID
KeI386Call16BitFunction (
IN OUT PCONTEXT Regs
);
USHORT
KeI386Call16BitCStyleFunction (
IN ULONG EntryOffset,
IN ULONG EntrySelector,
IN PUCHAR Parameters,
IN ULONG Size
);
NTSTATUS
KeI386FlatToGdtSelector(
IN ULONG SelectorBase,
IN USHORT Length,
IN USHORT Selector
);
NTSTATUS
KeI386ReleaseGdtSelectors(
OUT PUSHORT SelectorArray,
IN USHORT NumberOfSelectors
);
NTSTATUS
KeI386SetGdtSelector (
ULONG Selector,
PKGDTENTRY GdtValue
);
VOID
KeOptimizeProcessorControlState (
VOID
);
NTSTATUS
KeSaveFloatingPointState (
OUT PKFLOATING_SAVE FloatSave
);
NTSTATUS
KeRestoreFloatingPointState (
IN PKFLOATING_SAVE FloatSave
);
//
// i386 Vdm specific functions
//
BOOLEAN
Ke386VdmInsertQueueApc (
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 PVOID SystemArgument1 OPTIONAL,
IN PVOID SystemArgument2 OPTIONAL,
IN KPRIORITY Increment
);
VOID
Ke386VdmClearApcObject (
IN PKAPC Apc
);
VOID
KeI386VdmInitialize (
VOID
);
//
// x86 functions for special instructions
//
VOID
CPUID (
ULONG InEax,
PULONG OutEax,
PULONG OutEbx,
PULONG OutEcx,
PULONG OutEdx
);
LONGLONG
RDTSC (
VOID
);
ULONGLONG
FASTCALL
RDMSR (
IN ULONG MsrRegister
);
VOID
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;
//
// 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 macro to test if x86 feature is present.
//
extern ULONG KiBootFeatureBits;
#define Isx86FeaturePresent(_f_) ((KiBootFeatureBits & (_f_)) != 0)
#endif // _i386_