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.

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