Windows NT 4.0 source code leak
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.

433 lines
12 KiB

4 years ago
  1. // .ident "@(#) x4clock.s 1.1 95/09/28 18:39:17 nec"
  2. // TITLE("Interval and Profile Clock Interrupts")
  3. //++
  4. //
  5. // Copyright (c) 1991 Microsoft Corporation
  6. //
  7. // Module Name:
  8. //
  9. // x4clock.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements the code necessary to field and process the
  14. // interval and profile clock interrupts on a MIPS R4000 system.
  15. //
  16. // Author:
  17. //
  18. // David N. Cutler (davec) 26-Apr-1991
  19. //
  20. // Environment:
  21. //
  22. // Kernel mode only.
  23. //
  24. // Revision History:
  25. //
  26. // M001 Fri Feb 17 17:48:03 JST 1995 kbnes!kuriyama (A)
  27. // - Change HalpClockInterrupt0(()
  28. // for dump switch support.
  29. //
  30. // S002 Tue Feb 21 21:24:13 JST 1995 kbnes!kuriyama (A)
  31. // - use HalpNMIFlag
  32. //
  33. // S003 Wed Feb 22 11:18:59 JST 1995 kbnes!kuriyama (A)
  34. // - enter kernel debugger when NMI only checked version
  35. //
  36. // S004 Wed Feb 22 14:25:20 JST 1995 kbnes!kuriyama (A)
  37. // - enter kernel debugger when NMI free version
  38. //
  39. // S005 Sat Mar 18 20:30:05 JST 1995 kbnes!kuriyama (A)
  40. // - nmi logic change
  41. //
  42. // M006 [email protected] Wed Jun 28 14:16:29 JST 1995
  43. // - change nmi logic
  44. //
  45. // M007 Thu Jul 20 19:31:41 JST 1995 kbnes!kisimoto
  46. // - Merge build 1057
  47. //
  48. //--
  49. #include "halmips.h"
  50. #if defined(_DUO_)
  51. #include "duodef.h"
  52. #endif
  53. #if defined(_JAZZ_)
  54. #include "jazzdef.h"
  55. #endif
  56. // M001 +++
  57. #if defined(_R94A_)
  58. .extern HalpNMIFlag
  59. .extern HalpNMIInterrupt
  60. .extern HalpDumpNMIFlag //S002
  61. #endif //_R94A_
  62. // M001 ---
  63. SBTTL("System Clock Interrupt - Processor 0")
  64. //++
  65. //
  66. // Routine Description:
  67. //
  68. // This routine is entered as the result of an interrupt generated by
  69. // the interval timer. Its function is to acknowledge the interrupt and
  70. // transfer control to the standard system routine to update the system
  71. // time and the execution time of the current thread and process.
  72. //
  73. // Arguments:
  74. //
  75. // s8 - Supplies a pointer to a trap frame.
  76. //
  77. // Return Value:
  78. //
  79. // None.
  80. //
  81. //--
  82. .struct 0
  83. CiArgs: .space 4 * 4 // saved arguments
  84. .space 3 * 4 // fill
  85. CiRa: .space 4 // saved return address
  86. CiFrameLength: //
  87. NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
  88. subu sp,sp,CiFrameLength // allocate stack frame
  89. sw ra,CiRa(sp) // save return address
  90. PROLOGUE_END
  91. .set noreorder
  92. // M001 +++
  93. #if defined(_R94A_)
  94. //
  95. // check if dump swich flag set.
  96. //
  97. la t0,HalpNMIFlag // set NMI flag address
  98. li t1,0xa0000000 // set KSEG1_BASE
  99. or t0,t0,t1
  100. lw t1,(t0) // load NMI flag
  101. nop
  102. beq t1,zero,10f
  103. nop
  104. sw zero,(t0)
  105. lw t0,KdDebuggerEnabled // get address of debugger enable
  106. nop
  107. lbu t0,0(t0) // get debugger enable flag
  108. nop
  109. beq zero,t0,5f // if eq, debugger not enabled
  110. nop
  111. nop
  112. beq zero,v0,40f // if eq, no breakin requested
  113. nop
  114. break BREAKIN_BREAKPOINT // break into the debugger
  115. nop
  116. 5:
  117. // S002 +++
  118. la t0,HalpDumpNMIFlag // set Dump NMI flag address
  119. li t1,0xa0000000 // set KSEG1_BASE
  120. or t0,t0,t1 //
  121. lw a0,(t0) // load Dump NMI flag
  122. nop //
  123. // S003 +++
  124. sw zero,(t0) // clear Dump NMI flag
  125. nop //
  126. // S003 ---
  127. // S005
  128. lw zero,DMA_VIRTUAL_BASE + 0x58 // clear acknowledge // M006
  129. // S002 ---
  130. jal HalpNMIInterrupt // jump to NMI routine
  131. nop //
  132. 10:
  133. #endif // _R94A_
  134. // M001 ---
  135. #if defined(_DUO_)
  136. lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
  137. #endif
  138. #if defined(_JAZZ_)
  139. lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
  140. #endif
  141. .set reorder
  142. move a0,s8 // set address of trap frame
  143. lw a1,HalpCurrentTimeIncrement // set current time increment
  144. lw t0,__imp_KeUpdateSystemTime // update system time
  145. jal t0 //
  146. //
  147. // The following code is a work around for a bug in the Fusion machines
  148. // where the clock interrupt is not dismissed by reading the acknowledge
  149. // register.
  150. //
  151. #if defined(_JAZZ_)
  152. .set noreorder
  153. .set noat
  154. mfc0 t0,cause // read the cause register
  155. lw t1,HalpEisaControlBase // get EISA control base address
  156. sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit
  157. bgez t0,10f // if gez, no clock interrupt pending
  158. li t2,0x2 // get NMI port enable bit
  159. lb t3,0x70(t1) // save EISA NMI interrupt disable
  160. lb t4,0x461(t1) // save EISA extended NMI status
  161. sb zero,0x70(t1) // clear EISA NMI interrupt disable
  162. sb t2,0x461(t1) // set EISA NMI port enable
  163. sb zero,0x462(t1) // generate EISA NMI interrupt
  164. sb zero,0x461(t1) // clear EISA extended NMI status
  165. sb t2,0x461(t1) //
  166. lb zero,0x461(t1) // synchronize clear operatin
  167. sb t3,0x70(t1) // restore EISA NMI interupt disable
  168. sb t4,0x461(t1) // restore EISA exteneed NMI status
  169. lb zero,0x461(t1) // synchronize restore operation
  170. .set at
  171. .set reorder
  172. 10: //
  173. #endif
  174. //
  175. // At each clock interrupt the next time increment is moved to the current
  176. // time increment to "pipeline" the update of the current increment at the
  177. // correct time. If the next interval count is nonzero, then the new time
  178. // increment is moved to the next time increment and the next interval count
  179. // register is loaded with the specified interval count minus one (i.e., ms).
  180. //
  181. lw t0,KdDebuggerEnabled // get address of debugger enable
  182. lw t1,HalpNextIntervalCount // get next interval count
  183. lw t2,HalpNextTimeIncrement // get the next increment value
  184. lbu t0,0(t0) // get debugger enable flag
  185. lw t3,HalpNewTimeIncrement // get new new time increment value
  186. lw ra,CiRa(sp) // restore return address
  187. or t4,t1,t0 // set interval count or debugger?
  188. sw t2,HalpCurrentTimeIncrement // set current increment value
  189. bne zero,t4,20f // if ne, interval change or debugger
  190. addu sp,sp,CiFrameLength // deallocate stack frame
  191. j ra // return
  192. //
  193. // The interval count must be changed or the debugger is enabled.
  194. //
  195. 20: sw zero,HalpNextIntervalCount // clear next interval count
  196. beq zero,t1,30f // if eq, not interval count change
  197. subu t1,t1,1 // compute millisecond interval count
  198. .set noreorder
  199. #if defined(_DUO_)
  200. sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count
  201. #endif
  202. #if defined(_JAZZ_)
  203. sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
  204. #endif
  205. .set reorder
  206. sw t3,HalpNextTimeIncrement // set next time increment value
  207. 30: beq zero,t0,40f // if eq, debugger not enabled
  208. jal KdPollBreakIn // check if breakin is requested
  209. beq zero,v0,40f // if eq, no breakin requested
  210. li a0,DBG_STATUS_CONTROL_C // break in and send
  211. jal DbgBreakPointWithStatus // status to debugger
  212. 40: lw ra,CiRa(sp) // restore return address
  213. addu sp,sp,CiFrameLength // deallocate stack frame
  214. j ra // return
  215. .end HalpClockInterrupt0
  216. SBTTL("System Clock Interrupt - Processor N")
  217. //++
  218. //
  219. // Routine Description:
  220. //
  221. // This routine is entered as the result of an interrupt generated by
  222. // the interval timer. Its function is to acknowledge the interrupt
  223. // and transfer control to the standard system routine to update the
  224. // execution time of the current thread and process.
  225. //
  226. // Arguments:
  227. //
  228. // s8 - Supplies a pointer to a trap frame.
  229. //
  230. // Return Value:
  231. //
  232. // None.
  233. //
  234. //--
  235. LEAF_ENTRY(HalpClockInterrupt1)
  236. #if defined(_DUO_)
  237. lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
  238. move a0,s8 // set address of trap frame
  239. lw t1,__imp_KeUpdateRunTime // update system runtime
  240. j t1 //
  241. #else // M007
  242. j ra //
  243. #endif
  244. .end HalpClockInterrupt1
  245. SBTTL("Profile Clock Interrupt")
  246. //++
  247. //
  248. // Routine Description:
  249. //
  250. // This routine is entered as the result of an interrupt generated by the
  251. // profile clock. Its function is to acknowledge the profile interrupt,
  252. // compute the next compare value, update the performance counter, and
  253. // transfer control to the standard system routine to process any active
  254. // profiles.
  255. //
  256. // Arguments:
  257. //
  258. // s8 - Supplies a pointer to a trap frame.
  259. //
  260. // Return Value:
  261. //
  262. // None.
  263. //
  264. //--
  265. LEAF_ENTRY(HalpProfileInterrupt)
  266. .set noreorder
  267. .set noat
  268. mfc0 t1,count // get current count value
  269. mfc0 t0,compare // get current comparison value
  270. addu t1,t1,8 // factor in lost cycles
  271. subu t1,t1,t0 // compute initial count value
  272. mtc0 t0,compare // dismiss interrupt
  273. mtc0 t1,count // set new count register value
  274. .set at
  275. .set reorder
  276. #if defined(NT_UP)
  277. la t1,HalpPerformanceCounter // get performance counter address
  278. #else
  279. lw t1,KiPcr + PcPrcb(zero) // get current processor block address
  280. la t2,HalpPerformanceCounter // get performance counter address
  281. lbu t1,PbNumber(t1) // get processor number
  282. sll t1,t1,3 // compute address of performance count
  283. addu t1,t1,t2 //
  284. #endif
  285. lw t2,LiLowPart(t1) // get low part of performance count
  286. lw t3,LiHighPart(t1) // get high part of performance count
  287. addu t2,t2,t0 // update low part of performance count
  288. sw t2,LiLowPart(t1) // store low part of performance count
  289. sltu t4,t2,t0 // generate carry into high part
  290. addu t3,t3,t4 // update high part of performance count
  291. sw t3,LiHighPart(t1) // store high part of performance count
  292. move a0,s8 // set address of trap frame
  293. lw t4,__imp_KeProfileInterrupt // process profile interrupt
  294. j t4 //
  295. .end HalpProfileInterrupt
  296. SBTTL("Read Count Register")
  297. //++
  298. //
  299. // ULONG
  300. // HalpReadCountRegister (
  301. // VOID
  302. // );
  303. //
  304. // Routine Description:
  305. //
  306. // This routine reads the current value of the count register and
  307. // returns the value.
  308. //
  309. // Arguments:
  310. //
  311. // None.
  312. //
  313. // Return Value:
  314. //
  315. // Current value of the count register.
  316. //
  317. //--
  318. LEAF_ENTRY(HalpReadCountRegister)
  319. .set noreorder
  320. .set noat
  321. mfc0 v0,count // get count register value
  322. .set at
  323. .set reorder
  324. j ra // return
  325. .end HalpReadCountRegister
  326. SBTTL("Write Compare Register And Clear")
  327. //++
  328. //
  329. // ULONG
  330. // HalpWriteCompareRegisterAndClear (
  331. // IN ULONG Value
  332. // );
  333. //
  334. // Routine Description:
  335. //
  336. // This routine reads the current value of the count register, writes
  337. // the value of the compare register, clears the count register, and
  338. // returns the previous value of the count register.
  339. //
  340. // Arguments:
  341. //
  342. // Value - Supplies the value written to the compare register.
  343. //
  344. // Return Value:
  345. //
  346. // Previous value of the count register.
  347. //
  348. //--
  349. LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
  350. .set noreorder
  351. .set noat
  352. mfc0 v0,count // get count register value
  353. mtc0 a0,compare // set compare register value
  354. li t0,7 // set lost cycle count
  355. mtc0 t0,count // set count register to zero
  356. .set at
  357. .set reorder
  358. j ra // return
  359. .end HalpWriteCompareRegisterAndClear