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.

1212 lines
37 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1993, 1994 Digital Equipment Corporation
  4. Module Name:
  5. exceptn.c
  6. Abstract:
  7. This module implements the code necessary to dispatch exceptions to the
  8. proper mode and invoke the exception dispatcher.
  9. Author:
  10. David N. Cutler (davec) 3-Apr-1990
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. Thomas Van Baak (tvb) 12-May-1992
  15. Adapted for Alpha AXP.
  16. --*/
  17. #include "ki.h"
  18. BOOLEAN
  19. KiHandleAlignmentFault(
  20. IN PEXCEPTION_RECORD ExceptionRecord,
  21. IN PKEXCEPTION_FRAME ExceptionFrame,
  22. IN PKTRAP_FRAME TrapFrame,
  23. IN KPROCESSOR_MODE PreviousMode,
  24. IN BOOLEAN FirstChance,
  25. OUT BOOLEAN *ExceptionForwarded
  26. );
  27. VOID
  28. KiMachineCheck (
  29. IN PEXCEPTION_RECORD ExceptionRecord,
  30. IN PKEXCEPTION_FRAME ExceptionFrame,
  31. IN PKTRAP_FRAME TrapFrame
  32. );
  33. VOID
  34. KeContextFromKframes (
  35. IN PKTRAP_FRAME TrapFrame,
  36. IN PKEXCEPTION_FRAME ExceptionFrame,
  37. IN OUT PCONTEXT ContextFrame
  38. )
  39. /*++
  40. Routine Description:
  41. This routine moves the selected contents of the specified trap and exception
  42. frames into the specified context frame according to the specified context
  43. flags.
  44. Arguments:
  45. TrapFrame - Supplies a pointer to a trap frame from which volatile context
  46. should be copied into the context record.
  47. ExceptionFrame - Supplies a pointer to an exception frame from which context
  48. should be copied into the context record.
  49. ContextFrame - Supplies a pointer to the context frame that receives the
  50. context copied from the trap and exception frames.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. //
  56. // Set control information if specified.
  57. //
  58. if ((ContextFrame->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  59. //
  60. // Set integer register gp, ra, sp, FIR, and PSR from trap frame.
  61. //
  62. ContextFrame->IntGp = TrapFrame->IntGp;
  63. ContextFrame->IntSp = TrapFrame->IntSp;
  64. ContextFrame->IntRa = TrapFrame->IntRa;
  65. ContextFrame->Fir = TrapFrame->Fir;
  66. ContextFrame->Psr = TrapFrame->Psr;
  67. }
  68. //
  69. // Set integer register contents if specified.
  70. //
  71. if ((ContextFrame->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  72. //
  73. // Set volatile integer registers v0 and t0 - t7 from trap frame.
  74. //
  75. ContextFrame->IntV0 = TrapFrame->IntV0;
  76. ContextFrame->IntT0 = TrapFrame->IntT0;
  77. ContextFrame->IntT1 = TrapFrame->IntT1;
  78. ContextFrame->IntT2 = TrapFrame->IntT2;
  79. ContextFrame->IntT3 = TrapFrame->IntT3;
  80. ContextFrame->IntT4 = TrapFrame->IntT4;
  81. ContextFrame->IntT5 = TrapFrame->IntT5;
  82. ContextFrame->IntT6 = TrapFrame->IntT6;
  83. ContextFrame->IntT7 = TrapFrame->IntT7;
  84. //
  85. // Set nonvolatile integer registers s0 - s5 from exception frame.
  86. //
  87. ContextFrame->IntS0 = ExceptionFrame->IntS0;
  88. ContextFrame->IntS1 = ExceptionFrame->IntS1;
  89. ContextFrame->IntS2 = ExceptionFrame->IntS2;
  90. ContextFrame->IntS3 = ExceptionFrame->IntS3;
  91. ContextFrame->IntS4 = ExceptionFrame->IntS4;
  92. ContextFrame->IntS5 = ExceptionFrame->IntS5;
  93. //
  94. // Set volatile integer registers a0 - a5, and t8 - t11 from trap
  95. // frame.
  96. //
  97. ContextFrame->IntA0 = TrapFrame->IntA0;
  98. ContextFrame->IntA1 = TrapFrame->IntA1;
  99. ContextFrame->IntA2 = TrapFrame->IntA2;
  100. ContextFrame->IntA3 = TrapFrame->IntA3;
  101. ContextFrame->IntA4 = TrapFrame->IntA4;
  102. ContextFrame->IntA5 = TrapFrame->IntA5;
  103. ContextFrame->IntT8 = TrapFrame->IntT8;
  104. ContextFrame->IntT9 = TrapFrame->IntT9;
  105. ContextFrame->IntT10 = TrapFrame->IntT10;
  106. ContextFrame->IntT11 = TrapFrame->IntT11;
  107. //
  108. // Set volatile integer registers fp, t12 and at from trap frame.
  109. // Set integer register zero.
  110. //
  111. ContextFrame->IntFp = TrapFrame->IntFp;
  112. ContextFrame->IntT12 = TrapFrame->IntT12;
  113. ContextFrame->IntAt = TrapFrame->IntAt;
  114. ContextFrame->IntZero = 0;
  115. }
  116. //
  117. // Set floating register contents if specified.
  118. //
  119. if ((ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  120. //
  121. // Set volatile floating registers f0 - f1 from trap frame.
  122. // Set volatile floating registers f10 - f30 from trap frame.
  123. // Set floating zero register f31 to 0.
  124. //
  125. ContextFrame->FltF0 = TrapFrame->FltF0;
  126. ContextFrame->FltF1 = TrapFrame->FltF1;
  127. RtlMoveMemory(&ContextFrame->FltF10, &TrapFrame->FltF10,
  128. sizeof(ULONGLONG) * 21);
  129. ContextFrame->FltF31 = 0;
  130. //
  131. // Set nonvolatile floating registers f2 - f9 from exception frame.
  132. //
  133. ContextFrame->FltF2 = ExceptionFrame->FltF2;
  134. ContextFrame->FltF3 = ExceptionFrame->FltF3;
  135. ContextFrame->FltF4 = ExceptionFrame->FltF4;
  136. ContextFrame->FltF5 = ExceptionFrame->FltF5;
  137. ContextFrame->FltF6 = ExceptionFrame->FltF6;
  138. ContextFrame->FltF7 = ExceptionFrame->FltF7;
  139. ContextFrame->FltF8 = ExceptionFrame->FltF8;
  140. ContextFrame->FltF9 = ExceptionFrame->FltF9;
  141. //
  142. // Set floating point control register from trap frame.
  143. // Clear software floating point control register in context frame
  144. // (if necessary, it can be set to the proper value by the caller).
  145. //
  146. ContextFrame->Fpcr = TrapFrame->Fpcr;
  147. ContextFrame->SoftFpcr = 0;
  148. }
  149. return;
  150. }
  151. VOID
  152. KeContextToKframes (
  153. IN OUT PKTRAP_FRAME TrapFrame,
  154. IN OUT PKEXCEPTION_FRAME ExceptionFrame,
  155. IN PCONTEXT ContextFrame,
  156. IN ULONG ContextFlags,
  157. IN KPROCESSOR_MODE PreviousMode
  158. )
  159. /*++
  160. Routine Description:
  161. This routine moves the selected contents of the specified context frame into
  162. the specified trap and exception frames according to the specified context
  163. flags.
  164. Arguments:
  165. TrapFrame - Supplies a pointer to a trap frame that receives the volatile
  166. context from the context record.
  167. ExceptionFrame - Supplies a pointer to an exception frame that receives
  168. the nonvolatile context from the context record.
  169. ContextFrame - Supplies a pointer to a context frame that contains the
  170. context that is to be copied into the trap and exception frames.
  171. ContextFlags - Supplies the set of flags that specify which parts of the
  172. context frame are to be copied into the trap and exception frames.
  173. PreviousMode - Supplies the processor mode for which the trap and exception
  174. frames are being built.
  175. Return Value:
  176. None.
  177. --*/
  178. {
  179. //
  180. // Set control information if specified.
  181. //
  182. if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
  183. //
  184. // Set integer register gp, sp, ra, FIR, and PSR in trap frame.
  185. //
  186. TrapFrame->IntGp = ContextFrame->IntGp;
  187. TrapFrame->IntSp = ContextFrame->IntSp;
  188. TrapFrame->IntRa = ContextFrame->IntRa;
  189. TrapFrame->Fir = ContextFrame->Fir;
  190. TrapFrame->Psr = SANITIZE_PSR(ContextFrame->Psr, PreviousMode);
  191. }
  192. //
  193. // Set integer register contents if specified.
  194. //
  195. if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
  196. //
  197. // Set volatile integer registers v0 and t0 - t7 in trap frame.
  198. //
  199. TrapFrame->IntV0 = ContextFrame->IntV0;
  200. TrapFrame->IntT0 = ContextFrame->IntT0;
  201. TrapFrame->IntT1 = ContextFrame->IntT1;
  202. TrapFrame->IntT2 = ContextFrame->IntT2;
  203. TrapFrame->IntT3 = ContextFrame->IntT3;
  204. TrapFrame->IntT4 = ContextFrame->IntT4;
  205. TrapFrame->IntT5 = ContextFrame->IntT5;
  206. TrapFrame->IntT6 = ContextFrame->IntT6;
  207. TrapFrame->IntT7 = ContextFrame->IntT7;
  208. //
  209. // Set nonvolatile integer registers s0 - s5 in exception frame.
  210. //
  211. ExceptionFrame->IntS0 = ContextFrame->IntS0;
  212. ExceptionFrame->IntS1 = ContextFrame->IntS1;
  213. ExceptionFrame->IntS2 = ContextFrame->IntS2;
  214. ExceptionFrame->IntS3 = ContextFrame->IntS3;
  215. ExceptionFrame->IntS4 = ContextFrame->IntS4;
  216. ExceptionFrame->IntS5 = ContextFrame->IntS5;
  217. //
  218. // Set volatile integer registers a0 - a5, and t8 - t11 in trap frame.
  219. //
  220. TrapFrame->IntA0 = ContextFrame->IntA0;
  221. TrapFrame->IntA1 = ContextFrame->IntA1;
  222. TrapFrame->IntA2 = ContextFrame->IntA2;
  223. TrapFrame->IntA3 = ContextFrame->IntA3;
  224. TrapFrame->IntA4 = ContextFrame->IntA4;
  225. TrapFrame->IntA5 = ContextFrame->IntA5;
  226. TrapFrame->IntT8 = ContextFrame->IntT8;
  227. TrapFrame->IntT9 = ContextFrame->IntT9;
  228. TrapFrame->IntT10 = ContextFrame->IntT10;
  229. TrapFrame->IntT11 = ContextFrame->IntT11;
  230. //
  231. // Set volatile integer registers fp, t12 and at in trap frame.
  232. //
  233. TrapFrame->IntFp = ContextFrame->IntFp;
  234. TrapFrame->IntT12 = ContextFrame->IntT12;
  235. TrapFrame->IntAt = ContextFrame->IntAt;
  236. }
  237. //
  238. // Set floating register contents if specified.
  239. //
  240. if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
  241. //
  242. // Set volatile floating registers f0 - f1 in trap frame.
  243. // Set volatile floating registers f10 - f30 in trap frame.
  244. //
  245. TrapFrame->FltF0 = ContextFrame->FltF0;
  246. TrapFrame->FltF1 = ContextFrame->FltF1;
  247. RtlMoveMemory(&TrapFrame->FltF10, &ContextFrame->FltF10,
  248. sizeof(ULONGLONG) * 21);
  249. //
  250. // Set nonvolatile floating registers f2 - f9 in exception frame.
  251. //
  252. ExceptionFrame->FltF2 = ContextFrame->FltF2;
  253. ExceptionFrame->FltF3 = ContextFrame->FltF3;
  254. ExceptionFrame->FltF4 = ContextFrame->FltF4;
  255. ExceptionFrame->FltF5 = ContextFrame->FltF5;
  256. ExceptionFrame->FltF6 = ContextFrame->FltF6;
  257. ExceptionFrame->FltF7 = ContextFrame->FltF7;
  258. ExceptionFrame->FltF8 = ContextFrame->FltF8;
  259. ExceptionFrame->FltF9 = ContextFrame->FltF9;
  260. //
  261. // Set floating point control register in trap frame.
  262. //
  263. TrapFrame->Fpcr = ContextFrame->Fpcr;
  264. }
  265. return;
  266. }
  267. VOID
  268. KiDispatchException (
  269. IN PEXCEPTION_RECORD ExceptionRecord,
  270. IN PKEXCEPTION_FRAME ExceptionFrame,
  271. IN PKTRAP_FRAME TrapFrame,
  272. IN KPROCESSOR_MODE PreviousMode,
  273. IN BOOLEAN FirstChance
  274. )
  275. /*++
  276. Routine Description:
  277. This function is called to dispatch an exception to the proper mode and
  278. to cause the exception dispatcher to be called.
  279. If the exception is a data misalignment, the previous mode is user, this
  280. is the first chance for handling the exception, and the current thread
  281. has enabled automatic alignment fixup, then an attempt is made to emulate
  282. the unaligned reference. Data misalignment exceptions are never emulated
  283. for kernel mode.
  284. If the exception is a floating not implemented exception, then an attempt
  285. is made to emulate the floating operation. If the exception is an
  286. arithmetic exception, then an attempt is made to convert the imprecise
  287. exception into a precise exception, and then emulate the floating
  288. operation in order to obtain the proper IEEE results and exceptions.
  289. Floating exceptions are never emulated for kernel mode.
  290. If the exception is neither a data misalignment nor a floating point
  291. exception and the previous mode is kernel, then the exception
  292. dispatcher is called directly to process the exception. Otherwise the
  293. exception record, exception frame, and trap frame contents are copied
  294. to the user mode stack. The contents of the exception frame and trap
  295. are then modified such that when control is returned, execution will
  296. commence in user mode in a routine which will call the exception
  297. dispatcher.
  298. Arguments:
  299. ExceptionRecord - Supplies a pointer to an exception record.
  300. ExceptionFrame - Supplies a pointer to an exception frame.
  301. TrapFrame - Supplies a pointer to a trap frame.
  302. PreviousMode - Supplies the previous processor mode.
  303. FirstChance - Supplies a boolean variable that specifies whether this
  304. is the first (TRUE) or second (FALSE) time that this exception has
  305. been processed.
  306. Return Value:
  307. None.
  308. --*/
  309. {
  310. CONTEXT ContextFrame;
  311. EXCEPTION_RECORD ExceptionRecord1;
  312. PEXC_SUM ExceptionSummary;
  313. LONG Length;
  314. ULONG SoftFpcr;
  315. ULONGLONG UserStack1;
  316. ULONGLONG UserStack2;
  317. BOOLEAN AlignmentFaultHandled;
  318. BOOLEAN ExceptionForwarded;
  319. //
  320. // If the exception is an illegal instruction exception, then check for
  321. // a byte/word instruction that should be emulated.
  322. //
  323. // N.B. The exception code STATUS_ILLEGAL_INSTRUCTION may be converted
  324. // into STATUS_DATATYPE_MISALIGNMENT in the case of unaligned word
  325. // access.
  326. //
  327. if (ExceptionRecord->ExceptionCode == STATUS_ILLEGAL_INSTRUCTION) {
  328. if (KiEmulateByteWord(ExceptionRecord,
  329. ExceptionFrame,
  330. TrapFrame) != FALSE) {
  331. KeGetCurrentPrcb()->KeByteWordEmulationCount += 1;
  332. goto Handled2;
  333. }
  334. }
  335. ExceptionForwarded = FALSE;
  336. if (ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) {
  337. AlignmentFaultHandled = KiHandleAlignmentFault( ExceptionRecord,
  338. ExceptionFrame,
  339. TrapFrame,
  340. PreviousMode,
  341. FirstChance,
  342. &ExceptionForwarded );
  343. if (AlignmentFaultHandled != FALSE) {
  344. goto Handled2;
  345. }
  346. }
  347. //
  348. // If the exception is a data bus error then a machine check has
  349. // been trapped by the PALcode. The error will be forwarded to the
  350. // HAL eventually for logging or handling. If the handler returns
  351. // it is assumed that the HAL successfully handled the error and
  352. // execution may resume.
  353. //
  354. // N.B. A special exception code is used to signal a data bus error.
  355. // This code is equivalent to the bug check code merged with a
  356. // reserved facility code and the reserved bit set.
  357. //
  358. if (ExceptionRecord->ExceptionCode == (DATA_BUS_ERROR | 0xdfff0000)) {
  359. KiMachineCheck(ExceptionRecord, ExceptionFrame, TrapFrame);
  360. goto Handled2;
  361. }
  362. //
  363. // Initialize the copy of the software FPCR. The proper value is set
  364. // if a floating emulation operation is performed. Case on arithmetic
  365. // exception codes that require special handling by the kernel.
  366. //
  367. SoftFpcr = 0;
  368. switch (ExceptionRecord->ExceptionCode) {
  369. //
  370. // If the exception is a gentrap, then attempt to translate the
  371. // Alpha specific gentrap value to a status code value. This
  372. // exception is a precise trap.
  373. //
  374. // N.B. STATUS_ALPHA_GENTRAP is a pseudo status code generated by
  375. // PALcode when a callpal gentrap is executed. The status is
  376. // visible in user mode only when the gentrap code value is
  377. // unrecognized.
  378. //
  379. case STATUS_ALPHA_GENTRAP :
  380. switch (ExceptionRecord->ExceptionInformation[0]) {
  381. case GENTRAP_INTEGER_OVERFLOW :
  382. ExceptionRecord->ExceptionCode = STATUS_INTEGER_OVERFLOW;
  383. break;
  384. case GENTRAP_INTEGER_DIVIDE_BY_ZERO :
  385. ExceptionRecord->ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
  386. break;
  387. case GENTRAP_FLOATING_OVERFLOW :
  388. ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW;
  389. break;
  390. case GENTRAP_FLOATING_DIVIDE_BY_ZERO :
  391. ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
  392. break;
  393. case GENTRAP_FLOATING_UNDERFLOW :
  394. ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW;
  395. break;
  396. case GENTRAP_FLOATING_INVALID_OPERAND :
  397. ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
  398. break;
  399. case GENTRAP_FLOATING_INEXACT_RESULT :
  400. ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
  401. break;
  402. }
  403. break;
  404. //
  405. // If the exception is an unimplemented floating operation, then
  406. // PALcode has detected a subsetted floating point operation. These
  407. // include attempts to use round to plus or minus infinity rounding
  408. // modes on EV4. This exception is a fault.
  409. //
  410. // If the previous mode was user, an attempt is made to emulate the
  411. // operation. If the emulation is successful, the continuation
  412. // address is incremented to the next instruction.
  413. //
  414. // N.B. STATUS_ALPHA_FLOATING_NOT_IMPLEMENTED is a pseudo status code
  415. // generated by PALcode. The status is never visible outside of
  416. // this handler because the floating emulation routine converts
  417. // the status code to the proper floating status value.
  418. //
  419. case STATUS_ALPHA_FLOATING_NOT_IMPLEMENTED :
  420. if (PreviousMode != KernelMode) {
  421. if (KiFloatingException(ExceptionRecord,
  422. ExceptionFrame,
  423. TrapFrame,
  424. FALSE,
  425. &SoftFpcr) != FALSE) {
  426. TrapFrame->Fir += 4;
  427. goto Handled2;
  428. }
  429. } else {
  430. ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
  431. }
  432. break;
  433. //
  434. // If the exception is an arithmetic exception, then one or more
  435. // integer overflow or floating point traps has occurred. This
  436. // exception is an imprecise (asynchronous) trap. Attempt to locate
  437. // the original trapping instruction and emulate the instruction.
  438. //
  439. // N.B. STATUS_ALPHA_ARITHMETIC_EXCEPTION is a pseudo status code
  440. // generated by PALcode. The status is never visible outside of
  441. // this handler because the floating emulation routine converts
  442. // the status code to the proper floating status value.
  443. //
  444. case STATUS_ALPHA_ARITHMETIC_EXCEPTION :
  445. if (KiFloatingException(ExceptionRecord,
  446. ExceptionFrame,
  447. TrapFrame,
  448. TRUE,
  449. &SoftFpcr) != FALSE) {
  450. goto Handled2;
  451. }
  452. break;
  453. }
  454. //
  455. // Move machine state from trap and exception frames to a context frame,
  456. // and increment the number of exceptions dispatched.
  457. //
  458. // Explicitly set the value of the software FPCR in the context frame
  459. // (because it is not a hardware register and thus not present in the
  460. // trap or exception frames).
  461. //
  462. ContextFrame.ContextFlags = CONTEXT_FULL;
  463. KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame);
  464. KeGetCurrentPrcb()->KeExceptionDispatchCount += 1;
  465. ContextFrame.SoftFpcr = (ULONGLONG)SoftFpcr;
  466. //
  467. // Select the method of handling the exception based on the previous mode.
  468. //
  469. if (PreviousMode == KernelMode) {
  470. //
  471. // If the kernel debugger is active, the exception is a breakpoint,
  472. // the breakpoint is handled by the kernel debugger, and this is the
  473. // first chance, then give the kernel debugger a chance to handle
  474. // the exception.
  475. //
  476. if ((FirstChance != FALSE) && (KiDebugRoutine != NULL) &&
  477. (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  478. (KdIsThisAKdTrap(ExceptionRecord,
  479. &ContextFrame,
  480. KernelMode) != FALSE) &&
  481. (((KiDebugRoutine) (TrapFrame,
  482. ExceptionFrame,
  483. ExceptionRecord,
  484. &ContextFrame,
  485. KernelMode,
  486. FALSE)) != FALSE)) {
  487. goto Handled1;
  488. }
  489. //
  490. // Previous mode was kernel.
  491. //
  492. // If this is the first chance, then attempt to dispatch the exception
  493. // to a frame based handler. If the exception is handled, then continue
  494. // execution.
  495. //
  496. // If this is the second chance or the exception is not handled,
  497. // then if the kernel debugger is active, then give the kernel
  498. // debugger a second chance to handle the exception. If the kernel
  499. // debugger handles the exception, then continue execution. Otherwise
  500. // bug check.
  501. //
  502. if (FirstChance != FALSE) {
  503. //
  504. // This is the first chance to handle the exception.
  505. //
  506. if (RtlDispatchException(ExceptionRecord, &ContextFrame) != FALSE) {
  507. goto Handled1;
  508. }
  509. }
  510. //
  511. // This is the second chance to handle the exception.
  512. //
  513. if ((KiDebugRoutine != NULL) &&
  514. (((KiDebugRoutine) (TrapFrame,
  515. ExceptionFrame,
  516. ExceptionRecord,
  517. &ContextFrame,
  518. PreviousMode,
  519. TRUE)) != FALSE)) {
  520. goto Handled1;
  521. }
  522. KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
  523. ExceptionRecord->ExceptionCode,
  524. (ULONG_PTR)ExceptionRecord->ExceptionAddress,
  525. ExceptionRecord->ExceptionInformation[0],
  526. ExceptionRecord->ExceptionInformation[1]);
  527. } else {
  528. //
  529. // If the kernel debugger is active, the exception is a breakpoint,
  530. // the breakpoint is handled by the kernel debugger, and this is the
  531. // first chance, then give the kernel debugger a chance to handle
  532. // the exception.
  533. //
  534. if ((FirstChance != FALSE) &&
  535. (KiDebugRoutine != NULL) &&
  536. (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  537. (KdIsThisAKdTrap(ExceptionRecord,
  538. &ContextFrame,
  539. UserMode) != FALSE) &&
  540. ((PsGetCurrentProcess()->DebugPort == NULL) ||
  541. ((PsGetCurrentProcess()->DebugPort != NULL) &&
  542. (ExceptionRecord->ExceptionInformation[0] !=
  543. DEBUG_STOP_BREAKPOINT)))) {
  544. if (((KiDebugRoutine) (TrapFrame,
  545. ExceptionFrame,
  546. ExceptionRecord,
  547. &ContextFrame,
  548. UserMode,
  549. FALSE)) != FALSE) {
  550. goto Handled1;
  551. }
  552. }
  553. //
  554. // Previous mode was user.
  555. //
  556. // If this is the first chance and the current process has a debugger
  557. // port, then send a message to the debugger port and wait for a reply.
  558. // If the debugger handles the exception, then continue execution. Otherwise
  559. // transfer the exception information to the user stack, transition to
  560. // user mode, and attempt to dispatch the exception to a frame based
  561. // handler. If a frame based handler handles the exception, then continue
  562. // execution. Otherwise, execute the raise exception system service
  563. // which will call this routine a second time to process the exception.
  564. //
  565. // If this is the second chance and the current process has a debugger
  566. // port, then send a message to the debugger port and wait for a reply.
  567. // If the debugger handles the exception, then continue execution. Otherwise
  568. // if the current process has a subsystem port, then send a message to
  569. // the subsystem port and wait for a reply. If the subsystem handles the
  570. // exception, then continue execution. Otherwise terminate the thread.
  571. //
  572. if (FirstChance != FALSE) {
  573. //
  574. // This is the first chance to handle the exception.
  575. //
  576. if (ExceptionForwarded == FALSE &&
  577. DbgkForwardException(ExceptionRecord, TRUE, FALSE)) {
  578. goto Handled2;
  579. }
  580. //
  581. // Transfer exception information to the user stack, transition
  582. // to user mode, and attempt to dispatch the exception to a frame
  583. // based handler.
  584. //
  585. repeat:
  586. try {
  587. //
  588. // Compute length of exception record and new aligned stack
  589. // address.
  590. //
  591. Length = (sizeof(EXCEPTION_RECORD) + 15) & (~15);
  592. UserStack1 = (ContextFrame.IntSp & ~((ULONG_PTR)15)) - Length;
  593. //
  594. // Probe user stack area for writability and then transfer the
  595. // exception record to the user stack area.
  596. //
  597. ProbeForWrite((PCHAR)UserStack1, Length, sizeof(QUAD));
  598. RtlMoveMemory((PVOID)UserStack1, ExceptionRecord, Length);
  599. //
  600. // Compute length of context record and new aligned user stack
  601. // pointer.
  602. //
  603. Length = (sizeof(CONTEXT) + 15) & (~15);
  604. UserStack2 = UserStack1 - Length;
  605. //
  606. // Probe user stack area for writability and then transfer the
  607. // context record to the user stack.
  608. //
  609. ProbeForWrite((PCHAR)UserStack2, Length, sizeof(QUAD));
  610. RtlMoveMemory((PVOID)UserStack2, &ContextFrame, sizeof(CONTEXT));
  611. //
  612. // Set address of exception record, context record, and the
  613. // and the new stack pointer in the current trap frame.
  614. //
  615. TrapFrame->IntSp = UserStack2;
  616. TrapFrame->IntFp = UserStack2;
  617. ExceptionFrame->IntS0 = UserStack1;
  618. ExceptionFrame->IntS1 = UserStack2;
  619. //
  620. // Set the address of the exception routine that will call the
  621. // exception dispatcher and then return to the trap handler.
  622. // The trap handler will restore the exception and trap frame
  623. // context and continue execution in the routine that will
  624. // call the exception dispatcher.
  625. //
  626. TrapFrame->Fir = (ULONGLONG)(LONG_PTR)KeUserExceptionDispatcher;
  627. return;
  628. //
  629. // If an exception occurs, then copy the new exception information
  630. // to an exception record and handle the exception.
  631. //
  632. } except (KiCopyInformation(&ExceptionRecord1,
  633. (GetExceptionInformation())->ExceptionRecord)) {
  634. //
  635. // If the exception is a stack overflow, then attempt
  636. // to raise the stack overflow exception. Otherwise,
  637. // the user's stack is not accessible, or is misaligned,
  638. // and second chance processing is performed.
  639. //
  640. if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) {
  641. ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress;
  642. RtlMoveMemory((PVOID)ExceptionRecord,
  643. &ExceptionRecord1, sizeof(EXCEPTION_RECORD));
  644. goto repeat;
  645. }
  646. }
  647. }
  648. //
  649. // This is the second chance to handle the exception.
  650. //
  651. if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) {
  652. goto Handled2;
  653. } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) {
  654. goto Handled2;
  655. } else {
  656. ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
  657. KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
  658. ExceptionRecord->ExceptionCode,
  659. (ULONG_PTR)ExceptionRecord->ExceptionAddress,
  660. ExceptionRecord->ExceptionInformation[0],
  661. ExceptionRecord->ExceptionInformation[1]);
  662. }
  663. }
  664. //
  665. // Move machine state from context frame to trap and exception frames and
  666. // then return to continue execution with the restored state.
  667. //
  668. Handled1:
  669. KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame,
  670. ContextFrame.ContextFlags, PreviousMode);
  671. //
  672. // Exception was handled by the debugger or the associated subsystem
  673. // and state was modified, if necessary, using the get state and set
  674. // state capabilities. Therefore the context frame does not need to
  675. // be transferred to the trap and exception frames.
  676. //
  677. Handled2:
  678. return;
  679. }
  680. ULONG
  681. KiCopyInformation (
  682. IN OUT PEXCEPTION_RECORD ExceptionRecord1,
  683. IN PEXCEPTION_RECORD ExceptionRecord2
  684. )
  685. /*++
  686. Routine Description:
  687. This function is called from an exception filter to copy the exception
  688. information from one exception record to another when an exception occurs.
  689. Arguments:
  690. ExceptionRecord1 - Supplies a pointer to the destination exception record.
  691. ExceptionRecord2 - Supplies a pointer to the source exception record.
  692. Return Value:
  693. A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value.
  694. --*/
  695. {
  696. //
  697. // Copy one exception record to another and return value that causes
  698. // an exception handler to be executed.
  699. //
  700. RtlMoveMemory((PVOID)ExceptionRecord1,
  701. (PVOID)ExceptionRecord2,
  702. sizeof(EXCEPTION_RECORD));
  703. return EXCEPTION_EXECUTE_HANDLER;
  704. }
  705. NTSTATUS
  706. KeRaiseUserException(
  707. IN NTSTATUS ExceptionCode
  708. )
  709. /*++
  710. Routine Description:
  711. This function causes an exception to be raised in the calling thread's user-mode
  712. context. It does this by editing the trap frame the kernel was entered with to
  713. point to trampoline code that raises the requested exception.
  714. Arguments:
  715. ExceptionCode - Supplies the status value to be used as the exception
  716. code for the exception that is to be raised.
  717. Return Value:
  718. The status value that should be returned by the caller.
  719. --*/
  720. {
  721. PKTRAP_FRAME TrapFrame;
  722. ASSERT(KeGetPreviousMode() == UserMode);
  723. TrapFrame = KeGetCurrentThread()->TrapFrame;
  724. TrapFrame->Fir = (ULONGLONG)(LONG_PTR)KeRaiseUserExceptionDispatcher;
  725. return(ExceptionCode);
  726. }
  727. #if 0
  728. LOGICAL
  729. BdReportExceptionStateChange (
  730. IN PEXCEPTION_RECORD ExceptionRecord,
  731. IN OUT PCONTEXT ContextRecord
  732. );
  733. LOGICAL
  734. BdReportLoadSymbolsStateChange (
  735. IN PSTRING PathName,
  736. IN PKD_SYMBOLS_INFO SymbolInfo,
  737. IN LOGICAL UnloadSymbols,
  738. IN OUT PCONTEXT ContextRecord
  739. );
  740. LOGICAL
  741. BdPrintString (
  742. IN PSTRING Output
  743. );
  744. LOGICAL
  745. BdPromptString (
  746. IN PSTRING Output,
  747. IN OUT PSTRING Input
  748. );
  749. LOGICAL
  750. BdTrap (
  751. IN PEXCEPTION_RECORD ExceptionRecord,
  752. IN PKEXCEPTION_FRAME ExceptionFrame,
  753. IN PKTRAP_FRAME TrapFrame,
  754. IN KPROCESSOR_MODE PreviousMode,
  755. IN BOOLEAN FirstChance
  756. )
  757. /*++
  758. Routine Description:
  759. This routine is called whenever a exception is dispatched and the kernel
  760. debugger is active.
  761. Arguments:
  762. FirmwareFrame - Supplies a pointer to a firmware frame that describes the
  763. trap.
  764. Return Value:
  765. A value of TRUE is returned if the exception is handled. Otherwise a
  766. value of FALSE is returned.
  767. --*/
  768. {
  769. CONTEXT ContextFrame;
  770. LOGICAL Completion;
  771. PCONTEXT ContextRecord;
  772. STRING Input;
  773. ULONGLONG OldFir;
  774. STRING Output;
  775. PKD_SYMBOLS_INFO SymbolInfo;
  776. LOGICAL UnloadSymbols;
  777. //
  778. // Set address of context record and set context flags.
  779. //
  780. ContextRecord = &ContextFrame;
  781. ContextRecord->ContextFlags = CONTEXT_FULL;
  782. //
  783. // Print, prompt, load symbols, and unload symbols are all special cases
  784. // of breakpoint.
  785. //
  786. // BlPrint("bd: debug code entered with type %lx, p1 %lx\r\n",
  787. // (ULONG)FirmwareFrame->Type,
  788. // (ULONG)FirmwareFrame->Param1);
  789. if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  790. (ExceptionRecord->ExceptionInformation[0] >= DEBUG_PRINT_BREAKPOINT)) {
  791. //
  792. // Switch on the breakpoint code.
  793. //
  794. UnloadSymbols = FALSE;
  795. switch (ExceptionRecord->ExceptionInformation[0]) {
  796. //
  797. // Print:
  798. //
  799. // Arguments:
  800. //
  801. // a0 - Supplies a pointer to an output string buffer.
  802. // a1 - Supplies the length of the output string buffer.
  803. //
  804. case DEBUG_PRINT_BREAKPOINT:
  805. // BlPrint("bd/debug: print\r\n");
  806. Output.Buffer = (PCHAR)TrapFrame->IntA0;
  807. Output.Length = (USHORT)TrapFrame->IntA1;
  808. if (BdPrintString(&Output)) {
  809. TrapFrame->IntV0 = STATUS_BREAKPOINT;
  810. } else {
  811. TrapFrame->IntV0 = STATUS_SUCCESS;
  812. }
  813. TrapFrame->Fir += 4;
  814. // BlPrint("bd/debug: exit - print\r\n");
  815. KeSweepCurrentIcache();
  816. return TRUE;
  817. //
  818. // Stop in debugger:
  819. //
  820. // As this is not a normal breakpoint we must increment the
  821. // context past the breakpoint instruction.
  822. //
  823. case BREAKIN_BREAKPOINT:
  824. TrapFrame->Fir += 4;
  825. break;
  826. //
  827. // Prompt:
  828. //
  829. // a0 - Supplies a pointer to an output string buffer.
  830. // a1 - Supplies the length of the output string buffer..
  831. // a2 - supplies a pointer to an input string buffer.
  832. // a3 - Supplies the length of the input string bufffer.
  833. //
  834. case DEBUG_PROMPT_BREAKPOINT:
  835. // BlPrint("bd/debug: prompt\r\n");
  836. Output.Buffer = (PCHAR)TrapFrame->IntA0;
  837. Output.Length = (USHORT)TrapFrame->IntA1;
  838. Input.Buffer = (PCHAR)TrapFrame->IntA2;
  839. Input.MaximumLength = (USHORT)TrapFrame->IntA3;
  840. //
  841. // Prompt and keep prompting until no breakin seen.
  842. //
  843. do {
  844. } while(BdPromptString(&Output, &Input) != FALSE);
  845. TrapFrame->IntV0 = Input.Length;
  846. TrapFrame->Fir += 4;
  847. // BlPrint("bd/debug: exit - prompt\r\n");
  848. KeSweepCurrentIcache();
  849. return TRUE;
  850. //
  851. // Unload Symbols:
  852. //
  853. // Arguments:
  854. //
  855. // a0 - Supplies a pointer to the image path string descriptor.
  856. // a1 - Supplies a pointer to he symbol information.
  857. //
  858. case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
  859. // BlPrint("bd/debug: unload\r\n");
  860. UnloadSymbols = TRUE;
  861. //
  862. // Fall through to load symbol case.
  863. //
  864. case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
  865. // BlPrint("bd/debug: load\r\n");
  866. KeContextFromKframes(TrapFrame, ExceptionFrame, ContextRecord);
  867. OldFir = ContextRecord->Fir;
  868. SymbolInfo = (PKD_SYMBOLS_INFO)ContextRecord->IntA1;
  869. BdReportLoadSymbolsStateChange((PSTRING)ContextRecord->IntA0,
  870. SymbolInfo,
  871. UnloadSymbols,
  872. ContextRecord);
  873. //
  874. // If the kernel debugger did not update the FIR, then increment
  875. // past the breakpoint instruction.
  876. //
  877. if (ContextRecord->Fir == OldFir) {
  878. ContextRecord->Fir += 4;
  879. }
  880. KeContextToKframes(TrapFrame,
  881. ExceptionFrame,
  882. ContextRecord,
  883. ContextRecord->ContextFlags,
  884. PreviousMode);
  885. // BlPrint("bd/debug: exit - load/unload\r\n");
  886. KeSweepCurrentIcache();
  887. return TRUE;
  888. //
  889. // Unknown internal command.
  890. //
  891. default:
  892. break;
  893. }
  894. }
  895. //
  896. // Report state change to kernel debugger on host machine.
  897. //
  898. // BlPrint("bd/debug: report\r\n");
  899. KeContextFromKframes(TrapFrame, ExceptionFrame, ContextRecord);
  900. Completion = BdReportExceptionStateChange(ExceptionRecord,
  901. ContextRecord);
  902. KeContextToKframes(TrapFrame,
  903. ExceptionFrame,
  904. ContextRecord,
  905. ContextRecord->ContextFlags,
  906. PreviousMode);
  907. // BlPrint("bd/debug: exit - report\r\n");
  908. KeSweepCurrentIcache();
  909. return TRUE;
  910. }
  911. LOGICAL
  912. BdStub (
  913. IN PEXCEPTION_RECORD ExceptionRecord,
  914. IN PKEXCEPTION_FRAME ExceptionFrame,
  915. IN PKTRAP_FRAME TrapFrame,
  916. IN KPROCESSOR_MODE PreviousMode,
  917. IN BOOLEAN FirstChance
  918. )
  919. /*++
  920. Routine Description:
  921. This routine provides a kernel debugger stub routine that catchs debug
  922. prints in checked systems when the kernel debugger is not active.
  923. Arguments:
  924. FirmwareFrame - Supplies a pointer to a firmware frame that describes
  925. the trap.
  926. Return Value:
  927. A value of TRUE is returned if the exception is handled. Otherwise a
  928. value of FALSE is returned.
  929. --*/
  930. {
  931. return FALSE;
  932. }
  933. #endif