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.

1728 lines
61 KiB

  1. title "Trap Processing"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; trap.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to field and process AMD64
  13. ; trap conditions.
  14. ;
  15. ; Author:
  16. ;
  17. ; David N. Cutler (davec) 28-May-2000
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ;--
  24. include ksamd64.inc
  25. altentry KiExceptionExit
  26. altentry KiSystemService
  27. altentry KiSystemServiceCopyEnd
  28. altentry KiSystemServiceCopyStart
  29. altentry KiSystemServiceExit
  30. extern ExpInterlockedPopEntrySListFault:byte
  31. extern ExpInterlockedPopEntrySListResume:byte
  32. extern KdpOweBreakpoint:byte
  33. extern KdSetOwedBreakpoints:proc
  34. extern KeBugCheck:proc
  35. extern KeBugCheckEx:proc
  36. extern KeGdiFlushUserBatch:qword
  37. extern KeServiceDescriptorTableShadow:qword
  38. extern KiConvertToGuiThread:proc
  39. extern KiDispatchException:proc
  40. extern KiEmulateReferenceComplete:proc
  41. extern KiInitiateUserApc:proc
  42. extern MmAccessFault:proc
  43. extern MmUserProbeAddress:qword
  44. extern RtlUnwind:proc
  45. extern PsWatchEnabled:byte
  46. extern PsWatchWorkingSet:proc
  47. extern __imp_HalEndSystemInterrupt:qword
  48. extern __imp_HalHandleMcheck:qword
  49. extern __imp_HalHandleNMI:qword
  50. subttl "Divide Error Fault"
  51. ;++
  52. ;
  53. ; Routine Description:
  54. ;
  55. ; This routine is entered as the result of an attempted division by zero
  56. ; or the result of an attempted division does not fit in the destination
  57. ; operand (i.e., the largest negative number divided by minus one).
  58. ;
  59. ; N.B. The two possible conditions that can cause this exception are not
  60. ; separated and the exception is reported as a divide by zero.
  61. ;
  62. ; Arguments:
  63. ;
  64. ; The standard exception frame is pushed by hardware on the kernel stack.
  65. ; There is no error code for this exception.
  66. ;
  67. ; Disposition:
  68. ;
  69. ; A standard trap frame is constructed on the kernel stack, the exception
  70. ; parameters are loaded into registers, and the exception is dispatched via
  71. ; common code.
  72. ;
  73. ;--
  74. NESTED_ENTRY KiDivideErrorFault, _TEXT$00
  75. GENERATE_TRAP_FRAME ; generate trap frame
  76. mov ecx, STATUS_INTEGER_DIVIDE_BY_ZERO ; set exception code
  77. xor edx, edx ; set number of parameters
  78. mov r8, TrRip[rbp] ; set exception address
  79. call KiExceptionDispatch ; dispatch exception - no return
  80. nop ; fill - do not remove
  81. NESTED_END KiDivideErrorFault, _TEXT$00
  82. subttl "Debug Trap Or Fault"
  83. ;++
  84. ;
  85. ; Routine Description:
  86. ;
  87. ; This routine is entered as the result of a debug trap or fault. The
  88. ; following conditions cause entry to this routine:
  89. ;
  90. ; 1. Instruction fetch breakpoint fault.
  91. ; 2. Data read or write breakpoint trap.
  92. ; 3. I/O read or write breakpoint trap.
  93. ; 4. General detect condition fault (in-circuit emulator).
  94. ; 5. Single step trap (TF set).
  95. ; 6. Task switch trap (not possible on this system).
  96. ; 7. Execution of an int 1 instruction.
  97. ;
  98. ; Arguments:
  99. ;
  100. ; The standard exception frame is pushed by hardware on the kernel stack.
  101. ; There is no error code for this exception.
  102. ;
  103. ; Disposition:
  104. ;
  105. ; A standard trap frame is constructed on the kernel stack, the exception
  106. ; parameters are loaded into registers, and the exception is dispatched via
  107. ; common code.
  108. ;
  109. ;--
  110. NESTED_ENTRY KiDebugTrapOrFault, _TEXT$00
  111. GENERATE_TRAP_FRAME ; generate trap frame
  112. mov rcx, rsp ; set address of trap frame
  113. call KiEmulateReferenceComplete ; complete emulation reference
  114. or al, al ; test is reference complete
  115. jnz kdt10 ; if nz, reference not completed
  116. RESTORE_TRAP_STATE <Volatile> ; restore trap state and exit
  117. kdt10: mov ecx, STATUS_SINGLE_STEP ; set exception code
  118. xor edx, edx ; set number of parameters
  119. mov r8, TrRip[rbp] ; set exception address
  120. call KiExceptionDispatch ; dispatch exception - no return
  121. nop ; fill - do not remove
  122. NESTED_END KiDebugTrapOrFault, _TEXT$00
  123. subttl "Nonmaskable Interrupt"
  124. ;++
  125. ;
  126. ; Routine Description:
  127. ;
  128. ; This routine is entered as the result of a nonmaskable interrupt. A
  129. ; switch to the panic stack occurs before the exception frame is pushed
  130. ; on the stack.
  131. ;
  132. ; N.B. This routine executes on the panic stack.
  133. ;
  134. ; Arguments:
  135. ;
  136. ; The standard exception frame is pushed by hardware on the kernel stack.
  137. ; There is no error code for this exception.
  138. ;
  139. ; Disposition:
  140. ;
  141. ; A standard trap frame is constructed on the kernel stack and the HAL is
  142. ; called to determine if the nonmaskable interrupt is fatal. If the HAL
  143. ; call returns, then system operation is continued.
  144. ;
  145. ;--
  146. NESTED_ENTRY KiNmiInterrupt, _TEXT$00
  147. GENERATE_TRAP_FRAME ; generate trap frame
  148. xor ecx, ecx ; set parameter value
  149. call __imp_HalHandleNMI ; give HAL a chance to handle NMI
  150. RESTORE_TRAP_STATE <Volatile> ; restore trap state and exit
  151. NESTED_END KiNmiInterrupt, _TEXT$00
  152. subttl "Breakpoint Trap"
  153. ;++
  154. ;
  155. ; Routine Description:
  156. ;
  157. ; This routine is entered as the result of the execution of an int 3
  158. ; instruction.
  159. ;
  160. ; Arguments:
  161. ;
  162. ; The standard exception frame is pushed by hardware on the kernel stack.
  163. ; There is no error code for this exception.
  164. ;
  165. ; Disposition:
  166. ;
  167. ; A standard trap frame is constructed on the kernel stack, the exception
  168. ; parameters are loaded into registers, and the exception is dispatched via
  169. ; common code.
  170. ;
  171. ;--
  172. NESTED_ENTRY KiBreakpointTrap, _TEXT$00
  173. GENERATE_TRAP_FRAME ; generate trap frame
  174. mov ecx, STATUS_BREAKPOINT ; set exception code
  175. mov edx, 1 ; set number of parameters
  176. mov r8, TrRip[rbp] ; set exception address
  177. dec r8 ;
  178. mov r9d, BREAKPOINT_BREAK ; set parameter 1 value
  179. call KiExceptionDispatch ; dispatch exception - no return
  180. nop ; fill - do not remove
  181. NESTED_END KiBreakpointTrap, _TEXT$00
  182. subttl "Overflow Trap"
  183. ;++
  184. ;
  185. ; Routine Description:
  186. ;
  187. ; This routine is entered as the result of the execution of an into
  188. ; instruction when the OF flag is set.
  189. ;
  190. ; Arguments:
  191. ;
  192. ; The standard exception frame is pushed by hardware on the kernel stack.
  193. ; There is no error code for this exception.
  194. ;
  195. ; Disposition:
  196. ;
  197. ; A standard trap frame is constructed on the kernel stack, the exception
  198. ; parameters are loaded into registers, and the exception is dispatched via
  199. ; common code.
  200. ;
  201. ;--
  202. NESTED_ENTRY KiOverflowTrap, _TEXT$00
  203. GENERATE_TRAP_FRAME ; generate trap frame
  204. mov ecx, STATUS_INTEGER_OVERFLOW ; set exception code
  205. xor edx, edx ; set number of parameters
  206. mov r8, TrRip[rbp] ; set exception address
  207. dec r8 ;
  208. call KiExceptionDispatch ; dispatch exception - no return
  209. nop ; fill - do not remove
  210. NESTED_END KiOverflowTrap, _TEXT$00
  211. subttl "Bound Fault"
  212. ;++
  213. ;
  214. ; Routine Description:
  215. ;
  216. ; This routine is entered as the result of the execution of a bound
  217. ; instruction and when the bound range is exceeded.
  218. ;
  219. ; Arguments:
  220. ;
  221. ; The standard exception frame is pushed by hardware on the kernel stack.
  222. ; There is no error code for this exception.
  223. ;
  224. ; Disposition:
  225. ;
  226. ; A standard trap frame is constructed on the kernel stack, the exception
  227. ; parameters are loaded into registers, and the exception is dispatched via
  228. ; common code.
  229. ;
  230. ;--
  231. NESTED_ENTRY KiBoundFault, _TEXT$00
  232. GENERATE_TRAP_FRAME ; generate trap frame
  233. mov ecx, STATUS_ARRAY_BOUNDS_EXCEEDED ; set exception code
  234. xor edx, edx ; set number of parameters
  235. mov r8, TrRip[rbp] ; set exception address
  236. call KiExceptionDispatch ; dispatch exception - no return
  237. nop ; fill - do not remove
  238. NESTED_END KiBoundFault, _TEXT$00
  239. subttl "Invalid Opcode Fault"
  240. ;++
  241. ;
  242. ; Routine Description:
  243. ;
  244. ; This routine is entered as the result of the execution of an invalid
  245. ; instruction.
  246. ;
  247. ; Arguments:
  248. ;
  249. ; The standard exception frame is pushed by hardware on the kernel stack.
  250. ; There is no error code for this exception.
  251. ;
  252. ; Disposition:
  253. ;
  254. ; A standard trap frame is constructed on the kernel stack, the exception
  255. ; parameters are loaded into registers, and the exception is dispatched via
  256. ; common code.
  257. ;
  258. ;--
  259. NESTED_ENTRY KiInvalidOpcodeFault, _TEXT$00
  260. GENERATE_TRAP_FRAME ; generate trap frame
  261. mov ecx, STATUS_ILLEGAL_INSTRUCTION ; set exception code
  262. xor edx, edx ; set number of parameters
  263. mov r8, TrRip[rbp] ; set exception address
  264. call KiExceptionDispatch ; dispatch exception - no return
  265. nop ; fill - do not remove
  266. NESTED_END KiInvalidOpcodeFault, _TEXT$00
  267. subttl "NPX Not Available Fault"
  268. ;++
  269. ;
  270. ; Routine Description:
  271. ;
  272. ; This routine is entered as the result of the numeric coprocessor not
  273. ; being available for one of the following conditions:
  274. ;
  275. ; 1. A floating point instruction was executed and EM is set in CR0 -
  276. ; this condition should never happen since EM will never be set.
  277. ;
  278. ; 2. A floating point instruction was executed and the TS flag is set
  279. ; in CR0 - this condition should never happen since TS will never
  280. ; be set.
  281. ;
  282. ; 3. A WAIT of FWAIT instruction was executed and the MP and TS flags
  283. ; are set in CR0 - this condition should never occur since neither
  284. ; TS nor MP will ever be set.
  285. ;
  286. ; N.B. The NPX state should always be available.
  287. ;
  288. ; Arguments:
  289. ;
  290. ; The standard exception frame is pushed by hardware on the kernel stack.
  291. ; There is no error code for this exception.
  292. ;
  293. ; Disposition:
  294. ;
  295. ; A standard trap frame is constructed on the kernel stack and bug check
  296. ; is called.
  297. ;
  298. ;--
  299. NESTED_ENTRY KiNpxNotAvailableFault, _TEXT$00
  300. GENERATE_TRAP_FRAME ; generate trap frame
  301. mov r8, TrRip[rbp] ; set parameter 5 to exception address
  302. mov TrP5[rbp], r8 ;
  303. mov r9, cr4 ; set parameter 4 to control register 4
  304. mov r8, cr0 ; set parameter 3 to control register 0
  305. mov edx, 1 ; set unexpected trap number
  306. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  307. call KeBugCheckEx ; bugcheck system - no return
  308. nop ; fill - do not remove
  309. NESTED_END KiNpxNotAvailableFault, _TEXT$00
  310. subttl "Double Fault Abort"
  311. ;++
  312. ;
  313. ; Routine Description:
  314. ;
  315. ; This routine is entered as the result of the generation of a second
  316. ; exception while another exception is being generated. A switch to the
  317. ; panic stack occurs before the exception frame is pushed on the stack.
  318. ;
  319. ; N.B. This routine executes on the panic stack.
  320. ;
  321. ; Arguments:
  322. ;
  323. ; The standard exception frame is pushed by hardware on the new stack.
  324. ; There is no error code for this exception.
  325. ;
  326. ; Disposition:
  327. ;
  328. ; A standard trap frame is constructed on the kernel stack and bug check
  329. ; is called.
  330. ;
  331. ;--
  332. NESTED_ENTRY KiDoubleFaultAbort, _TEXT$00
  333. GENERATE_TRAP_FRAME <ErrorCode> ; generate trap frame
  334. mov r8, TrRip[rbp] ; set parameter 5 to exception address
  335. mov TrP5[rbp], r8 ;
  336. mov r9, cr4 ; set parameter 4 to control register 4
  337. mov r8, cr0 ; set parameter 3 to control register 0
  338. mov edx, 2 ; set unexpected trap number
  339. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  340. call KeBugCheckEx ; bugcheck system - no return
  341. nop ; fill - do not remove
  342. NESTED_END KiDoubleFaultAbort, _TEXT$00
  343. subttl "NPX Segment Overrrun Abort"
  344. ;++
  345. ;
  346. ; Routine Description:
  347. ;
  348. ; This routine is entered as the result of a hardware failure since this
  349. ; vector is obsolete.
  350. ;
  351. ; Arguments:
  352. ;
  353. ; The standard exception frame is pushed by hardware on the new stack.
  354. ; There is no error code for this exception.
  355. ;
  356. ; Disposition:
  357. ;
  358. ; This trap should never occur and the system is shutdown via a call to
  359. ; bug check.
  360. ;
  361. ;--
  362. NESTED_ENTRY KiNpxSegmentOverrunAbort, _TEXT$00
  363. GENERATE_TRAP_FRAME ; generate trap frame
  364. mov r8, TrRip[rbp] ; set parameter 5 to exception address
  365. mov TrP5[rbp], r8 ;
  366. mov r9, cr4 ; set parameter 4 to control register 4
  367. mov r8, cr0 ; set parameter 3 to control register 0
  368. mov edx, 3 ; set unexpected trap number
  369. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  370. call KeBugCheckEx ; bugcheck system - no return
  371. nop ; fill - do not remove
  372. NESTED_END KiNpxSegmentOverrunAbort, _TEXT$00
  373. subttl "Invalid TSS Fault"
  374. ;++
  375. ;
  376. ; Routine Description:
  377. ;
  378. ; This routine is entered as the result of a hardware or software failure
  379. ; since there is no task switching in 64-bit mode and 32-bit code does not
  380. ; have any task state segments.
  381. ;
  382. ; Arguments:
  383. ;
  384. ; The standard exception frame is pushed by hardware on the new stack.
  385. ; The segment selector index for the segment descriptor that caused the
  386. ; violation is pushed as the error code.
  387. ;
  388. ; Disposition:
  389. ;
  390. ; A standard trap frame is constructed on the kernel stack and bug check
  391. ; is called.
  392. ;
  393. ;--
  394. NESTED_ENTRY KiInvalidTssFault, _TEXT$00
  395. GENERATE_TRAP_FRAME <ErrorCode> ; generate trap frame
  396. mov r8, TrRip[rbp] ; set parameter 5 to exception address
  397. mov TrP5[rbp], r8 ;
  398. mov r9d, TrErrorCode[rbp] ; set parameter 4 to selector index
  399. mov r8, cr0 ; set parameter 3 to control register 0
  400. mov edx, 4 ; set unexpected trap number
  401. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  402. call KeBugCheckEx ; bugcheck system - no return
  403. nop ; fill - do not remove
  404. NESTED_END KiInvalidTssFault, _TEXT$00
  405. subttl "Segment Not Present Fault"
  406. ;++
  407. ;
  408. ; Routine Description:
  409. ;
  410. ; This routine is entered as the result of a segment not present (P bit 0)
  411. ; fault. This fault can only occur in legacy 32-bit code.
  412. ;
  413. ; Arguments:
  414. ;
  415. ; The standard exception frame is pushed by hardware on the new stack.
  416. ; The segment selector index for the segment descriptor that is not
  417. ; present is pushed as the error code.
  418. ;
  419. ; Disposition:
  420. ;
  421. ; A standard trap frame is constructed. If the previous mode is user,
  422. ; then the exception parameters are loaded into registers and the exception
  423. ; is dispatched via common code. Otherwise, bug check is called.
  424. ;
  425. ;--
  426. NESTED_ENTRY KiSegmentNotPresentFault, _TEXT$00
  427. GENERATE_TRAP_FRAME <ErrorCode> ; generate trap frame
  428. mov r8, TrRip[rbp] ; get exception address
  429. test byte ptr TrSegCs[rbp], MODE_MASK ; test if previous mode user
  430. jz short KiSN10 ; if z, previous mode not user
  431. ;
  432. ; The previous mode was user.
  433. ;
  434. mov ecx, STATUS_ACCESS_VIOLATION ; set exception code
  435. mov edx, 2 ; set number of parameters
  436. mov r9d, TrErrorCode[rbp] ; set parameter 1 value
  437. or r9d, RPL_MASK ;
  438. and r9d, 0ffffh ;
  439. xor r10, r10 ; set parameter 2 value
  440. call KiExceptionDispatch ; dispatch exception - no return
  441. ;
  442. ; The previous mode was kernel.
  443. ;
  444. KiSN10: mov TrP5[rbp], r8 ; set parameter 5 to exception address
  445. mov r9d, TrErrorCode[rbp] ; set parameter 4 to selector index
  446. mov r8, cr0 ; set parameter 3 to control register 0
  447. mov edx, 5 ; set unexpected trap number
  448. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  449. call KeBugCheckEx ; bugcheck system - no return
  450. nop ; fill - do not remove
  451. NESTED_END KiSegmentNotPresentFault, _TEXT$00
  452. subttl "Stack Fault"
  453. ;++
  454. ;
  455. ; Routine Description:
  456. ;
  457. ; This routine is entered as the result of a stack fault. This fault can
  458. ; only occur in legacy 32-bit code.
  459. ;
  460. ; Arguments:
  461. ;
  462. ; The standard exception frame is pushed by hardware on the new stack.
  463. ; The segment selector index for the segment descriptor that caused the
  464. ; exception is pushed as the error code.
  465. ;
  466. ; Disposition:
  467. ;
  468. ; A standard trap frame is constructed. If the previous mode is user,
  469. ; then the exception parameters are loaded into registers and the exception
  470. ; is dispatched via common code. Otherwise, bug check is called.
  471. ;
  472. ;--
  473. NESTED_ENTRY KiStackFault, _TEXT$00
  474. GENERATE_TRAP_FRAME <ErrorCode> ; generate trap frame
  475. mov r8, TrRip[rbp] ; get exception address
  476. test byte ptr TrSegCs[rbp], MODE_MASK ; test if previous mode user
  477. jz short KiSF10 ; if z, previous mode not user
  478. ;
  479. ; The previous mode was user.
  480. ;
  481. mov ecx, STATUS_ACCESS_VIOLATION ; set exception code
  482. mov edx, 2 ; set number of parameters
  483. mov r9d, TrErrorCode[rbp] ; set parameter 1 value
  484. or r9d, RPL_MASK ;
  485. and r9d, 0ffffh ;
  486. xor r10, r10 ; set parameter 2 value
  487. call KiExceptionDispatch ; dispatch exception - no return
  488. ;
  489. ; The previous mode was kernel.
  490. ;
  491. KiSF10: mov TrP5[rbp], r8 ;
  492. mov r9d, TrErrorCode[rbp] ; set parameter 4 to selector index
  493. mov r8, cr0 ; set parameter 3 to control register 0
  494. mov edx, 6 ; set unexpected trap number
  495. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  496. call KeBugCheckEx ; bugcheck system - no return
  497. nop ; fill - do not remove
  498. NESTED_END KiStackFault, _TEXT$00
  499. subttl "General Protection Fault"
  500. ;++
  501. ;
  502. ; Routine Description:
  503. ;
  504. ; This routine is entered as the result of a general protection violation.
  505. ;
  506. ; Arguments:
  507. ;
  508. ; The standard exception frame is pushed by hardware on the kernel stack.
  509. ; The segment selector index for the segment descriptor that caused the
  510. ; exception, the IDT vector number for the descriptor that caused the
  511. ; exception, or zero is pushed as the error code.
  512. ;
  513. ; Disposition:
  514. ;
  515. ; A standard trap frame is constructed on the kernel stack, the exception
  516. ; parameters are loaded into registers, and the exception is dispatched via
  517. ; common code.
  518. ;
  519. ;--
  520. NESTED_ENTRY KiGeneralProtectionFault, _TEXT$00
  521. GENERATE_TRAP_FRAME <ErrorCode> ; generate trap frame
  522. mov ecx, STATUS_ACCESS_VIOLATION ; set exception code
  523. mov edx, 2 ; set number of parameters
  524. mov r9d, TrErrorCode[rbp] ; set parameter 1 to error code
  525. and r9d, 0ffffh ;
  526. xor r10, r10 ; set parameter 2 value
  527. mov r8, TrRip[rbp] ; set exception address
  528. call KiExceptionDispatch ; dispatch exception - no return
  529. nop ; fill - do not remove
  530. NESTED_END KiGeneralProtectionFault, _TEXT$00
  531. subttl "Page Fault"
  532. ;++
  533. ;
  534. ; Routine Description:
  535. ;
  536. ; This routine is entered as the result of a page fault which can occur
  537. ; because of the following reasons:
  538. ;
  539. ; 1. The referenced page is not present.
  540. ;
  541. ; 2. The referenced page does not allow the requested access.
  542. ;
  543. ; Arguments:
  544. ;
  545. ; A standard exception frame is pushed by hardware on the kernel stack.
  546. ; A special format error code is pushed which specifies the cause of the
  547. ; page fault as not present, read/write access denied, from user/kernel
  548. ; mode, and attempting to set reserved bits.
  549. ;
  550. ; Disposition:
  551. ;
  552. ; A standard trap frame is constructed on the kernel stack and memory
  553. ; management is called to resolve the page fault. If memory management
  554. ; successfully resolves the page fault, then working set information is
  555. ; recorded, owed breakpoints are inserted, and execution is continued.
  556. ; If memory management cannot resolve the page fault and the fault
  557. ; address is the pop SLIST code, then the execution of the pop SLIST
  558. ; code is continued at the resumption address. Otherwise, if the page
  559. ; fault occurred at an IRQL greater than APC_LEVEL, then the system is
  560. ; shut down via a call to bug check. Otherwise, an appropriate exception
  561. ; is raised.
  562. ;
  563. ;--
  564. NESTED_ENTRY KiPageFault, _TEXT$00
  565. GENERATE_TRAP_FRAME <Virtual> ; generate trap frame
  566. ;
  567. ; The registers eax and rcx are loaded with the error code and the virtual
  568. ; address of the fault respectively when the trap frame is generated.
  569. ;
  570. shr eax, 1 ; isolate load/store and i/d indicators
  571. and eax, 09h ;
  572. ;
  573. ; Save the load/store indicator and the faulting virtual address in the
  574. ; exception record in case an exception is raised.
  575. ;
  576. mov TrExceptionRecord + ErExceptionInformation[rbp], rax ;
  577. mov TrExceptionRecord + ErExceptionInformation + 8[rbp], rcx ;
  578. lea r9, (-128)[rbp] ; set trap frame address
  579. mov r8b, TrSegCs[rbp] ; isolate previous mode
  580. and r8b, MODE_MASK ;
  581. mov rdx, rcx ; set faulting virtual address
  582. mov cl, al ; set load/store indicator
  583. call MmAccessFault ; attempt to resolve page fault
  584. test eax, eax ; test for successful completion
  585. jl short KiPF20 ; if l, not successful completion
  586. ;
  587. ; If watch working set is enabled, then record working set information.
  588. ;
  589. cmp PsWatchEnabled, 0 ; check if working set watch enabled
  590. je short KiPF10 ; if e, working set watch not enabled
  591. mov r8, TrExceptionRecord + ErExceptionInformation + 8[rbp] ;
  592. mov rdx, TrRip[rbp] ; set exception address
  593. mov ecx, eax ; set completion status
  594. call PsWatchWorkingSet ; record working set information
  595. ;
  596. ; If the debugger has any breakpoints that should be inserted, then attempt
  597. ; to insert them now.
  598. ;
  599. KiPF10: cmp KdpOweBreakPoint, 0 ; check if breakpoints are owed
  600. je KiPF60 ; if e, no owed breakpoints
  601. call KdSetOwedBreakpoints ; notify the debugger of new page
  602. jmp KiPF60 ; finish in common code
  603. ;
  604. ; Check to determine if the page fault occurred in the interlocked pop entry
  605. ; SLIST code. There is a case where a page fault may occur in this code when
  606. ; the right set of circumstances present themselves. The page fault can be
  607. ; ignored by simply restarting the instruction sequence.
  608. ;
  609. KiPF20: lea rcx, ExpInterlockedPopEntrySListFault ; get fault address
  610. cmp rcx, TrRip[rbp] ; check if address matches
  611. je KiPF50 ; if e, address match
  612. ;
  613. ; Memory management failed to resolve the fault.
  614. ;
  615. ; STATUS_IN_PAGE_ERROR | 0x10000000 is a special status that indicates a
  616. ; page fault at IRQL greater than APC level. This status causes a
  617. ; bugcheck.
  618. ;
  619. ; The following status values can be raised:
  620. ;
  621. ; STATUS_ACCESS_VIOLATION
  622. ; STATUS_GUARD_PAGE_VIOLATION
  623. ; STATUS_STACK_OVERFLOW
  624. ;
  625. ; All other status values are sconverted to:
  626. ;
  627. ; STATUS_IN_PAGE_ERROR
  628. ;
  629. mov ecx, eax ; set status code
  630. mov edx, 2 ; set number of parameters
  631. cmp ecx, STATUS_IN_PAGE_ERROR or 10000000h ; check for bugcheck code
  632. je short KiPF40 ; if e, bugcheck code returned
  633. cmp ecx, STATUS_ACCESS_VIOLATION ; check for status values
  634. je short KiPF30 ; if e, raise exception with code
  635. cmp ecx, STATUS_GUARD_PAGE_VIOLATION ; check for status code
  636. je short KiPF30 ; if e, raise exception with code
  637. cmp ecx, STATUS_STACK_OVERFLOW ; check for status code
  638. je short KiPF30 ; if e, raise exception with code
  639. mov ecx, STATUS_IN_PAGE_ERROR ; convert all other status codes
  640. mov edx, 3 ; set number of parameters
  641. mov r11d, eax ; set parameter 3 to real status value
  642. ;
  643. ; Set virtual address, load/store and i/d indicators, exception address, and
  644. ; dispatch the exception.
  645. ;
  646. KiPF30: mov r10, TrExceptionRecord + ErExceptionInformation + 8[rbp] ;
  647. mov r9, TrExceptionRecord + ErExceptionInformation[rbp] ;
  648. mov r8, TrRip[rbp] ; set exception address
  649. call KiExceptionDispatch ; dispatch exception - no return
  650. ;
  651. ; A page fault occurred at an IRQL that was greater than APC_LEVEL. Set bug
  652. ; check parameters and join common code.
  653. ;
  654. KiPF40: CurrentIrql ; get current IRQL
  655. mov r8, TrRip[rbp] ; set parameter 5 to exception address
  656. mov TrP5[rbp], r8 ;
  657. mov r9, TrExceptionRecord + ErExceptionInformation[rbp] ;
  658. and eax, 0ffh ; isolate current IRQL
  659. mov r8, rax ;
  660. mov rdx, TrExceptionRecord + ErExceptionInformation + 8[rbp] ;
  661. mov ecx, IRQL_NOT_LESS_OR_EQUAL ; set bug check code
  662. call KeBugCheckEx ; bug check system - no return
  663. ;
  664. ; An unresolved page fault occurred in the pop SLIST code at the resumable
  665. ; fault address.
  666. ;
  667. KiPF50: lea rax, ExpInterlockedPopEntrySListResume ; get resume address
  668. mov TrRip[rbp], rax ; set resume address
  669. ;
  670. ; Test if a user APC should be delivered and exit exception.
  671. ;
  672. KiPF60: RESTORE_TRAP_STATE <Volatile> ; restore trap state and exit
  673. NESTED_END KiPageFault, _TEXT$00
  674. subttl "Legacy Floating Error"
  675. ;++
  676. ;
  677. ; Routine Description:
  678. ;
  679. ; This routine is entered as the result of a legacy floating point fault.
  680. ;
  681. ; Arguments:
  682. ;
  683. ; The standard exception frame is pushed by hardware on the kernel stack.
  684. ; There is no error code for this exception.
  685. ;
  686. ; Disposition:
  687. ;
  688. ; A standard trap frame is constructed on the kernel stack. If the previous
  689. ; mode is user, then reason for the exception is determine, the exception
  690. ; parameters are loaded into registers, and the exception is dispatched via
  691. ; common code. Otherwise, bug check is called.
  692. ;
  693. ;--
  694. NESTED_ENTRY KiFloatingErrorFault, _TEXT$00
  695. GENERATE_TRAP_FRAME ; generate trap frame
  696. mov edx, 7 ; set unexpected trap number
  697. test byte ptr TrSegCs[rbp], MODE_MASK ; check if previous mode user
  698. jz KiFE30 ; if z, previous mode not user
  699. ;
  700. ; The previous mode was user mode.
  701. ;
  702. fnstcw TrErrorCode[rbp] ; store floating control word
  703. fnstsw ax ; store floating status word
  704. mov cx, TrErrorCode[rbp] ; get control word
  705. and cx, FSW_ERROR_MASK ; isolate masked exceptions
  706. not cx ; compute enabled exceptions
  707. and ax, cx ; isolate exceptions
  708. mov ecx, STATUS_FLOAT_INVALID_OPERATION ; set exception code
  709. xor edx, edx ; set number of parameters
  710. mov r8, TrRip[rbp] ; set exception address
  711. test ax, FSW_INVALID_OPERATION ; test for invalid operation
  712. jz short KiFE10 ; if z, non invalid operation
  713. test ax, FSW_STACK_FAULT ; test is caused by stack fault
  714. jz short KiFE20 ; if z, not caused by stack fault
  715. mov ecx, STATUS_FLOAT_STACK_CHECK ; set exception code
  716. jmp short KiFE20 ; finish in common code
  717. KiFE10: mov ecx, STATUS_FLOAT_DIVIDE_BY_ZERO ; set exception code
  718. test ax, FSW_ZERO_DIVIDE ; test for divide by zero
  719. jnz short KiFE20 ; if nz, divide by zero
  720. mov ecx, STATUS_FLOAT_INVALID_OPERATION ; set exception code
  721. test ax, FSW_DENORMAL ; test if denormal operand
  722. jnz short KiFE20 ; if nz, denormal operand
  723. mov ecx, STATUS_FLOAT_OVERFLOW ; set exception code
  724. test ax, FSW_OVERFLOW ; test if overflow
  725. jnz short KiFE20 ; if nz, overflow
  726. mov ecx, STATUS_FLOAT_UNDERFLOW ; set exception code
  727. test ax, FSW_UNDERFLOW ; test if underflow
  728. jnz short KiFE20 ; if nz, underflow
  729. mov ecx, STATUS_FLOAT_INEXACT_RESULT ; set exception code
  730. mov edx, 8 ; set unexpected trap number
  731. test ax, FSW_PRECISION ; test for inexact result
  732. jz short KiFE30 ; if z, not inexact result
  733. KiFe20: call KiExceptionDispatch ; dispatch exception - no return
  734. ;
  735. ; The previous mode was kernel mode or the cause of the exception is unknown.
  736. ;
  737. KiFE30: mov r8, TrRip[rbp] ; set parameter 5 to exception address
  738. mov TrP5[rbp], r8 ;
  739. mov r9, cr4 ; set parameter 4 to control register 4
  740. mov r8, cr0 ; set parameter 3 to control register 0
  741. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  742. call KeBugCheckEx ; bugcheck system - no return
  743. nop ; fill - do not remove
  744. NESTED_END KiFloatingErrorFault, _TEXT$00
  745. subttl "Alignment Fault"
  746. ;++
  747. ;
  748. ; Routine Description:
  749. ;
  750. ; This routine is entered as the result of an attempted access to unaligned
  751. ; data.
  752. ;
  753. ; Arguments:
  754. ;
  755. ; The standard exception frame is pushed by hardware on the kernel stack.
  756. ; An error error code of zero is pushed on the stack.
  757. ;
  758. ; Disposition:
  759. ;
  760. ; A standard trap frame is constructed on the kernel stack, the exception
  761. ; parameters are loaded into registers, and the exception is dispatched via
  762. ; common code.
  763. ;
  764. ;--
  765. NESTED_ENTRY KiAlignmentFault, _TEXT$00
  766. GENERATE_TRAP_FRAME <ErrorCode> ; generate trap frame
  767. mov ecx, STATUS_DATATYPE_MISALIGNMENT ; set exception code
  768. xor edx, edx ; set number of parameters
  769. mov r8, TrRip[rbp] ; set exception address
  770. call KiExceptionDispatch ; dispatch exception - no return
  771. nop ; fill - do not remove
  772. NESTED_END KiAlignmentFault, _TEXT$00
  773. subttl "Machine Check Abort"
  774. ;++
  775. ;
  776. ; Routine Description:
  777. ;
  778. ; This routine is entered as the result of a machine check. A switch to
  779. ; the machine check stack occurs before the exception frame is pushed on
  780. ; the stack.
  781. ;
  782. ; Arguments:
  783. ;
  784. ; The standard exception frame is pushed by hardware on the kernel stack.
  785. ; There is no error code for this exception.
  786. ;
  787. ; Disposition:
  788. ;
  789. ; A standard trap and exception frame are constructed on the kernel stack
  790. ; and the HAL is called to determine if the machine check abort is fatal.
  791. ; If the HAL call returns, then system operation is continued.
  792. ;
  793. ;--
  794. NESTED_ENTRY KiMcheckAbort, _TEXT$00
  795. GENERATE_TRAP_FRAME ; generate trap frame
  796. call KxMcheckAbort ; call secondary routine
  797. RESTORE_TRAP_STATE <Volatile> ; restore trap state and exit
  798. NESTED_END KiMcheckAbort, _TEXT$00
  799. ;
  800. ; This routine generates an exception frame, then calls the HAL to process
  801. ; the machine check.
  802. ;
  803. NESTED_ENTRY KxMcheckAbort, _TEXT$00
  804. GENERATE_EXCEPTION_FRAME ; generate exception frame
  805. lea rcx, (-128)[rbp] ; set trap frame address
  806. mov rdx, rsp ; set exception frame address
  807. call __imp_HalHandleMcheck ; give HAL a chance to handle mcheck
  808. RESTORE_EXCEPTION_STATE ; restore exception state/deallocate
  809. ret ; return
  810. NESTED_END KxMcheckAbort, _TEXT$00
  811. subttl "XMM Floating Error"
  812. ;++
  813. ;
  814. ; Routine Description:
  815. ;
  816. ; This routine is entered as the result of a XMM floating point fault.
  817. ;
  818. ; Arguments:
  819. ;
  820. ; The standard exception frame is pushed by hardware on the kernel stack.
  821. ; There is no error code for this exception.
  822. ;
  823. ; Disposition:
  824. ;
  825. ; A standard trap frame is constructed on the kernel stack, mode is user,
  826. ; then reason for the exception is determine, the exception parameters are
  827. ; loaded into registers, and the exception is dispatched via common code.
  828. ; If no reason can be determined for the exception, then bug check is called.
  829. ;
  830. ;--
  831. NESTED_ENTRY KiXmmException, _TEXT$00
  832. GENERATE_TRAP_FRAME ; generate trap frame
  833. mov ax, TrMxCsr[rbp] ; get saved MXCSR
  834. test byte ptr TrSegCs[rbp], MODE_MASK ; test if previous mode user
  835. jnz short KiXE05 ; if nz, previous mode user
  836. stmxcsr TrErrorCode[rbp] ; get floating control/status word
  837. mov ax, TrErrorCode[rbp] ; for kernel mode
  838. KiXE05: mov cx, ax ; shift enables into position
  839. shr cx, XSW_ERROR_SHIFT ;
  840. and cx, XSW_ERROR_MASK ; isolate masked exceptions
  841. not cx ; compute enabled exceptions
  842. and ax, cx ; isolate exceptions
  843. mov ecx, STATUS_FLOAT_INVALID_OPERATION ; set exception code
  844. xor edx, edx ; set number of parameters
  845. mov r8, TrRip[rbp] ; set exception address
  846. test ax, XSW_INVALID_OPERATION ; test for invalid operation
  847. jnz short KiXE10 ; if z, invalid operation
  848. mov ecx, STATUS_FLOAT_DIVIDE_BY_ZERO ; set exception code
  849. test ax, XSW_ZERO_DIVIDE ; test for divide by zero
  850. jnz short KiXE10 ; if nz, divide by zero
  851. mov ecx, STATUS_FLOAT_INVALID_OPERATION ; set exception code
  852. test ax, XSW_DENORMAL ; test if denormal operand
  853. jnz short KiXE10 ; if nz, denormal operand
  854. mov ecx, STATUS_FLOAT_OVERFLOW ; set exception code
  855. test ax, XSW_OVERFLOW ; test if overflow
  856. jnz short KiXE10 ; if nz, overflow
  857. mov ecx, STATUS_FLOAT_UNDERFLOW ; set exception code
  858. test ax, XSW_UNDERFLOW ; test if underflow
  859. jnz short KiXE10 ; if nz, underflow
  860. mov ecx, STATUS_FLOAT_INEXACT_RESULT ; set exception code
  861. test ax, XSW_PRECISION ; test for inexact result
  862. jz short KiXE20 ; if z, not inexact result
  863. KiXE10: call KiExceptionDispatch ; dispatch exception - no return
  864. ;
  865. ; The previous mode was kernel mode or the cause of the exception is unknown.
  866. ;
  867. KiXE20: mov r8, TrRip[rbp] ; set parameter 5 to exception address
  868. mov TrP5[rbp], r8 ;
  869. mov r9, cr4 ; set parameter 4 to control register 4
  870. mov r8, cr0 ; set parameter 3 to control register 0
  871. mov edx, 9 ; set unexpected trap number
  872. mov ecx, UNEXPECTED_KERNEL_MODE_TRAP ; set bugcheck code
  873. call KeBugCheckEx ; bugcheck system - no return
  874. nop ; fill - do not remove
  875. NESTED_END KiXmmException, _TEXT$00
  876. subttl "Debug Service Trap"
  877. ;++
  878. ;
  879. ; Routine Description:
  880. ;
  881. ; This routine is entered as the result of the execution of an int 2d
  882. ; instruction.
  883. ;
  884. ; Arguments:
  885. ;
  886. ; The standard exception frame is pushed by hardware on the kernel stack.
  887. ; There is no error code for this exception.
  888. ;
  889. ; Disposition:
  890. ;
  891. ; A standard trap frame is constructed on the kernel stack, the exception
  892. ; arguments are loaded into registers, and the exception is dispatched via
  893. ; common code.
  894. ;
  895. ;--
  896. NESTED_ENTRY KiDebugServiceTrap, _TEXT$00
  897. GENERATE_TRAP_FRAME ; generate trap frame
  898. mov ecx, STATUS_BREAKPOINT ; set exception code
  899. mov edx, 1 ; set number of parameters
  900. mov r9, TrRax[rbp] ; set parameter 1 value
  901. mov r8, TrRip[rbp] ; set exception address
  902. inc qword ptr TrRip[rbp] ; point to int 3 instruction
  903. call KiExceptionDispatch ; dispatch exception - no return
  904. nop ; fill - do not remove
  905. NESTED_END KiDebugServiceTrap, _TEXT$00
  906. subttl "System Service Call 32-bit"
  907. ;++
  908. ;
  909. ; Routine Description:
  910. ;
  911. ; This routine gains control when a system call instruction is executed
  912. ; from 32-bit mode. System service calls from 32-bit code are not supported
  913. ; and this exception is turned into an invalid opcode fault.
  914. ;
  915. ; N.B. This routine is never entered from kernel mode and it executed with
  916. ; interrupts disabled.
  917. ;
  918. ; Arguments:
  919. ;
  920. ; The standard exception frame is pushed on the stack.
  921. ;
  922. ; Return Value:
  923. ;
  924. ; A standard trap frame is constructed on the kernel stack, the exception
  925. ; parameters are loaded into registers, and the exception is dispatched via
  926. ; common code.
  927. ;
  928. ;--
  929. NESTED_ENTRY KiSystemCall32, _TEXT$00
  930. swapgs ; swap GS base to kernel PCR
  931. mov r8, gs:[PcTss] ; get address of task state segment
  932. mov r9, rsp ; save user stack pointer
  933. mov rsp, TssRsp0[r8] ; set kernel stack pointer
  934. pushq KGDT64_R3_DATA or RPL_MASK ; push dummy SS selector
  935. push r9 ; push user stack pointer
  936. pushq r11 ; push previous EFLAGS
  937. pushq KGDT64_R3_CODE or RPL_MASK ; push dummy 64-bit CS selector
  938. pushq rcx ; push return address
  939. GENERATE_TRAP_FRAME ; generate trap frame
  940. mov ecx, STATUS_ILLEGAL_INSTRUCTION ; set exception code
  941. xor edx, edx ; set number of parameters
  942. mov r8, TrRip[rbp] ; set exception address
  943. call KiExceptionDispatch ; dispatch exception - no return
  944. nop ; fill - do not remove
  945. NESTED_END KiSystemCall32, _TEXT$00
  946. subttl "System Service Exception Handler"
  947. ;++
  948. ;
  949. ; EXCEPTION_DISPOSITION
  950. ; KiSystemServiceHandler (
  951. ; IN PEXCEPTION_RECORD ExceptionRecord,
  952. ; IN PVOID EstablisherFrame,
  953. ; IN OUT PCONTEXT ContextRecord,
  954. ; IN OUT PDISPATCHER_CONTEXT DispatcherContext
  955. ; )
  956. ;
  957. ; Routine Description:
  958. ;
  959. ; This routine is the exception handler for the system service dispatcher.
  960. ;
  961. ; If an unwind is being performed and the system service dispatcher is
  962. ; the target of the unwind, then an exception occured while attempting
  963. ; to copy the user's in-memory argument list. Control is transfered to
  964. ; the system service exit by return a continue execution disposition
  965. ; value.
  966. ;
  967. ; If an unwind is being performed and the previous mode is user, then
  968. ; bug check is called to crash the system. It is not valid to unwind
  969. ; out of a system service into user mode.
  970. ;
  971. ; If an unwind is being performed and the previous mode is kernel, then
  972. ; the previous mode field from the trap frame is restored to the thread
  973. ; object.
  974. ;
  975. ; If an exception is being raised and the exception PC is the address
  976. ; of the system service dispatcher in-memory argument copy code, then an
  977. ; unwind to the system service exit code is initiated.
  978. ;
  979. ; If an exception is being raised and the exception PC is not within
  980. ; the range of the system service dispatcher, and the previous mode is
  981. ; not user, then a continue search disposition value is returned. Otherwise,
  982. ; a system service has failed to handle an exception and bug check is
  983. ; called. It is invalid for a system service not to handle all exceptions
  984. ; that can be raised in the service.
  985. ;
  986. ; Arguments:
  987. ;
  988. ; ExceptionRecord (rcx) - Supplies a pointer to an exception record.
  989. ;
  990. ; EstablisherFrame (rdx) - Supplies the frame pointer of the establisher
  991. ; of this exception handler.
  992. ;
  993. ; ContextRecord (r8) - Supplies a pointer to a context record.
  994. ;
  995. ; DispatcherContext (r9) - Supplies a pointer to the dispatcher context
  996. ; record.
  997. ;
  998. ; Return Value:
  999. ;
  1000. ; If bug check is called, there is no return from this routine and the
  1001. ; system is crashed. If an exception occured while attempting to copy
  1002. ; the user in-memory argument list, then there is no return from this
  1003. ; routine, and unwind is called. Otherwise, ExceptionContinueSearch is
  1004. ; returned as the function value.
  1005. ;
  1006. ;--
  1007. ShFrame struct
  1008. P1Home dq ? ; parameter home addresses
  1009. P2Home dq ? ;
  1010. P3Home dq ? ;
  1011. P4Home dq ? ;
  1012. Fill dq ? ; fill to 8 mod 16
  1013. ShFrame ends
  1014. NESTED_ENTRY KiSystemServiceHandler, _TEXT$00
  1015. alloc_stack (sizeof ShFrame) ; allocate stack frame
  1016. END_PROLOGUE
  1017. test dword ptr ErExceptionFlags[rcx], EXCEPTION_UNWIND ; test for unwind
  1018. jnz short KiSH30 ; if nz, unwind in progress
  1019. ;
  1020. ; An exception is in progress.
  1021. ;
  1022. ; If the exception PC is the address of the in-memory argument copy code for
  1023. ; the system service dispatcher, then call unwind to transfer control to the
  1024. ; system service exit code. Otherwise, check if the previous mode is user
  1025. ; or kernel mode.
  1026. ;
  1027. lea rax, KiSystemServiceCopyStart ; get copy code start address
  1028. cmp rax, ErExceptionAddress[rcx] ; check if within range
  1029. jb short KiSH10 ; if b, address not within range
  1030. lea rax, KiSystemServiceCopyEnd ; get copy code end address
  1031. cmp rax, ErExceptionAddress[rcx] ; check if within range
  1032. jae short KiSH10 ; if ae, not within range
  1033. ;
  1034. ; The exception was raised by the system service dispatcher argument copy
  1035. ; code. Unwind to the system service exit with the exception status code as
  1036. ; the return value.
  1037. ;
  1038. mov r9d, ErExceptionCode[rcx] ; set return value
  1039. xor r8, r8 ; set exception record address
  1040. mov rcx, rdx ; set target frame address
  1041. lea rdx, KiSystemServiceExit ; set target IP address
  1042. call RtlUnwind ; unwind - no return
  1043. ;
  1044. ; If the previous mode was kernel mode, then the continue the search for an
  1045. ; exception handler. Otherwise, bug check the system.
  1046. ;
  1047. KiSH10: mov rax, gs:[PcCurrentThread] ; get current thread address
  1048. cmp byte ptr ThPreviousMode[rax], KernelMode ; check for kernel mode
  1049. je short KiSH20 ; if e, previous mode kernel
  1050. ;
  1051. ; Previous mode is user mode - bug check the system.
  1052. ;
  1053. mov ecx, SYSTEM_SERVICE_EXCEPTION ; set bug check code
  1054. call KeBugCheck ; bug check - no return
  1055. ;
  1056. ; Previous mode is kernel mode - continue search for a handler.
  1057. ;
  1058. KiSH20: mov eax, ExceptionContinueSearch ; set return value
  1059. add rsp, sizeof ShFrame ; deallocate stack frame
  1060. ret ; return
  1061. ;
  1062. ; An unwind is in progress.
  1063. ;
  1064. ; If a target unwind is being performed, then continue the unwind operation.
  1065. ; Otherwise, check if the previous mode is user or kernel mode.
  1066. ;
  1067. KiSH30: test dword ptr ErExceptionFlags[rcx], EXCEPTION_TARGET_UNWIND ; test for target unwind
  1068. jnz short KiSH20 ; if nz, target unwind in progress
  1069. ;
  1070. ; If the previous mode was kernel mode, then restore the previous mode and
  1071. ; continue the unwind operation. Otherwise, bug check the system.
  1072. ;
  1073. mov rax, gs:[PcCurrentThread] ; get current thread address
  1074. cmp byte ptr ThPreviousMode[rax], KernelMode ; check for kernel mode
  1075. je short KiSH40 ; if e, previous mode kernel
  1076. ;
  1077. ; Previous mode was user mode - bug check the system.
  1078. ;
  1079. mov ecx, SYSTEM_UNWIND_PREVIOUS_USER ; set bug check code
  1080. call KeBugCheck ; bug check - no return
  1081. ;
  1082. ; Previous mode is kernel mode - restore previous mode and continue unwind
  1083. ; operation.
  1084. ;
  1085. KiSH40: mov rcx, ThTrapFrame[rax] ; get current frame pointer address
  1086. mov cl, TrPreviousMode[rcx] ; get previous mode
  1087. mov ThPreviousMode[rax], cl ; restore previous mode
  1088. jmp short KiSH20 ; finish in common code
  1089. NESTED_END KiSystemServiceHandler, _TEXT$00
  1090. subttl "System Service Call 64-bit"
  1091. ;++
  1092. ;
  1093. ; Routine Description:
  1094. ;
  1095. ; This routine gains control when a system call instruction is executed
  1096. ; from 64-bit mode. The specified system service is executed by locating
  1097. ; its routine address in system service dispatch table and calling the
  1098. ; specified function.
  1099. ;
  1100. ; N.B. This routine is never entered from kernel mode and it executed with
  1101. ; interrupts disabled.
  1102. ;
  1103. ; Arguments:
  1104. ;
  1105. ; eax - Supplies the system service number.
  1106. ;
  1107. ; Return Value:
  1108. ;
  1109. ; eax - System service status code.
  1110. ;
  1111. ; r10, rdx, r8, and r9 - Supply the first four system call arguments.
  1112. ;
  1113. ; rcx - Supplies the RIP of the system call.
  1114. ;
  1115. ; r11 - Supplies the previous EFLAGS.
  1116. ;
  1117. ;--
  1118. NESTED_ENTRY KiSystemCall64, _TEXT$00, KiSystemServiceHandler
  1119. swapgs ; swap GS base to kernel PCR
  1120. mov gs:[PcSavedRcx], rcx ; save return address
  1121. mov gs:[PcSavedR11], r11 ; save previous EFLAGS
  1122. mov rcx, gs:[PcTss] ; get address of task state segment
  1123. mov r11, rsp ; save user stack pointer
  1124. mov rsp, TssRsp0[rcx] ; set kernel stack pointer
  1125. pushq KGDT64_R3_DATA or RPL_MASK ; push dummy SS selector
  1126. push r11 ; push user stack pointer
  1127. pushq gs:[PcSavedR11] ; push previous EFLAGS
  1128. pushq KGDT64_R3_CODE or RPL_MASK ; push dummy 64-bit CS selector
  1129. pushq gs:[PcSavedRcx] ; push return address
  1130. mov rcx, r10 ; set first argument value
  1131. ;
  1132. ; Generate a trap frame without saving any of the volatile registers, i.e.,
  1133. ; they are assumed to be destroyed as per the AMD64 calling standard.
  1134. ;
  1135. ; N.B. RBX, RDI, and RSI are also saved in this trap frame.
  1136. ;
  1137. ALTERNATE_ENTRY KiSystemService
  1138. push_frame ; mark machine frame
  1139. alloc_stack 8 ; allocate dummy error code
  1140. push_reg rbp ; save standard register
  1141. push_reg rsi ; save extra registers
  1142. push_reg rdi ;
  1143. push_reg rbx ;
  1144. alloc_stack (KTRAP_FRAME_LENGTH - (10 * 8)) ; allocate fixed frame
  1145. set_frame rbp, 128 ; set frame pointer
  1146. END_PROLOGUE
  1147. SAVE_TRAP_STATE <Service> ; save trap state
  1148. sti ; enable interrupts
  1149. mov rbx, gs:[PcCurrentThread] ; get current thread address
  1150. mov r10b, TrSegCs[rbp] ; ioslate system call previous mode
  1151. and r10b, MODE_MASK ;
  1152. mov r11b, ThPreviousMode[rbx] ; save previous mode in trap frame
  1153. mov TrPreviousMode[rbp], r11b ;
  1154. mov ThPreviousMode[rbx], r10b ; set thread previous mode
  1155. mov r10, ThTrapFrame[rbx] ; save previous frame pointer address
  1156. mov TrTrapFrame[rbp], r10 ;
  1157. ;
  1158. ; Dispatch system service.
  1159. ;
  1160. ; eax - Supplies the system service number.
  1161. ; rbx - Supplies the current thread address.
  1162. ; rcx - Supplies the first argument if present.
  1163. ; rdx - Supplies the second argument if present.
  1164. ; r8 - Supplies the third argument if present.
  1165. ; r9 - Supplies the fourth argument if present.
  1166. ;
  1167. ALTERNATE_ENTRY KiSystemServiceRepeat
  1168. mov ThTrapFrame[rbx], rsp ; set current frame pointer address
  1169. mov edi, eax ; copy system service number
  1170. shr edi, SERVICE_TABLE_SHIFT ; isolate service table number
  1171. and edi, SERVICE_TABLE_MASK ;
  1172. mov esi, edi ; save service table number
  1173. add rdi, ThServiceTable[rbx] ; compute service descriptor address
  1174. mov r10d, eax ; save system service number
  1175. and eax, SERVICE_NUMBER_MASK ; isolate service table offset
  1176. ;
  1177. ; If the specified system service number is not within range, then attempt
  1178. ; to convert the thread to a GUI thread and retry the service dispatch.
  1179. ;
  1180. cmp eax, SdLimit[rdi] ; check if valid service
  1181. jae KiSS50 ;if ae, not valid service
  1182. ;
  1183. ; If the service is a GUI service and the GDI user batch queue is not empty,
  1184. ; then call the appropriate service to flush the user batch.
  1185. ;
  1186. cmp esi, SERVICE_TABLE_TEST ; check if GUI service
  1187. jne short KiSS10 ; if ne, not GUI service
  1188. mov r10, ThTeb[rbx] ; get user TEB adresss
  1189. cmp dword ptr TeGdiBatchCount[r10], 0 ; check batch queue depth
  1190. je short KiSS10 ; if e, batch queue empty
  1191. mov TrRax[rbp], eax ; save system service table offset
  1192. mov TrP1Home[rbp], rcx ; save system service arguments
  1193. mov TrP2Home[rbp], rdx ;
  1194. mov TrP3Home[rbp], r8 ;
  1195. mov TrP4Home[rbp], r9 ;
  1196. call KeGdiFlushUserBatch ; call flush GDI user batch routine
  1197. mov eax, TrRax[rbp] ; restore system service table offset
  1198. mov rcx, TrP1Home[rbp] ; restore system service arguments
  1199. mov rdx, TrP2Home[rbp] ;
  1200. mov r8, TrP3Home[rbp] ;
  1201. mov r9, TrP4Home[rbp] ;
  1202. ;
  1203. ; Check if system service has any in memory arguments.
  1204. ;
  1205. KiSS10: mov r10, SdBase[rdi] ; get service table base address
  1206. mov r10, [r10][rax * 8] ; get system service routine address
  1207. btr r10, 0 ; check if any in memory arguments
  1208. jnc short KiSS30 ; if nc, no in memory arguments
  1209. mov TrP1Home[rbp], rcx ; save first argument if present
  1210. mov rdi, SdNumber[rdi] ; get argument table address
  1211. movzx ecx, byte ptr [rdi][rax] ; get number of in memory bytes
  1212. sub rsp, rcx ; allocate stack argument area
  1213. and spl, 0f0h ; align stack on 0 mod 16 boundary
  1214. mov rdi, rsp ; set copy destination address
  1215. mov rsi, TrRsp[rbp] ; get previous stack address
  1216. add rsi, 5 * 8 ; compute copy source address
  1217. test byte ptr TrSegCs[rbp], MODE_MASK ; check if previous mode user
  1218. jz short KiSS20 ; if z, previous mode kernel
  1219. cmp rsi, MmUserProbeAddress ; check if source address in range
  1220. cmovae rsi, MmUserProbeAddress ; if ae, reset copy source address
  1221. KiSS20: shr ecx, 3 ; compute number of quadwords
  1222. ALTERNATE_ENTRY KiSystemServiceCopyStart
  1223. rep movsq ; move arguments to kernel stack
  1224. ALTERNATE_ENTRY KiSystemServiceCopyEnd
  1225. sub rsp, 4 * 8 ; allocate argument home area
  1226. mov rcx, TrP1Home[rbp] ; restore first argument if present
  1227. ;
  1228. ; Call system service.
  1229. ;
  1230. KiSS30: call r10 ; call system service
  1231. inc dword ptr gs:[PcSystemCalls] ; increment number of system calls
  1232. ;
  1233. ; System service exit.
  1234. ;
  1235. ; eax - Supplies the system service status.
  1236. ;
  1237. ; rbp - Supplies the address of the trap frame.
  1238. ;
  1239. ALTERNATE_ENTRY KiSystemServiceExit
  1240. mov rcx, gs:[PcCurrentThread] ; get current thread address
  1241. mov rdx, TrTrapFrame[rbp] ; restore frame pointer address
  1242. mov ThTrapFrame[rcx], rdx ;
  1243. mov dl, TrPreviousMode[rbp] ; restore previous mode
  1244. mov ThPreviousMode[rbx], dl ;
  1245. mov rbx, TrRbx[rbp] ; restore extra registers
  1246. mov rdi, TrRdi[rbp] ;
  1247. mov rsi, TrRsi[rbp] ;
  1248. ;
  1249. ; Test if a user APC should be delivered and exit system service.
  1250. ;
  1251. test byte ptr TrSegCs[rbp], MODE_MASK ; test if previous mode user
  1252. jz KiSS40 ; if z, previous mode not user
  1253. RESTORE_TRAP_STATE <Service> ; restore trap state/exit to user mode
  1254. KiSS40: RESTORE_TRAP_STATE <Kernel> ; restore trap state/exit to kernel mode
  1255. ;
  1256. ; The specified system service number is not within range. Attempt to convert
  1257. ; the thread to a GUI thread if the specified system service is a GUI service
  1258. ; and the thread has not already been converted to a GUI thread.
  1259. ;
  1260. KiSS50: cmp esi, SERVICE_TABLE_TEST ; check if GUI service
  1261. jne short KiSS60 ; if ne, not GUI service
  1262. mov TrRax[rbp], r10d ; save system service number
  1263. mov TrP1Home[rbp], rcx ; save system service arguments
  1264. mov TrP2Home[rbp], rdx ;
  1265. mov TrP3Home[rbp], r8 ;
  1266. mov TrP4Home[rbp], r9 ;
  1267. call KiConvertToGuiThread ; attempt to convert to GUI thread
  1268. or eax, eax ; check if service was successful
  1269. mov eax, TrRax[rbp] ; restore system service number
  1270. mov rcx, TrP1Home[rbp] ; restore system service arguments
  1271. mov rdx, TrP2Home[rbp] ;
  1272. mov r8, TrP3Home[rbp] ;
  1273. mov r9, TrP4Home[rbp] ;
  1274. jz KiSystemServiceRepeat ; if z, successful conversion to GUI
  1275. ;
  1276. ; The conversion to a GUI thread failed. The correct return value is encoded
  1277. ; in a byte table indexed by the service number that is at the end of the
  1278. ; service address table. The encoding is as follows:
  1279. ;
  1280. ; 0 - return 0.
  1281. ; -1 - return -1.
  1282. ; 1 - return status code.
  1283. ;
  1284. lea rdi, KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST ;
  1285. mov esi, SdLimit[rdi] ; get service table limit
  1286. mov rdi, SdBase[rdi] ; get service table base
  1287. lea rdi, [rdi][rsi * 8] ; get ending service table address
  1288. and eax, SERVICE_NUMBER_MASK ; isolate service number
  1289. movsx eax, byte ptr [rdi][rax] ; get status byte value
  1290. or eax, eax ; check for 0 or - 1
  1291. jle KiSystemServiceExit ; if le, return status byte value
  1292. KiSS60: mov eax, STATUS_INVALID_SYSTEM_SERVICE ; set return status
  1293. jmp KiSystemServiceExit ; finish in common code
  1294. NESTED_END KiSystemCall64, _TEXT$00
  1295. subttl "Common Exception Dispatch"
  1296. ;++
  1297. ;
  1298. ; Routine Description:
  1299. ;
  1300. ; This routine allocates an exception frame on stack, saves nonvolatile
  1301. ; machine state, and calls the system exception dispatcher.
  1302. ;
  1303. ; N.B. It is the responsibility of the caller to initialize the exception
  1304. ; record.
  1305. ;
  1306. ; Arguments:
  1307. ;
  1308. ; ecx - Supplies the exception code.
  1309. ;
  1310. ; edx - Supplies the number of parameters.
  1311. ;
  1312. ; r8 - Supplies the exception address.
  1313. ;
  1314. ; r9 - r11 - Supply the exception parameters.
  1315. ;
  1316. ; rbp - Supplies a pointer to the trap frame.
  1317. ;
  1318. ; rsp - Supplies a pointer to the trap frame.
  1319. ;
  1320. ; Return Value:
  1321. ;
  1322. ; There is no return from this function.
  1323. ;
  1324. ;--
  1325. NESTED_ENTRY KiExceptionDispatch, _TEXT$00
  1326. GENERATE_EXCEPTION_FRAME ; generate exception frame
  1327. lea rax, TrExceptionRecord[rbp] ; get exception record address
  1328. mov ErExceptionCode[rax], ecx ; set exception code
  1329. xor ecx, ecx ;
  1330. mov dword ptr ErExceptionFlags[rax], ecx ; clear exception flags
  1331. mov ErExceptionRecord[rax], rcx ; clear exception record address
  1332. mov ErExceptionAddress[rax], r8 ; set exception address
  1333. mov ErNumberParameters[rax], edx ; set number of parameters
  1334. mov ErExceptionInformation[rax], r9 ; set exception parameters
  1335. mov ErExceptionInformation + 8[rax], r10 ;
  1336. mov ErExceptionInformation + 16[rax], r11 ;
  1337. mov r9b, TrSegCs[rbp] ; isolate previous mode
  1338. and r9b, MODE_MASK ;
  1339. jz short KiEE10 ; if z, previous mode not user
  1340. lea rbx, (KTRAP_FRAME_LENGTH - 128)[rbp] ; get save area address
  1341. fnsaved [rbx] ; save legacy floating state
  1342. KiEE10: mov byte ptr ExP5[rsp], TRUE ; set first chance parameter
  1343. lea r8, (-128)[rbp] ; set trap frame address
  1344. mov rdx, rsp ; set exception frame address
  1345. mov rcx, rax ; set exception record address
  1346. call KiDispatchException ; dispatch exception
  1347. subttl "Common Exception Exit"
  1348. ;++
  1349. ;
  1350. ; Routine Description:
  1351. ;
  1352. ; This routine is called to exit an exception.
  1353. ;
  1354. ; N.B. This transfer of control occurs from:
  1355. ;
  1356. ; 1. a fall through from above.
  1357. ; 2. the exit from a continue system service.
  1358. ; 3. the exit form a raise exception system service.
  1359. ; 4. the exit into user mode from thread startup.
  1360. ;
  1361. ; N.B. Control is transfered to this code via a jump.
  1362. ;
  1363. ; Arguments:
  1364. ;
  1365. ; rbp - Supplies the address of the trap frame.
  1366. ;
  1367. ; rsp - Supplies the address of the exception frame.
  1368. ;
  1369. ; Return Value:
  1370. ;
  1371. ; Function does not return.
  1372. ;
  1373. ;--
  1374. ALTERNATE_ENTRY KiExceptionExit
  1375. RESTORE_EXCEPTION_STATE <NoPop> ; restore exception state/deallocate
  1376. RESTORE_TRAP_STATE <Volatile> ; restore trap state and exit
  1377. NESTED_END KiExceptionDispatch, _TEXT$00
  1378. subttl "Check for Allowable Invalid Address"
  1379. ;++
  1380. ;
  1381. ; BOOLEAN
  1382. ; KeInvalidAccessAllowed (
  1383. ; IN PVOID TrapFrame
  1384. ; )
  1385. ;
  1386. ; Routine Description:
  1387. ;
  1388. ; This function checks to determine if the fault address in the specified
  1389. ; trap frame is an allowed fault address. Currently there is only one such
  1390. ; address and it is the pop SLIST fault address.
  1391. ;
  1392. ; Arguments:
  1393. ;
  1394. ; TrapFrame (rcx) - Supplies a pointer to a trap frame.
  1395. ;
  1396. ; Return value:
  1397. ;
  1398. ; If the fault address is allowed, then TRUE is returned. Otherwise, FALSE
  1399. ; is returned.
  1400. ;
  1401. ;--
  1402. LEAF_ENTRY KeInvalidAccessAllowed, _TEXT$00
  1403. lea rdx, ExpInterlockedPopEntrySListFault ; get fault address
  1404. cmp rdx, TrRip[rcx] ; check if address match
  1405. sete al ; set return value
  1406. ret ; return
  1407. LEAF_END KeInvalidAccessAllowed, _TEXT$00
  1408. subttl "System Service Linkage"
  1409. ;++
  1410. ;
  1411. ; VOID
  1412. ; KiServiceLinkage (
  1413. ; VOID
  1414. ; )
  1415. ;
  1416. ; Routine Description:
  1417. ;
  1418. ; This is a dummay function that only exists to make trace back through
  1419. ; a kernel mode to kernel mode system call work.
  1420. ; Arguments:
  1421. ;
  1422. ; None.
  1423. ;
  1424. ; Return value:
  1425. ;
  1426. ; None.
  1427. ;
  1428. ;--
  1429. LEAF_ENTRY KiServiceLinkage, _TEXT$00
  1430. ret ;
  1431. LEAF_END KiServiceLinkage, _TEXT$00
  1432. subttl "Unexpected Interrupt Code"
  1433. ;++
  1434. ;
  1435. ; RoutineDescription:
  1436. ;
  1437. ; An entry in the following table is generated for each vector that can
  1438. ; receive an unexpected interrupt. Each entry in the table contains code
  1439. ; to push the vector number on the stack and then jump to common code to
  1440. ; process the unexpected interrupt.
  1441. ;
  1442. ; Arguments:
  1443. ;
  1444. ; None.
  1445. ;
  1446. ;--
  1447. NESTED_ENTRY KiUnexpectedInterrupt, _TEXT$00
  1448. .pushframe code ; mark machine frame
  1449. .pushreg rbp ; mark nonvolatile register push
  1450. GENERATE_INTERRUPT_FRAME <Vector> ; generate interrupt frame
  1451. mov ecx, eax ; compute interrupt IRQL
  1452. shr ecx, 4 ;
  1453. ENTER_INTERRUPT <NoEOI> ; raise IRQL and enable interrupts
  1454. EXIT_INTERRUPT ; do EOI, lower IRQL, and restore state
  1455. NESTED_END KiUnexpectedInterrupt, _TEXT$00
  1456. subttl "Unexpected Interrupt Dispatch Code"
  1457. ;++
  1458. ; The following code is a table of unexpected interrupt dispatch code
  1459. ; fragments for each interrupt vector. Empty interrupt vectors are
  1460. ; initialized to jump to this code which pushes the interrupt vector
  1461. ; number on the stack and jumps to the above unexpected interrupt code.
  1462. ;--
  1463. EMPTY_VECTOR macro Vector
  1464. LEAF_ENTRY KxUnexpectedInterrupt&Vector, _TEXT$00
  1465. push &Vector ; push vector number
  1466. push rbp ; push nonvolatile register
  1467. jmp KiUnexpectedInterrupt ; finish in common code
  1468. LEAF_END KxUnexpectedInterrupt&Vector, _TEXT$00
  1469. endm
  1470. interrupt_vector = 0
  1471. rept (MAXIMUM_PRIMARY_VECTOR + 1)
  1472. EMPTY_VECTOR %interrupt_vector
  1473. interrupt_vector = interrupt_vector + 1
  1474. endm
  1475. end