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.

331 lines
7.7 KiB

  1. title "Query Performace Counter"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; mpclksup.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to do
  13. ; QueryPerformaceCounter the MPS way.
  14. ;
  15. ; Author:
  16. ;
  17. ; Shie-Lin Tzong (shielint) 12-Jan-1990
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Revision History:
  24. ;
  25. ; bryanwi 20-Sep-90
  26. ; jakeo 12-16-97 -- moved code from mpprofil.asm
  27. ;
  28. ;--
  29. .586p
  30. .xlist
  31. include hal386.inc
  32. include callconv.inc ; calling convention macros
  33. include i386\kimacro.inc
  34. include mac386.inc
  35. include apic.inc
  36. include ntapic.inc
  37. include i386\mp8254.inc
  38. .list
  39. EXTRNP _HalpAcquireSystemHardwareSpinLock,0
  40. EXTRNP _HalpReleaseSystemHardwareSpinLock,0
  41. extrn _HalpUse8254:BYTE
  42. _DATA SEGMENT DWORD PUBLIC 'DATA'
  43. ALIGN dword
  44. ;
  45. ; counters for the performance counter
  46. ;
  47. public _HalpPerfCounterLow, _HalpPerfCounterHigh
  48. public _HalpLastPerfCounterLow, _HalpLastPerfCounterHigh
  49. _HalpPerfCounterLow dd 0
  50. _HalpPerfCounterHigh dd 0
  51. _HalpLastPerfCounterLow dd 0
  52. _HalpLastPerfCounterHigh dd 0
  53. _DATA ends
  54. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  55. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  56. page ,132
  57. subttl "Query Performance Counter"
  58. ;++
  59. ;
  60. ; LARGE_INTEGER
  61. ; KeQueryPerformanceCounter (
  62. ; OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
  63. ; )
  64. ;
  65. ; Routine Description:
  66. ;
  67. ; This routine returns current 64-bit performance counter and,
  68. ; optionally, the Performance Frequency.
  69. ;
  70. ; Note this routine can NOT be called at Profiling interrupt
  71. ; service routine. Because this routine depends on IRR0 to determine
  72. ; the actual count.
  73. ;
  74. ; Also note that the performace counter returned by this routine
  75. ; is not necessary the value when this routine is just entered.
  76. ; The value returned is actually the counter value at any point
  77. ; between the routine is entered and is exited.
  78. ;
  79. ; Arguments:
  80. ;
  81. ; PerformanceFrequency [TOS+4] - optionally, supplies the address
  82. ; of a variable to receive the performance counter frequency.
  83. ;
  84. ; Return Value:
  85. ;
  86. ; Current value of the performance counter will be returned.
  87. ;
  88. ;--
  89. ;
  90. ; Parameter definitions
  91. ;
  92. KqpcFrequency EQU [esp+4] ; User supplied Performance Frequence
  93. ifdef MMTIMER
  94. cPublicProc _HalpAcpiTimerQueryPerfCount ,1
  95. else
  96. cPublicProc _KeQueryPerformanceCounter ,1
  97. endif
  98. mov al, _HalpUse8254
  99. or al, al
  100. jnz short KqpcUse8254
  101. KqpcUseTSC:
  102. ; use time stamp counter as performance counter
  103. mov ecx, KqpcFrequency
  104. or ecx, ecx
  105. jz short kpc10
  106. mov eax, PCR[PcHal.TSCHz]
  107. mov dword ptr [ecx], eax
  108. mov dword ptr [ecx+4], 0
  109. kpc10:
  110. rdtsc
  111. add eax, PCR[PcHal.PerfCounterLow]
  112. adc edx, PCR[PcHal.PerfCounterHigh]
  113. ifdef MMTIMER
  114. stdRET _HalpAcpiTimerQueryPerfCount
  115. else
  116. stdRET _KeQueryPerformanceCounter
  117. endif
  118. KqpcUse8254:
  119. ; use 8254 as time base for performance counters
  120. mov ecx, KqpcFrequency
  121. or ecx, ecx
  122. jz short Kqpc10
  123. mov dword ptr [ecx], PERFORMANCE_FREQUENCY
  124. mov dword ptr [ecx+4], 0
  125. xor ecx, ecx
  126. Kqpc10:
  127. test al, PERF_8254_INITIALIZED
  128. jz KqpcNoInit
  129. stdCall _HalpAcquireSystemHardwareSpinLock ; intr disabled
  130. ; Read current offset from 8254 counter 0
  131. ; Counter Latch PIT Ctr 0 command
  132. mov al, COMMAND_8254_LATCH_READ+COMMAND_8254_COUNTER0
  133. out TIMER1_CONTROL_PORT0, al
  134. IODelay
  135. in al, TIMER1_DATA_PORT0 ; Read 8254 Ctr 0, LSByte.
  136. IODelay
  137. movzx edx,al ; Zero upper bytes of (EDX).
  138. in al, TIMER1_DATA_PORT0 ; Read 8254 Ctr 0, MSByte.
  139. mov dh, al ; (DX) = 8254 Ctr 0 count.
  140. neg edx ; PIT counts down, calculate interval
  141. add edx, PERFORMANCE_INTERVAL
  142. ; (edx) = offset value from most recent base value in
  143. ; _HalpPerfCounterHigh:_HalpPerfCounterLow
  144. mov eax, _HalpPerfCounterLow
  145. add eax, edx
  146. mov edx, _HalpPerfCounterHigh
  147. adc edx, ecx
  148. ; (edx:eax) = 64 bit counter value
  149. ;
  150. ; Check to see if the new value is sane - should be greater than
  151. ; the last counter value returned by KeQueryPerformanceCounter.
  152. ; Can happen only due to wrap around of the 8254. Correct by
  153. ; updating the performance counter base.
  154. cmp edx, _HalpLastPerfCounterHigh
  155. jg short KqpcContinue ; Current value > last returned value
  156. jl short KqpcCatchupPerfCounter ; Current value < last returned value
  157. ; high dwords equal, compare low dword
  158. cmp eax, _HalpLastPerfCounterLow
  159. jg short KqpcContinue ; Current value > last returned value
  160. KqpcCatchupPerfCounter:
  161. ; Current counter value is not greater than the previously returned
  162. ; counter value - can happen only due to the 8254 timer wraparound.
  163. ; Update base to account for wrap around.
  164. add eax, PERFORMANCE_INTERVAL
  165. adc edx, ecx
  166. add _HalpPerfCounterLow, PERFORMANCE_INTERVAL
  167. adc _HalpPerfCounterHigh, ecx
  168. KqpcContinue:
  169. mov _HalpLastPerfCounterLow, eax
  170. mov _HalpLastPerfCounterHigh, edx
  171. stdCall _HalpReleaseSystemHardwareSpinLock
  172. ifdef MMTIMER
  173. stdRET _HalpAcpiTimerQueryPerfCount
  174. else
  175. stdRET _KeQueryPerformanceCounter
  176. endif
  177. KqpcNoInit:
  178. ; 8254 is not yet initialized. Just return 0 for now
  179. xor eax, eax
  180. xor edx, edx
  181. ifdef MMTIMER
  182. stdRET _HalpAcpiTimerQueryPerfCount
  183. stdENDP _HalpAcpiTimerQueryPerfCount
  184. else
  185. stdRET _KeQueryPerformanceCounter
  186. stdENDP _KeQueryPerformanceCounter
  187. endif
  188. page ,132
  189. subttl "Stall Execution"
  190. ;++
  191. ;
  192. ; VOID
  193. ; KeStallExecutionProcessor (
  194. ; IN ULONG MicroSeconds
  195. ; )
  196. ;
  197. ; Routine Description:
  198. ;
  199. ; This function stalls execution for the specified number of microseconds.
  200. ; KeStallExecutionProcessor
  201. ;
  202. ; Arguments:
  203. ;
  204. ; MicroSeconds - Supplies the number of microseconds that execution is to be
  205. ; stalled.
  206. ;
  207. ; Return Value:
  208. ;
  209. ; None.
  210. ;
  211. ;--
  212. MicroSeconds equ [esp + 12]
  213. ifdef MMTIMER
  214. cPublicProc _HalpAcpiTimerStallExecProc ,1
  215. else
  216. cPublicProc _KeStallExecutionProcessor ,1
  217. endif
  218. cPublicFpo 1,2
  219. push ebx
  220. push edi
  221. ;
  222. ; Issue a CPUID to implement a "fence"
  223. ;
  224. xor eax, eax
  225. fence1: cpuid
  226. ;
  227. ; Get current TSC
  228. ;
  229. rdtsc
  230. mov ebx, eax
  231. mov edi, edx
  232. ;
  233. ; Determine ending TSC
  234. ;
  235. mov ecx, MicroSeconds ; (ecx) = Microseconds
  236. mov eax, PCR[PcStallScaleFactor] ; get per microsecond
  237. mul ecx
  238. add ebx, eax
  239. adc edi, edx
  240. ;
  241. ; Wait for ending TSC
  242. ;
  243. kese10: rdtsc
  244. cmp edi, edx
  245. ja short kese10
  246. jc short kese20
  247. cmp ebx, eax
  248. ja short kese10
  249. kese20: pop edi
  250. pop ebx
  251. ifdef MMTIMER
  252. stdRET _HalpAcpiTimerStallExecProc
  253. stdENDP _HalpAcpiTimerStallExecProc
  254. else
  255. stdRET _KeStallExecutionProcessor
  256. stdENDP _KeStallExecutionProcessor
  257. endif
  258. _TEXT ends
  259. INIT SEGMENT DWORD PUBLIC 'CODE'
  260. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  261. cPublicProc _HalpRemoveFences
  262. mov word ptr fence1, 0c98bh
  263. stdRET _HalpRemoveFences
  264. stdENDP _HalpRemoveFences
  265. INIT ends
  266. end