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.

1334 lines
33 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. trapc.c
  5. Abstract:
  6. This module implements the specific exception handlers for EM
  7. exceptions. Called by the KiGenericExceptionHandler.
  8. Author:
  9. Bernard Lint 4-Apr-96
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. #include "ps.h"
  16. #include <inbv.h>
  17. extern BOOLEAN PsWatchEnabled;
  18. extern VOID ExpInterlockedPopEntrySListResume();
  19. BOOLEAN
  20. KiMemoryFault (
  21. IN PKTRAP_FRAME TrapFrame
  22. )
  23. /*++
  24. Routine Description:
  25. This function processes memory faults.
  26. Arguments:
  27. TrapFrame - Pointer to the trap frame.
  28. Return Value:
  29. TRUE on success, FALSE on failure.
  30. --*/
  31. {
  32. PEXCEPTION_RECORD ExceptionRecord;
  33. BOOLEAN StoreInstruction;
  34. PVOID VirtualAddress;
  35. NTSTATUS Status;
  36. VirtualAddress = (PVOID)TrapFrame->StIFA;
  37. if (TrapFrame->StISR & (1i64 << ISR_X)) {
  38. #if _MERCED_A0_
  39. if ((TrapFrame->StIPSR & (1i64 << PSR_IS)) == 0) {
  40. VirtualAddress = (PVOID)TrapFrame->StIIP;
  41. }
  42. #endif
  43. //
  44. // Indicate execution fault.
  45. //
  46. StoreInstruction = 2;
  47. }
  48. else if (TrapFrame->StISR & (1i64 << ISR_W)) {
  49. //
  50. // Indicate store.
  51. //
  52. StoreInstruction = 1;
  53. } else {
  54. //
  55. // Indicate read.
  56. //
  57. StoreInstruction = 0;
  58. }
  59. if (((ULONG_PTR)VirtualAddress < MM_MAX_WOW64_ADDRESS) &&
  60. (PsGetCurrentProcess()->Wow64Process != NULL)) {
  61. Status = MmX86Fault(StoreInstruction, VirtualAddress,
  62. (KPROCESSOR_MODE)TrapFrame->PreviousMode, TrapFrame);
  63. } else {
  64. Status = MmAccessFault(StoreInstruction, VirtualAddress,
  65. (KPROCESSOR_MODE)TrapFrame->PreviousMode, TrapFrame);
  66. }
  67. //
  68. // Check if working set watch is enabled.
  69. //
  70. if (NT_SUCCESS(Status)) {
  71. if (PsWatchEnabled) {
  72. PsWatchWorkingSet(Status,
  73. (PVOID)TrapFrame->StIIP,
  74. (PVOID)VirtualAddress);
  75. }
  76. //
  77. // Check if debugger has any breakpoints that should be inserted
  78. //
  79. KdSetOwedBreakpoints();
  80. return FALSE;
  81. }
  82. if (KeInvalidAccessAllowed(TrapFrame)) {
  83. TrapFrame->StIIP = ((PPLABEL_DESCRIPTOR)ExpInterlockedPopEntrySListResume)->EntryPoint;
  84. return FALSE;
  85. }
  86. if (TrapFrame->StISR & (1i64 << ISR_SP)) {
  87. //
  88. // Set IPSR.ed bit if it was a fault on a speculative load.
  89. //
  90. TrapFrame->StIPSR |= (1i64 << PSR_ED);
  91. return FALSE;
  92. }
  93. //
  94. // Failure returned from MmAccessFault.
  95. // Initialize Exception record.
  96. //
  97. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  98. ExceptionRecord->ExceptionCode = Status;
  99. ExceptionRecord->ExceptionAddress =
  100. (PVOID)RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  101. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  102. ExceptionRecord->ExceptionFlags = 0;
  103. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  104. ExceptionRecord->NumberParameters = 5;
  105. if (StoreInstruction == 2) {
  106. PSR Psr;
  107. Psr.ull = TrapFrame->StIPSR;
  108. //
  109. // instruction access fault
  110. //
  111. ExceptionRecord->ExceptionInformation[0] = TrapFrame->StIIPA;
  112. } else {
  113. //
  114. // data access fault
  115. //
  116. ExceptionRecord->ExceptionInformation[0] = (ULONG_PTR)StoreInstruction;
  117. }
  118. ExceptionRecord->ExceptionInformation[1] = (ULONG_PTR)VirtualAddress;
  119. ExceptionRecord->ExceptionInformation[2] = (ULONG_PTR)Status;
  120. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  121. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  122. //
  123. // Status = STATUS_IN_PAGE_ERROR | 0x10000000
  124. // is a special status that indicates a page fault at Irql > APC
  125. //
  126. // The following statuses can be forwarded:
  127. // STATUS_ACCESS_VIOLATION
  128. // STATUS_GUARD_PAGE_VIOLATION
  129. // STATUS_STACK_OVERFLOW
  130. //
  131. // All other status will be set to:
  132. // STATUS_IN_PAGE_ERROR
  133. //
  134. switch (Status) {
  135. case STATUS_ACCESS_VIOLATION:
  136. case STATUS_GUARD_PAGE_VIOLATION:
  137. case STATUS_STACK_OVERFLOW:
  138. case STATUS_IN_PAGE_ERROR:
  139. break;
  140. default:
  141. ExceptionRecord->ExceptionCode = STATUS_IN_PAGE_ERROR;
  142. break;
  143. case STATUS_IN_PAGE_ERROR | 0x10000000:
  144. //
  145. // Handle the special case status returned from MmAccessFault,
  146. // we have taken a page fault at Irql > APC_LEVEL.
  147. //
  148. KeBugCheckEx(IRQL_NOT_LESS_OR_EQUAL,
  149. (ULONG_PTR)VirtualAddress,
  150. (ULONG_PTR)KeGetCurrentIrql(),
  151. (ULONG_PTR)StoreInstruction,
  152. (ULONG_PTR)TrapFrame->StIIP);
  153. //
  154. // should not get here
  155. //
  156. break;
  157. }
  158. return TRUE;
  159. }
  160. typedef struct _BREAK_INST {
  161. union {
  162. struct {
  163. ULONGLONG qp: 6;
  164. ULONGLONG imm20: 20;
  165. ULONGLONG x: 1;
  166. ULONGLONG x6: 6;
  167. ULONGLONG x3: 3;
  168. ULONGLONG i: 1;
  169. ULONGLONG Op: 4;
  170. ULONGLONG Rsv: 23;
  171. } i_field;
  172. ULONGLONG Ulong64;
  173. } u;
  174. } BREAK_INST;
  175. ULONG
  176. KiExtractImmediate (
  177. IN ULONGLONG Iip,
  178. IN ULONG SlotNumber
  179. )
  180. /*++
  181. Routine Description:
  182. Extract immediate operand from break instruction.
  183. Arguments:
  184. Iip - Bundle address of instruction
  185. SlotNumber - Slot of break instruction within bundle
  186. Return Value:
  187. Value of immediate operand.
  188. --*/
  189. {
  190. PULONGLONG BundleAddress;
  191. ULONGLONG BundleLow;
  192. ULONGLONG BundleHigh;
  193. BREAK_INST BreakInst;
  194. ULONG Imm21;
  195. BundleAddress = (PULONGLONG)Iip;
  196. BundleLow = *BundleAddress;
  197. BundleHigh = *(BundleAddress+1);
  198. //
  199. // Align instruction
  200. //
  201. switch (SlotNumber) {
  202. case 0:
  203. BreakInst.u.Ulong64 = BundleLow >> 5;
  204. break;
  205. case 1:
  206. BreakInst.u.Ulong64 = (BundleLow >> 46) | (BundleHigh << 18);
  207. break;
  208. case 2:
  209. BreakInst.u.Ulong64 = (BundleHigh >> 23);
  210. break;
  211. }
  212. //
  213. // Extract immediate value
  214. //
  215. Imm21 = (ULONG)(BreakInst.u.i_field.i<<20) | (ULONG)(BreakInst.u.i_field.imm20);
  216. return Imm21;
  217. }
  218. BOOLEAN
  219. KiDebugFault (
  220. IN PKTRAP_FRAME TrapFrame
  221. )
  222. {
  223. PEXCEPTION_RECORD ExceptionRecord;
  224. KEXCEPTION_FRAME Dummy;
  225. PKPRCB Prcb;
  226. TrapFrame->StIPSR |= (1i64 << PSR_DD);
  227. if (((TrapFrame->StIPSR >> PSR_CPL) & (PSR_CPL_LEN - 1)) == IA64_KERNEL_PL) {
  228. //
  229. // Disable all hardware breakpoints
  230. //
  231. KeSetLowPsrBit(PSR_DB, 0);
  232. }
  233. //
  234. // Initialize exception record
  235. //
  236. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  237. ExceptionRecord->ExceptionCode = STATUS_SINGLE_STEP;
  238. ExceptionRecord->ExceptionAddress =
  239. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  240. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  241. ExceptionRecord->ExceptionFlags = 0;
  242. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  243. ExceptionRecord->NumberParameters = 5;
  244. ExceptionRecord->ExceptionInformation[0] = 0;
  245. ExceptionRecord->ExceptionInformation[1] = TrapFrame->StIFA;
  246. ExceptionRecord->ExceptionInformation[2] = 0;
  247. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  248. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  249. return TRUE;
  250. }
  251. BOOLEAN
  252. KiOtherBreakException (
  253. IN PKTRAP_FRAME TrapFrame
  254. )
  255. /*++
  256. Routine Description:
  257. Handler for break exception other than the ones for fast and
  258. normal system calls. This includes debug break points.
  259. Arguments:
  260. TrapFrame - Pointer to the trap frame.
  261. Return Value:
  262. NT status code.
  263. --*/
  264. {
  265. PEXCEPTION_RECORD ExceptionRecord;
  266. ULONG BreakImmediate;
  267. ISR Isr;
  268. BreakImmediate = (ULONG)(TrapFrame->StIIM);
  269. //
  270. // Handle break.b case
  271. //
  272. try {
  273. if (BreakImmediate == 0) {
  274. Isr.ull = TrapFrame->StISR;
  275. BreakImmediate = KiExtractImmediate(TrapFrame->StIIP,
  276. (ULONG)Isr.sb.isr_ei);
  277. TrapFrame->StIIM = BreakImmediate;
  278. }
  279. } except (EXCEPTION_EXECUTE_HANDLER) {
  280. //
  281. // if an exception (memory fault) occurs, then let it re-execute break.b.
  282. //
  283. return FALSE;
  284. }
  285. //
  286. // Initialize exception record
  287. //
  288. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  289. ExceptionRecord->ExceptionAddress =
  290. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  291. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  292. ExceptionRecord->ExceptionFlags = 0;
  293. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  294. ExceptionRecord->NumberParameters = 5;
  295. ExceptionRecord->ExceptionInformation[0] = 0;
  296. ExceptionRecord->ExceptionInformation[1] = 0;
  297. ExceptionRecord->ExceptionInformation[2] = 0;
  298. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  299. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  300. switch (BreakImmediate) {
  301. case KERNEL_BREAKPOINT:
  302. case USER_BREAKPOINT:
  303. case BREAKPOINT_PRINT:
  304. case BREAKPOINT_PROMPT:
  305. case BREAKPOINT_STOP:
  306. case BREAKPOINT_LOAD_SYMBOLS:
  307. case BREAKPOINT_UNLOAD_SYMBOLS:
  308. case BREAKPOINT_BREAKIN:
  309. ExceptionRecord->ExceptionCode = STATUS_BREAKPOINT;
  310. ExceptionRecord->ExceptionInformation[0] = BreakImmediate;
  311. break;
  312. case INTEGER_DIVIDE_BY_ZERO_BREAK:
  313. ExceptionRecord->ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
  314. break;
  315. case INTEGER_OVERFLOW_BREAK:
  316. ExceptionRecord->ExceptionCode = STATUS_INTEGER_OVERFLOW;
  317. break;
  318. case MISALIGNED_DATA_BREAK:
  319. ExceptionRecord->ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
  320. break;
  321. case RANGE_CHECK_BREAK:
  322. case NULL_POINTER_DEFERENCE_BREAK:
  323. case DECIMAL_OVERFLOW_BREAK:
  324. case DECIMAL_DIVIDE_BY_ZERO_BREAK:
  325. case PACKED_DECIMAL_ERROR_BREAK:
  326. case INVALID_ASCII_DIGIT_BREAK:
  327. case INVALID_DECIMAL_DIGIT_BREAK:
  328. case PARAGRAPH_STACK_OVERFLOW_BREAK:
  329. default:
  330. #if DBG
  331. InbvDisplayString ("KiOtherBreakException: Unknown break code.\n");
  332. #endif // DBG
  333. ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
  334. break;
  335. }
  336. return TRUE;
  337. }
  338. BOOLEAN
  339. KiGeneralExceptions (
  340. IN PKTRAP_FRAME TrapFrame
  341. )
  342. /*++
  343. Routine Description:
  344. Handler for general exception faults: attempt to execute an illegal
  345. operation, privileged instruction, access a privileged register,
  346. unimplemented field, unimplemented register, or take an inter-ISA
  347. branch when disabled.
  348. Arguments:
  349. TrapFrame - Pointer to the trap frame.
  350. Return Value:
  351. None.
  352. Notes:
  353. ISR.ei bits indicate which instruction caused the exception.
  354. ISR.code{3:0} Non-access instruction (ISR.na = 1)
  355. = 0 tpa
  356. = 1 fc
  357. = 2 probe
  358. = 3 tak
  359. = 4 lfetch
  360. ISR.code{7:4} = 0: Illegal operation fault: All reported as STATUS_ILLEGAL_INSTRUCTION.
  361. ISR.rs = 0: An attempt to execute an illegal operation:
  362. -- unassigned major opcodes
  363. -- unassigned sub-opcodes
  364. -- reserved instruction fields
  365. -- writing a read-only register
  366. -- accessing a reserved register
  367. ISR.rs = 1:
  368. -- attempt to write outside the current register stack frame
  369. -- INVALRS operation with RCS.en = 1
  370. -- write to BSP with RCS.en = 1
  371. -- write to RNATRC with RCS.en = 1
  372. -- read from RNATRC with RCS.en = 1
  373. ISR.code{7:4} = 1: Privileged operation fault: Reported as STATUS_PRIVILEGED_INSTRUCTION.
  374. ISR.code{7:4} = 2: Privileged register fault: Reported as STATUS_PRIVILEGED_INSTRUCTION.
  375. ISR.code{7:4} = 3: Reserved register fault: Reported as STATUS_ILLEGAL_INSTRUCTION.
  376. ISR.code{7:4} = 4: Illegal ISA transition fault: Reported as STATUS_ILLEGAL_INSTRUCTION.
  377. --*/
  378. {
  379. BOOLEAN StoreInstruction = FALSE;
  380. ULONG IsrCode;
  381. PEXCEPTION_RECORD ExceptionRecord;
  382. //
  383. // Initialize the exception record
  384. //
  385. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  386. ExceptionRecord->ExceptionAddress =
  387. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  388. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  389. ExceptionRecord->ExceptionFlags = 0;
  390. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  391. ExceptionRecord->NumberParameters = 5;
  392. ExceptionRecord->ExceptionInformation[0] = 0;
  393. ExceptionRecord->ExceptionInformation[1] = 0;
  394. ExceptionRecord->ExceptionInformation[2] = 0;
  395. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  396. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  397. IsrCode = (LONG)((TrapFrame->StISR >> ISR_CODE) & ISR_CODE_MASK);
  398. //
  399. // Look at ISR code bits {7:4}
  400. //
  401. switch (IsrCode >> 4) {
  402. case ISR_PRIV_OP:
  403. case ISR_PRIV_REG:
  404. ExceptionRecord->ExceptionCode = STATUS_PRIVILEGED_INSTRUCTION;
  405. break;
  406. case ISR_RESVD_REG:
  407. //
  408. // Indicate store or not
  409. //
  410. if (TrapFrame->StISR & (1i64 << ISR_W)) {
  411. StoreInstruction = TRUE;
  412. } else if (TrapFrame->StISR & (1i64 << ISR_X)) {
  413. //
  414. // Indicate execution fault or not
  415. //
  416. StoreInstruction = 2;
  417. }
  418. ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
  419. ExceptionRecord->ExceptionInformation[0] = (ULONG_PTR)StoreInstruction;
  420. ExceptionRecord->ExceptionInformation[1] = 0x1ff8000000000000;
  421. ExceptionRecord->ExceptionInformation[2] = (ULONG_PTR)STATUS_ACCESS_VIOLATION;
  422. break;
  423. case ISR_ILLEGAL_OP:
  424. case ISR_ILLEGAL_ISA:
  425. ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
  426. break;
  427. case ISR_ILLEGAL_HAZARD:
  428. //
  429. // a new status code will be introduced for hazard faults.
  430. //
  431. ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
  432. break;
  433. default:
  434. if (TrapFrame->PreviousMode == KernelMode) {
  435. KeBugCheckEx(0xFFFFFFFF,
  436. (ULONG_PTR)TrapFrame->StISR,
  437. (ULONG_PTR)TrapFrame->StIIP,
  438. (ULONG_PTR)TrapFrame,
  439. 0
  440. );
  441. }
  442. break;
  443. }
  444. return TRUE;
  445. }
  446. BOOLEAN
  447. KiUnimplementedAddressTrap (
  448. IN PKTRAP_FRAME TrapFrame
  449. )
  450. /*++
  451. Routine Description:
  452. Handler for unimplemented instruction faults: an attempt is made
  453. to execute an instruction at an unimplemented address.
  454. Arguments:
  455. TrapFrame - Pointer to the trap frame.
  456. Return Value:
  457. --*/
  458. {
  459. PEXCEPTION_RECORD ExceptionRecord;
  460. //
  461. // Initialize the exception record
  462. //
  463. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  464. ExceptionRecord->ExceptionAddress =
  465. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  466. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  467. ExceptionRecord->ExceptionFlags = 0;
  468. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  469. ExceptionRecord->NumberParameters = 5;
  470. ExceptionRecord->ExceptionInformation[0] = TrapFrame->StIIPA;
  471. ExceptionRecord->ExceptionInformation[1] = TrapFrame->StIIP;
  472. ExceptionRecord->ExceptionInformation[2] = STATUS_ACCESS_VIOLATION;
  473. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  474. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  475. ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
  476. return TRUE;
  477. }
  478. BOOLEAN
  479. KiNatExceptions (
  480. IN PKTRAP_FRAME TrapFrame
  481. )
  482. /*++
  483. Routine Description:
  484. Handler for NaT consumption exception faults
  485. Arguments:
  486. TrapFrame - Pointer to the trap frame.
  487. Return Value:
  488. None.
  489. Notes:
  490. ISR.ei bits indicate which instruction caused the exception.
  491. ISR.code{3:0} Non-access instruction (ISR.na = 1)
  492. = 0 tpa
  493. = 1 fc
  494. = 2 probe
  495. = 3 tak
  496. = 4 lfetch
  497. ISR.code{7:4} = 1: Register NaT consumption fault
  498. ISR.code{7:4} = 2: NaT page consumption fault
  499. --*/
  500. {
  501. BOOLEAN StoreInstruction = FALSE;
  502. ULONG IsrCode;
  503. PEXCEPTION_RECORD ExceptionRecord;
  504. //
  505. // Initialize the exception record
  506. //
  507. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  508. ExceptionRecord->ExceptionAddress =
  509. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  510. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  511. ExceptionRecord->ExceptionFlags = 0;
  512. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  513. ExceptionRecord->NumberParameters = 5;
  514. ExceptionRecord->ExceptionInformation[0] = 0;
  515. ExceptionRecord->ExceptionInformation[1] = 0;
  516. ExceptionRecord->ExceptionInformation[2] = 0;
  517. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  518. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  519. IsrCode = (LONG)((TrapFrame->StISR >> ISR_CODE) & ISR_CODE_MASK);
  520. //
  521. // Look at ISR code bits {7:4}
  522. //
  523. switch (IsrCode >> 4) {
  524. case ISR_NAT_REG:
  525. #if 0
  526. if (TrapFrame->PreviousMode == KernelMode) {
  527. DbgPrint("FATAL ERROR: Kernel hit a Nat Consumpation Fault!\n");
  528. KeBugCheckEx(0xFFFFFFFF,
  529. (ULONG_PTR)TrapFrame->StISR,
  530. (ULONG_PTR)TrapFrame->StIIP,
  531. (ULONG_PTR)TrapFrame,
  532. 0
  533. );
  534. // Do not return from KeBugCheckEx
  535. }
  536. #endif // 0
  537. ExceptionRecord->ExceptionCode = STATUS_REG_NAT_CONSUMPTION;
  538. break;
  539. case ISR_NAT_PAGE:
  540. //
  541. // If we start using a NaT page, we should treat this as a page fault and
  542. // should call KiMemoryFault().
  543. //
  544. ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
  545. break;
  546. default:
  547. if (TrapFrame->PreviousMode == KernelMode) {
  548. KeBugCheckEx(0xFFFFFFFF,
  549. (ULONG_PTR)TrapFrame->StISR,
  550. (ULONG_PTR)TrapFrame->StIIP,
  551. (ULONG_PTR)TrapFrame,
  552. 0
  553. );
  554. }
  555. break;
  556. }
  557. return TRUE;
  558. }
  559. BOOLEAN
  560. KiSingleStep (
  561. IN PKTRAP_FRAME TrapFrame
  562. )
  563. /*++
  564. Routine Description:
  565. Handler for single step trap. An instruction was successfully
  566. executed and the PSR.ss bit is 1.
  567. Arguments:
  568. TrapFrame - Pointer to the trap frame.
  569. Return Value:
  570. None.
  571. Notes:
  572. ISR.ei bits indicate which instruction caused the exception.
  573. ISR.code{3:0} = 1000
  574. --*/
  575. {
  576. PEXCEPTION_RECORD ExceptionRecord;
  577. ULONG IpsrRi;
  578. //
  579. // Initialize the exception record
  580. //
  581. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  582. //
  583. // We only want the low order 2 bits so typecast to ULONG
  584. //
  585. IpsrRi = (ULONG)(TrapFrame->StIPSR >> PSR_RI) & 0x3;
  586. ExceptionRecord->ExceptionAddress =
  587. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP, IpsrRi);
  588. ExceptionRecord->ExceptionFlags = 0;
  589. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  590. ExceptionRecord->NumberParameters = 5;
  591. ExceptionRecord->ExceptionInformation[0] = 0;
  592. ExceptionRecord->ExceptionInformation[1] = 0; // 0 for traps
  593. ExceptionRecord->ExceptionInformation[2] = 0;
  594. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  595. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  596. ExceptionRecord->ExceptionCode = STATUS_SINGLE_STEP;
  597. return TRUE;
  598. }
  599. BOOLEAN
  600. KiFloatFault (
  601. IN PKTRAP_FRAME TrapFrame
  602. )
  603. /*++
  604. Routine Description:
  605. Handler for EM floating point fault.
  606. Arguments:
  607. TrapFrame - Pointer to the trap frame.
  608. Return Value:
  609. None.
  610. Notes:
  611. IIP contains address of bundle causing the fault.
  612. ISR.ei bits indicate which instruction caused the exception.
  613. ISR.code{7:0} =
  614. ISR.code{0} = 1: IEEE V (invalid) exception (Normal or SIMD-HI)
  615. ISR.code{1} = 1: Denormal/Unnormal operand exception (Normal or SIMD-HI)
  616. ISR.code{2} = 1: IEEE Z (divide by zero) exception (Normal or SIMD-HI)
  617. ISR.code{3} = 1: Software assist (Normal or SIMD-HI)
  618. ISR.code{4} = 1: IEEE V (invalid) exception (SIMD-LO)
  619. ISR.code{5} = 1: Denormal/Unnormal operand exception (SIMD-LO)
  620. ISR.code{6} = 1: IEEE Z (divide by zero) exception (SIMD-LO)
  621. ISR.code{7} = 1: Software assist (SIMD-LO)
  622. --*/
  623. {
  624. PEXCEPTION_RECORD ExceptionRecord;
  625. //
  626. // Initialize the exception record
  627. //
  628. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  629. ExceptionRecord->ExceptionAddress =
  630. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  631. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  632. ExceptionRecord->ExceptionFlags = 0;
  633. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  634. ExceptionRecord->NumberParameters = 5;
  635. ExceptionRecord->ExceptionInformation[0] = 0;
  636. ExceptionRecord->ExceptionInformation[1] = 0;
  637. ExceptionRecord->ExceptionInformation[2] = 0;
  638. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  639. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  640. ExceptionRecord->ExceptionCode = STATUS_FLOAT_MULTIPLE_FAULTS;
  641. return TRUE;
  642. }
  643. BOOLEAN
  644. KiFloatTrap (
  645. IN PKTRAP_FRAME TrapFrame
  646. )
  647. /*++
  648. Routine Description:
  649. Handler for EM floating point trap.
  650. Arguments:
  651. TrapFrame - Pointer to the trap frame.
  652. Return Value:
  653. None.
  654. Notes:
  655. IIP contains address of bundle with the instruction to be
  656. executed next.
  657. ISR.ei bits indicate which instruction caused the exception.
  658. The fp trap may occur simultaneously with single-step traps. The
  659. fp trap is reported by the hardware. The singel step trap must
  660. be detected by software.
  661. ISR.code{3:0} = ss 0 0 1 (ss = single step)
  662. ISR{15:7} = fp trap code.
  663. --*/
  664. {
  665. PEXCEPTION_RECORD ExceptionRecord;
  666. ULONGLONG SavedISR = TrapFrame->StISR;
  667. //
  668. // Initialize the exception record
  669. //
  670. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  671. ExceptionRecord->ExceptionAddress =
  672. (PVOID) RtlIa64InsertIPSlotNumber(TrapFrame->StIIPA,
  673. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  674. ExceptionRecord->ExceptionFlags = 0;
  675. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  676. ExceptionRecord->NumberParameters = 5;
  677. ExceptionRecord->ExceptionInformation[0] = 0;
  678. ExceptionRecord->ExceptionInformation[1] = 0;
  679. ExceptionRecord->ExceptionInformation[2] = 0;
  680. ExceptionRecord->ExceptionInformation[3] = TrapFrame->StIIPA;
  681. ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR;
  682. ExceptionRecord->ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS;
  683. //
  684. // check for single-step trap
  685. //
  686. if (SavedISR & (1i64 << ISR_SS_TRAP)) {
  687. return KiSingleStep(TrapFrame);
  688. }
  689. return TRUE;
  690. }
  691. #pragma warning( disable : 4715 ) // not all control paths return a value
  692. EXCEPTION_DISPOSITION
  693. KiSystemServiceHandler (
  694. IN PEXCEPTION_RECORD ExceptionRecord,
  695. IN FRAME_POINTERS EstablisherFrame,
  696. IN OUT PCONTEXT ContextRecord,
  697. IN OUT PDISPATCHER_CONTEXT DispatcherContext
  698. )
  699. /*++
  700. Routine Description:
  701. Control reaches here when a exception is raised in a system service
  702. or the system service dispatcher, and for an unwind during a kernel
  703. exception.
  704. If an unwind is being performed and the system service dispatcher is
  705. the target of the unwind, then an exception occured while attempting
  706. to copy the user's in-memory argument list. Control is transfered to
  707. the system service exit by return a continue execution disposition
  708. value.
  709. If an unwind is being performed and the previous mode is user, then
  710. bug check is called to crash the system. It is not valid to unwind
  711. out of a system service into user mode.
  712. If an unwind is being performed, the previous mode is kernel, the
  713. system service dispatcher is not the target of the unwind, and the
  714. thread does not own any mutexes, then the previous mode field from
  715. the trap frame is restored to the thread object. Otherwise, bug
  716. check is called to crash the system. It is invalid to unwind out of
  717. a system service while owning a mutex.
  718. If an exception is being raised and the exception PC is within the
  719. range of the system service dispatcher in-memory argument copy code,
  720. then an unwind to the system service exit code is initiated.
  721. If an exception is being raised and the exception PC is not within
  722. the range of the system service dispatcher, and the previous mode is
  723. not user, then a continue searh disposition value is returned. Otherwise,
  724. a system service has failed to handle an exception and bug check is
  725. called. It is invalid for a system service not to handle all exceptions
  726. that can be raised in the service.
  727. Arguments:
  728. ExceptionRecord - Supplies a pointer to an exception record.
  729. EstablisherFrame - Supplies the frame pointer of the establisher
  730. of this exception handler.
  731. N.B. This is not actually the frame pointer of the establisher of
  732. this handler. It is actually the stack pointer of the caller
  733. of the system service. Therefore, the establisher frame pointer
  734. is not used and the address of the trap frame is determined by
  735. examining the saved s8 register in the context record.
  736. ContextRecord - Supplies a pointer to a context record.
  737. DispatcherContext - Supplies a pointer to the dispatcher context
  738. record.
  739. Return Value:
  740. If bug check is called, there is no return from this routine and the
  741. system is crashed. If an exception occured while attempting to copy
  742. the user in-memory argument list, then there is no return from this
  743. routine, and unwind is called. Otherwise, ExceptionContinueSearch is
  744. returned as the function value.
  745. --*/
  746. {
  747. CONTEXT Context;
  748. PKTHREAD Thread;
  749. PKTRAP_FRAME TrapFrame;
  750. ULONG_PTR ExceptionAddress;
  751. extern ULONG KiSystemServiceStartOffset;
  752. extern ULONG KiSystemServiceEndOffset;
  753. extern ULONG KiSystemServiceExitOffset;
  754. if (IS_UNWINDING(ExceptionRecord->ExceptionFlags)) {
  755. //
  756. // An unwind is in progress.
  757. // If a target unwind is being performed, then continue execution
  758. // is returned to transfer control to the system service exit
  759. // code. Otherwise, restore the previous mode if the previous
  760. // mode is not user and there is no mutex owned by the current
  761. // thread.
  762. //
  763. if (ExceptionRecord->ExceptionFlags & EXCEPTION_TARGET_UNWIND) {
  764. return ExceptionContinueSearch;
  765. } else {
  766. Thread = KeGetCurrentThread();
  767. if (Thread->PreviousMode == KernelMode) {
  768. //
  769. // Previous mode is kernel and no mutex owned.
  770. //
  771. // N.B. System convention: unwinder puts the trap frame
  772. // address in IntT0 field of
  773. // context record when it
  774. // encounters an interrupt region.
  775. //
  776. TrapFrame = (PKTRAP_FRAME) ContextRecord->IntT0;
  777. Thread->PreviousMode = (KPROCESSOR_MODE)TrapFrame->PreviousMode;
  778. return ExceptionContinueSearch;
  779. } else {
  780. //
  781. // Previous mode is user, call bug check.
  782. //
  783. KeBugCheck(SYSTEM_UNWIND_PREVIOUS_USER);
  784. }
  785. }
  786. } else {
  787. ULONG IsrCode;
  788. //
  789. // An exception dispatching is in progress.
  790. // If the exception PC is within the in-memory argument copy code
  791. // of the system service dispatcher, then call unwind to transfer
  792. // control to the system service exit code. Otherwise, check if
  793. // the previous mode is user or kernel mode.
  794. //
  795. ExceptionAddress = (ULONG_PTR)ExceptionRecord->ExceptionAddress;
  796. if ((ExceptionAddress < MM_EPC_VA+KiSystemServiceStartOffset) ||
  797. (ExceptionAddress >= MM_EPC_VA+KiSystemServiceEndOffset))
  798. {
  799. if (KeGetCurrentThread()->PreviousMode == UserMode) {
  800. //
  801. // Previous mode is user, call bug check.
  802. //
  803. KeBugCheck(SYSTEM_SERVICE_EXCEPTION);
  804. } else {
  805. //
  806. // Previous mode is kernel, continue to search
  807. //
  808. return ExceptionContinueSearch;
  809. }
  810. } else {
  811. IsrCode = (ULONG)((ExceptionRecord->ExceptionInformation[4] >> ISR_CODE) & ISR_CODE_MASK) >> 4;
  812. if ( (IsrCode == ISR_NAT_REG) || (IsrCode == ISR_NAT_PAGE) ) {
  813. DbgPrint("WARNING: Kernel hit a Nat Consumpation Fault\n");
  814. DbgPrint("WARNING: At %p\n", ExceptionRecord->ExceptionAddress);
  815. }
  816. #pragma warning( disable : 4312 ) // disabling warning on PVOID casting for the ExceptionCode
  817. RtlUnwind2(EstablisherFrame,
  818. (PVOID)(MM_EPC_VA+KiSystemServiceExitOffset),
  819. NULL, (PVOID)ExceptionRecord->ExceptionCode, &Context);
  820. #pragma warning ( default: 4312 )
  821. }
  822. }
  823. } // KiSystemServiceHandler( )
  824. #pragma warning( default : 4715 )
  825. BOOLEAN
  826. KiUnalignedFault (
  827. IN PKTRAP_FRAME TrapFrame
  828. )
  829. /*++
  830. Routine Description:
  831. Handler for unaligned data reference.
  832. Arguments:
  833. TrapFrame - Pointer to the trap frame.
  834. Return Value:
  835. None.
  836. Notes:
  837. ISR.ei bits indicate which instruction caused the exception.
  838. --*/
  839. {
  840. PEXCEPTION_RECORD ExceptionRecord;
  841. PVOID VirtualAddress;
  842. VirtualAddress = (PVOID)TrapFrame->StIFA;
  843. ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
  844. ExceptionRecord->ExceptionAddress =
  845. (PVOID)RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  846. ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI));
  847. ExceptionRecord->ExceptionFlags = 0;
  848. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  849. ExceptionRecord->NumberParameters = 5;
  850. ExceptionRecord->ExceptionInformation[0] = (ULONG_PTR)0;
  851. ExceptionRecord->ExceptionInformation[1] = (ULONG_PTR)VirtualAddress;
  852. ExceptionRecord->ExceptionInformation[2] = (ULONG_PTR)0;
  853. ExceptionRecord->ExceptionInformation[3] = (ULONG_PTR)TrapFrame->StIIPA;
  854. ExceptionRecord->ExceptionInformation[4] = (ULONG_PTR)TrapFrame->StISR;
  855. ExceptionRecord->ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
  856. return TRUE;
  857. }
  858. VOID
  859. KiAdvanceInstPointer(
  860. IN PKTRAP_FRAME TrapFrame
  861. )
  862. /*++
  863. Routine Description:
  864. This function is called to advance the instruction pointer in the trap frame.
  865. Arguments:
  866. TrapFrame - Supplies a pointer to a trap frame.
  867. Return Value:
  868. The intruction pointer in the trap frame has been advanced.
  869. --*/
  870. {
  871. ULONGLONG PsrRi;
  872. PsrRi = ((TrapFrame->StIPSR >> PSR_RI) & 3i64) + 1;
  873. if (PsrRi == 3) {
  874. PsrRi = 0;
  875. TrapFrame->StIIP += 16;
  876. }
  877. TrapFrame->StIPSR &= ~(3i64 << PSR_RI);
  878. TrapFrame->StIPSR |= (PsrRi << PSR_RI);
  879. return;
  880. }
  881. #if 0 // obsolete; may be used for debug purposes
  882. typedef struct _CHECK_INST {
  883. union {
  884. struct {
  885. ULONGLONG qp: 6;
  886. ULONGLONG imm7: 7;
  887. ULONGLONG r2: 7;
  888. ULONGLONG imm13:13;
  889. ULONGLONG x3: 3;
  890. ULONGLONG s: 1;
  891. ULONGLONG Op: 4;
  892. ULONGLONG Rsv: 23;
  893. } i;
  894. ULONGLONG Ulong64;
  895. } u;
  896. } CHECK_INST;
  897. BOOLEAN
  898. KiEmulateSpeculationFault(
  899. IN PKTRAP_FRAME TrapFrame
  900. )
  901. {
  902. PULONGLONG BundleAddress;
  903. ULONGLONG BundleLow;
  904. ULONGLONG BundleHigh;
  905. ULONG SlotNumber;
  906. CHECK_INST CheckInst;
  907. ISR Isr;
  908. ULONGLONG Imm24;
  909. BundleAddress = (PULONGLONG)TrapFrame->StIIP;
  910. try {
  911. BundleLow = *BundleAddress;
  912. BundleHigh = *(BundleAddress+1);
  913. } except (EXCEPTION_EXECUTE_HANDLER) {
  914. //
  915. // if an exception (memory fault) occurs, then let it re-execute chk.s again
  916. //
  917. return FALSE;
  918. }
  919. Isr.ull = TrapFrame->StISR;
  920. SlotNumber = (ULONG)Isr.sb.isr_ei;
  921. //
  922. // Align instruction
  923. //
  924. switch (SlotNumber) {
  925. case 0:
  926. CheckInst.u.Ulong64 = BundleLow >> 5;
  927. break;
  928. case 1:
  929. CheckInst.u.Ulong64 = (BundleLow >> 46) | (BundleHigh << 18);
  930. break;
  931. case 2:
  932. CheckInst.u.Ulong64 = (BundleHigh >> 23);
  933. break;
  934. }
  935. //
  936. // Extract immediate value
  937. //
  938. Imm24 = ((CheckInst.u.i.imm13 << 7)|(CheckInst.u.i.imm7)) << 4;
  939. if (CheckInst.u.i.s == 1) {
  940. Imm24 = 0xFFFFFFFFFF000000|Imm24;
  941. }
  942. TrapFrame->StIIP += Imm24;
  943. TrapFrame->StIPSR &= ~(3i64 << PSR_RI);
  944. return FALSE;
  945. }
  946. #endif // 0