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.

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