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.

480 lines
15 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 "Synchronize Execution"
  30. ;++
  31. ;
  32. ; BOOLEAN
  33. ; KeSynchronizeExecution (
  34. ; IN PKINTERRUPT Interrupt,
  35. ; IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  36. ; IN PVOID SynchronizeContext
  37. ; )
  38. ;
  39. ; Routine Description:
  40. ;
  41. ; This function synchronizes the execution of the specified routine with
  42. ; the execution of the service routine associated with the specified
  43. ; interrupt object.
  44. ;
  45. ; Arguments:
  46. ;
  47. ; Interrupt (rcx) - Supplies a pointer to an interrupt object.
  48. ;
  49. ; SynchronizeRoutine (rdx) - Supplies a pointer to the function whose
  50. ; execution is to be synchronized with the execution of the service
  51. ; routine associated with the specified interrupt object.
  52. ;
  53. ; SynchronizeContext (r8) - Supplies a context pointer which is to be
  54. ; passed to the synchronization function as a parameter.
  55. ;
  56. ; Return Value:
  57. ;
  58. ; The value returned by the synchronization routine is returned as the
  59. ; function value.
  60. ;
  61. ;--
  62. SyFrame struct
  63. P1Home dq ? ; parameter home address
  64. OldIrql dd ? ; saved IRQL
  65. Fill dd ? ; fill
  66. syFrame ends
  67. NESTED_ENTRY KeSynchronizeExecution, _TEXT$00
  68. push_reg rsi ; save nonvolatile register
  69. alloc_stack (sizeof SyFrame) ; allocate stack frame
  70. END_PROLOGUE
  71. mov rsi, rcx ; save interrupt object address
  72. movzx ecx, byte ptr InSynchronizeIrql[rsi] ; get synchronization IRQL
  73. RaiseIrql ; raise IRQL to synchronization level
  74. mov SyFrame.OldIrql[rsp], eax ; save previous IRQL
  75. AcquireSpinLock InActualLock[rsi] ; acquire interrupt spin lock
  76. mov rcx, r8 ; set synchronization context
  77. call rdx ; call synchronization routine
  78. ReleaseSpinlock InActualLock[rsi] ; release interrutp spin lock
  79. mov ecx, SyFrame.OldIrql[rsp] ; get previous IRQL
  80. LowerIrql ; lower IRQL to previous level
  81. add rsp, sizeof SyFrame ; deallocate stack frame
  82. pop rsi ; restore nonvolatile register
  83. ret ;
  84. NESTED_END KeSynchronizeExecution, _TEXT$00
  85. subttl "Interrupt Exception Handler"
  86. ;++
  87. ;
  88. ; EXCEPTION_DISPOSITION
  89. ; KiInterruptHandler (
  90. ; IN PEXCEPTION_RECORD ExceptionRecord,
  91. ; IN PVOID EstablisherFrame,
  92. ; IN OUT PCONTEXT ContextRecord,
  93. ; IN OUT PDISPATCHER_CONTEXT DispatcherContext
  94. ; )
  95. ;
  96. ; Routine Description:
  97. ;
  98. ; This routine is the exception handler for the interrupt dispatcher. The
  99. ; dispatching or unwinding of an exception across an interrupt causes a
  100. ; bug check.
  101. ;
  102. ; Arguments:
  103. ;
  104. ; ExceptionRecord (rcx) - Supplies a pointer to an exception record.
  105. ;
  106. ; EstablisherFrame (rdx) - Supplies the frame pointer of the establisher
  107. ; of this exception handler.
  108. ;
  109. ; ContextRecord (r8) - Supplies a pointer to a context record.
  110. ;
  111. ; DispatcherContext (r9) - Supplies a pointer to the dispatcher context
  112. ; record.
  113. ;
  114. ; Return Value:
  115. ;
  116. ; There is no return from this routine.
  117. ;
  118. ;--
  119. IhFrame struct
  120. P1Home dq ? ; parameter home address
  121. IhFrame ends
  122. NESTED_ENTRY KiInterruptHandler, _TEXT$00
  123. alloc_stack (sizeof IhFrame) ; allocate stack frame
  124. END_PROLOGUE
  125. test dword ptr ErExceptionFlags[rcx], EXCEPTION_UNWIND ; test for unwind
  126. mov ecx, INTERRUPT_UNWIND_ATTEMPTED ; set bug check code
  127. jnz short KiIH10 ; if nz, unwind in progress
  128. mov ecx, INTERRUPT_EXCEPTION_NOT_HANDLED ; set bug check code
  129. KiIH10: call KeBugCheck ; bug check - no return
  130. nop ; fill - do not remove
  131. NESTED_END KiInterruptHandler, _TEXT$00
  132. subttl "Chained Dispatch"
  133. ;++
  134. ;
  135. ; VOID
  136. ; KiChainedDispatch (
  137. ; VOID
  138. ; );
  139. ;
  140. ; Routine Description:
  141. ;
  142. ; This routine is entered as the result of an interrupt being generated
  143. ; via a vector that is connected to more than one interrupt object.
  144. ;
  145. ; Arguments:
  146. ;
  147. ; rbp - Supplies a pointer to the interrupt object.
  148. ;
  149. ; Return Value:
  150. ;
  151. ; None.
  152. ;
  153. ;--
  154. NESTED_ENTRY KiChainedDispatch, _TEXT$00, KiInterruptHandler
  155. .pushframe code ; mark machine frame
  156. .pushreg rbp ; mark mark nonvolatile register push
  157. GENERATE_INTERRUPT_FRAME ; generate interrupt frame
  158. movzx ecx, byte ptr InIrql[rsi] ; set interrupt IRQL
  159. ENTER_INTERRUPT <NoEOI> ; raise IRQL and enable interrupts
  160. call KiScanInterruptObjectList ; scan interrupt object list
  161. EXIT_INTERRUPT ; do EOI, lower IRQL, and restore state
  162. NESTED_END KiChainedDispatch, _TEXT$00
  163. subttl "Scan Interrupt Object List"
  164. ;++
  165. ;
  166. ; Routine Description:
  167. ;
  168. ; This routine scans the list of interrupt objects for chained interrupt
  169. ; dispatch. If the mode of the interrupt is latched, then a complete scan
  170. ; of the list must be performed. Otherwise, the scan can be cut short as
  171. ; soon as an interrupt routine returns
  172. ;
  173. ; Arguments:
  174. ;
  175. ; rsi - Supplies a pointer to the interrupt object.
  176. ;
  177. ; Return Value:
  178. ;
  179. ; None.
  180. ;
  181. ;--
  182. SiFrame struct
  183. P1Home dq ? ; interrupt object parameter
  184. P2Home dq ? ; service context parameter
  185. Return db ? ; service routine return value
  186. Fill db 15 dup (?) ; fill
  187. SavedRbx dq ? ; saved register RBX
  188. SavedRdi dq ? ; saved register RDI
  189. SavedR12 dq ? ; saved register RSI
  190. SiFrame ends
  191. NESTED_ENTRY KiScanInterruptObjectList, _TEXT$00
  192. push_reg r12 ; save nonvolatile registers
  193. push_reg rdi ;
  194. push_reg rbx ;
  195. alloc_stack (sizeof SiFrame - (3 * 8)) ; allocate stack frame
  196. END_PROLOGUE
  197. lea rbx, InInterruptListEntry[rsi] ; get list head address
  198. mov r12, rbx ; set address of first list entry
  199. ;
  200. ; Scan the list of connected interrupt objects and call the service routine.
  201. ;
  202. Si05: xor edi, edi ; clear interrupt handled flag
  203. Si10: sub r12, InInterruptListEntry ; compute interrupt object address
  204. movzx ecx, byte ptr InSynchronizeIrql[r12] ; get synchronization IRQL
  205. cmp cl, InIrql[rsi] ; check if equal interrupt IRQL
  206. je short Si20 ; if e, IRQL levels equal
  207. SetIrql ; set IRQL to synchronization level
  208. Si20: AcquireSpinLock InActualLock[r12] ; acquire interrupt spin lock
  209. mov rcx, r12 ; set interrupt object parameter
  210. mov rdx, InServiceContext[r12] ; set context parameter
  211. call qword ptr InServiceRoutine[r12] ; call interrupt service routine
  212. mov SiFrame.Return[rsp], al ; save return value
  213. ReleaseSpinLock InActualLock[r12] ; release interrupt spin lock
  214. movzx ecx, byte ptr InIrql[rsi] ; get interrupt IRQL
  215. cmp cl, InSynchronizeIrql[r12] ; check if equal synchronization IRQL
  216. je short Si30 ; if e, IRQL levels equal
  217. SetIrql ; set IRQL to interrupt level
  218. Si30: test byte ptr SiFrame.Return[rsp], 0ffh ; test if interrupt handled
  219. jz short Si40 ; if z, interrupt not handled
  220. cmp word ptr InMode[r12], InLatched ; check if latched interrupt
  221. jne short Si50 ; if ne, not latched interrupt
  222. inc edi ; indicate latched interrupt handled
  223. Si40: mov r12, InInterruptListEntry[r12] ; get next interrupt list entry
  224. cmp r12, rbx ; check if end of list
  225. jne Si10 ; if ne, not end of list
  226. ;
  227. ; The complete interrupt object list has been scanned. This can only happen
  228. ; if the interrupt is a level sensitive interrupt and no interrupt was handled
  229. ; or the interrupt is a latched interrupt. Therefore, if any interrupt was
  230. ; handled it was a latched interrupt and the list needs to be scanned again
  231. ; to ensure that no interrupts are lost.
  232. ;
  233. test edi, edi ; test if any interrupts handled
  234. jnz Si05 ; if nz, latched interrupt handled
  235. Si50: add rsp, sizeof SiFrame - (3 * 8) ; deallocate stack frame
  236. pop rbx ; restore nonvolatile register
  237. pop rdi ;
  238. pop r12 ;
  239. ret ;
  240. NESTED_END KiscanInterruptObjectList, _TEXT$00
  241. subttl "Interrupt Dispatch"
  242. ;++
  243. ;
  244. ; Routine Description:
  245. ;
  246. ; This routine is entered as the result of an interrupt being generated
  247. ; via a vector that is connected to an interrupt object. Its function is
  248. ; to directly call the specified interrupt service routine.
  249. ;
  250. ; This routine is identical to KiInterruptDispatchNoLock except that
  251. ; the interrupt spinlock is taken.
  252. ;
  253. ; N.B. On entry rbp and rsi have been saved on the stack.
  254. ;
  255. ; Arguments:
  256. ;
  257. ; rbp - Supplies a pointer to the interrupt object.
  258. ;
  259. ; Return Value:
  260. ;
  261. ; None.
  262. ;
  263. ;--
  264. NESTED_ENTRY KiInterruptDispatch, _TEXT$00, KiInterruptHandler
  265. .pushframe code ; mark machine frame
  266. .pushreg rbp ; mark mark nonvolatile register push
  267. GENERATE_INTERRUPT_FRAME ; generate interrupt frame
  268. ;
  269. ; N.B. It is possible for a interrupt to occur at an IRQL that is lower
  270. ; than the current IRQL. This happens when the IRQL raised and at
  271. ; the same time an interrupt request is granted.
  272. ;
  273. movzx ecx, byte ptr InIrql[rsi] ; set interrupt IRQL
  274. ENTER_INTERRUPT <NoEOI> ; raise IRQL and enable interrupts
  275. lea rax, (-128)[rbp] ; set trap frame address
  276. mov InTrapFrame[rsi], rax ;
  277. AcquireSpinLock InActualLock[rsi] ; acquire interrupt spin lock
  278. mov rcx, rsi ; set address of interrupt object
  279. mov rdx, InServiceContext[rsi] ; set service context
  280. call qword ptr InServiceRoutine[rsi] ; call interrupt service routine
  281. ReleaseSpinLock InActualLock[rsi] ; release interrupt spin lock
  282. EXIT_INTERRUPT ; do EOI, lower IRQL, and restore state
  283. NESTED_END KiInterruptDispatch, _TEXT$00
  284. subttl "Interrupt Dispatch, No Lock"
  285. ;++
  286. ;
  287. ; Routine Description:
  288. ;
  289. ; This routine is entered as the result of an interrupt being generated
  290. ; via a vector that is connected to an interrupt object. Its function is
  291. ; to directly call the specified interrupt service routine.
  292. ;
  293. ; This routine is identical to KiInterruptDispatch except that no spinlock
  294. ; is taken.
  295. ;
  296. ; N.B. On entry rbp and rsi have been saved on the stack.
  297. ;
  298. ; Arguments:
  299. ;
  300. ; rbp - Supplies a pointer to the interrupt object.
  301. ;
  302. ; Return Value:
  303. ;
  304. ; None.
  305. ;
  306. ;--
  307. NESTED_ENTRY KiInterruptDispatchNoLock, _TEXT$00, KiInterruptHandler
  308. .pushframe code ; mark machine frame
  309. .pushreg rbp ; mark mark nonvolatile register push
  310. GENERATE_INTERRUPT_FRAME ; generate interrupt frame
  311. ;
  312. ; N.B. It is possible for a interrupt to occur at an IRQL that is lower
  313. ; than the current IRQL. This happens when the IRQL raised and at
  314. ; the same time an interrupt request is granted.
  315. ;
  316. movzx ecx, byte ptr InIrql[rsi] ; set interrupt IRQL
  317. ENTER_INTERRUPT <NoEOI> ; raise IRQL and enable interrupts
  318. lea rax, (-128)[rbp] ; set trap frame address
  319. mov InTrapFrame[rsi], rax ;
  320. mov rcx, rsi ; set address of interrupt object
  321. mov rdx, InServiceContext[rsi] ; set service context
  322. call qword ptr InServiceRoutine[rsi] ; call interrupt service routine
  323. EXIT_INTERRUPT ; do EOI, lower IRQL, and restore state
  324. NESTED_END KiInterruptDispatchNoLock, _TEXT$00
  325. subttl "Disable Processor Interrupts"
  326. ;++
  327. ;
  328. ; BOOLEAN
  329. ; KeDisableInterrupts(
  330. ; VOID
  331. ; )
  332. ;
  333. ; Routine Description:
  334. ;
  335. ; This function saves the state of the interrupt enable flag, clear the
  336. ; state of the interrupt flag (disables interrupts), and return the old
  337. ; inerrrupt enable flag state.
  338. ;
  339. ; Arguments:
  340. ;
  341. ; None.
  342. ;
  343. ; Return Value:
  344. ;
  345. ; If interrupts were previously enabled, then 1 is returned as the function
  346. ; value. Otherwise, 0 is returned.
  347. ;
  348. ;--
  349. DiFrame struct
  350. Flags dd ? ; processor flags
  351. Fill dd ? ; fill
  352. DiFrame ends
  353. NESTED_ENTRY KeDisableInterrupts, _TEXT$00
  354. push_eflags ; push processor flags
  355. END_PROLOGUE
  356. mov eax, DiFrame.Flags[rsp] ; isolate interrupt enable bit
  357. shr eax, EFLAGS_IF_SHIFT ;
  358. and al, 1 ;
  359. cli ; disable interrupts
  360. add rsp, sizeof DiFrame ; deallocate stack frame
  361. ret ; return
  362. NESTED_END KeDisableInterrupts, _TEXT$00
  363. subttl "Interrupt Template"
  364. ;++
  365. ;
  366. ; Routine Description:
  367. ;
  368. ; This routine is a template that is copied into each interrupt object.
  369. ; Its function is to save volatile machine state, compute the interrupt
  370. ; object address, and transfer control to the appropriate interrupt
  371. ; dispatcher.
  372. ;
  373. ; N.B. Interrupts are disabled on entry to this routine.
  374. ;
  375. ; Arguments:
  376. ;
  377. ; None.
  378. ;
  379. ; Return Value:
  380. ;
  381. ; N.B. Control does not return to this routine. The respective interrupt
  382. ; dispatcher dismisses the interrupt directly.
  383. ;
  384. ;--
  385. LEAF_ENTRY KiInterruptTemplate, _TEXT$00
  386. push rax ; push dummy vector number
  387. push rbp ; save nonvolatile register
  388. lea rbp, KiInterruptTemplate - InDispatchCode ; get interrupt object address
  389. jmp qword ptr InDispatchAddress[rbp] ; finish in common code
  390. LEAF_END KiInterruptTemplate, _TEXT$00
  391. end