Source code of Windows XP (NT5)
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.

294 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation. All Rights Reserved.
  3. Module Name:
  4. rtp.h
  5. Abstract:
  6. This header contains private internal realtime executive information.
  7. Author:
  8. Joseph Ballantyne
  9. Environment:
  10. Kernel Mode
  11. Revision History:
  12. --*/
  13. #define INSTRUCTIONCOUNT PERFORMANCECOUNTER1
  14. #define CYCLECOUNT PERFORMANCECOUNTER0
  15. //#define USERING1
  16. //#define NONMI 1
  17. // When USERING1 is defined, the realtime executive runs realtime threads with
  18. // a priviledge level of ring 1 rather than ring 0. This allows the executive to
  19. // trap when code in a realtime thread uses CLI/STI instructions. That allows the
  20. // realtime executive to syncronize that code with Windows code.
  21. // The real time executive stores eax on the
  22. // stack and then uses that space in eax to switch to a known valid
  23. // data segment.
  24. // Currently we ALWAYS use a maskable interrupt to take control from Windows.
  25. // We use a maskable interrupt to be nice to the OS and also to make
  26. // sure old debuggers like WDEB work properly.
  27. // The real time executive currently always runs the real time threads
  28. // with interrupts disabled, and uses a NMI interrupt to switch between
  29. // them.
  30. // We always use a private IDT for
  31. // the realtime executive and the realtime threads. We use them to catch
  32. // any faults, or exceptions before they get to the normal Windows
  33. // handlers. It is an error to generate any faults or exceptions inside
  34. // a real time thread.
  35. // Although we used to use the performance counters to generate both the maskable
  36. // and the non maskable interrupts, and we switched the perf counter
  37. // interrupt dynamically between generating an NMI, and generating a
  38. // maskable interrupt, we currently only use the local apic timer interrupt
  39. // to generate the maskable interrupt. We use the performance counters
  40. // to generate the NMI to switch between the real time threads.
  41. // This eliminates dual sources of maskable interrupts which was causing a
  42. // single rt thread to get more time than it should have.
  43. // One problem with using the performance counters to generate the maskable
  44. // interrupt was also that the maskable interrupt was not guaranteed to hit -
  45. // especially when vpowerd is doing idle detection and halting the cpu to
  46. // reduce power consumption. Unfortunately, I have not yet found a performance
  47. // counter that will count cycles or bus cycles regardless of the power state
  48. // of the processor. Not even simply when the processor is halted or in a light
  49. // power down state.
  50. //#define MASKABLEINTERRUPT 1
  51. // If MASKABLEINTERRUPT is defined, then we make the performance counters generate
  52. // a maskable interrupt! We do this so that we can quickly and surely guarantee
  53. // that all of the ntkern functions that are called by ks2 are realtime safe.
  54. // I will go fix those anyway, but to get ks2 up and running quickly, safely,
  55. // and stable, changing rt.sys to never use NMI is the easiest way to go.
  56. #define NMIIDTINDEX 2
  57. #define MASKABLEIDTINDEX 0x4c
  58. #define APICERRORIDTINDEX 0x4e
  59. #define APICSPURIOUSIDTINDEX 0x4f // This ABSOLUTELY MUST end in 0xf. Hardware forces that.
  60. #ifdef MASKABLEINTERRUPT
  61. #define RTMASKABLEIDTINDEX 0x20
  62. #define RTINTERRUPT (RTMASKABLEIDTINDEX)
  63. #else
  64. #define RTINTERRUPT (NMI|MASKABLEIDTINDEX)
  65. #endif
  66. #define TRANSFERCONTROLIDTINDEX MASKABLEIDTINDEX
  67. // EIPRETURNADDRESSOFFSET is the offset in DWORDS from the bottom of the
  68. // realtime thread's stack to the EIP DWORD of the IRET return address.
  69. #define EIPRETURNADDRESSOFFSET (1)
  70. // CSRETURNADDRESSOFFSET is the offset in DWORDS from the bottom of the
  71. // realtime thread's stack to the CS DWORD of the IRET return address.
  72. #define CSRETURNADDRESSOFFSET (2)
  73. // EFLAGSOFFSET is the offset in DWORDS from the bottom of the
  74. // realtime thread's stack to the EFLAGS DWORD.
  75. #define EFLAGSOFFSET (3)
  76. // RTPTRANSFERCONTROLEFLAGSOFFSET is the offset in DWORDS from the bottom of the
  77. // realtime thread's stack to the EFLAGS DWORD that is pushed in the
  78. // RtpTransferControl routine before doing a CLI and eventually transfering control
  79. // to the realtime executive.
  80. #define RTPTRANSFERCONTROLEFLAGSOFFSET (1+EFLAGSOFFSET)
  81. // IF is the bit in the eflags register that is set and cleared to enable
  82. // and disable maskable interrupts.
  83. #define IF 0x200
  84. // This is the starting address of the WDM driver address space on Win9x. All
  85. // preemtible WDM drivers are loaded into memory with virtual memory addresses
  86. // equal to or larger than this address.
  87. // We use this to check on Win9x if we are being called from a WDM driver or a
  88. // VXD. We do not support calling realtime functions from VXDs - so we check
  89. // where we are called from and fail the call if it is not from WDM address
  90. // space.
  91. // On Windows NT, we allow any drivers to call our functions and so do not
  92. // make this check. It would not work anyway, since the driver address space
  93. // does not start in the same place anyway.
  94. #ifndef UNDER_NT
  95. #define WDMADDRESSSPACE 0xff000000
  96. #endif
  97. #define RT_LOG_ENTRY_SIZE 16
  98. // This structure is the header to the realtime log.
  99. typedef struct {
  100. PCHAR Buffer;
  101. ULONG BufferSize;
  102. ULONG WriteLocation;
  103. } RTLOGHEADER, *PRTLOGHEADER;
  104. extern PRTLOGHEADER RtLog;
  105. // RtExecCS is the real time executive code segment.
  106. extern WORD RtExecCS;
  107. extern WORD RealTimeDS;
  108. extern WORD RealTimeSS;
  109. extern WORD RtExecTSS;
  110. // These are globals with information about the processor we are running on.
  111. extern ULONG CPUArchitecture;
  112. extern ULONG CPUManufacturer;
  113. extern LONG CPUFamily;
  114. extern LONG CPUModel;
  115. extern LONG CPUStepping;
  116. extern ULONGLONG CPUFeatures;
  117. // This global counts the number of times we have switched realtime threads since
  118. // the machine was booted. Note that this value is not cleared to zero if the
  119. // machine is hibernated.
  120. extern ULONGLONG threadswitchcount;
  121. // This global points to the system irql level.
  122. extern PKIRQL pCurrentIrql;
  123. // Various prototypes of internally used functions.
  124. BOOL
  125. SetupRealTimeThreads (
  126. VOID
  127. );
  128. VOID
  129. SetTimeLimit (
  130. LONG cycles,
  131. LONG instructions
  132. );
  133. __inline
  134. ULONG
  135. RtpCompareExchange (
  136. ULONG *destination,
  137. ULONG source,
  138. ULONG value
  139. );
  140. ULONGLONG
  141. __cdecl
  142. RtCompareExchange8 (
  143. ULONGLONG *destination,
  144. ULONGLONG source,
  145. ULONGLONG value
  146. );
  147. NTSTATUS
  148. RtpCalibrateCpuClock (
  149. ULONG *cyclesperusec
  150. );
  151. BOOL
  152. RtpTransferControl (
  153. WORD State,
  154. ULONG Data,
  155. BOOL (*DoTransfer)(PVOID),
  156. PVOID Context
  157. );
  158. VOID
  159. RtpForceAtomic (
  160. VOID (*AtomicOperation)(PVOID),
  161. PVOID Context
  162. );
  163. VOID
  164. FASTCALL
  165. RtKfAcquireLock (
  166. IN PKSPIN_LOCK SpinLock
  167. );
  168. VOID
  169. FASTCALL
  170. RtKfReleaseLock (
  171. IN PKSPIN_LOCK SpinLock
  172. );
  173. KIRQL
  174. FASTCALL
  175. RtKfAcquireSpinLock (
  176. IN PKSPIN_LOCK SpinLock
  177. );
  178. VOID
  179. FASTCALL
  180. RtKfReleaseSpinLock (
  181. IN PKSPIN_LOCK SpinLock,
  182. IN KIRQL NewIrql
  183. );
  184. #define RtpSimulateRtInterrupt() \
  185. __asm int TRANSFERCONTROLIDTINDEX