Leaked source code of windows server 2003
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.

429 lines
12 KiB

  1. title "Interval Clock Interrupt"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; ixprofile.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to initialize,
  13. ; field and process the profile 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 ([email protected]) 26-Mar-1992
  51. ; Move much code into separate modules for easy inclusion by various
  52. ; HAL builds.
  53. ;
  54. ; Add HalBeginSystemInterrupt() call at beginning of ProfileInterrupt
  55. ; code - this must be done before any sti.
  56. ; Also add HalpProfileInterrupt2ndEntry for additional processors to
  57. ; join the flow of things.
  58. ;
  59. ;--
  60. .386p
  61. .xlist
  62. include hal386.inc
  63. include callconv.inc ; calling convention macros
  64. include i386\kimacro.inc
  65. include mac386.inc
  66. include i386\ix8259.inc
  67. include i386\ixcmos.inc
  68. .list
  69. EXTRNP _DbgBreakPoint,0,IMPORT
  70. EXTRNP _KeProfileInterrupt,1,IMPORT
  71. EXTRNP Kei386EoiHelper,0,IMPORT
  72. EXTRNP _HalEndSystemInterrupt,2
  73. EXTRNP _HalBeginSystemInterrupt,3
  74. EXTRNP _HalpAcquireCmosSpinLock ,0
  75. EXTRNP _HalpReleaseCmosSpinLock ,0
  76. ;
  77. ; Constants used to initialize CMOS/Real Time Clock
  78. ;
  79. D_INT032 EQU 8E00h ; access word for 386 ring 0 interrupt gate
  80. _TEXT SEGMENT DWORD PUBLIC 'DATA'
  81. align 4
  82. ProfileIntervalTable dd 1221 ; unit = 100 ns
  83. dd 2441
  84. dd 4883
  85. dd 9766
  86. dd 19531
  87. dd 39063
  88. dd 78125
  89. dd 156250
  90. dd 312500
  91. dd 625000
  92. dd 1250000
  93. dd 2500000
  94. dd 5000000
  95. dd 5000000 OR 80000000H
  96. ProfileIntervalInitTable db 00100011B
  97. db 00100100B
  98. db 00100101B
  99. db 00100110B
  100. db 00100111B
  101. db 00101000B
  102. db 00101001B
  103. db 00101010B
  104. db 00101011B
  105. db 00101100B
  106. db 00101101B
  107. db 00101110B
  108. db 00101111B
  109. db 00101111B
  110. ;
  111. ; HALs wishing to reuse the code in this module should set the HAL
  112. ; global variable IxProfileVector to their profile vector.
  113. ;
  114. public _IxProfileVector
  115. _IxProfileVector dd PROFILE_VECTOR
  116. _TEXT ends
  117. _DATA SEGMENT DWORD PUBLIC 'DATA'
  118. RegisterAProfileValue db 00101000B ; default interval = 3.90625 ms
  119. ;
  120. ; The following array stores the per microsecond loop count for each
  121. ; central processor.
  122. ;
  123. HalpProfileInterval dd -1
  124. public _HalpProfilingStopped
  125. _HalpProfilingStopped dd 1
  126. _DATA ends
  127. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  128. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  129. ;++
  130. ;
  131. ; HalStartProfileInterrupt(
  132. ; IN ULONG Reserved
  133. ; );
  134. ;
  135. ; Routine Description:
  136. ;
  137. ; What we do here is change the interrupt
  138. ; rate from the slowest thing we can get away with to the value
  139. ; that's been KeSetProfileInterval
  140. ;
  141. ; All processors will run this routine, but it doesn't hurt to have
  142. ; each one reinitialize the CMOS, since none of them will be let go
  143. ; from the stall until they all finish.
  144. ;
  145. ;--
  146. cPublicProc _HalStartProfileInterrupt ,1
  147. ; Mark profiling as active
  148. ;
  149. mov dword ptr _HalpProfilingStopped, 0
  150. ;
  151. ; Set the interrupt rate to what is actually needed
  152. ;
  153. stdCall _HalpAcquireCmosSpinLock ; intr disabled
  154. mov al, RegisterAProfileValue
  155. shl ax, 8
  156. mov al, 0AH ; Register A
  157. CMOS_WRITE ; Initialize it
  158. ;
  159. ; Don't clobber the Daylight Savings Time bit in register B, because we
  160. ; stash the LastKnownGood "environment variable" there.
  161. ;
  162. mov ax, 0bh
  163. CMOS_READ
  164. and al, 1
  165. mov ah, al
  166. or ah, REGISTER_B_ENABLE_PERIODIC_INTERRUPT
  167. mov al, 0bh
  168. CMOS_WRITE ; Initialize it
  169. mov al,0CH ; Register C
  170. CMOS_READ ; Read to initialize
  171. mov al,0DH ; Register D
  172. CMOS_READ ; Read to initialize
  173. stdCall _HalpReleaseCmosSpinLock
  174. stdRET _HalStartProfileInterrupt
  175. stdENDP _HalStartProfileInterrupt
  176. ;++
  177. ;
  178. ; HalStopProfileInterrupt(
  179. ; IN ULONG Reserved
  180. ; );
  181. ;
  182. ; Routine Description:
  183. ;
  184. ; What we do here is change the interrupt
  185. ; rate from the high profiling rate to the slowest thing we
  186. ; can get away with for PerformanceCounter rollover notification.
  187. ;
  188. ;--
  189. cPublicProc _HalStopProfileInterrupt ,1
  190. ;
  191. ; Turn off profiling hit computation and profile interrupt
  192. ;
  193. ;
  194. ; Don't clobber the Daylight Savings Time bit in register B, because we
  195. ; stash the LastKnownGood "environment variable" there.
  196. stdCall _HalpAcquireCmosSpinLock ; intr disabled
  197. mov ax, 0bh
  198. CMOS_READ
  199. and al, 1
  200. mov ah, al
  201. or ah, REGISTER_B_DISABLE_PERIODIC_INTERRUPT
  202. mov al, 0bh
  203. CMOS_WRITE ; Initialize it
  204. mov al,0CH ; Register C
  205. CMOS_READ ; dismiss pending profiling interrupt
  206. mov dword ptr _HalpProfilingStopped, 1
  207. stdCall _HalpReleaseCmosSpinLock
  208. stdRET _HalStopProfileInterrupt
  209. stdENDP _HalStopProfileInterrupt
  210. ;++
  211. ; ULONG
  212. ; HalSetProfileInterval (
  213. ; ULONG Interval
  214. ; );
  215. ;
  216. ; Routine Description:
  217. ;
  218. ; This procedure sets the interrupt rate (and thus the sampling
  219. ; interval) for the profiling interrupt.
  220. ;
  221. ; If profiling is active (KiProfilingStopped == 0) the actual
  222. ; hardware interrupt rate will be set. Otherwise, a simple
  223. ; rate validation computation is done.
  224. ;
  225. ; Arguments:
  226. ;
  227. ; (TOS+4) - Interval in 100ns unit.
  228. ;
  229. ; Return Value:
  230. ;
  231. ; Interval actually used by system.
  232. ;
  233. ;--
  234. cPublicProc _HalSetProfileInterval ,1
  235. mov edx, [esp+4] ; [edx] = interval in 100ns unit
  236. and edx, 7FFFFFFFh ; Remove highest bit.
  237. mov ecx, 0 ; index = 0
  238. Hspi00:
  239. mov eax, ProfileIntervalTable[ecx * 4]
  240. cmp edx, eax ; if request interval < suport interval
  241. jbe short Hspi10 ; if be, find supported interval
  242. inc ecx
  243. jmp short Hspi00
  244. Hspi10:
  245. and eax, 7FFFFFFFh ; remove highest bit from supported interval
  246. jecxz short Hspi20 ; If first entry then use it
  247. push esi ; See which is closer to requested
  248. mov esi, eax ; rate - current entry, or preceeding
  249. sub esi, edx
  250. sub edx, ProfileIntervalTable[ecx * 4 - 4]
  251. cmp esi, edx
  252. pop esi
  253. jc short Hspi20
  254. dec ecx ; use preceeding entry
  255. mov eax, ProfileIntervalTable[ecx * 4]
  256. Hspi20:
  257. push eax ; save interval value
  258. mov al, ProfileIntervalInitTable[ecx]
  259. mov RegisterAProfileValue, al
  260. test dword ptr _HalpProfilingStopped,-1
  261. jnz short Hspi90
  262. stdCall _HalStartProfileInterrupt,<0> ; Re-start profile interrupt
  263. ; with the new interval
  264. Hspi90: pop eax
  265. stdRET _HalSetProfileInterval ; (eax) = cReturn interval
  266. stdENDP _HalSetProfileInterval
  267. page ,132
  268. subttl "System Profile Interrupt"
  269. ;++
  270. ;
  271. ; Routine Description:
  272. ;
  273. ; This routine is entered as the result of a profile interrupt.
  274. ; Its function is to dismiss the interrupt, raise system Irql to
  275. ; PROFILE_LEVEL and transfer control to
  276. ; the standard system routine to process any active profiles.
  277. ;
  278. ; Arguments:
  279. ;
  280. ; None
  281. ; Interrupt is disabled
  282. ;
  283. ; Return Value:
  284. ;
  285. ; Does not return, jumps directly to KeProfileInterrupt, which returns
  286. ;
  287. ; Sets Irql = PROFILE_LEVEL and dismisses the interrupt
  288. ;
  289. ;--
  290. ENTER_DR_ASSIST Hpi_a, Hpi_t
  291. cPublicProc _HalpProfileInterrupt ,0
  292. ;
  293. ; Save machine state in trap frame
  294. ;
  295. ENTER_INTERRUPT Hpi_a, Hpi_t
  296. ;
  297. ; (esp) - base of trap frame
  298. ;
  299. ; HalBeginSystemInterrupt must be called before any sti's
  300. ;
  301. ;
  302. push _IxProfileVector
  303. sub esp, 4 ; allocate space to save OldIrql
  304. stdCall _HalBeginSystemInterrupt, <PROFILE_LEVEL,_IxProfileVector,esp>
  305. or al,al ; check for spurious interrupt
  306. jz Hpi100
  307. ;
  308. ; This is the RTC interrupt, so we have to clear the
  309. ; interrupt flag on the RTC.
  310. ;
  311. stdCall _HalpAcquireCmosSpinLock
  312. ;
  313. ; clear interrupt flag on RTC by banging on the CMOS. On some systems this
  314. ; doesn't work the first time we do it, so we do it twice. It is rumored that
  315. ; some machines require more than this, but that hasn't been observed with NT.
  316. ;
  317. mov al,0CH ; Register C
  318. CMOS_READ ; Read to initialize
  319. mov al,0CH ; Register C
  320. CMOS_READ ; Read to initialize
  321. if DBG
  322. align 4
  323. Hpi10: test al, 80h
  324. jz short Hpi15
  325. mov al,0CH ; Register C
  326. CMOS_READ ; Read to initialize
  327. jmp short Hpi10
  328. Hpi15:
  329. endif ; DBG
  330. stdCall _HalpReleaseCmosSpinLock
  331. sti
  332. ;
  333. ; This entry point is provided for symmetric multiprocessor HALs.
  334. ; Since it only makes sense for one processor to clear the CMOS,
  335. ; all other processors can instead jmp into this entry point.
  336. ;
  337. align 4
  338. public _HalpProfileInterrupt2ndEntry@0
  339. _HalpProfileInterrupt2ndEntry@0:
  340. ;
  341. ; (esp) = OldIrql
  342. ; (esp+4) = H/W vector
  343. ; (esp+8) = base of trap frame
  344. ;
  345. ;
  346. ; Now check for any profiling stuff to do.
  347. ;
  348. cmp _HalpProfilingStopped, dword ptr 1 ; Has profiling been stopped?
  349. jz short Hpi90 ; if z, prof disenabled
  350. stdCall _KeProfileInterrupt,<ebp> ; (ebp) = trapframe
  351. Hpi90:
  352. INTERRUPT_EXIT
  353. align 4
  354. Hpi100:
  355. add esp, 8 ; spurious, no EndOfInterrupt
  356. SPURIOUS_INTERRUPT_EXIT ; exit interrupt without eoi
  357. stdENDP _HalpProfileInterrupt
  358. _TEXT ends
  359. end