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.

341 lines
6.7 KiB

  1. // TITLE("Manipulate Interrupt Request Level")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // irql.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements the code necessary to lower and raise the current
  11. // Interrupt Request Level (IRQL).
  12. //
  13. //
  14. // Author:
  15. //
  16. // William K. Cheung (wcheung) 05-Oct-1995
  17. //
  18. // Environment:
  19. //
  20. // Kernel mode only.
  21. //
  22. // Revision History:
  23. //
  24. // 08-Feb-1996 Updated to EAS2.1
  25. //
  26. //--
  27. #include "ksia64.h"
  28. .file "irql.s"
  29. //
  30. // Globals
  31. //
  32. PublicFunction(KiCheckForSoftwareInterrupt)
  33. //++
  34. //
  35. // VOID
  36. // KiLowerIrqlSpecial (
  37. // KIRQL NewIrql
  38. // )
  39. //
  40. // Routine Description:
  41. //
  42. // This function lowers the current IRQL to the specified value.
  43. // Does not check for software interrupts. For use within the software interupt
  44. // dispatch code.
  45. //
  46. // Arguments:
  47. //
  48. // NewIrql (a0) - Supplies the new IRQL value.
  49. //
  50. // Return Value:
  51. //
  52. // None.
  53. //
  54. // N.B. The IRQL is being lowered. Therefore, it is not necessary to
  55. // do a data serialization after the TPR is updated unless it is
  56. // very critical to accept interrupts of lower priorities as soon
  57. // as possible. The TPR change will take into effect eventually.
  58. //
  59. //--
  60. LEAF_ENTRY(KiLowerIrqlSpecial)
  61. SET_IRQL(a0)
  62. LEAF_RETURN
  63. LEAF_EXIT(KiLowerIrqlSpecial)
  64. //++
  65. //
  66. // VOID
  67. // KiLowerIrqlSoftwareInterruptPending(
  68. // IN TEMP_REG NewIrql
  69. // )
  70. //
  71. // Routine Description:
  72. //
  73. // This function is entered directly from a LEAF function that is
  74. // lowering IRQL before it exits when there is a software interrupt
  75. // pending that will fire as a result of lowering IRQL.
  76. //
  77. // In this special case, we need to promote to a nested entry in
  78. // order to process the simulated interrupt.
  79. //
  80. // Return is directly to the caller of the leaf function.
  81. //
  82. // This routine is entered with interrupts disabled, this is a
  83. // side effect of the code that branched here needing interrupts
  84. // disabled while checking and lowering.
  85. //
  86. // Arguments:
  87. //
  88. // NewIrql - Because we are branched to from a leaf routine,
  89. // the argument must be passed in non-windowed
  90. // register t22 (r31).
  91. //
  92. // Return Value:
  93. //
  94. // None.
  95. //
  96. //--
  97. NESTED_ENTRY(KiLowerIrqlSoftwareInterruptPending)
  98. NESTED_SETUP(0,3,1,0)
  99. PROLOGUE_END
  100. mov out0 = t22
  101. ssm 1 << PSR_I
  102. ;;
  103. br.call.spnt brp = KiCheckForSoftwareInterrupt;;
  104. NESTED_RETURN
  105. NESTED_EXIT(KiLowerIrqlSoftwareInterruptPending)
  106. //++
  107. //
  108. // VOID
  109. // KeLowerIrql (
  110. // KIRQL NewIrql
  111. // )
  112. //
  113. // Routine Description:
  114. //
  115. // This function lowers the current IRQL to the specified value.
  116. //
  117. // Arguments:
  118. //
  119. // NewIrql (a0) - Supplies the new IRQL value.
  120. //
  121. // Return Value:
  122. //
  123. // None.
  124. //
  125. // N.B. The IRQL is being lowered. Therefore, it is not necessary to
  126. // do a data serialization after the TPR is updated unless it is
  127. // very critical to accept interrupts of lower priorities as soon
  128. // as possible. The TPR change will take into effect eventually.
  129. //
  130. //--
  131. LEAF_ENTRY(KeLowerIrql)
  132. //
  133. // KIRQL is a byte, extend to 64 bits.
  134. //
  135. zxt1 a0 = a0
  136. ;;
  137. //
  138. // If lowering below DISPATCH_LEVEL, check for pending
  139. // software interrupts that could run now.
  140. //
  141. // This needs to be done with interrupts disabled to
  142. // avoid the case where an interrupt is set pending
  143. // while we check but before IRQL is actually lowered.
  144. //
  145. cmp.gtu pt0 = DISPATCH_LEVEL, a0
  146. movl t21 = KiPcr+PcSoftwareInterruptPending;;
  147. (pt0) rsm 1 << PSR_I
  148. (pt0) ld2 t21 = [t21]
  149. mov t22 = a0;;
  150. (pt0) cmp.ltu.unc pt1, pt2 = a0, t21
  151. //
  152. // If a software interrupt would fire now, branch directly
  153. // to KiLowerIrqlSoftwareInterruptPending which will promote
  154. // to a NESTED routine, handle the interrupt, lower IRQL and
  155. // return directly to the caller.
  156. //
  157. (pt1) br.spnt KiLowerIrqlSoftwareInterruptPending
  158. //
  159. // Didn't have an interrupt pending, lower IRQL and return.
  160. //
  161. SET_IRQL(a0)
  162. //
  163. // Enable interrupts and return.
  164. //
  165. ssm 1 << PSR_I
  166. LEAF_RETURN
  167. LEAF_EXIT(KeLowerIrql)
  168. //++
  169. //
  170. // VOID
  171. // KeRaiseIrql (
  172. // KIRQL NewIrql,
  173. // PKIRQL OldIrql
  174. // )
  175. //
  176. // Routine Description:
  177. //
  178. // This function raises the current IRQL to the specified value and returns
  179. // the old IRQL value.
  180. //
  181. // Arguments:
  182. //
  183. // NewIrql (a0) - Supplies the new IRQL value.
  184. //
  185. // OldIrql (a1) - Supplies a pointer to a variable that recieves the old
  186. // IRQL value.
  187. //
  188. // Return Value:
  189. //
  190. // None.
  191. //
  192. //--
  193. LEAF_ENTRY(KeRaiseIrql)
  194. //
  195. // Register aliases
  196. //
  197. rOldIrql = t3
  198. GET_IRQL (rOldIrql)
  199. SET_IRQL (a0) // Raise IRQL
  200. ;;
  201. st1 [a1] = rOldIrql // return old IRQL value
  202. LEAF_RETURN
  203. LEAF_EXIT(KeRaiseIrql)
  204. //++
  205. //
  206. // KIRQL
  207. // KfRaiseIrql (
  208. // KIRQL NewIrql
  209. // )
  210. //
  211. // Routine Description:
  212. //
  213. // This function raises the current IRQL to the specified value and returns
  214. // the old IRQL value.
  215. //
  216. // Arguments:
  217. //
  218. // NewIrql (a0) - Supplies the new IRQL value.
  219. //
  220. // Return Value:
  221. //
  222. // Old Irql value.
  223. //
  224. //--
  225. LEAF_ENTRY(KfRaiseIrql)
  226. GET_IRQL (r8) // Put old IRQL in return register.
  227. SET_IRQL (a0) // Raise IRQL
  228. LEAF_RETURN
  229. LEAF_EXIT(KfRaiseIrql)
  230. //++
  231. //
  232. // KIRQL
  233. // KeRaiseIrqlToDpcLevel (
  234. // VOID
  235. // )
  236. //
  237. // Routine Description:
  238. //
  239. // This function raises the current IRQL to DISPATCH_LEVEL and returns
  240. // the old IRQL value.
  241. //
  242. // Arguments:
  243. //
  244. // None.
  245. //
  246. // Return Value:
  247. //
  248. // Old IRQL value
  249. //
  250. //--
  251. LEAF_ENTRY(KeRaiseIrqlToDpcLevel)
  252. //
  253. // Register aliases
  254. //
  255. rNewIrql = t0
  256. mov rNewIrql = DISPATCH_LEVEL
  257. GET_IRQL(v0)
  258. ;;
  259. SET_IRQL (rNewIrql) // Raise IRQL
  260. LEAF_RETURN
  261. LEAF_EXIT(KeRaiseIrqlToDpcLevel)
  262. //++
  263. //
  264. // KIRQL
  265. // KeRaiseIrqlToSynchLevel (
  266. // VOID
  267. // )
  268. //
  269. // Routine Description:
  270. //
  271. // This function raises the current IRQL to SYNCH_LEVEL and returns
  272. // the old IRQL value.
  273. //
  274. // Arguments:
  275. //
  276. // None.
  277. //
  278. // Return Value:
  279. //
  280. // Old IRQL value
  281. //
  282. //--
  283. LEAF_ENTRY(KeRaiseIrqlToSynchLevel)
  284. //
  285. // Register aliases
  286. //
  287. rNewIrql = t0
  288. mov rNewIrql = SYNCH_LEVEL
  289. GET_IRQL(v0)
  290. ;;
  291. SET_IRQL (rNewIrql) // Raise IRQL
  292. LEAF_RETURN
  293. LEAF_EXIT(KeRaiseIrqlToSynchLevel)