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.

479 lines
16 KiB

  1. title "User Mode Dispatch Code"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; trampoln.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the trampoline code necessary to dispatch user
  13. ; mode APCs and exceptions.
  14. ;
  15. ; Author:
  16. ;
  17. ; David N. Cutler (davec) 4-Jul-2000
  18. ;
  19. ; Environment:
  20. ;
  21. ; User mode.
  22. ;
  23. ;--
  24. include ksamd64.inc
  25. extern RtlDispatchException:proc
  26. extern RtlRaiseException:proc
  27. extern RtlRaiseStatus:proc
  28. extern RtlRestoreContext:proc
  29. extern Wow64PrepareForException:qword
  30. extern ZwCallbackReturn:proc
  31. extern ZwContinue:proc
  32. extern ZwRaiseException:proc
  33. extern ZwTestAlert:proc
  34. subttl "User APC Exception Handler"
  35. ;++
  36. ;
  37. ; EXCEPTION_DISPOSITION
  38. ; KiUserApcHandler (
  39. ; IN PEXCEPTION_RECORD ExceptionRecord,
  40. ; IN UINT_PTR EstablisherFrame,
  41. ; IN OUT PCONTEXT ContextRecord,
  42. ; IN OUT PDISPATCHER_CONTEXT DispatcherContext
  43. ; )
  44. ;
  45. ; Routine Description:
  46. ;
  47. ; This function is called when an exception occurs in an APC routine or one
  48. ; of its dynamic descendents, or when an unwind through the APC dispatcher
  49. ; is in progress. If an unwind is in progress, then test alert is called to
  50. ; ensure that all currently queued APCs are executed.
  51. ;
  52. ; Arguments:
  53. ;
  54. ; ExceptionRecord (rcx) - Supplies a pointer to an exception record.
  55. ;
  56. ; EstablisherFrame (rdx) - Supplies the frame pointer of the establisher
  57. ; of this exception handler.
  58. ;
  59. ; ContextRecord (r8) - Supplies a pointer to a context record.
  60. ;
  61. ; DispatcherContext (r9) - Supplies a pointer to the dispatcher context
  62. ; record.
  63. ;
  64. ; Return Value:
  65. ;
  66. ; Continue search is returned as the function value.
  67. ;
  68. ;--
  69. UaFrame struct
  70. Fill dq ? ; fill to 8 mod 16
  71. UaFrame ends
  72. NESTED_ENTRY KiUserApcHandler, _TEXT$00
  73. alloc_stack (sizeof UaFrame) ; allocate stack frame
  74. END_PROLOGUE
  75. test dword ptr ErExceptionFlags[rcx], EXCEPTION_UNWIND ; test if unwinding
  76. jz short @f ; if z, unwind not in progress
  77. call ZwTestAlert ; test for alert pending
  78. @@: mov eax, ExceptionContinueSearch ; set continue search disposition
  79. add rsp, sizeof UaFrame ; deallocate stack frame
  80. ret ; return
  81. NESTED_END KiUserApcHandler, _TEXT$00
  82. subttl "User APC Dispatcher"
  83. ;++
  84. ;
  85. ; The following code is never executed. Its purpose is to support exception
  86. ; dispatching and unwinding through the call to the APC dispatcher.
  87. ;
  88. ;--
  89. altentry KiUserApcDispatcher
  90. NESTED_ENTRY KiUserApcDispatch, _TEXT$00, KiUserApcHandler
  91. .pushframe ; push machine frame
  92. .allocstack CONTEXT_FRAME_LENGTH ; allocate stack frame
  93. .savereg rbx, CxRbx ; save nonvolatile integer registers
  94. .savereg rbp, CxRbp ;
  95. .savereg rsi, CxRsi ;
  96. .savereg rdi, CxRdi ;
  97. .savereg r12, CxR12 ;
  98. .savereg r13, CxR13 ;
  99. .savereg r14, CxR14 ;
  100. .savereg r15, CxR15 ;
  101. .savexmm128 xmm6, CxXmm6 ; save nonvolatile floating register
  102. .savexmm128 xmm7, CxXmm7 ;
  103. .savexmm128 xmm8, CxXmm8 ;
  104. .savexmm128 xmm9, CxXmm9 ;
  105. .savexmm128 xmm10, CxXmm10 ;
  106. .savexmm128 xmm11, CxXmm11 ;
  107. .savexmm128 xmm12, CxXmm12 ;
  108. .savexmm128 xmm13, CxXmm13 ;
  109. .savexmm128 xmm14, CxXmm14 ;
  110. .savexmm128 xmm15, CxXmm15 ;
  111. END_PROLOGUE
  112. ;++
  113. ;
  114. ; VOID
  115. ; KiUserApcDispatcher (
  116. ; IN PVOID NormalContext,
  117. ; IN PVOID SystemArgument1,
  118. ; IN PVOID SystemArgument2,
  119. ; IN PKNORMAL_ROUTINE NormalRoutine
  120. ; )
  121. ;
  122. ; Routine Description:
  123. ;
  124. ; This routine is entered on return from kernel mode to deliver an APC
  125. ; in user mode. The context frame for this routine was built when the
  126. ; APC interrupt was processed and contains the entire machine state of
  127. ; the current thread. The specified APC routine is called and then the
  128. ; machine state is restored and execution is continued.
  129. ;
  130. ; N.B. This function is not called in the typical way. Instead of a normal
  131. ; subroutine call to the nested entry point above, the alternate entry
  132. ; point below is stored into the RIP address of the trap frame. Thus
  133. ; when the kernel returns from the trap, the following code is executed
  134. ; directly.
  135. ;
  136. ; N.B. The home addresses for called routine register parameters are
  137. ; allocated in the context record.
  138. ;
  139. ; Arguments:
  140. ;
  141. ; NormalContext (P1Home) - Supplies the normal context parameter that was
  142. ; specified when the APC was initialized.
  143. ;
  144. ; SystemArgument1 (P2Home) - Supplies the first argument that was provided by
  145. ; the system when the APC was queued.
  146. ;
  147. ; SystemArgument2 (P3Home) - Supplies the second argument that was provided by
  148. ; the system when the APC was queued.
  149. ;
  150. ; NormalRoutine (P4Home) - Supplies the address of the function that is to
  151. ; be called.
  152. ;
  153. ; N.B. Register RSP supplies a pointer to a context record.
  154. ;
  155. ; Return Value:
  156. ;
  157. ; None.
  158. ;
  159. ;--
  160. ALTERNATE_ENTRY KiUserApcDispatcher
  161. mov rcx, CxP1Home[rsp] ; get APC parameters
  162. mov rdx, CxP2Home[rsp] ;
  163. mov r8, CxP3Home[rsp] ;
  164. call qword ptr CxP4Home[rsp] ; call APC routine
  165. ;
  166. ; N.B. The system service to continue execution must be called since test
  167. ; alert must also be executed.
  168. ;
  169. mov rcx, rsp ; set address of context record
  170. mov dl, TRUE ; set test alert argument
  171. call ZwContinue ; continue execution
  172. ;
  173. ; Unsuccessful completion after attempting to continue execution. Use the
  174. ; return status as the exception code and attempt to raise another exception.
  175. ;
  176. mov esi, eax ; save return status
  177. @@: mov ecx, esi ; set status value
  178. call RtlRaiseStatus ; raise status
  179. jmp short @b ; loop forever
  180. NESTED_END KiUserApcDispatch, _TEXT$00
  181. subttl "User Callback Dispatcher"
  182. ;++
  183. ;
  184. ; The following code is never executed. Its purpose is to support exception
  185. ; dispatching and unwinding through the call to the exception dispatcher.
  186. ;
  187. ;--
  188. altentry KiUserCallbackDispatcher
  189. NESTED_ENTRY KiUserCallbackDispatch, _TEXT$00
  190. .pushframe ; push machine frame
  191. .allocstack (CalloutFrameLength - MachineFrameLength) ; allocate stack frame
  192. END_PROLOGUE
  193. ;++
  194. ;
  195. ; VOID
  196. ; KiUserCallbackDispatcher (
  197. ; IN ULONG ApiNumber,
  198. ; IN PVOID InputBuffer,
  199. ; IN ULONG INputLength
  200. ; )
  201. ;
  202. ; Routine Description:
  203. ;
  204. ; This routine is entered on a callout from kernel mode to execute a user
  205. ; mode callback function. All arguments for this function have been placed
  206. ; on the stack.
  207. ;
  208. ; N.B. This function is not called in the typical way. Instead of a normal
  209. ; subroutine call to the nested entry point above, the alternate entry
  210. ; point below is stored into the RIP address of the trap frame. Thus
  211. ; when the kernel returns from the trap, the following code is executed
  212. ; directly.
  213. ;
  214. ; N.B. The home addresses for called routine register parameters are
  215. ; allocated in the user callout frame.
  216. ;
  217. ; Arguments:
  218. ;
  219. ; N.B. Register RSP supplies a pointer to a user callout record.
  220. ;
  221. ; Return Value:
  222. ;
  223. ; This function returns to kernel mode.
  224. ;
  225. ;--
  226. ALTERNATE_ENTRY KiUserCallbackDispatcher
  227. mov rcx, CkBuffer[rsp] ; set input buffer address
  228. mov edx, CkLength[rsp] ; set input buffer length
  229. mov r8d, CkApiNumber[rsp] ; get API number
  230. mov rax, gs:[TePeb] ; get process environment block address
  231. mov r9, PeKernelCallbackTable[rax] ; get callback table address
  232. call qword ptr [r9][r8 * 8] ; call specified function
  233. ;
  234. ; If a return from the callback function occurs, then the output buffer
  235. ; address and length are returned as NULL.
  236. ;
  237. xor ecx, ecx ; clear output buffer address
  238. xor edx, edx ; clear output buffer length
  239. mov r8d, eax ; set completion status
  240. call ZwCallbackReturn ; return to kernel mode
  241. ;
  242. ; Unsuccessful completion after attempting to return to kernel mode. Use the
  243. ; return status as the exception code and attempt to raise another exception.
  244. ;
  245. mov esi, eax ; save status value
  246. @@: mov ecx, esi ; set status value
  247. call RtlRaiseStatus ; raise exception
  248. jmp short @b ; loop forever
  249. NESTED_END KiUserCallbackDispatch, _TEXT$00
  250. subttl "User Exception Dispatcher"
  251. ;++
  252. ;
  253. ; The following code is never executed. Its purpose is to support exception
  254. ; dispatching and unwinding through the call to the exception dispatcher.
  255. ;
  256. ;--
  257. ExceptionFramelength equ (ExceptionRecordLength + CONTEXT_FRAME_LENGTH)
  258. altentry KiUserExceptionDispatcher
  259. NESTED_ENTRY KiUserExceptionDispatch, _TEXT$00
  260. .pushframe ;
  261. .allocstack (ExceptionRecordLength + CONTEXT_FRAME_LENGTH) ; allocate stack frame
  262. .savereg rbx, CxRbx ; save nonvolatile integer registers
  263. .savereg rbp, CxRbp ;
  264. .savereg rsi, CxRsi ;
  265. .savereg rdi, CxRdi ;
  266. .savereg r12, CxR12 ;
  267. .savereg r13, CxR13 ;
  268. .savereg r14, CxR14 ;
  269. .savereg r15, CxR15 ;
  270. .savexmm128 xmm6, CxXmm6 ; save nonvolatile floating register
  271. .savexmm128 xmm7, CxXmm7 ;
  272. .savexmm128 xmm8, CxXmm8 ;
  273. .savexmm128 xmm9, CxXmm9 ;
  274. .savexmm128 xmm10, CxXmm10 ;
  275. .savexmm128 xmm11, CxXmm11 ;
  276. .savexmm128 xmm12, CxXmm12 ;
  277. .savexmm128 xmm13, CxXmm13 ;
  278. .savexmm128 xmm14, CxXmm14 ;
  279. .savexmm128 xmm15, CxXmm15 ;
  280. END_PROLOGUE
  281. ;++
  282. ;
  283. ; VOID
  284. ; KiUserExceptionDispatcher (
  285. ; IN PEXCEPTION_RECORD ExceptionRecord,
  286. ; IN PCONTEXT ContextRecord
  287. ; )
  288. ;
  289. ; Routine Description:
  290. ;
  291. ; This routine is entered on return from kernel mode to dispatch a user
  292. ; mode exception. If a frame based handler handles the exception, then
  293. ; the execution is continued. Else last chance processing is performed.
  294. ;
  295. ; N.B. This function is not called in the typical way. Instead of a normal
  296. ; subroutine call to the nested entry point above, the alternate entry
  297. ; point below is stored into the RIP address of the trap frame. Thus
  298. ; when the kernel returns from the trap, the following code is executed
  299. ; directly.
  300. ;
  301. ; N.B. The home addresses for called routine register parameters are
  302. ; allocated in the context record.
  303. ;
  304. ; Arguments:
  305. ;
  306. ; ExceptionRecord (rsi) - Supplies a pointer to an exception record.
  307. ;
  308. ; ContextRecord (rdi) - Supplies a pointer to a context record.
  309. ;
  310. ; Return Value:
  311. ;
  312. ; None.
  313. ;
  314. ;--
  315. ALTERNATE_ENTRY KiUserExceptionDispatcher
  316. ;
  317. ; If this is a wow64 process, then give wow64 a chance to clean up before
  318. ; dispatching the exception.
  319. ;
  320. mov rax, Wow64PrepareForException ; get wow64 routine address
  321. test rax, rax ; test if routine specified
  322. jz short Ue05 ; if z, routine not specified
  323. mov rcx, rsi ; set exception record address
  324. mov rdx, rdi ; set context record address
  325. call rax ; call wow64 clean up routine
  326. Ue05: mov rcx, rsi ; set exception record address
  327. mov rdx, rdi ; set context record address
  328. call RtlDispatchException ; dispatch the exception
  329. ;
  330. ; If the return status is TRUE, then the exception was handled and execution
  331. ; should be continued with the continue service in case the context was
  332. ; changed. If the return status is FALSE, then the exception was not handled
  333. ; and raise exception is called to perform last chance exception processing.
  334. ;
  335. test al, al ; test if the exception was handled
  336. jz short Ue10 ; if z, exception was not handled
  337. ;
  338. ; Restore context and continue execution.
  339. ;
  340. mov rcx, rdi ; set context record address
  341. xor edx, edx ; set set exception record address
  342. call RtlRestoreContext ; restore context
  343. jmp short Ue20 ; finish in common code
  344. ;
  345. ; Last chance processing.
  346. ;
  347. Ue10: mov rcx, rsi ; set exception record address
  348. mov rdx, rdi ; set context record address
  349. xor r8b, r8b ; set first change argument falue
  350. call ZwRaiseException ; raise exception
  351. ;
  352. ; Common code for nonsuccessful completion of the continue or raise exception
  353. ; services. Use the return status as the exception code and attempt to raise
  354. ; another exception.
  355. ;
  356. Ue20: mov esi, eax ; save status value
  357. @@: mov ecx, esi ; set status value
  358. call RtlRaiseStatus ; raise exception
  359. jmp short @b ; loop forever
  360. NESTED_END KiUserExceptionDispatch, _TEXT$00
  361. subttl "Raise User Exception Dispatcher"
  362. ;++
  363. ;
  364. ; NTSTATUS
  365. ; KiRaiseUserExceptionDispatcher (
  366. ; VOID
  367. ; )
  368. ;
  369. ; Routine Description:
  370. ;
  371. ; This routine is entered on return from kernel mode to raise a user
  372. ; mode exception.
  373. ;
  374. ; N.B. This function is not called in the normal manner. An exception is
  375. ; raised from within the system by placing the address of this
  376. ; function in the RIP of the trap frame. This replaces the normal
  377. ; return to the system service stub.
  378. ;
  379. ; Arguments:
  380. ;
  381. ; None.
  382. ;
  383. ; Implicit Arguments:
  384. ;
  385. ; Status (eax) - Supplies the system service status.
  386. ;
  387. ; Return Value:
  388. ;
  389. ; The exception code that was raised.
  390. ;
  391. ;--
  392. RuFrame struct ;
  393. P1Home dq ? ; parameter home address
  394. Xrecord db ExceptionRecordLength dup (?) ; exception record
  395. Status dd ? ; saved exception code
  396. Fill1 dd ? ; fill to 0 mod 8
  397. Fill2 dq ? ; fill to 8 mod 16
  398. RuFrame ends
  399. NESTED_ENTRY KiRaiseUserExceptionDispatcher, _TEXT$00
  400. alloc_stack (sizeof RuFrame) ; allocate stack frame
  401. END_PROLOGUE
  402. mov RuFrame.Status[rsp], eax ; save the service status
  403. mov eax, gs:[TeExceptionCode] ; get exception code
  404. lea rcx, RuFrame.Xrecord[rsp] ; get exception record address
  405. mov ErExceptionCode[rcx], eax ; set exception code
  406. xor eax, eax ; generate zero value
  407. mov ErExceptionFlags[rcx], eax ; zero exception flags
  408. mov ErExceptionRecord[rcx], rax ; zero exception record
  409. mov rdx, sizeof RuFrame[rsp] ; get the real return address
  410. mov ErExceptionAddress[rcx], rdx ; set exception address
  411. mov ErNumberParameters[rcx], eax ; zero number of parameters
  412. call RtlRaiseException ; raise exception
  413. mov eax, RuFrame.Status[rsp] ; get exception code to return
  414. add rsp, sizeof RuFrame ; dealloate stack frame
  415. ret ; return
  416. NESTED_END KiRaiseUserExceptionDispatcher, _TEXT$00
  417. end