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.

352 lines
11 KiB

  1. TITLE "Interrupt Object Support Routines"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; intsup.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the platform specific code to support interrupt
  13. ; objects. It contains the interrupt dispatch code and the code template
  14. ; that gets copied into an interrupt object.
  15. ;
  16. ; Author:
  17. ;
  18. ; David N. Cutler (davec) 19-Jun-2000
  19. ;
  20. ; Environment:
  21. ;
  22. ; Kernel mode only.
  23. ;
  24. ;--
  25. include ksamd64.inc
  26. extern KeBugCheck:proc
  27. extern KiInitiateUserApc:proc
  28. extern __imp_HalEndSystemInterrupt:qword
  29. subttl "Interrupt Exception Handler"
  30. ;++
  31. ;
  32. ; EXCEPTION_DISPOSITION
  33. ; KiInterruptHandler (
  34. ; IN PEXCEPTION_RECORD ExceptionRecord,
  35. ; IN PVOID EstablisherFrame,
  36. ; IN OUT PCONTEXT ContextRecord,
  37. ; IN OUT PDISPATCHER_CONTEXT DispatcherContext
  38. ; )
  39. ;
  40. ; Routine Description:
  41. ;
  42. ; This routine is the exception handler for the interrupt dispatcher. The
  43. ; dispatching or unwinding of an exception across an interrupt causes a
  44. ; bug check.
  45. ;
  46. ; Arguments:
  47. ;
  48. ; ExceptionRecord (rcx) - Supplies a pointer to an exception record.
  49. ;
  50. ; EstablisherFrame (rdx) - Supplies the frame pointer of the establisher
  51. ; of this exception handler.
  52. ;
  53. ; ContextRecord (r8) - Supplies a pointer to a context record.
  54. ;
  55. ; DispatcherContext (r9) - Supplies a pointer to the dispatcher context
  56. ; record.
  57. ;
  58. ; Return Value:
  59. ;
  60. ; There is no return from this routine.
  61. ;
  62. ;--
  63. IhFrame struct
  64. P1Home dq ? ; parameter home address
  65. IhFrame ends
  66. NESTED_ENTRY KiInterruptHandler, _TEXT$00
  67. alloc_stack (sizeof IhFrame) ; allocate stack frame
  68. END_PROLOGUE
  69. mov ecx, INTERRUPT_UNWIND_ATTEMPTED ; set bug check code
  70. test dword ptr ErExceptionFlags[rcx], EXCEPTION_UNWIND ; test for unwind
  71. jnz short KiIH10 ; if nz, unwind in progress
  72. mov ecx, INTERRUPT_EXCEPTION_NOT_HANDLED ; set bug check code
  73. KiIH10: call KeBugCheck ; bug check - no return
  74. nop ; fill - do not remove
  75. NESTED_END KiInterruptHandler, _TEXT$00
  76. subttl "Chained Dispatch"
  77. ;++
  78. ;
  79. ; VOID
  80. ; KiChainedDispatch (
  81. ; VOID
  82. ; );
  83. ;
  84. ; Routine Description:
  85. ;
  86. ; This routine is entered as the result of an interrupt being generated
  87. ; via a vector that is connected to more than one interrupt object.
  88. ;
  89. ; Arguments:
  90. ;
  91. ; rbp - Supplies a pointer to the interrupt object.
  92. ;
  93. ; Return Value:
  94. ;
  95. ; None.
  96. ;
  97. ;--
  98. NESTED_ENTRY KiChainedDispatch, _TEXT$00, KiInterruptHandler
  99. .pushframe code ; mark machine frame
  100. .pushreg rbp ; mark mark nonvolatile register push
  101. GENERATE_INTERRUPT_FRAME ; generate interrupt frame
  102. movzx ecx, byte ptr InIrql[rsi] ; set interrupt IRQL
  103. ENTER_INTERRUPT <NoEOI> ; raise IRQL and enable interrupts
  104. call KiScanInterruptObjectList ; scan interrupt object list
  105. EXIT_INTERRUPT ; do EOI, lower IRQL, and restore state
  106. NESTED_END KiChainedDispatch, _TEXT$00
  107. subttl "Scan Interrupt Object List"
  108. ;++
  109. ;
  110. ; Routine Description:
  111. ;
  112. ; This routine scans the list of interrupt objects for chained interrupt
  113. ; dispatch. If the mode of the interrupt is latched, then a complete scan
  114. ; of the list must be performed. Otherwise, the scan can be cut short as
  115. ; soon as an interrupt routine returns
  116. ;
  117. ; Arguments:
  118. ;
  119. ; rsi - Supplies a pointer to the interrupt object.
  120. ;
  121. ; Return Value:
  122. ;
  123. ; None.
  124. ;
  125. ;--
  126. SiFrame struct
  127. P1Home dq ? ; interrupt object parameter
  128. P2Home dq ? ; service context parameter
  129. Return db ? ; service routine return value
  130. Fill db 15 dup (?) ; fill
  131. SavedRbx dq ? ; saved register RBX
  132. SavedRdi dq ? ; saved register RDI
  133. SavedR12 dq ? ; saved register RSI
  134. SiFrame ends
  135. NESTED_ENTRY KiScanInterruptObjectList, _TEXT$00
  136. push_reg r12 ; save nonvolatile registers
  137. push_reg rdi ;
  138. push_reg rbx ;
  139. alloc_stack (sizeof SiFrame - (3 * 8)) ; allocate stack frame
  140. END_PROLOGUE
  141. lea rbx, InInterruptListEntry[rsi] ; get list head address
  142. mov r12, rbx ; set address of first list entry
  143. ;
  144. ; Scan the list of connected interrupt objects and call the service routine.
  145. ;
  146. Si05: xor edi, edi ; clear interrupt handled flag
  147. Si10: sub r12, InInterruptListEntry ; compute interrupt object address
  148. movzx ecx, byte ptr InSynchronizeIrql[r12] ; get synchronization IRQL
  149. cmp cl, InIrql[rsi] ; check if equal interrupt IRQL
  150. je short Si20 ; if e, IRQL levels equal
  151. SetIrql ; set IRQL to synchronization level
  152. Si20: AcquireSpinLock InActualLock[r12] ; acquire interrupt spin lock
  153. mov rcx, r12 ; set interrupt object parameter
  154. mov rdx, InServiceContext[r12] ; set context parameter
  155. call qword ptr InServiceRoutine[r12] ; call interrupt service routine
  156. mov SiFrame.Return[rsp], al ; save return value
  157. ReleaseSpinLock InActualLock[r12] ; release interrupt spin lock
  158. movzx ecx, byte ptr InIrql[rsi] ; get interrupt IRQL
  159. cmp cl, InSynchronizeIrql[r12] ; check if equal synchronization IRQL
  160. je short Si30 ; if e, IRQL levels equal
  161. SetIrql ; set IRQL to interrupt level
  162. Si30: test byte ptr SiFrame.Return[rsp], 0ffh ; test if interrupt handled
  163. jz short Si40 ; if z, interrupt not handled
  164. cmp word ptr InMode[r12], InLatched ; check if latched interrupt
  165. jne short Si50 ; if ne, not latched interrupt
  166. inc edi ; indicate latched interrupt handled
  167. Si40: mov r12, InInterruptListEntry[r12] ; get next interrupt list entry
  168. cmp r12, rbx ; check if end of list
  169. jne Si10 ; if ne, not end of list
  170. ;
  171. ; The complete interrupt object list has been scanned. This can only happen
  172. ; if the interrupt is a level sensitive interrupt and no interrupt was handled
  173. ; or the interrupt is a latched interrupt. Therefore, if any interrupt was
  174. ; handled it was a latched interrupt and the list needs to be scanned again
  175. ; to ensure that no interrupts are lost.
  176. ;
  177. test edi, edi ; test if any interrupts handled
  178. jnz Si05 ; if nz, latched interrupt handled
  179. Si50: add rsp, sizeof SiFrame - (3 * 8) ; deallocate stack frame
  180. pop rbx ; restore nonvolatile register
  181. pop rdi ;
  182. pop r12 ;
  183. ret ;
  184. NESTED_END KiscanInterruptObjectList, _TEXT$00
  185. subttl "Interrupt Dispatch"
  186. ;++
  187. ;
  188. ; Routine Description:
  189. ;
  190. ; This routine is entered as the result of an interrupt being generated
  191. ; via a vector that is connected to an interrupt object. Its function is
  192. ; to directly call the specified interrupt service routine.
  193. ;
  194. ; N.B. On entry rbp and rsi have been saved on the stack.
  195. ;
  196. ; Arguments:
  197. ;
  198. ; rbp - Supplies a pointer to the interrupt object.
  199. ;
  200. ; Return Value:
  201. ;
  202. ; None.
  203. ;
  204. ;--
  205. NESTED_ENTRY KiInterruptDispatch, _TEXT$00, KiInterruptHandler
  206. .pushframe code ; mark machine frame
  207. .pushreg rbp ; mark mark nonvolatile register push
  208. GENERATE_INTERRUPT_FRAME ; generate interrupt frame
  209. ;
  210. ; N.B. It is possible for a interrupt to occur at an IRQL that is lower
  211. ; than the current IRQL. This happens when the IRQL raised and at
  212. ; the same time an interrupt request is granted.
  213. ;
  214. movzx ecx, byte ptr InIrql[rsi] ; set interrupt IRQL
  215. ENTER_INTERRUPT <NoEOI> ; raise IRQL and enable interrupts
  216. lea rax, (-128)[rbp] ; set trap frame address
  217. mov InTrapFrame[rsi], rax ;
  218. AcquireSpinLock InActualLock[rsi] ; acquire interrupt spin lock
  219. mov rcx, rsi ; set address of interrupt object
  220. mov rdx, InServiceContext[rsi] ; set service context
  221. call qword ptr InServiceRoutine[rsi] ; call interrupt service routine
  222. ReleaseSpinLock InActualLock[rsi] ; release interrupt spin lock
  223. EXIT_INTERRUPT ; do EOI, lower IRQL, and restore state
  224. NESTED_END KiInterruptDispatch, _TEXT$00
  225. subttl "Disable Processor Interrupts"
  226. ;++
  227. ;
  228. ; BOOLEAN
  229. ; KeDisableInterrupts(
  230. ; VOID
  231. ; )
  232. ;
  233. ; Routine Description:
  234. ;
  235. ; This function saves the state of the interrupt enable flag, clear the
  236. ; state of the interrupt flag (disables interrupts), and return the old
  237. ; inerrrupt enable flag state.
  238. ;
  239. ; Arguments:
  240. ;
  241. ; None.
  242. ;
  243. ; Return Value:
  244. ;
  245. ; If interrupts were previously enabled, then 1 is returned as the function
  246. ; value. Otherwise, 0 is returned.
  247. ;
  248. ;--
  249. DiFrame struct
  250. Flags dd ? ; processor flags
  251. Fill dd ? ; fill
  252. DiFrame ends
  253. NESTED_ENTRY KeDisableInterrupts, _TEXT$00
  254. push_eflags ; push processor flags
  255. END_PROLOGUE
  256. mov eax, DiFrame.Flags[rsp] ; isolate interrupt enable bit
  257. shr eax, EFLAGS_IF_SHIFT ;
  258. and al, 1 ;
  259. cli ; disable interrupts
  260. add rsp, sizeof DiFrame ; deallocate stack frame
  261. ret ; return
  262. NESTED_END KeDisableInterrupts, _TEXT$00
  263. subttl "Interrupt Template"
  264. ;++
  265. ;
  266. ; Routine Description:
  267. ;
  268. ; This routine is a template that is copied into each interrupt object.
  269. ; Its function is to save volatile machine state, compute the interrupt
  270. ; object address, and transfer control to the appropriate interrupt
  271. ; dispatcher.
  272. ;
  273. ; N.B. Interrupts are disabled on entry to this routine.
  274. ;
  275. ; Arguments:
  276. ;
  277. ; None.
  278. ;
  279. ; Return Value:
  280. ;
  281. ; N.B. Control does not return to this routine. The respective interrupt
  282. ; dispatcher dismisses the interrupt directly.
  283. ;
  284. ;--
  285. LEAF_ENTRY KiInterruptTemplate, _TEXT$00
  286. push rax ; push dummy vector number
  287. push rbp ; save nonvolatile register
  288. lea rbp, KiInterruptTemplate - InDispatchCode ; get interrupt object address
  289. jmp qword ptr InDispatchAddress[rbp] ; finish in common code
  290. LEAF_END KiInterruptTemplate, _TEXT$00
  291. end