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.

989 lines
24 KiB

  1. ;++
  2. ;
  3. ; Copyright (c) Microsoft Corporation. All rights reserved.
  4. ;
  5. ;
  6. ; Module:
  7. ;
  8. ; kxamd64.w
  9. ;
  10. ; Astract:
  11. ;
  12. ; Contains AMD64 architecture constants and assembly macros.
  13. ;
  14. ; Author:
  15. ;
  16. ; David N. Cutler (davec) 27-May-2000
  17. ;
  18. ; Revision History:
  19. ;
  20. ;--
  21. ;
  22. ; Define macros to build unwind data for prologues.
  23. ;
  24. push_reg macro Reg
  25. pushq Reg
  26. .pushreg Reg
  27. endm
  28. push_eflags macro
  29. pushfq
  30. .allocstack 8
  31. endm
  32. alloc_stack macro Size
  33. sub rsp, Size
  34. .allocstack Size
  35. endm
  36. save_reg macro Reg, Offset
  37. mov Offset[rsp], Reg
  38. .savereg Reg, Offset
  39. endm
  40. save_xmm macro Reg, Offset
  41. movq Offset[rsp], Reg
  42. .savexmm Reg, Offset
  43. endm
  44. save_xmm128 macro Reg, Offset
  45. movdqa Offset[rsp], Reg
  46. .savexmm128 Reg, Offset
  47. endm
  48. push_frame macro Code
  49. .pushframe Code
  50. endm
  51. set_frame macro Reg, Offset
  52. if Offset
  53. lea Reg, Offset[rsp]
  54. else
  55. mov reg, rsp
  56. endif
  57. .setframe Reg, Offset
  58. endm
  59. END_PROLOGUE macro
  60. .endprolog
  61. endm
  62. ;
  63. ; Define macro to acquire spin lock.
  64. ;
  65. ; Arguments:
  66. ;
  67. ; None.
  68. ;
  69. ; N.B. The register r11 is destroyed by this macro.
  70. ;
  71. ; N.B. This macro is restricted to using only r11.
  72. ;
  73. AcquireSpinLock macro Address
  74. local exit, spin
  75. ifndef NT_UP
  76. ifdifi <Address>, <r11>
  77. mov r11, Address ; get spin lock address
  78. endif
  79. lock bts qword ptr [r11], 0 ; attempt to acquire spin lock
  80. jnc short exit ; if nc, spin lock acquired
  81. spin: bt qword ptr [r11], 0 ; check if lock currently owned
  82. jc short spin ; if c, spin lock owned
  83. lock bts qword ptr [r11], 0 ; attempt to acquire spin lock
  84. jc short spin ; if c, spin lock owned
  85. exit: ; continue
  86. endif
  87. endm
  88. ;
  89. ; Define macro to release spin lock.
  90. ;
  91. ; Arguments:
  92. ;
  93. ; None.
  94. ;
  95. ; N.B. The register r11 is destroyed by this macro.
  96. ;
  97. ; N.B. This macro is restricted to using only r11.
  98. ;
  99. ReleaseSpinLock macro Address
  100. ifndef NT_UP
  101. ifdifi <Address>, <r11>
  102. mov r11, Address ; get spin lock address
  103. endif
  104. mov qword ptr [r11], 0 ; release spin lock
  105. endif
  106. endm
  107. ;
  108. ; Define macro to try to acquire spin lock.
  109. ;
  110. ; Arguments:
  111. ;
  112. ; None.
  113. ;
  114. ; N.B. The register r11 is destroyed by this macro.
  115. ;
  116. ; N.B. This macro is restricted to using only r11.
  117. ;
  118. TryToAcquireSpinLock macro Address
  119. ifndef NT_UP
  120. ifdifi <Address>, <r11>
  121. mov r11, Address ; get spin lock address
  122. endif
  123. lock bts qword ptr [r11], 0 ; attempt to acquire spin lock
  124. endif
  125. endm
  126. ;
  127. ; Define macro to perform the equivalent of reading cr8.
  128. ;
  129. ; Arguments:
  130. ;
  131. ; None
  132. ;
  133. ; The equivalent of the contents of cr8 is returned in rax
  134. ;
  135. ; N.B. This macro is restricted to using only rax.
  136. ;
  137. ReadCr8 macro
  138. mov rax, cr8 ; read IRQL
  139. endm
  140. ;
  141. ; Define macro to perform the equivalent of writing cr8.
  142. ;
  143. ; Arguments:
  144. ;
  145. ; rcx - The desired value of cr8.
  146. ;
  147. WriteCr8 macro
  148. mov cr8, rcx ; write IRQL
  149. endm
  150. ;
  151. ; Define macro to get current IRQL.
  152. ;
  153. ; Arguments:
  154. ;
  155. ; None.
  156. ;
  157. ; The previous IRQL is returned in rax.
  158. ;
  159. CurrentIrql macro
  160. ReadCr8 ; get current IRQL
  161. endm
  162. ;
  163. ; Define macro to lower IRQL.
  164. ;
  165. ; Arguments:
  166. ;
  167. ; rcx - Supplies the new IRQL.
  168. ;
  169. ; N.B. The register rax is destroyed.
  170. ;
  171. ; N.B. This macro is restricted to using only rax and rcx.
  172. ;
  173. LowerIrql macro
  174. local exit
  175. if DBG
  176. ReadCr8 ; get current IRQL
  177. cmp eax, ecx ; check new IRQL
  178. jge short exit ; if ge, new IRQL okay
  179. int 3 ; break into debugger
  180. endif
  181. exit: WriteCr8 ; set new IRQL
  182. endm
  183. ;
  184. ; Define macro to raise IRQL.
  185. ;
  186. ; Arguments:
  187. ;
  188. ; rcx - Supplies the new IRQL.
  189. ;
  190. ; The previous IRQL is returned in rax.
  191. ;
  192. ; N.B. This macro is restricted to using only rax and rcx.
  193. ;
  194. RaiseIrql macro
  195. local exit
  196. ReadCr8 ; get current IRQL
  197. if DBG
  198. cmp eax, ecx ; check new IRQL
  199. jle short exit ; if le, new IRQL okay
  200. int 3 ; break into debugger
  201. endif
  202. exit: WriteCr8 ; set new IRQL
  203. endm
  204. ;
  205. ; Define macro to set IRQL.
  206. ;
  207. ; Arguments:
  208. ;
  209. ; rcx - Supplies the new IRQL.
  210. ;
  211. ; N.B. This macro is restricted to using only rcx.
  212. ;
  213. SetIrql macro
  214. WriteCr8 ; set new IRQL
  215. endm
  216. ;
  217. ; Define macro to swap IRQL.
  218. ;
  219. ; Arguments:
  220. ;
  221. ; rcx - Supplies the new IRQL.
  222. ;
  223. ; The previous IRQL is returned in rax.
  224. ;
  225. ; N.B. This macro is restricted to using only rax and rcx.
  226. ;
  227. SwapIrql macro
  228. ReadCr8 ; get current IRQL
  229. WriteCr8 ; set new IRQL
  230. endm
  231. ;
  232. ; Define alternate entry macro.
  233. ;
  234. ALTERNATE_ENTRY macro Name
  235. Name:
  236. endm
  237. ;
  238. ; Define function entry/end macros.
  239. ;
  240. LEAF_ENTRY macro Name, Section
  241. Section segment para 'CODE'
  242. align 16
  243. public Name
  244. Name proc
  245. endm
  246. LEAF_END macro Name, section
  247. Name endp
  248. Section ends
  249. endm
  250. NESTED_ENTRY macro Name, Section, Handler
  251. Section segment para 'CODE'
  252. align 16
  253. public Name
  254. ifb <Handler>
  255. Name proc frame
  256. else
  257. Name proc frame:Handler
  258. endif
  259. endm
  260. NESTED_END macro Name, section
  261. Name endp
  262. Section ends
  263. endm
  264. ;
  265. ; Define restore exception state macro.
  266. ;
  267. ; This macro restores the nonvolatile state.
  268. ;
  269. ; Arguments:
  270. ;
  271. ; Flag - If blank, then nonvolatile floating and integer registers are
  272. ; restored. If nonblank and identical to "Rbp", then rbp is restored
  273. ; in addition to the nonvolatile floating and integer registers. If
  274. ; nonblank and identical to "NoFp", then only the nonvolatile integer
  275. ; registers are restored.
  276. ;
  277. ; Implicit arguments:
  278. ;
  279. ; rsp - Supplies the address of the exception frame.
  280. ;
  281. RESTORE_EXCEPTION_STATE macro Flag
  282. ifdif <Flag>, <NoFp>
  283. movdqa xmm6, qword ptr ExXmm6[rsp] ; restore nonvolatile xmm registers
  284. movdqa xmm7, qword ptr ExXmm7[rsp] ;
  285. movdqa xmm8, qword ptr ExXmm8[rsp] ;
  286. movdqa xmm9, qword ptr ExXmm9[rsp] ;
  287. movdqa xmm10, qword ptr ExXmm10[rsp] ;
  288. movdqa xmm11, qword ptr ExXmm11[rsp] ;
  289. movdqa xmm12, qword ptr ExXmm12[rsp] ;
  290. movdqa xmm13, qword ptr ExXmm13[rsp] ;
  291. movdqa xmm14, qword ptr ExXmm14[rsp] ;
  292. movdqa xmm15, qword ptr ExXmm15[rsp] ;
  293. endif
  294. ifidn <Flag>, <NoPop>
  295. mov rbx, ExRbx[rsp] ; restore nonvolatile integer registers
  296. mov rdi, ExRdi[rsp] ;
  297. mov rsi, ExRsi[rsp] ;
  298. mov r12, ExR12[rsp] ;
  299. mov r13, ExR13[rsp] ;
  300. mov r14, ExR14[rsp] ;
  301. mov r15, ExR15[rsp] ;
  302. else
  303. ifidn <Flag>, <Rbp>
  304. add rsp, KEXCEPTION_FRAME_LENGTH - (9 * 8) ; deallocate frame
  305. pop rbp ; restore nonvolatile integer register
  306. else
  307. add rsp, KEXCEPTION_FRAME_LENGTH - (8 * 8) ; deallocate frame
  308. endif
  309. pop rbx ; restore integer nonvolatile registers
  310. pop rdi ;
  311. pop rsi ;
  312. pop r12 ;
  313. pop r13 ;
  314. pop r14 ;
  315. pop r15 ;
  316. endif
  317. endm
  318. ;
  319. ; Define generate exception frame macro.
  320. ;
  321. ; This macro allocates an exception frame and saves the nonvolatile state.
  322. ;
  323. ; Arguments:
  324. ;
  325. ; Flag - If blank, then nonvolatile floating and integer registers are
  326. ; saved. If nonblank and identical to "Rbp", then rbp is saved in
  327. ; addition to the nonvolatile floating and integer registers. If
  328. ; nonblank and identical to "NoFp", then only the nonvolatile integer
  329. ; registers are saved.
  330. ;
  331. ; Implicit arguments:
  332. ;
  333. ; The top of the stack is assumed to contain a return address.
  334. ;
  335. GENERATE_EXCEPTION_FRAME macro Flag
  336. push_reg r15 ; push integer nonvolatile registers
  337. push_reg r14 ;
  338. push_reg r13 ;
  339. push_reg r12 ;
  340. push_reg rsi ;
  341. push_reg rdi ;
  342. push_reg rbx ;
  343. ifidn <Flag>, <Rbp>
  344. push_reg rbp ; push frame pointer
  345. alloc_stack KEXCEPTION_FRAME_LENGTH - (9 * 8) ; allocate frame
  346. set_frame rbp, 0 ; set frame register
  347. else
  348. alloc_stack KEXCEPTION_FRAME_LENGTH - (8 * 8) ; allocate frame
  349. endif
  350. ifdif <Flag>, <NoFp>
  351. save_xmm128 xmm6, ExXmm6 ; save xmm nonvolatile registers
  352. save_xmm128 xmm7, ExXmm7 ;
  353. save_xmm128 xmm8, ExXmm8 ;
  354. save_xmm128 xmm9, ExXmm9 ;
  355. save_xmm128 xmm10, ExXmm10 ;
  356. save_xmm128 xmm11, ExXmm11 ;
  357. save_xmm128 xmm12, ExXmm12 ;
  358. save_xmm128 xmm13, ExXmm13 ;
  359. save_xmm128 xmm14, ExXmm14 ;
  360. save_xmm128 xmm15, ExXmm15 ;
  361. endif
  362. END_PROLOGUE
  363. endm
  364. ;
  365. ; Define restore trap state macro.
  366. ;
  367. ; This macro restores the volatile state, and if necessary, restorss the
  368. ; user debug state, deallocats the trap frame, and exits the trap.
  369. ;
  370. ; N.B. This macro must preserve eax in case it is not reloaded from the
  371. ; trap frame.
  372. ;
  373. ; Arguments:
  374. ;
  375. ; State - Determines what state is restored and what tests are made. Valid
  376. ; values are:
  377. ;
  378. ; Service - restore state for a service executed from user mode.
  379. ; Kernel - restore state for a service executed from kernel mode.
  380. ; Volatile - restore state for a trap or interrupt.
  381. ;
  382. ; Disable - If blank, then disable interrupts.
  383. ;
  384. ; Implicit arguments:
  385. ;
  386. ; rbp - Supplies the address of the trap frame.
  387. ;
  388. RESTORE_TRAP_STATE macro State, Disable
  389. local first, second, third
  390. ifb <Disable>
  391. cli ; disable interrupts
  392. endif
  393. ifdif <State>, <Kernel>
  394. ;
  395. ; State is either <Volatile> or <Service>
  396. ;
  397. ifidn <State>, <Volatile>
  398. test byte ptr TrSegCs[rbp], MODE_MASK ; test if previous mode user
  399. jz third ; if z, previous mode not user
  400. endif
  401. mov rcx, gs:[PcCurrentThread] ; get current thread address
  402. cmp byte ptr ThApcState + AsUserApcPending[rcx], 0 ; APC pending?
  403. je short first ; if e, no user APC pending
  404. ifidn <State>, <Service>
  405. mov TrRax[rbp], eax ; save service status
  406. xor eax, eax ; scrub volatile integer registers
  407. mov TrRcx[rbp], rax ;
  408. mov TrRdx[rbp], rax ;
  409. mov TrR8[rbp], rax ;
  410. mov TrR9[rbp], rax ;
  411. mov TrR10[rbp], rax ;
  412. mov TrR11[rbp], rax ;
  413. pxor xmm0, xmm0 ; scrub volatile floating registers
  414. movdqa qword ptr TrXmm0[rbp], xmm0 ;
  415. movdqa qword ptr TrXmm1[rbp], xmm0 ;
  416. movdqa qword ptr TrXmm2[rbp], xmm0 ;
  417. movdqa qword ptr TrXmm3[rbp], xmm0 ;
  418. movdqa qword ptr TrXmm4[rbp], xmm0 ;
  419. movdqa qword ptr TrXmm5[rbp], xmm0 ;
  420. endif
  421. mov ecx, APC_LEVEL ; get APC level
  422. SetIrql ; set IRQL to APC level
  423. sti ; allow interrupts
  424. call KiInitiateUserApc ; initiate APC execution
  425. cli ; disable interrupts
  426. mov ecx, PASSIVE_LEVEL ; get PASSIVE level
  427. SetIrql ; set IRQL to PASSIVE level
  428. ifidn <State>, <Service>
  429. mov eax, TrRax[rbp] ; restore service status
  430. endif
  431. first: ldmxcsr TrMxCsr[rbp] ; restore user mode XMM control/status
  432. test byte ptr TrDr7[rbp], DR7_ACTIVE ; test if user debug active
  433. jz short second ; if z, user debug not active
  434. xor edx, edx ; clear register
  435. mov dr7, rdx ; clear control before loading
  436. mov rcx, TrDr0[rbp] ; restore debug registers
  437. mov rdx, TrDr1[rbp] ;
  438. mov dr0, rcx ;
  439. mov dr1, rdx ;
  440. mov rcx, TrDr2[rbp] ;
  441. mov rdx, TrDr3[rbp] ;
  442. mov dr2, rcx ;
  443. mov dr3, rdx ;
  444. xor ecx, ecx ;
  445. mov rdx, TrDr7[rbp] ;
  446. mov dr6, rcx ;
  447. mov dr7, rdx ;
  448. second: ;
  449. ;
  450. ; At this point it is known that the return will be to user mode.
  451. ;
  452. ifidn <State>, <Volatile>
  453. movdqa xmm0, qword ptr TrXmm0[rbp] ; restore volatile XMM registers
  454. movdqa xmm1, qword ptr TrXmm1[rbp] ;
  455. movdqa xmm2, qword ptr TrXmm2[rbp] ;
  456. movdqa xmm3, qword ptr TrXmm3[rbp] ;
  457. movdqa xmm4, qword ptr TrXmm4[rbp] ;
  458. movdqa xmm5, qword ptr TrXmm5[rbp] ;
  459. mov r11, TrR11[rbp] ; restore volatile integer state
  460. mov r10, TrR10[rbp] ;
  461. mov r9, TrR9[rbp] ;
  462. mov r8, TrR8[rbp] ;
  463. mov rdx, TrRdx[rbp] ;
  464. mov rcx, TrRcx[rbp] ;
  465. mov rax, TrRax[rbp] ;
  466. mov rsp, rbp ; trim stack to frame offset
  467. mov rbp, TrRbp[rbp] ; restore RBP
  468. add rsp, (KTRAP_FRAME_LENGTH - (5 * 8) - 128) ; deallocate stack
  469. swapgs ; swap GS base to user mode TEB
  470. iretq ;
  471. else
  472. xor edx, edx ; scrub volatile integer registers
  473. xor r8, r8 ;
  474. xor r9, r9 ;
  475. xor r10, r10 ;
  476. pxor xmm0, xmm0 ; scrub volatile floating registers
  477. pxor xmm1, xmm1 ;
  478. pxor xmm2, xmm2 ;
  479. pxor xmm3, xmm3 ;
  480. pxor xmm4, xmm4 ;
  481. pxor xmm5, xmm5 ;
  482. mov rcx, TrRip[rbp] ; get return address
  483. mov r11, TrEFlags[rbp] ; get previous EFLAGS
  484. mov rsp, rbp ; trim stack to frame offset
  485. mov rbp, TrRbp[rbp] ; restore RBP
  486. mov rsp, TrRsp[rsp] ; restore RSP
  487. swapgs ; swap GS base to user mode TEB
  488. sysretq ; return from system call to user mode
  489. endif
  490. ifidn <State>, <Volatile>
  491. third: movdqa xmm0, qword ptr TrXmm0[rbp] ; restore volatile XMM registers
  492. movdqa xmm1, qword ptr TrXmm1[rbp] ;
  493. movdqa xmm2, qword ptr TrXmm2[rbp] ;
  494. movdqa xmm3, qword ptr TrXmm3[rbp] ;
  495. movdqa xmm4, qword ptr TrXmm4[rbp] ;
  496. movdqa xmm5, qword ptr TrXmm5[rbp] ;
  497. mov r11, TrR11[rbp] ; restore volatile integer state
  498. mov r10, TrR10[rbp] ;
  499. mov r9, TrR9[rbp] ;
  500. mov r8, TrR8[rbp] ;
  501. mov rdx, TrRdx[rbp] ;
  502. mov rcx, TrRcx[rbp] ;
  503. mov rax, TrRax[rbp] ;
  504. mov rsp, rbp ; trim stack to frame offset
  505. mov rbp, TrRbp[rbp] ; restore RBP
  506. add rsp, (KTRAP_FRAME_LENGTH - (5 * 8) - 128) ; deallocate stack
  507. iretq ;
  508. endif
  509. ;
  510. ; State is <Kernel>
  511. ;
  512. else
  513. mov rsp, rbp ; trim stack to frame offset
  514. mov rbp, TrRbp[rbp] ; restore RBP
  515. mov rsp, TrRsp[rsp] ; restore RSP
  516. sti ; enable interrupts
  517. ret ; return from system call to kernel mode
  518. endif
  519. endm
  520. ;
  521. ; Define save trap state macro.
  522. ;
  523. ; This macro saves the volatile state, and if necessary, saves the user
  524. ; debug state and loads the kernel debug state.
  525. ;
  526. ; Arguments:
  527. ;
  528. ; Service - If non-blank, then a partial trap frame is being restored for
  529. ; a system service.
  530. ;
  531. ; Implicit arguments:
  532. ;
  533. ; rbp - Supplies the address of the trap frame.
  534. ;
  535. SAVE_TRAP_STATE macro Service
  536. local first, second, third
  537. ifb <Service>
  538. mov TrRax[rbp], rax ; save volatile integer registers
  539. mov TrRcx[rbp], rcx ;
  540. mov TrRdx[rbp], rdx ;
  541. mov TrR8[rbp], r8 ;
  542. mov TrR9[rbp], r9 ;
  543. mov TrR10[rbp], r10 ;
  544. mov TrR11[rbp], r11 ;
  545. endif
  546. test byte ptr TrSegCs[rbp], MODE_MASK ; test if previous mode user
  547. jz third ; if z, previous mode kernel
  548. ifb <Service>
  549. swapgs ; swap GS base to kernel mode PCR
  550. endif
  551. stmxcsr TrMxCsr[rbp] ; save XMM control/status
  552. ldmxcsr dword ptr gs:[PcMxCsr] ; set default XMM control/status
  553. mov r10, gs:[PcCurrentThread] ; get current thread address
  554. xor r11, r11 ; clear register
  555. test byte ptr ThDebugActive[r10], DR7_ACTIVE ; test if break enabled
  556. jz short first ; if z, break not enabled
  557. mov r10, dr0 ; save debug registers
  558. mov r11, dr1 ;
  559. mov TrDr0[rbp], r10 ;
  560. mov TrDr1[rbp], r11 ;
  561. mov r10, dr2 ;
  562. mov r11, dr3 ;
  563. mov TrDr2[rbp], r10 ;
  564. mov TrDr3[rbp], r11 ;
  565. mov r10, dr6 ;
  566. mov r11, dr7 ;
  567. mov TrDr6[rbp], r10 ;
  568. first: mov TrDr7[rbp], r11 ;
  569. xor r11, r11 ; assume debug breakpoints not active
  570. test byte ptr gs:[PcKernelDr7], DR7_ACTIVE ; test if breakpoints enabled
  571. jz short second ; if z, no breakpoints enabled
  572. mov dr7, r11 ; clear control register before loading registers
  573. mov r10, gs:[PcKernelDr0] ; set debug registers
  574. mov r11, gs:[PcKernelDr1] ;
  575. mov dr0, r10 ;
  576. mov dr1, r11 ;
  577. mov r10, gs:[PcKernelDr2] ;
  578. mov r11, gs:[PcKernelDr3] ;
  579. mov dr2, r10 ;
  580. mov dr3, r11 ;
  581. xor r10, r10 ;
  582. mov r11, gs:[PcKernelDr7] ;
  583. mov dr6, r10 ;
  584. second: mov dr7, r11 ;
  585. third: cld ; clear direction flag
  586. ifb <Service>
  587. movdqa qword ptr TrXmm0[rbp], xmm0 ; save volatile xmm registers
  588. movdqa qword ptr TrXmm1[rbp], xmm1 ;
  589. movdqa qword ptr TrXmm2[rbp], xmm2 ;
  590. movdqa qword ptr TrXmm3[rbp], xmm3 ;
  591. movdqa qword ptr TrXmm4[rbp], xmm4 ;
  592. movdqa qword ptr TrXmm5[rbp], xmm5 ;
  593. endif
  594. endm
  595. ;
  596. ; Define interrupt frame generation macro.
  597. ;
  598. ; This macro generates an interrupt frame.
  599. ;
  600. ; Arguments:
  601. ;
  602. ; Vector - If non-blank, then the vector number is on the stack.
  603. ;
  604. ; Return value:
  605. ;
  606. ; If Vector is non-blank, then the value of the vector is returned in eax.
  607. ;
  608. GENERATE_INTERRUPT_FRAME macro Vector
  609. ;
  610. ; At this point the hardware frame has been pushed onto an aligned stack. The
  611. ; vector number or a dummy vector number and rbp have also been pushed on the
  612. ; stack.
  613. ;
  614. push_reg rsi ; save nonvolatile register
  615. alloc_stack (KTRAP_FRAME_LENGTH - (8 * 8)) ; allocate fixed frame
  616. mov rsi, rbp ; set address of interrupt object
  617. set_frame rbp, 128 ; set frame pointer
  618. END_PROLOGUE
  619. SAVE_TRAP_STATE ; save trap state
  620. ifnb <Vector>
  621. mov eax, TrErrorCode[rbp] ; return vector number
  622. endif
  623. inc dword ptr gs:[PcInterruptCount] ; increment interrupt count
  624. endm
  625. ;
  626. ; Define enter interrupt macro.
  627. ;
  628. ; This macro raises IRQL, sets the interrupt flag, records the previous
  629. ; IRQL in the trap frame, and invokes the HAL to perform an EOI.
  630. ;
  631. ; Arguments:
  632. ;
  633. ; NoEOI - If blank, then generate end of interrupt.
  634. ;
  635. ; Implicit arguments:
  636. ;
  637. ; rcx - Supplies the interrupt IRQL.
  638. ;
  639. ; rbp - Supplies the address of the trap frame.
  640. ;
  641. ; Interrupt flag is clear.
  642. ;
  643. ; Return Value:
  644. ;
  645. ; None.
  646. ;
  647. ENTER_INTERRUPT macro NoEOI
  648. ;
  649. ; N.B. It is possible for a interrupt to occur at an IRQL that is lower
  650. ; than the current IRQL. This happens when the IRQL raised and at
  651. ; the same time an interrupt request is granted.
  652. ;
  653. RaiseIrql ; raise IRQL to interrupt level
  654. mov TrPreviousIrql[rbp], al ; save previous IRQL
  655. ifb <NoEOI>
  656. call __imp_HalEndSystemInterrupt ; perform EOI
  657. endif
  658. sti ; enable interrupts
  659. endm
  660. ;
  661. ; Define exit interrupt macro.
  662. ;
  663. ; This macro exits an interrupt.
  664. ;
  665. ; Arguments:
  666. ;
  667. ; NoEOI - If blank, then generate end of interrupt.
  668. ;
  669. ; Implicit arguments:
  670. ;
  671. ; rbp - Supplies the address of the trap frame.
  672. ;
  673. ; Return Value:
  674. ;
  675. ; None.
  676. ;
  677. EXIT_INTERRUPT macro NoEOI
  678. ifb <NoEOI>
  679. call __imp_HalEndSystemInterrupt ; perform EOI
  680. endif
  681. movzx ecx, byte ptr TrPreviousIrql[rbp] ; get previous IRQL
  682. cli ; disable interrupts
  683. SetIrql ; set IRQL to previous level
  684. mov rsi, TrRsi[rbp] ; restore extra register
  685. RESTORE_TRAP_STATE <Volatile>, <NoDisable> ; restore trap state
  686. endm
  687. ;
  688. ; Define trap frame generation macro.
  689. ;
  690. ; This macro generates a trap frame.
  691. ;
  692. ; Arguments:
  693. ;
  694. ; ErrorCode - If non-blank, then an error code is on the stack.
  695. ;
  696. ; Return value:
  697. ;
  698. ; If ErrorCode is non-blank, then the value of the error code is returned
  699. ; in eax.
  700. ;
  701. GENERATE_TRAP_FRAME macro ErrorCode
  702. local exit
  703. ifb <ErrorCode>
  704. push_frame ; mark machine frame without error code
  705. alloc_stack 8 ; allocate dummy error code
  706. else
  707. push_frame code ; mark machine frame with error code
  708. endif
  709. push_reg rbp ; save nonvolatile register
  710. alloc_stack (KTRAP_FRAME_LENGTH - (7 * 8)) ; allocate fixed frame
  711. set_frame rbp, 128 ; set frame pointer
  712. END_PROLOGUE
  713. SAVE_TRAP_STATE ; save trap state
  714. ifnb <ErrorCode>
  715. mov eax, TrErrorCode[rbp] ; return error code
  716. ifidn <ErrorCode>, <Virtual>
  717. mov rcx, cr2 ; return virtual address
  718. endif
  719. endif
  720. ;
  721. ; Enable interrupts if and only if they were enabled before the trap occurred.
  722. ; If the exception is not handled by the kernel debugger and interrupts were
  723. ; previously disabled, then a bug check will occur.
  724. ;
  725. test dword ptr TrEFlags[rbp], EFLAGS_IF_MASK ; check interrupt enabled
  726. jz short exit ; if z, interrupts not enabled
  727. sti ; enable interrupts
  728. exit: ; reference label
  729. endm