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.

317 lines
8.3 KiB

  1. title "Stall Execution Support"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; ixstall.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to field and process the
  13. ; interval clock interrupt.
  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. ;
  27. ; Add KiSetProfileInterval, KiStartProfileInterrupt,
  28. ; KiStopProfileInterrupt procedures.
  29. ; KiProfileInterrupt ISR.
  30. ; KiProfileList, KiProfileLock are delcared here.
  31. ;
  32. ; shielint 10-Dec-90
  33. ; Add performance counter support.
  34. ; Move system clock to irq8, ie we now use RTC to generate system
  35. ; clock. Performance count and Profile use timer 1 counter 0.
  36. ; The interval of the irq0 interrupt can be changed by
  37. ; KiSetProfileInterval. Performance counter does not care about the
  38. ; interval of the interrupt as long as it knows the rollover count.
  39. ; Note: Currently I implemented 1 performance counter for the whole
  40. ; i386 NT.
  41. ;
  42. ; John Vert (jvert) 11-Jul-1991
  43. ; Moved from ke\i386 to hal\i386. Removed non-HAL stuff
  44. ;
  45. ; shie-lin tzong (shielint) 13-March-92
  46. ; Move System clock back to irq0 and use RTC (irq8) to generate
  47. ; profile interrupt. Performance counter and system clock use time1
  48. ; counter 0 of 8254.
  49. ;
  50. ; Landy Wang (corollary!landy) 04-Dec-92
  51. ; Created this module by moving routines from ixclock.asm to here.
  52. ;
  53. ;--
  54. .386p
  55. .xlist
  56. include hal386.inc
  57. include callconv.inc ; calling convention macros
  58. include i386\ix8259.inc
  59. include i386\kimacro.inc
  60. include mac386.inc
  61. include i386\ixcmos.inc
  62. include xxacpi.h
  63. .list
  64. EXTRNP _KeBugCheckEx,5,IMPORT
  65. EXTRNP _DbgBreakPoint,0,IMPORT
  66. EXTRNP _HalpAcquireCmosSpinLock ,0
  67. EXTRNP _HalpReleaseCmosSpinLock ,0
  68. extrn _HalpFixedAcpiDescTable:DWORD
  69. extrn _QueryTimer:DWORD
  70. extrn _PMTimerFreq:DWORD
  71. _DATA SEGMENT DWORD PUBLIC 'DATA'
  72. MinimumLoopQuantum equ 42
  73. MinimumLoopCount dd MinimumLoopQuantum
  74. KqpcStallCount db 0
  75. ; temptemp
  76. if DBG
  77. HalpAcpiStallIns dd 0
  78. endif
  79. _DATA ends
  80. INIT SEGMENT PARA PUBLIC 'CODE'
  81. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  82. page ,132
  83. subttl "Initialize Stall Execution Counter"
  84. ;++
  85. ;
  86. ; VOID
  87. ; HalpInitializeStallExecution (
  88. ; IN CCHAR ProcessorNumber
  89. ; )
  90. ;
  91. ; Routine Description:
  92. ;
  93. ; This routine is obsolete in this HAL.
  94. ;
  95. ; Arguments:
  96. ;
  97. ; ProcessorNumber - Processor Number
  98. ;
  99. ; Return Value:
  100. ;
  101. ; None.
  102. ;
  103. ;--
  104. cPublicProc _HalpInitializeStallExecution ,1
  105. stdRET _HalpInitializeStallExecution
  106. stdENDP _HalpInitializeStallExecution
  107. page ,132
  108. subttl "Stall Execution"
  109. cPublicProc _HalpRemoveFences
  110. mov word ptr fence1, 0c98bh
  111. stdRET _HalpRemoveFences
  112. stdENDP _HalpRemoveFences
  113. INIT ends
  114. _TEXT SEGMENT PARA PUBLIC 'CODE'
  115. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  116. ;++
  117. ;
  118. ; VOID
  119. ; HalpAcpiTimerStallExecProc(
  120. ; IN ULONG MicroSeconds
  121. ; )
  122. ;
  123. ; Routine Description:
  124. ;
  125. ; This function stalls execution for the specified number of microseconds.
  126. ; KeStallExecutionProcessor
  127. ;
  128. ; Arguments:
  129. ;
  130. ; MicroSeconds - Supplies the number of microseconds that execution is to be
  131. ; stalled.
  132. ;
  133. ; Return Value:
  134. ;
  135. ; None.
  136. ;
  137. ; Comments:
  138. ;
  139. ; edi - total ticks elapsed
  140. ; ebx:esi - starting time, in ticks
  141. ;
  142. ;--
  143. Target equ [ebp + 8]
  144. cyclesStalled equ [ebp - 4]
  145. MASK24 equ 0ff000000h
  146. BIT24 equ 001000000h
  147. cPublicProc _HalpAcpiTimerStallExecProc ,1
  148. cPublicFpo 1, 5
  149. ;
  150. ; Issue a CPUID to implement a "fence"
  151. ;
  152. push ebp
  153. mov ebp, esp
  154. sub esp, 4 ; make room for locals
  155. push ebx ; cpuid uses eax, ebx, ecx, edx
  156. push esi
  157. push edi
  158. xor eax, eax ; Processor zero
  159. .586p
  160. fence1: cpuid
  161. .386p
  162. xor edi, edi ; zero total stall count
  163. mov eax, Target
  164. or eax, eax
  165. jz aese10 ; return if no loop needed
  166. ; 'Target' starts out as the argument of the function.
  167. ; It is in uSeconds. We convert to timer ticks.
  168. mov ebx, _PMTimerFreq
  169. mul ebx
  170. mov ebx, 1000000
  171. div ebx
  172. sub eax, 1 ; fudge factor
  173. mov Target, eax
  174. mov eax, _QueryTimer ; move current counter into edx:eax
  175. call eax
  176. mov esi, eax ; record the starting tick count
  177. mov ebx, edx
  178. if DBG
  179. inc HalpAcpiStallIns
  180. endif
  181. mov cyclesStalled, 0
  182. mov eax, MinimumLoopCount
  183. AcpiLoop:
  184. add cyclesStalled, eax ; update total cycles stalled
  185. ALIGN 16
  186. YIELD
  187. jmp short aese05
  188. ALIGN 16
  189. YIELD
  190. aese05: sub eax, 1 ; (eax) = (eax) - 1
  191. jnz short aese05
  192. ;
  193. ; Now figure out if we have to loop again
  194. ;
  195. mov eax, _QueryTimer ; move current counter into edx:eax
  196. call eax
  197. sub eax, esi ; get actual elapsed ticks
  198. sbb edx, ebx ; check to see that the upper 32 bits agrees
  199. if 0
  200. jnl short @f
  201. int 3 ; time seems to have gone backwards
  202. @@:
  203. endif
  204. jz short aese06
  205. ;
  206. ; If the upper 32 bits doesn't agree, then something, perhaps the debugger,
  207. ; has caused time to slip a whole lot. Just fix up the bottom 32-bits to
  208. ; reflect a large time slip to make the math simpler.
  209. ;
  210. mov eax, 7fffffffh
  211. aese06:
  212. ; edx:eax now contains the number of timer ticks elapsed
  213. cmp eax, 3 ; if 1 less than 1uS elapsed, loop some more
  214. jge short aese09
  215. add MinimumLoopCount, MinimumLoopQuantum
  216. mov eax, MinimumLoopCount
  217. jmp short AcpiLoop ; loop some more
  218. aese09: mov edi, eax ; edi <- total number of ticks elapsed
  219. if DBG
  220. or edi, edi ; if the total elapsed ticks is still 0,
  221. jz short aese20 ; the timer hardware is broken. Bugcheck.
  222. endif
  223. ; if we have waited long enough, quit
  224. cmp edi, Target
  225. jge short aese10
  226. ; calculate remaining wait
  227. push ebx
  228. mov ebx, Target
  229. sub ebx, edi ; ebx <- remaining ticks
  230. mov eax, cyclesStalled
  231. mul ebx ; multiply by number of ticks remaining to wait
  232. and edx, 011b ; chop edx so that we don't overflow
  233. div edi ; divide by the number of ticks we have waited
  234. inc eax ; Never zero!
  235. pop ebx
  236. @@: jmp AcpiLoop
  237. aese10:
  238. ;
  239. ; Knock down MinimumLoopCount once every 0x100 calls to this
  240. ; function so that we don't accidentally stall for very
  241. ; large amounts of time.
  242. ;
  243. inc KqpcStallCount
  244. .if ((KqpcStallCount == 0) && (MinimumLoopCount > MinimumLoopQuantum))
  245. mov eax, MinimumLoopCount
  246. sub eax, MinimumLoopQuantum
  247. mov MinimumLoopCount, eax
  248. .endif
  249. pop edi
  250. pop esi
  251. pop ebx
  252. mov esp, ebp
  253. pop ebp
  254. stdRET _HalpAcpiTimerStallExecProc
  255. if DBG
  256. aese20:
  257. mov eax, 0a5h
  258. mov ebx, 020000h
  259. xor esi, esi
  260. xor edi, edi
  261. stdCall _KeBugCheckEx, <eax, ebx, edx, esi, edi>
  262. jmp short aese10
  263. endif
  264. stdENDP _HalpAcpiTimerStallExecProc
  265. _TEXT ends
  266. end