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.

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