/*++ Copyright (c) 1999-2001 Microsoft Corporation. All Rights Reserved. Module Name: rtp.h Abstract: This header contains private internal realtime executive information. Author: Joseph Ballantyne Environment: Kernel Mode Revision History: --*/ #define INSTRUCTIONCOUNT PERFORMANCECOUNTER1 #define CYCLECOUNT PERFORMANCECOUNTER0 //#define USERING1 //#define NONMI 1 // When USERING1 is defined, the realtime executive runs realtime threads with // a priviledge level of ring 1 rather than ring 0. This allows the executive to // trap when code in a realtime thread uses CLI/STI instructions. That allows the // realtime executive to syncronize that code with Windows code. // The real time executive stores eax on the // stack and then uses that space in eax to switch to a known valid // data segment. // Currently we ALWAYS use a maskable interrupt to take control from Windows. // We use a maskable interrupt to be nice to the OS and also to make // sure old debuggers like WDEB work properly. // The real time executive currently always runs the real time threads // with interrupts disabled, and uses a NMI interrupt to switch between // them. // We always use a private IDT for // the realtime executive and the realtime threads. We use them to catch // any faults, or exceptions before they get to the normal Windows // handlers. It is an error to generate any faults or exceptions inside // a real time thread. // Although we used to use the performance counters to generate both the maskable // and the non maskable interrupts, and we switched the perf counter // interrupt dynamically between generating an NMI, and generating a // maskable interrupt, we currently only use the local apic timer interrupt // to generate the maskable interrupt. We use the performance counters // to generate the NMI to switch between the real time threads. // This eliminates dual sources of maskable interrupts which was causing a // single rt thread to get more time than it should have. // One problem with using the performance counters to generate the maskable // interrupt was also that the maskable interrupt was not guaranteed to hit - // especially when vpowerd is doing idle detection and halting the cpu to // reduce power consumption. Unfortunately, I have not yet found a performance // counter that will count cycles or bus cycles regardless of the power state // of the processor. Not even simply when the processor is halted or in a light // power down state. //#define MASKABLEINTERRUPT 1 // If MASKABLEINTERRUPT is defined, then we make the performance counters generate // a maskable interrupt! We do this so that we can quickly and surely guarantee // that all of the ntkern functions that are called by ks2 are realtime safe. // I will go fix those anyway, but to get ks2 up and running quickly, safely, // and stable, changing rt.sys to never use NMI is the easiest way to go. #define NMIIDTINDEX 2 #define MASKABLEIDTINDEX 0x4c #define APICERRORIDTINDEX 0x4e #define APICSPURIOUSIDTINDEX 0x4f // This ABSOLUTELY MUST end in 0xf. Hardware forces that. #ifdef MASKABLEINTERRUPT #define RTMASKABLEIDTINDEX 0x20 #define RTINTERRUPT (RTMASKABLEIDTINDEX) #else #define RTINTERRUPT (NMI|MASKABLEIDTINDEX) #endif #define TRANSFERCONTROLIDTINDEX MASKABLEIDTINDEX // EIPRETURNADDRESSOFFSET is the offset in DWORDS from the bottom of the // realtime thread's stack to the EIP DWORD of the IRET return address. #define EIPRETURNADDRESSOFFSET (1) // CSRETURNADDRESSOFFSET is the offset in DWORDS from the bottom of the // realtime thread's stack to the CS DWORD of the IRET return address. #define CSRETURNADDRESSOFFSET (2) // EFLAGSOFFSET is the offset in DWORDS from the bottom of the // realtime thread's stack to the EFLAGS DWORD. #define EFLAGSOFFSET (3) // RTPTRANSFERCONTROLEFLAGSOFFSET is the offset in DWORDS from the bottom of the // realtime thread's stack to the EFLAGS DWORD that is pushed in the // RtpTransferControl routine before doing a CLI and eventually transfering control // to the realtime executive. #define RTPTRANSFERCONTROLEFLAGSOFFSET (1+EFLAGSOFFSET) // IF is the bit in the eflags register that is set and cleared to enable // and disable maskable interrupts. #define IF 0x200 // This is the starting address of the WDM driver address space on Win9x. All // preemtible WDM drivers are loaded into memory with virtual memory addresses // equal to or larger than this address. // We use this to check on Win9x if we are being called from a WDM driver or a // VXD. We do not support calling realtime functions from VXDs - so we check // where we are called from and fail the call if it is not from WDM address // space. // On Windows NT, we allow any drivers to call our functions and so do not // make this check. It would not work anyway, since the driver address space // does not start in the same place anyway. #ifndef UNDER_NT #define WDMADDRESSSPACE 0xff000000 #endif #define RT_LOG_ENTRY_SIZE 16 // This structure is the header to the realtime log. typedef struct { PCHAR Buffer; ULONG BufferSize; ULONG WriteLocation; } RTLOGHEADER, *PRTLOGHEADER; extern PRTLOGHEADER RtLog; // RtExecCS is the real time executive code segment. extern WORD RtExecCS; extern WORD RealTimeDS; extern WORD RealTimeSS; extern WORD RtExecTSS; // These are globals with information about the processor we are running on. extern ULONG CPUArchitecture; extern ULONG CPUManufacturer; extern LONG CPUFamily; extern LONG CPUModel; extern LONG CPUStepping; extern ULONGLONG CPUFeatures; // This global counts the number of times we have switched realtime threads since // the machine was booted. Note that this value is not cleared to zero if the // machine is hibernated. extern ULONGLONG threadswitchcount; // This global points to the system irql level. extern PKIRQL pCurrentIrql; // Various prototypes of internally used functions. BOOL SetupRealTimeThreads ( VOID ); VOID SetTimeLimit ( LONG cycles, LONG instructions ); __inline ULONG RtpCompareExchange ( ULONG *destination, ULONG source, ULONG value ); ULONGLONG __cdecl RtCompareExchange8 ( ULONGLONG *destination, ULONGLONG source, ULONGLONG value ); NTSTATUS RtpCalibrateCpuClock ( ULONG *cyclesperusec ); BOOL RtpTransferControl ( WORD State, ULONG Data, BOOL (*DoTransfer)(PVOID), PVOID Context ); VOID RtpForceAtomic ( VOID (*AtomicOperation)(PVOID), PVOID Context ); VOID FASTCALL RtKfAcquireLock ( IN PKSPIN_LOCK SpinLock ); VOID FASTCALL RtKfReleaseLock ( IN PKSPIN_LOCK SpinLock ); KIRQL FASTCALL RtKfAcquireSpinLock ( IN PKSPIN_LOCK SpinLock ); VOID FASTCALL RtKfReleaseSpinLock ( IN PKSPIN_LOCK SpinLock, IN KIRQL NewIrql ); #define RtpSimulateRtInterrupt() \ __asm int TRANSFERCONTROLIDTINDEX