|
|
/*++
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
|