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.

724 lines
21 KiB

  1. // TITLE("Interrupt Object Support Routines")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // intsup.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements the code necessary to support interrupt objects.
  11. // It contains the interrupt dispatch code and the code template that gets
  12. // copied into an interrupt object.
  13. //
  14. // Author:
  15. //
  16. // Bernard Lint 20-Nov-1995
  17. //
  18. // Environment:
  19. //
  20. // Kernel mode only.
  21. //
  22. // Revision History:
  23. //
  24. // Based on MIPS version (David N. Cutler (davec) 2-Apr-1990)
  25. //
  26. //--
  27. #include "ksia64.h"
  28. #include "icecap.h"
  29. #define PREF_INT_FLAG_SHIFT 14
  30. #if (PERF_INTERRUPT_FLAG != (1 << PREF_INT_FLAG_SHIFT))
  31. #error PERF_INTERRUPT_FLAG changed PREF_INT_FLAG_SHIFT now wrong!
  32. #endif
  33. .global PPerfGlobalGroupMask
  34. PublicFunction(PerfInfoLogInterrupt)
  35. //
  36. SBTTL("Synchronize Execution")
  37. //++
  38. //
  39. // BOOLEAN
  40. // KeSynchronizeExecution (
  41. // IN PKINTERRUPT Interrupt,
  42. // IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
  43. // IN PVOID SynchronizeContext
  44. // )
  45. //
  46. // Routine Description:
  47. //
  48. // This function synchronizes the execution of the specified routine with the
  49. // execution of the service routine associated with the specified interrupt
  50. // object.
  51. //
  52. // Arguments:
  53. //
  54. // Interrupt (a0) - Supplies a pointer to a control object of type interrupt.
  55. //
  56. // SynchronizeRoutine (a1) - Supplies a pointer to a function whose execution
  57. // is to be synchronized with the execution of the service routine associated
  58. // with the specified interrupt object.
  59. //
  60. // SynchronizeContext (a2) - Supplies a pointer to an arbitrary data structure
  61. // which is to be passed to the function specified by the SynchronizeRoutine
  62. // parameter.
  63. //
  64. // Return Value:
  65. //
  66. // The value returned by the SynchronizeRoutine function is returned as the
  67. // function value.
  68. //
  69. //--
  70. NESTED_ENTRY(KeSynchronizeExecution)
  71. NESTED_SETUP(3,4,1,0)
  72. add t2 = InSynchronizeIrql, a0 // -> sync IRQL
  73. ;;
  74. PROLOGUE_END
  75. //
  76. // Register aliases for entire procedure
  77. //
  78. rOldIrql = loc2 // saved IRQL value
  79. rpSpinLock= loc3 // address of spin lock
  80. //
  81. // Raise IRQL to the synchronization level and acquire the associated
  82. // spin lock.
  83. //
  84. ld8.nt1 t1 = [a1], PlGlobalPointer-PlEntryPoint
  85. ld1.nt1 t3 = [t2], InActualLock-InSynchronizeIrql
  86. mov out0 = a2 // get synchronize context
  87. ;;
  88. #if !defined(NT_UP)
  89. ld8.nt1 rpSpinLock = [t2] // get address of spin lock
  90. #endif // !defined(NT_UP)
  91. SWAP_IRQL (t3) // raise IRQL
  92. #if !defined(NT_UP)
  93. #ifndef CAPKERN_SYNCH_POINTS
  94. ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kse10)
  95. #else
  96. CAP_ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kse10,t2,t3,t4,t5)
  97. #endif
  98. #endif // !defined(NT_UP)
  99. //
  100. // Call specified routine passing the specified context parameter.
  101. //
  102. ld8.nt1 gp = [a1]
  103. mov bt0 = t1 // setup br
  104. mov rOldIrql = v0
  105. br.call.sptk.many brp = bt0 // call routine
  106. //
  107. // Release spin lock, lower IRQL to its previous level, and return the value
  108. // returned by the specified routine.
  109. //
  110. #if !defined(NT_UP)
  111. #ifndef CAPKERN_SYNCH_POINTS
  112. RELEASE_SPINLOCK(rpSpinLock)
  113. #else
  114. CAP_RELEASE_SPINLOCK(rpSpinLock, t2,t3,t4,t5, pt0)
  115. #endif
  116. #endif // !defined(NT_UP)
  117. SET_IRQL(rOldIrql) // lower IRQL to previous level
  118. NESTED_RETURN
  119. NESTED_EXIT(KeSynchronizeExecution)
  120. //
  121. SBTTL("Chained Dispatch")
  122. //++
  123. //
  124. // Routine Description:
  125. //
  126. // This routine is entered as the result of an interrupt being generated
  127. // via a vector that is connected to more than one interrupt object. Its
  128. // function is to walk the list of connected interrupt objects and call
  129. // each interrupt service routine. If the mode of the interrupt is latched,
  130. // then a complete traversal of the chain must be performed. If any of the
  131. // routines require saving the volatile floating point machine state, then
  132. // it is only saved once.
  133. //
  134. // N.B. On entry to this routine only the volatile integer registers have
  135. // been saved. Also the volatile lower floating point registers saved.
  136. //
  137. // N.B. gp will be destroyed by the interrupt service routine; if this code
  138. // uses the gp of this module after the call, then it must save and
  139. // restore gp.
  140. //
  141. // Arguments:
  142. //
  143. // a0 - Supplies a function pointer to the ISR (in the interrupt object
  144. // dispatch code).
  145. //
  146. // a1 - Supplies a pointer to a trap frame.
  147. //
  148. // Return Value:
  149. //
  150. // None.
  151. //
  152. //--
  153. NESTED_ENTRY(KiChainedDispatch)
  154. NESTED_SETUP(2,11,3,0)
  155. .save pr, loc7
  156. mov loc7 = pr
  157. PROLOGUE_END
  158. //
  159. // Register aliases
  160. //
  161. rpSpinLock = loc2 // pointer to spinlock
  162. rMode = loc3 // interrupt mode (level sensitive)
  163. rpEntry = loc4 // current list entry
  164. rIrql = loc5 // source interrupt IRQL
  165. rSirql = loc6 // new interrupt IRQL
  166. rFptr = loc8 // ISR fptr
  167. rpI1 = t0 // temp pointer
  168. rpI2 = t1 // temp pointer
  169. rpFptr = t2 // pointer to ISR fptr
  170. rpCtxt = t3 // pointer to service context
  171. pLoop1 = pt1 // do another loop
  172. pLoop2 = pt2 // do another loop
  173. pNEqual = ps0 // true if source IRQL != sync IRQL
  174. //
  175. // Initialize loop variables.
  176. //
  177. add out0 = -InDispatchCode, a0 // out0 -> interrupt object
  178. add out2 = @gprel(PPerfGlobalGroupMask), gp
  179. ;;
  180. ld8.nt1 out2 = [out2] // Load PPerfGlobalGroupMask pointer
  181. add rpEntry = InInterruptListEntry, out0 // set addr of listhead
  182. add rpI1 = InMode, out0 // -> mode of interrupt
  183. add rpI2 = InIrql, out0 // -> interrupt source IRQL
  184. ;;
  185. ld1.nt1 rMode = [rpI1] // get mode of interrupt
  186. ld1.nt1 rIrql = [rpI2] // get interrupt source IRQL
  187. cmp.ne ps5 = 0, out2 // Test PPerfGlobalGroupMask point for !0
  188. add out2 = PERF_INTERRUPT_OFFSET, out2
  189. ;;
  190. mov loc10 = gp // Save current GP
  191. (ps5) ld4 out2 = [out2] // Load bit mask if tracing on.
  192. ;;
  193. (ps5) tbit.nz ps5 = out2, PREF_INT_FLAG_SHIFT // Test for interrupt tracing.
  194. //
  195. // Walk the list of connected interrupt objects and call the respective
  196. // interrupt service routines.
  197. //
  198. // Raise IRQL to synchronization level if synchronization level is not
  199. // equal to the interrupt source level.
  200. //
  201. Kcd_Loop:
  202. add rpI1 = InSynchronizeIrql, out0
  203. ;;
  204. ld1 rSirql = [rpI1], InActualLock-InSynchronizeIrql
  205. ;;
  206. cmp.ne pNEqual = rIrql, rSirql // if ne, IRQL levels are
  207. // not the same
  208. ;;
  209. PSET_IRQL(pNEqual, rSirql) // raise to synchronization IRQL
  210. //
  211. //
  212. // Acquire the service routine spin lock and call the service routine.
  213. //
  214. #if !defined(NT_UP)
  215. ld8.nt1 rpSpinLock = [rpI1] // get address of spin lock
  216. #ifndef CAPKERN_SYNCH_POINTS
  217. ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kcd_Lock)
  218. #else
  219. CAP_ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kcd_Lock,t4,t5,t6,t7)
  220. #endif
  221. #endif // !defined(NT_UP)
  222. add rpFptr = InServiceRoutine, out0 // pointer to fptr
  223. add rpCtxt = InServiceContext, out0 // pointer to service context
  224. ;;
  225. LDPTR (rFptr, rpFptr) // get fptr
  226. #ifdef _CAPKERN
  227. mov t5 = out0;;
  228. movl out0 = @fptr(KiChainedDispatch)
  229. mov out1 = rFptr
  230. br.call.sptk.few b0=_CAP_Start_Profiling2;;
  231. mov out0 = t5
  232. #endif
  233. LDPTR (out1, rpCtxt) // get service context
  234. ;;
  235. ld8.nt1 t5 = [rFptr], PlGlobalPointer-PlEntryPoint
  236. (ps5) mov loc9 = ar.itc
  237. ;;
  238. ld8.nt1 gp = [rFptr],PlEntryPoint-PlGlobalPointer
  239. mov bt0 = t5 // set br address
  240. br.call.sptk brp = bt0 // call ISR
  241. CAPEND(KiChainedDispatch)
  242. //
  243. // Release the service routine spin lock.
  244. //
  245. #if !defined(NT_UP)
  246. #ifndef CAPKERN_SYNCH_POINTS
  247. RELEASE_SPINLOCK(rpSpinLock)
  248. #else
  249. CAP_RELEASE_SPINLOCK(rpSpinLock, t4,t5,t6,t7, pt0)
  250. #endif
  251. #endif
  252. //
  253. // Lower IRQL to the interrupt source level if synchronization level is not
  254. // the same as the interrupt source level.
  255. //
  256. PSET_IRQL(pNEqual,rIrql)
  257. mov gp=loc10 // Restore GP
  258. mov out2 = loc9 // Pass the start time.
  259. (ps5) br.spnt Kic_PerfLog
  260. //
  261. // Get next list entry and check for end of loop.
  262. //
  263. Kic_Return:
  264. add rpI1 = LsFlink, rpEntry // -> next entry
  265. ;;
  266. LDPTR (rpEntry, rpI1) // -> next interrupt object
  267. ;;
  268. //
  269. // Loop if (1) interrrupt not handled and not end of list or
  270. // if (2) interrupt handled, and not level sensistive, and not end of list
  271. //
  272. cmp4.eq pLoop1 = zero, zero // initialize pLoop1
  273. cmp4.eq pLoop2 = zero, zero // initialize pLoop2
  274. add out0 = InDispatchCode-InInterruptListEntry, rpEntry // -> ISR if done
  275. ;;
  276. cmp4.eq.and pLoop1 = zero, v0 // if eq, interrupt not handled
  277. cmp.ne.and pLoop1, pLoop2 = a0, out0 // if ne, not end of list
  278. ;;
  279. add out0 = -InInterruptListEntry, rpEntry // -> next interrupt object
  280. (pLoop1) br.dptk Kcd_Loop // loop to handle next enrty
  281. ;;
  282. cmp4.ne.and pLoop2 = zero, v0 // if ne, interrupt handled
  283. cmp4.ne.and pLoop2 = zero, rMode // if ne, not level sensitive
  284. (pLoop2) br.dptk Kcd_Loop // loop to handle next enrty
  285. ;;
  286. //
  287. // Either the interrupt is level sensitive and has been handled or the end of
  288. // the interrupt object chain has been reached.
  289. //
  290. mov pr = loc7, -2
  291. NESTED_RETURN
  292. Kic_PerfLog:
  293. mov out0 = rFptr // ISR Plabel
  294. mov out1 = v0 // Pass the return value.
  295. mov loc9 = v0 // Save v0
  296. br.call.sptk brp = PerfInfoLogInterrupt
  297. ;;
  298. mov v0 = loc9 // Restore v0
  299. br.sptk Kic_Return // Return to normal execution.
  300. NESTED_EXIT(KiChainedDispatch)
  301. SBTTL("Interrupt Dispatch - Raise IRQL")
  302. //++
  303. //
  304. // Routine Description:
  305. //
  306. // This routine is entered as the result of an interrupt being generated
  307. // via a vector that is connected to an interrupt object. Its function is
  308. // to directly call the specified interrupt service routine.
  309. //
  310. // N.B. On entry to this routine only the volatile integer registers have
  311. // been saved. Also volatile lower floating point registers saved.
  312. //
  313. // N.B. This routine raises the interrupt level to the synchronization
  314. // level specified in the interrupt object.
  315. //
  316. // N.B. gp will be destroyed by the interrupt service routine; if this code
  317. // uses the gp of this module after the call, then it must save and
  318. // restore gp.
  319. //
  320. // Arguments:
  321. //
  322. // a0 - Supplies a function pointer to the ISR (in the interrupt object
  323. // dispatch code).
  324. //
  325. // a1 - Supplies a pointer to a trap frame.
  326. //
  327. // Return Value:
  328. //
  329. // None.
  330. //
  331. //--
  332. NESTED_ENTRY(KiInterruptDispatchRaise)
  333. NESTED_SETUP(2,4,2,0)
  334. PROLOGUE_END
  335. //
  336. // Register aliases
  337. //
  338. rpSpinLock = loc2
  339. rSirql = loc3 // sync IRQL
  340. //
  341. // Raise IRQL to synchronization level.
  342. //
  343. add t1 = InSynchronizeIrql-InDispatchCode, a0
  344. add t2 = InActualLock-InDispatchCode, a0
  345. add out0 = -InDispatchCode, a0 // out0 -> interrupt object
  346. ;;
  347. ld1.nt1 rSirql = [t1], InActualLock-InSynchronizeIrql
  348. #if !defined(NT_UP)
  349. ld8.nt1 rpSpinLock = [t2] // get address of spin lock
  350. #endif // !defined(NT_UP)
  351. add t5 = InServiceRoutine, out0 // pointer to fptr
  352. ;;
  353. ld8.nt1 t5 = [t5] // get function pointer
  354. SET_IRQL (rSirql) // raise to synchronization IRQL
  355. add t3 = InServiceContext, out0 // pointer to service context
  356. ;;
  357. #ifdef _CAPKERN
  358. mov t6 = out0;;
  359. movl out0 = @fptr(KiInterruptDispatchRaise)
  360. mov out1 = t5
  361. br.call.sptk.few b0=_CAP_Start_Profiling2;;
  362. mov out0 = t6;;
  363. #endif
  364. ld8.nt1 t6 = [t5], PlGlobalPointer-PlEntryPoint
  365. ld8.nt1 out1 = [t3] // get service context
  366. //
  367. //
  368. // Acquire the service routine spin lock and call the service routine.
  369. //
  370. #if !defined(NT_UP)
  371. #ifndef CAPKERN_SYNCH_POINTS
  372. ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kidr_Lock)
  373. #else
  374. CAP_ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kidr_Lock,t3,t7,t8,t9)
  375. #endif
  376. #endif // !defined(NT_UP)
  377. ;;
  378. ld8.nt1 gp = [t5]
  379. mov bt0 = t6 // set br address
  380. br.call.sptk brp = bt0 // call ISR
  381. ;;
  382. CAPEND(KiInterruptDispatchRaise)
  383. //
  384. // Release the service routine spin lock.
  385. //
  386. #if !defined(NT_UP)
  387. #ifndef CAPKERN_SYNCH_POINTS
  388. RELEASE_SPINLOCK(rpSpinLock)
  389. #else
  390. CAP_RELEASE_SPINLOCK(rpSpinLock, t3,t7,t8,t9, pt0)
  391. #endif
  392. #endif // !defined(NT_UP)
  393. //
  394. // IRQL lowered to the previous level in the external handler.
  395. //
  396. NESTED_RETURN
  397. NESTED_EXIT(KiInterruptDispatchRaise)
  398. //
  399. SBTTL("Interrupt Dispatch - Same IRQL")
  400. //++
  401. //
  402. // Routine Description:
  403. //
  404. // This routine is entered as the result of an interrupt being generated
  405. // via a vector that is connected to an interrupt object. Its function is
  406. // to directly call the specified interrupt service routine.
  407. //
  408. // N.B. On entry to this routine only the volatile integer registers have
  409. // been saved. Also the volatile lower float point registers.
  410. //
  411. // N.B. gp will be destroyed by the interrupt service routine; if this code
  412. // uses the gp of this module after the call, then it must save and
  413. // restore gp.
  414. //
  415. // Arguments:
  416. //
  417. // a0 - Supplies a function pointer to the ISR (in the interrupt object
  418. // dispatch code).
  419. //
  420. // a1 - Supplies a pointer to a trap frame..
  421. //
  422. // Return Value:
  423. //
  424. // None.
  425. //
  426. //--
  427. #if defined(NT_UP)
  428. LEAF_ENTRY(KiInterruptDispatchSame)
  429. alloc t3 = ar.pfs, 2, 0, 0, 0
  430. add a0 = -InDispatchCode, a0 // a0 points to interrupt object
  431. ;;
  432. add t2 = InServiceRoutine, a0 // -> service routine fptr
  433. add t1 = InServiceContext, a0 // -> service context
  434. ;;
  435. ld8.nt1 t2 = [t2] // service routine fptr
  436. ld8.nt1 a1 = [t1] // service context
  437. ;;
  438. ld8.nt1 t5 = [t2], PlGlobalPointer-PlEntryPoint
  439. ;;
  440. ld8.nt1 gp = [t2]
  441. mov bt0 = t5
  442. br.sptk.many bt0 // branch to service routine
  443. //
  444. // N.B.: Return to trap handler from ISR.
  445. //
  446. LEAF_EXIT(KiInterruptDispatchSame)
  447. #else
  448. NESTED_ENTRY(KiInterruptDispatchSame)
  449. .regstk 2,8,3,0
  450. .prologue 0x0D, loc0
  451. alloc savedpfs=ar.pfs,2,8,3,0
  452. mov savedbrp=brp;
  453. mov loc2 = pr
  454. PROLOGUE_END
  455. //
  456. // Register aliases
  457. //
  458. rpSpinLock = loc3
  459. //
  460. //
  461. // Acquire the service routine spin lock and call the service routine.
  462. //
  463. add loc4 = @gprel(PPerfGlobalGroupMask), gp
  464. add out0 = -InDispatchCode, a0 // -> interrupt object
  465. mov loc7 = gp // Save gp
  466. ;;
  467. add loc5 = InServiceRoutine, out0 // addr of function pointer
  468. add t1 = InActualLock, out0 // pointer to address of lock
  469. ld8.nt1 loc4 = [loc4] // Load PPerfGlobalGroupMask pointer
  470. ;;
  471. ld8.nt1 loc5 = [loc5] // get function pointer
  472. ld8.nt1 rpSpinLock = [t1], InServiceContext-InActualLock
  473. cmp.ne ps5 = 0, loc4 // Test PPerfGlobalGroupMask point for !0
  474. ;;
  475. add loc4 = PERF_INTERRUPT_OFFSET, loc4
  476. #ifndef CAPKERN_SYNCH_POINTS
  477. ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kids_Lock)
  478. #else
  479. CAP_ACQUIRE_SPINLOCK(rpSpinLock, rpSpinLock, Kids_Lock ,t2,t3,t4,t5)
  480. #endif
  481. #ifdef _CAPKERN
  482. mov t5 = out0;;
  483. movl out0 = @fptr(KiInterruptDispatchSame)
  484. mov out1 = loc5
  485. br.call.sptk.few b0=_CAP_Start_Profiling2;;
  486. mov out0 = t5;;
  487. #endif
  488. (ps5) ld4.nt1 t4 = [loc4]
  489. ld8.nt1 t5 = [loc5], PlGlobalPointer-PlEntryPoint
  490. ld8.nt1 out1 = [t1] // get service context
  491. ;;
  492. mov bt0 = t5 // set br address
  493. (ps5) tbit.nz ps5 = t4, PREF_INT_FLAG_SHIFT
  494. ld8.nt1 gp = [loc5],PlEntryPoint-PlGlobalPointer
  495. mov loc4 = ar.itc // Capture the current time.
  496. br.call.sptk.many brp = bt0 // call ISR
  497. ;;
  498. CAPEND(KiInterruptDispatchSame)
  499. //
  500. // Release the service routine spin lock.
  501. //
  502. #ifndef CAPKERN_SYNCH_POINTS
  503. RELEASE_SPINLOCK(rpSpinLock)
  504. #else
  505. CAP_RELEASE_SPINLOCK(rpSpinLock, t4,t5,t6,t7, pt0)
  506. #endif
  507. (ps5) br.spnt Kids_PerfLog
  508. mov pr = loc2
  509. NESTED_RETURN
  510. Kids_PerfLog:
  511. mov out0 = loc5 // ISR Plabel
  512. mov gp = loc7 // Restore GP
  513. mov out1 = v0 // Pass the return value.
  514. mov out2 = loc4 // Pass the start time.
  515. br.call.sptk brp = PerfInfoLogInterrupt
  516. ;;
  517. mov pr = loc2
  518. NESTED_RETURN
  519. NESTED_EXIT(KiInterruptDispatchSame)
  520. #endif // !defined(NT_UP)
  521. SBTTL("Disable Interrupts")
  522. //++
  523. //
  524. // BOOLEAN
  525. // KeDisableInterrupts (
  526. // VOID
  527. // )
  528. //
  529. // Routine Description:
  530. //
  531. // This function disables interrupts and returns whether interrupts
  532. // were previously enabled.
  533. //
  534. // Arguments:
  535. //
  536. // None.
  537. //
  538. // Return Value:
  539. //
  540. // A boolean value that determines whether interrupts were previously
  541. // enabled (TRUE) or disabled(FALSE).
  542. //
  543. //--
  544. LEAF_ENTRY(KeDisableInterrupts)
  545. DISABLE_INTERRUPTS(t0) // t0 = previous state
  546. ;;
  547. tbit.nz pt0, pt1 = t0, PSR_I // pt0 = 1, if enabled; pt1 = 1 if disabled
  548. ;;
  549. (pt0) mov v0 = TRUE // set return value -- TRUE if enabled
  550. (pt1) mov v0 = FALSE // FALSE if disabled
  551. LEAF_RETURN
  552. LEAF_EXIT(KeDisableInterrupts)
  553. //++
  554. //
  555. // VOID
  556. // KiPassiveRelease (
  557. // VOID
  558. // )
  559. //
  560. // Routine Description:
  561. //
  562. // This function is called when an interrupt has been passively released.
  563. //
  564. // Arguments:
  565. //
  566. // None.
  567. //
  568. // Return Value:
  569. //
  570. // None.
  571. //
  572. //--
  573. LEAF_ENTRY(KiPassiveRelease)
  574. LEAF_RETURN
  575. LEAF_EXIT(KiPassiveRelease)
  576. SBTTL("Unexpected Interrupt")
  577. //++
  578. //
  579. // Routine Description:
  580. //
  581. // This routine is entered as the result of an interrupt being generated
  582. // via a vector that is not connected to an interrupt object. Its function
  583. // is to report the error and dismiss the interrupt.
  584. //
  585. // N.B. On entry to this routine only the volatile integer registers have
  586. // been saved. Also the volatile lower float point registers.
  587. //
  588. // Arguments:
  589. //
  590. // a0 - Supplies a function pointer to the ISR (in the interrupt object
  591. // dispatch code).
  592. //
  593. // a1 - Supplies a pointer to a trap frame.
  594. //
  595. // Return Value:
  596. //
  597. // None.
  598. //
  599. //--
  600. LEAF_ENTRY(KiUnexpectedInterrupt)
  601. LEAF_RETURN
  602. LEAF_EXIT(KiUnexpectedInterrupt)
  603. LEAF_ENTRY(KiFloatingDispatch)
  604. LEAF_RETURN
  605. LEAF_EXIT(KiFloatingDispatch)