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.

472 lines
16 KiB

  1. title "Capture and Restore Context"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; capture.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the platform specific code to capture and restore
  13. ; the context of the caller.
  14. ;
  15. ; Author:
  16. ;
  17. ; David N. Cutler (davec) 4-Jul-2000
  18. ;
  19. ; Environment:
  20. ;
  21. ; Any mode.
  22. ;
  23. ;--
  24. include ksamd64.inc
  25. altentry RcConsolidateFrames
  26. subttl "Capture Context"
  27. ;++
  28. ;
  29. ; VOID
  30. ; RtlCaptureContext (
  31. ; IN PCONTEXT ContextRecord
  32. ; )
  33. ;
  34. ; Routine Description:
  35. ;
  36. ; This function captures the context of the caller in the specified
  37. ; context record.
  38. ;
  39. ; N.B. The stored value of registers rcx and rsp will be a side effect of
  40. ; having made this call. All other registers will be stored as they
  41. ; were when the call to this function was made.
  42. ;
  43. ; Arguments:
  44. ;
  45. ; ContextRecord (rcx) - Supplies a pointer to a context record.
  46. ;
  47. ; Return Value:
  48. ;
  49. ; None.
  50. ;
  51. ;--
  52. CcFrame struct
  53. EFlags dd ? ; saved procssor flags
  54. Fill dd ? ; fill
  55. CcFrame ends
  56. NESTED_ENTRY RtlCaptureContext, _TEXT$00
  57. push_eflags ; save processor flags
  58. END_PROLOGUE
  59. mov CxSegCs[rcx], cs ; save segment registers
  60. mov CxSegDs[rcx], ds ;
  61. mov CxSegEs[rcx], es ;
  62. mov CxSegSs[rcx], ss ;
  63. mov CxSegFs[rcx], fs ;
  64. mov CxSegGs[rcx], gs ;
  65. mov CxRax[rcx], rax ; save integer registers
  66. mov CxRcx[rcx], rcx ;
  67. mov CxRdx[rcx], rdx ;
  68. mov CxRbx[rcx], rbx ;
  69. lea rax, 16[rsp] ;
  70. mov CxRsp[rcx], rax ;
  71. mov CxRbp[rcx], rbp ;
  72. mov CxRsi[rcx], rsi ;
  73. mov CxRdi[rcx], rdi ;
  74. mov CxR8[rcx], r8 ;
  75. mov CxR9[rcx], r9 ;
  76. mov CxR10[rcx], r10 ;
  77. mov CxR11[rcx], r11 ;
  78. mov CxR12[rcx], r12 ;
  79. mov CxR13[rcx], r13 ;
  80. mov CxR14[rcx], r14 ;
  81. mov CxR15[rcx], r15 ;
  82. movdqa CxXmm0[rcx], xmm0 ; save xmm floating registers
  83. movdqa CxXmm1[rcx], xmm1 ;
  84. movdqa CxXmm2[rcx], xmm2 ;
  85. movdqa CxXmm3[rcx], xmm3 ;
  86. movdqa CxXmm4[rcx], xmm4 ;
  87. movdqa CxXmm5[rcx], xmm5 ;
  88. movdqa CxXmm6[rcx], xmm6 ;
  89. movdqa CxXmm7[rcx], xmm7 ;
  90. movdqa CxXmm8[rcx], xmm8 ;
  91. movdqa CxXmm9[rcx], xmm9 ;
  92. movdqa CxXmm10[rcx], xmm10 ;
  93. movdqa CxXmm11[rcx], xmm11 ;
  94. movdqa CxXmm12[rcx], xmm12 ;
  95. movdqa CxXmm13[rcx], xmm13 ;
  96. movdqa CxXmm14[rcx], xmm14 ;
  97. movdqa CxXmm15[rcx], xmm15 ;
  98. stmxcsr CxMxCsr[rcx] ; save xmm floating state
  99. ifndef NTOS_KERNEL_RUNTIME
  100. fnsaved CxFltSave[rcx] ; save legacy floating state
  101. endif
  102. mov rax, 8[rsp] ; set return address
  103. mov CxRip[rcx], rax ;
  104. mov eax, Ccframe.EFlags[rsp] ; set processor flags
  105. mov CxEFlags[rcx], eax ;
  106. mov dword ptr CxContextFlags[rcx], CONTEXT_FULL ; set context flags
  107. add rsp, sizeof CcFrame ; deallocate stack frame
  108. ret ; return
  109. NESTED_END RtlCaptureContext, _TEXT$00
  110. subttl "Restore Context"
  111. ;++
  112. ;
  113. ; VOID
  114. ; RtlRestoreContext (
  115. ; IN PCONTEXT ContextRecord,
  116. ; IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL
  117. ; )
  118. ;
  119. ; Routine Description:
  120. ;
  121. ; This function restores the context of the caller to the specified
  122. ; context.
  123. ;
  124. ; Arguments:
  125. ;
  126. ; ContextRecord (rcx) - Supplies a pointer to a context record.
  127. ;
  128. ; ExceptionRecord (rdx) - Supplies an optional pointer to an exception
  129. ; record.
  130. ;
  131. ; Return Value:
  132. ;
  133. ; None - there is no return from this function.
  134. ;
  135. ;--
  136. RcFrame struct
  137. Mframe db MachineFrameLength dup (?) ; machine frame
  138. Fill dq ? ; fill to 0 mod 16
  139. RcFrame ends
  140. NESTED_ENTRY RtlRestoreContext, _TEXT$00
  141. push_reg rbp ; save nonvolatile registers
  142. push_reg rsi ;
  143. push_reg rdi ;
  144. alloc_stack (sizeof RcFrame) ; allocate stack frame
  145. set_frame rbp, 0 ; set frame pointer
  146. END_PROLOGUE
  147. ;
  148. ; If an exception record is specified and the exception status is the unwind
  149. ; consolidation code and there is at least one parameter, then consolidate
  150. ; all the frames that have been unwound and call back to a language specified
  151. ; routine.
  152. ;
  153. test rdx, rdx ; test if exception record specified
  154. jz Rc10 ; if z, no exception record specified
  155. cmp dword ptr ErExceptionCode[rdx], STATUS_UNWIND_CONSOLIDATE ; check call back
  156. jne short Rc05 ; if ne, not C++ unwind
  157. cmp dword ptr ErNumberParameters[rdx], 1 ; check number parameters
  158. jae Rc20 ; if ae, unwind consolidation
  159. ;
  160. ; If an exception record is specified and the exception status is long jump,
  161. ; then restore the nonvolatile registers to their state at the call to set
  162. ; jump before restoring the context record.
  163. ;
  164. Rc05: cmp dword ptr ErExceptionCode[rdx], STATUS_LONGJUMP ; check for long jump
  165. jne Rc10 ; if ne, not a long jump
  166. ;
  167. ; Long jump unwind.
  168. ;
  169. ; Copy register values from the jump buffer to the context record.
  170. ;
  171. mov rax, ErExceptionInformation[rdx] ; get jump buffer address
  172. mov r8, JbRbx[rax] ; move nonvolatile integer registers
  173. mov CxRbx[rcx], r8 ; to context record
  174. mov r8, JbRsp[rax] ;
  175. mov CxRsp[rcx], r8 ;
  176. mov r8, JbRbp[rax] ;
  177. mov CxRbp[rcx], r8 ;
  178. mov r8, JbRsi[rax] ;
  179. mov CxRsi[rcx], r8 ;
  180. mov r8, JbRdi[rax] ;
  181. mov CxRdi[rcx], r8 ;
  182. mov r8, JbR12[rax] ;
  183. mov CxR12[rcx], r8 ;
  184. mov r8, JbR13[rax] ;
  185. mov CxR13[rcx], r8 ;
  186. mov r8, JbR14[rax] ;
  187. mov CxR14[rcx], r8 ;
  188. mov r8, JbR15[rax] ;
  189. mov CxR15[rcx], r8 ;
  190. mov r8, JbRip[rax] ;
  191. mov CxRip[rcx], r8 ;
  192. movdqa xmm0, JbXmm6[rax] ; move nonvolatile floating register
  193. movdqa CxXmm6[rcx], xmm0 ; to context record
  194. movdqa xmm0, JbXmm7[rax] ;
  195. movdqa CxXmm7[rcx], xmm0 ;
  196. movdqa xmm0, JbXmm8[rax] ;
  197. movdqa CxXmm8[rcx], xmm0 ;
  198. movdqa xmm0, JbXmm9[rax] ;
  199. movdqa CxXmm9[rcx], xmm0 ;
  200. movdqa xmm0, JbXmm10[rax] ;
  201. movdqa CxXmm10[rcx], xmm0 ;
  202. movdqa xmm0, JbXmm11[rax] ;
  203. movdqa CxXmm11[rcx], xmm0 ;
  204. movdqa xmm0, JbXmm12[rax] ;
  205. movdqa CxXmm12[rcx], xmm0 ;
  206. movdqa xmm0, JbXmm13[rax] ;
  207. movdqa CxXmm13[rcx], xmm0 ;
  208. movdqa xmm0, JbXmm14[rax] ;
  209. movdqa CxXmm14[rcx], xmm0 ;
  210. movdqa xmm0, JbXmm15[rax] ;
  211. movdqa CxXmm15[rcx], xmm0 ;
  212. ;
  213. ; Restore context and continue.
  214. ;
  215. Rc10: movdqa xmm0, CxXmm0[rcx] ; restore floating registers
  216. movdqa xmm1, CxXmm1[rcx] ;
  217. movdqa xmm2, CxXmm2[rcx] ;
  218. movdqa xmm3, CxXmm3[rcx] ;
  219. movdqa xmm4, CxXmm4[rcx] ;
  220. movdqa xmm5, CxXmm5[rcx] ;
  221. movdqa xmm6, CxXmm6[rcx] ;
  222. movdqa xmm7, CxXmm7[rcx] ;
  223. movdqa xmm8, CxXmm8[rcx] ;
  224. movdqa xmm9, CxXmm9[rcx] ;
  225. movdqa xmm10, CxXmm10[rcx] ;
  226. movdqa xmm11, CxXmm11[rcx] ;
  227. movdqa xmm12, CxXmm12[rcx] ;
  228. movdqa xmm13, CxXmm13[rcx] ;
  229. movdqa xmm14, CxXmm14[rcx] ;
  230. movdqa xmm15, CxXmm15[rcx] ;
  231. ldmxcsr CxMxCsr[rcx] ; restore floating state
  232. mov eax, CxSegSs[rcx] ; set SS segment
  233. mov MfSegSs[rsp], eax ;
  234. mov rax, CxRsp[rcx] ; set stack address
  235. mov MfRsp[rsp], rax ;
  236. mov eax, CxEFlags[rcx] ; set processor flags
  237. mov MfEFlags[rsp], eax ;
  238. mov eax, CxSegCs[rcx] ; set CS segment
  239. mov MfSegCs[rsp], eax ;
  240. mov rax, CxRip[rcx] ; set return address
  241. mov MfRip[rsp], rax ;
  242. mov rax, CxRax[rcx] ; restore volatile integer registers
  243. mov rdx, CxRdx[rcx] ;
  244. mov r8, CxR8[rcx] ;
  245. mov r9, CxR9[rcx] ;
  246. mov r10, CxR10[rcx] ;
  247. mov r11, CxR11[rcx] ;
  248. ifdef NTOS_KERNEL_RUNTIME
  249. cli ; disable interrupts
  250. endif
  251. mov rbx, CxRbx[rcx] ; restore nonvolatile integer registers
  252. mov rsi, CxRsi[rcx] ;
  253. mov rdi, CxRdi[rcx] ;
  254. mov rbp, CxRbp[rcx] ;
  255. mov r12, CxR12[rcx] ;
  256. mov r13, CxR13[rcx] ;
  257. mov r14, CxR14[rcx] ;
  258. mov r15, CxR15[rcx] ;
  259. mov rcx, CxRcx[rcx] ; restore integer register
  260. iretq ; return
  261. ;
  262. ; Frame consoldation and language specific unwind call back.
  263. ;
  264. Rc20: sub rsp, MachineFrameLength + 8; allocate machine frame
  265. mov r8, rsp ; save machine frame address
  266. sub rsp, CONTEXT_FRAME_LENGTH ; allocate context frame
  267. mov rsi, rcx ; set source copy address
  268. mov rdi, rsp ; set destination copy address
  269. mov ecx, CONTEXT_FRAME_LENGTH / 8 ; set length of copy
  270. rep movsq ; copy context frame
  271. mov rax, CxRsp[rsp] ; set destination stack address in
  272. mov MfRsp[r8], rax ; machine frame
  273. mov rax, CxRip[rsp] ; set destination address in machine
  274. mov MfRip[r8], rax ; frame
  275. mov rcx, rdx ; set address of exception record
  276. jmp RcConsolidateFrames ; consolidate frames - no return
  277. NESTED_END RtlRestoreContext, _TEXT$00
  278. subttl "Frame Consolidation"
  279. ;++
  280. ;
  281. ; Ths following code is never executed. Its purpose is to provide the dummy
  282. ; prologue necessary to consolidate stack frames for unwind call back processing
  283. ; at the end of an unwind operation.
  284. ;
  285. ;--
  286. NESTED_ENTRY RcFrameConsolidation, _TEXT$00
  287. .pushframe ;
  288. .allocstack CONTEXT_FRAME_LENGTH ; allocate stack frame
  289. .savereg rbx, CxRbx ; save nonvolatile integer registers
  290. .savereg rbp, CxRbp ;
  291. .savereg rsi, CxRsi ;
  292. .savereg rdi, CxRdi ;
  293. .savereg r12, CxR12 ;
  294. .savereg r13, CxR13 ;
  295. .savereg r14, CxR14 ;
  296. .savereg r15, CxR15 ;
  297. .savexmm128 xmm6, CxXmm6 ; save nonvolatile floating register
  298. .savexmm128 xmm7, CxXmm7 ;
  299. .savexmm128 xmm8, CxXmm8 ;
  300. .savexmm128 xmm9, CxXmm9 ;
  301. .savexmm128 xmm10, CxXmm10 ;
  302. .savexmm128 xmm11, CxXmm11 ;
  303. .savexmm128 xmm12, CxXmm12 ;
  304. .savexmm128 xmm13, CxXmm13 ;
  305. .savexmm128 xmm14, CxXmm14 ;
  306. .savexmm128 xmm15, CxXmm15 ;
  307. END_PROLOGUE
  308. ;++
  309. ;
  310. ; VOID
  311. ; RcConsolidateFrames (
  312. ; IN PEXCEPTION_RECORD ExceptionRecord
  313. ; )
  314. ;
  315. ; Routine Description:
  316. ;
  317. ; This routine is called at the end of a unwind operation to logically
  318. ; remove unwound frames from the stack. This is accomplished by building a
  319. ; call frame using a machine frame and a context record and then calling
  320. ; the alternate entry of this function.
  321. ;
  322. ; The following code calls the language call back function specified in the
  323. ; exception record. If the function returns, then the destination frame
  324. ; context is restored and control transfered to the address returned by the
  325. ; language call back function. If control does not return, then another
  326. ; exception must be raised.
  327. ;
  328. ; Arguments:
  329. ;
  330. ; ExceptionRecord (rdx) - Supplies a pointer to an exception record.
  331. ;
  332. ; Implicit Arguments:
  333. ;
  334. ; ContextRecord (rsp) - Supplies a pointer to a context record.
  335. ;
  336. ; Return Value:
  337. ;
  338. ; None.
  339. ;
  340. ;--
  341. ALTERNATE_ENTRY RcConsolidateFrames
  342. ;
  343. ; At this point all call frames from the dispatching of the an exception to
  344. ; a destination language specific handler have been logically unwound and
  345. ; consolidated into a single large frame.
  346. ;
  347. ; The first parameter in the exception record is the address of a callback
  348. ; routine that performs language specific operations. This routine is called
  349. ; with the specified exception record as a parameter.
  350. ;
  351. call qword ptr ErExceptionInformation[rcx] ; call back to handler
  352. ;
  353. ; Restore context and continue.
  354. ;
  355. mov rcx, rsp ; set address of context record
  356. mov CxRip[rcx], rax ; set destination address
  357. movdqa xmm0, CxXmm0[rcx] ; restore floating registers
  358. movdqa xmm1, CxXmm1[rcx] ;
  359. movdqa xmm2, CxXmm2[rcx] ;
  360. movdqa xmm3, CxXmm3[rcx] ;
  361. movdqa xmm4, CxXmm4[rcx] ;
  362. movdqa xmm5, CxXmm5[rcx] ;
  363. movdqa xmm6, CxXmm6[rcx] ;
  364. movdqa xmm7, CxXmm7[rcx] ;
  365. movdqa xmm8, CxXmm8[rcx] ;
  366. movdqa xmm9, CxXmm9[rcx] ;
  367. movdqa xmm10, CxXmm10[rcx] ;
  368. movdqa xmm11, CxXmm11[rcx] ;
  369. movdqa xmm12, CxXmm12[rcx] ;
  370. movdqa xmm13, CxXmm13[rcx] ;
  371. movdqa xmm14, CxXmm14[rcx] ;
  372. movdqa xmm15, CxXmm15[rcx] ;
  373. ldmxcsr CxMxCsr[rcx] ; restore floating state
  374. ;
  375. ; Contruct a machine frame of the stack using information from the context
  376. ; record.
  377. ;
  378. ; N.B. The machine frame overlays the parameter area in the context record.
  379. ;
  380. mov eax, CxSegSs[rcx] ; set SS segment
  381. mov MfSegSs[rsp], eax ;
  382. mov rax, CxRsp[rcx] ; set stack address
  383. mov MfRsp[rsp], rax ;
  384. mov eax, CxEFlags[rcx] ; set processor flags
  385. mov MfEFlags[rsp], eax ;
  386. mov eax, CxSegCs[rcx] ; set CS segment
  387. mov MfSegCs[rsp], eax ;
  388. mov rax, CxRip[rcx] ; set return address
  389. mov MfRip[rsp], rax ;
  390. mov rax, CxRax[rcx] ; restore volatile integer registers
  391. mov rdx, CxRdx[rcx] ;
  392. mov r8, CxR8[rcx] ;
  393. mov r9, CxR9[rcx] ;
  394. mov r10, CxR10[rcx] ;
  395. mov r11, CxR11[rcx] ;
  396. ifdef NTOS_KERNEL_RUNTIME
  397. cli ; disable interrupts
  398. endif
  399. mov rbx, CxRbx[rcx] ; restore nonvolatile integer registers
  400. mov rsi, CxRsi[rcx] ;
  401. mov rdi, CxRdi[rcx] ;
  402. mov rbp, CxRbp[rcx] ;
  403. mov r12, CxR12[rcx] ;
  404. mov r13, CxR13[rcx] ;
  405. mov r14, CxR14[rcx] ;
  406. mov r15, CxR15[rcx] ;
  407. mov rcx, CxRcx[rcx] ; restore integer register
  408. iretq ; return
  409. NESTED_END RcFrameConsolidation, _TEXT$00
  410. end