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.

1483 lines
36 KiB

  1. /*++
  2. Module Name:
  3. ia32trap.c
  4. Abstract:
  5. This module contains iA32 trap handling code.
  6. Only used by kernel.
  7. Fault can ONLY be initiated from user mode code. There is no support
  8. for iA32 code in the kernel mode.
  9. For common pratice, we always return to the caller (lower level fault
  10. handler) and have the system do a normal ia64 exception dispatch. The
  11. wow64 code takes that exception and passes it back to the ia32 code
  12. as needed.
  13. Revision History:
  14. 1 Feb. 1999 Initial Version
  15. 16 Feb. 2000 SamerA Don't break on POPF/POPFD instructions and
  16. alignment faults for Wow64 processes.
  17. 17 Oct. 2000 v-cspira Fix the emulation of smsw to handle the SIB byte
  18. 31 Oct. 2000 SamerA Ia32 Lock prefix emulation.
  19. 25 Sep. 2001 SamerA Stack-Selector (SS) Load instruction emulation.
  20. 02 Mar. 2002 SamerA Security fixes.
  21. --*/
  22. #if DBG
  23. // Get all the iadebugging stuff when running a checked build
  24. #define IADBG 1
  25. #endif
  26. #include "ki.h"
  27. #include "ia32def.h"
  28. BOOLEAN
  29. KiIsTrapFrameModifiedAtApcLevel (
  30. IN PKTRAP_FRAME TrapFrame,
  31. BOOLEAN *IrqlChanged,
  32. KIRQL *OldIrql
  33. )
  34. /*++
  35. Routine Description
  36. This function verifies we are running at APC level, and if not, elevates the
  37. current thread's IRQL to APC level. It checks whether the trap frame has been
  38. modified.
  39. Arguments:
  40. Frame - Supply a pointer to an iA32 TrapFrame
  41. IrqlChanged - Pointer to boolean to indicate whether this function changed
  42. OldIrql - Old Irql value.
  43. Return:
  44. TRUE - Trap frame has been modified since established.
  45. FALSE - Trap frame has not been modified yet.
  46. --*/
  47. {
  48. //
  49. // Aquire APC_LEVEL so that SetContext calls on this thread are blocked.
  50. //
  51. if (KeGetCurrentIrql () < APC_LEVEL) {
  52. KeRaiseIrql (APC_LEVEL, OldIrql);
  53. *IrqlChanged = TRUE;
  54. } else {
  55. *OldIrql = PASSIVE_LEVEL;
  56. *IrqlChanged = FALSE;
  57. }
  58. return (((TrapFrame->EOFMarker & MODIFIED_FRAME) != 0) ? TRUE : FALSE);
  59. }
  60. VOID
  61. KiIA32CommonArgs (
  62. IN PKTRAP_FRAME Frame,
  63. IN NTSTATUS ExceptionCode,
  64. IN PVOID ExceptionAddress,
  65. IN ULONG_PTR Argument0,
  66. IN ULONG_PTR Argument1,
  67. IN ULONG_PTR Argument2
  68. )
  69. /*++
  70. Routine Description
  71. This routine sets up the ExceptionFrame
  72. Arguments:
  73. Frame - Supply a pointer to an iA32 TrapFrame
  74. ExceptionCode - Supplies a Exception Code
  75. ExceptionAddress - Supplies a pointer to user exception address
  76. Argument0, Argument1, Argument2 - Possible ExceptionInformation
  77. Return:
  78. Nothing
  79. --*/
  80. {
  81. PEXCEPTION_RECORD ExceptionRecord;
  82. ExceptionRecord = (PEXCEPTION_RECORD)&Frame->ExceptionRecord;
  83. ExceptionRecord->ExceptionRecord = (PEXCEPTION_RECORD)NULL;
  84. ExceptionRecord->ExceptionCode = ExceptionCode;
  85. ExceptionRecord->ExceptionFlags = 0;
  86. ExceptionRecord->ExceptionAddress = ExceptionAddress;
  87. ExceptionRecord->NumberParameters = 5;
  88. ExceptionRecord->ExceptionInformation[0] = Argument0;
  89. ExceptionRecord->ExceptionInformation[1] = Argument1;
  90. ExceptionRecord->ExceptionInformation[2] = Argument2;
  91. ExceptionRecord->ExceptionInformation[3] = (ULONG_PTR)Frame->StIIPA;
  92. ExceptionRecord->ExceptionInformation[4] = (ULONG_PTR)Frame->StISR;
  93. }
  94. BOOLEAN
  95. KiIA32ExceptionDivide(
  96. IN PKTRAP_FRAME Frame
  97. )
  98. /*++
  99. Routine Description:
  100. iA-32_Exception(Divide) - fault
  101. Handle divide error fault.
  102. Called from iA32_Exception() with
  103. ISR.vector : 0
  104. The divide error fault occurs if a DIV or IDIV instructions is
  105. executed with a divisor of 0, or if the quotient is too big to
  106. fit in the result operand.
  107. An INTEGER DIVIDED BY ZERO exception will be raised for the fault.
  108. The Faults can only come from user mode.
  109. Arguments:
  110. Frame - Supply a pointer to an iA32 TrapFrame
  111. Return value:
  112. --*/
  113. {
  114. //
  115. // Setup exception and back to caller
  116. //
  117. KiIA32CommonArgs(Frame,
  118. Ki386CheckDivideByZeroTrap(Frame),
  119. (PVOID) (ULONG_PTR) EIP(Frame),
  120. 0, 0, 0);
  121. return TRUE;
  122. }
  123. BOOLEAN
  124. KiIA32ExceptionDebug(
  125. IN PKTRAP_FRAME Frame
  126. )
  127. /*++
  128. Routine Description:
  129. iA-32_Exception(Debug)
  130. Called from iA32_Exception() with
  131. ISR.Vector = 1
  132. Depend on ISR.Code
  133. 0: It is Code BreakPoint Trap
  134. TrapCode: Can be Concurrent Single Step |
  135. Taken Branch | Data BreakPoint Trap
  136. Handler needs to decode ISR.Code to distinguish
  137. Note: EFlag isn't saved yet, so write directly to ar.24
  138. Arguments:
  139. Frame - Supply a pointer to an iA32 TrapFrame
  140. Return Value:
  141. No return
  142. --*/
  143. {
  144. ULONGLONG EFlag;
  145. #if defined(IADBG)
  146. IF_IA32TRAP_DEBUG( DEBUG )
  147. DbgPrint( "IA32 Debug: Eip 0x%p\n", EIP(Frame) );
  148. #endif // IADBG
  149. // Turn off the TF bit
  150. EFlag = __getReg(CV_IA64_AR24);
  151. EFlag &= ~EFLAGS_TF_BIT;
  152. __setReg(CV_IA64_AR24, EFlag);
  153. KiIA32CommonArgs(Frame,
  154. STATUS_WX86_SINGLE_STEP,
  155. (PVOID) (ULONG_PTR) EIP(Frame),
  156. 0, 0, 0);
  157. return TRUE;
  158. }
  159. BOOLEAN
  160. KiIA32ExceptionBreak(
  161. IN PKTRAP_FRAME Frame
  162. )
  163. /*++
  164. Routine Description:
  165. iA-32_Exception(Break) - Trap
  166. BreakPoint instruction (INT 3) trigged a trap.
  167. Note: EFlag isn't saved yet, so write directly to ar.24
  168. Arguments:
  169. Frame - Supply a pointer to an iA32 TrapFrame
  170. Return Value:
  171. --*/
  172. {
  173. ULONGLONG EFlag;
  174. #if defined(IADBG)
  175. IF_IA32TRAP_DEBUG( BREAK )
  176. DbgPrint( "IA32 Break: Eip 0x%p\n", EIP(Frame) );
  177. #endif // IADBG
  178. // Turn off the TF bit
  179. EFlag = __getReg(CV_IA64_AR24);
  180. EFlag &= ~EFLAGS_TF_BIT;
  181. __setReg(CV_IA64_AR24, EFlag);
  182. KiIA32CommonArgs(Frame,
  183. STATUS_WX86_BREAKPOINT,
  184. (PVOID) (ULONG_PTR) EIP(Frame),
  185. BREAKPOINT_X86_BREAK,
  186. ECX(Frame),
  187. EDX(Frame));
  188. return TRUE;
  189. }
  190. BOOLEAN
  191. KiIA32ExceptionOverflow(
  192. IN PKTRAP_FRAME Frame
  193. )
  194. /*++
  195. Routine Description:
  196. iA-32_Exception(Overflow) - Trap
  197. ISR.Vector = 4
  198. Handle INTO overflow
  199. Eip - point to the address that next to the one causing INTO
  200. Occurres when INTO instruction as well as EFlags.OF is ON
  201. Trap only initiated from user mode
  202. Arguments:
  203. Frame - Supply a pointer to an iA32 TrapFrame
  204. Return Value:
  205. --*/
  206. {
  207. #if defined(IADBG)
  208. IF_IA32TRAP_DEBUG( OVERFLOW )
  209. DbgPrint( "IA32 OverFlow: Eip 0x%p\n", EIP(Frame) );
  210. #endif // IADBG
  211. //
  212. // All error, generate exception and Eip point to INTO instruction
  213. //
  214. KiIA32CommonArgs(Frame,
  215. STATUS_INTEGER_OVERFLOW,
  216. (PVOID) (ULONG_PTR) (EIP(Frame) - 1),
  217. 0, 0, 0);
  218. return TRUE;
  219. }
  220. BOOLEAN
  221. KiIA32ExceptionBound(
  222. IN PKTRAP_FRAME Frame
  223. )
  224. /*++
  225. Routine Description:
  226. iA-32_Exception(Bound) - Fault
  227. Handle Bound check fault
  228. ISR.Vector = 5
  229. Eip - point to BOUND instruction
  230. The bound check fault occurs if a BOUND instruction finds that
  231. the tested value is outside the specified range.
  232. For bound check fault, an ARRAY BOUND EXCEEDED exception will be raised.
  233. Arguments:
  234. Frame - Supply a pointer to an iA32 TrapFrame
  235. Return Value:
  236. --*/
  237. {
  238. #if defined(IADBG)
  239. IF_IA32TRAP_DEBUG( BOUND )
  240. DbgPrint( "IA32 Bound: Eip 0x%p\n", EIP(Frame) );
  241. #endif // IADBG
  242. //
  243. // All error, generate exception with Eip point to BOUND instruction
  244. //
  245. KiIA32CommonArgs(Frame,
  246. STATUS_ARRAY_BOUNDS_EXCEEDED,
  247. (PVOID) (ULONG_PTR) EIP(Frame),
  248. 0, 0, 0);
  249. return TRUE;
  250. }
  251. ULONG
  252. IA32EmulateSmsw(
  253. IN PKTRAP_FRAME Frame
  254. )
  255. /*++
  256. Routine Description:
  257. Emulate the SMSW instruction
  258. Arguments:
  259. Frame: Pointer to iA32 TrapFrame in the stack
  260. Return Value:
  261. Exception code
  262. --*/
  263. {
  264. ULONG Code;
  265. PUCHAR InstAddr;
  266. UINT_PTR EffectiveAddress;
  267. PUSHORT toAddr; // SMSW deals with 16 bits all the time...
  268. BOOLEAN RegisterMode;
  269. NTSTATUS status = STATUS_SUCCESS;
  270. //
  271. // Get the code for the prefix bytes that have already been grabbed
  272. // and placed into the IIM
  273. //
  274. Code = ISRCode(Frame);
  275. //
  276. // The operand size is always 16 for this instruction. We don't care about
  277. // overrides as the segment registers all contain the same thing.
  278. //
  279. //
  280. // Find the instruction in memory and point the Effective Address
  281. // at the byte after the opcode
  282. // Inst Address is start of ia32 inst + length of prefix + number of
  283. // bytes in opcode
  284. //
  285. InstAddr = (PUCHAR) (Frame->StIIP + ((Code >> 12) & 0xf) + 2);
  286. if (!KiIa32Compute32BitEffectiveAddress(Frame, &InstAddr, &EffectiveAddress, &RegisterMode)) {
  287. status = STATUS_ACCESS_VIOLATION;
  288. }
  289. if (NT_SUCCESS(status)) {
  290. //
  291. // The adress given to us hasn't been checked for user-space
  292. // validity, so check it now
  293. //
  294. toAddr = (PUSHORT) EffectiveAddress;
  295. try {
  296. //
  297. // Make sure we can write to the address
  298. //
  299. if (RegisterMode == FALSE) {
  300. ProbeForWriteSmallStructure(toAddr, sizeof(SHORT), 2);
  301. }
  302. //
  303. // and do the write
  304. //
  305. *toAddr = (SHORT) (__getReg(CV_IA64_AR27) & 0xffff);
  306. }
  307. except (EXCEPTION_EXECUTE_HANDLER) {
  308. //
  309. // return the exception
  310. //
  311. status = GetExceptionCode();
  312. }
  313. if (NT_SUCCESS(status)) {
  314. //
  315. // the store worked, so update the IIP so we can continue
  316. // executing
  317. //
  318. Frame->StIIP = (UINT_PTR) InstAddr;
  319. }
  320. }
  321. return status;
  322. }
  323. NTSTATUS
  324. IA32CheckOpcode(
  325. IN PKTRAP_FRAME Frame
  326. )
  327. /*++
  328. Routine Description:
  329. To identify the Opcode violation state
  330. Arguments:
  331. Frame: Pointer to iA32 TrapFrame in the stack
  332. Return Value:
  333. Exception code
  334. --*/
  335. {
  336. UCHAR OpCodeByte0;
  337. UCHAR OpCodeByte1;
  338. UCHAR OpCodeByte2;
  339. OpCodeByte0 = (UCHAR) Frame->StIIM & 0xff;
  340. OpCodeByte1 = (UCHAR) (Frame->StIIM >> 8) & 0xff;
  341. OpCodeByte2 = (UCHAR) (Frame->StIIM >> 16) & 0xff;
  342. switch (OpCodeByte0) {
  343. case MI_HLT:
  344. return (STATUS_PRIVILEGED_INSTRUCTION);
  345. break;
  346. case MI_TWO_BYTE:
  347. if ((OpCodeByte1 == MI_SMSW)
  348. && ((OpCodeByte2 & MI_MODRM_MASK) == MI_SMSW_REGOP)) {
  349. //
  350. // We have the SMSW instruction
  351. // So now need to emulate it...
  352. //
  353. return (IA32EmulateSmsw(Frame));
  354. }
  355. else if ((OpCodeByte1 == MI_LTR_LLDT) ||
  356. (OpCodeByte2 == MI_LGDT_LIDT_LMSW)) {
  357. OpCodeByte2 &= MI_MODRM_MASK; // get bit 3-5 of ModRM byte
  358. if (OpCodeByte2==MI_LLDT_MASK || OpCodeByte2==MI_LTR_MASK ||
  359. OpCodeByte2==MI_LGDT_MASK || OpCodeByte2==MI_LIDT_MASK ||
  360. OpCodeByte2==MI_LMSW_MASK) {
  361. return (STATUS_PRIVILEGED_INSTRUCTION);
  362. } else {
  363. return (STATUS_ACCESS_VIOLATION);
  364. }
  365. } else {
  366. if (OpCodeByte1 & MI_SPECIAL_MOV_MASK) {
  367. //
  368. // mov may have special_mov_mask
  369. // but they are not 2 bytes OpCode
  370. //
  371. return (STATUS_PRIVILEGED_INSTRUCTION);
  372. } else {
  373. //
  374. // Do we need to further check if it is INVD, INVLPG ... ?
  375. //
  376. return (STATUS_ACCESS_VIOLATION);
  377. }
  378. }
  379. break;
  380. default:
  381. //
  382. // All other
  383. //
  384. return (STATUS_ILLEGAL_INSTRUCTION);
  385. break;
  386. }
  387. }
  388. BOOLEAN
  389. KiIA32InterceptInstruction(
  390. IN PKTRAP_FRAME Frame
  391. )
  392. /*++
  393. Routine Description:
  394. iA-32_Exception(InstructionIntercept Opcode)
  395. Program entry for either
  396. 1. IA-32 Invalid Opcode Fault #6, or
  397. 2. IA-32 interceptions(Inst)
  398. Execution of unimplemented IA-32 opcodes, illegal opcodes or sensitive
  399. privileged IA32 operating system instructions results this interception.
  400. Possible Opcodes:
  401. Privileged Opcodes: CLTS, HLT, INVD, INVLPG, LIDT, LMSW, LTR,
  402. mov to/from CRs, DRs
  403. RDMSR, RSM, SMSW, WBINVD, WRMSR
  404. Arguments:
  405. Frame - Supply a pointer to an iA32 TrapFrame
  406. Return Value:
  407. --*/
  408. {
  409. NTSTATUS status;
  410. #if defined(IADBG)
  411. IF_IA32TRAP_DEBUG( INSTRUCTION )
  412. DbgPrint( "IA32 Instruction: Eip 0x%p\n", EIP(Frame) );
  413. #endif // IADBG
  414. status = IA32CheckOpcode(Frame);
  415. switch (status) {
  416. case STATUS_PRIVILEGED_INSTRUCTION:
  417. KiIA32CommonArgs(Frame,
  418. STATUS_PRIVILEGED_INSTRUCTION,
  419. (PVOID) (ULONG_PTR) EIP(Frame),
  420. 0, 0, 0);
  421. break;
  422. case STATUS_ACCESS_VIOLATION:
  423. KiIA32CommonArgs(Frame,
  424. STATUS_ACCESS_VIOLATION,
  425. (PVOID) (ULONG_PTR) EIP(Frame),
  426. 0, (ULONG_PTR)-1, 0);
  427. break;
  428. case STATUS_ILLEGAL_INSTRUCTION:
  429. KiIA32CommonArgs(Frame,
  430. STATUS_ILLEGAL_INSTRUCTION,
  431. (PVOID) (ULONG_PTR) EIP(Frame),
  432. 0, (ULONG_PTR)-1, 0);
  433. break;
  434. case STATUS_SUCCESS:
  435. //
  436. // This means the OpCode was dealt with, so let the code continue
  437. //
  438. return FALSE;
  439. default:
  440. KiIA32CommonArgs(Frame,
  441. status,
  442. (PVOID) (ULONG_PTR) EIP(Frame),
  443. 0, (ULONG_PTR)-1, 0);
  444. break;
  445. }
  446. return TRUE;
  447. }
  448. BOOLEAN
  449. KiIA32ExceptionNoDevice(
  450. IN PKTRAP_FRAME Frame
  451. )
  452. /*++
  453. Routine Description:
  454. iA-32_Exception(Coprocessor Not Available) - fault
  455. This routine is called from iA32_Exception() with
  456. ISR.Vector = 7
  457. Note:
  458. At this time, the AR registers have not been saved. This
  459. includes, CFLAGS (AR.27), EFLAGS (AR.24), FCR (AR.21),
  460. FSR (AR.28), FIR (AR.29) and FDR (AR.30).
  461. Arguments:
  462. Frame - iA32 TrapFrame that was saved in the memory stack
  463. Return Value:
  464. --*/
  465. {
  466. NTSTATUS ErrorCode;
  467. ULONG FirOffset, FdrOffset;
  468. ULONG FpState;
  469. ULONGLONG FcrRegister, FsrRegister;
  470. #if defined(IADBG)
  471. IF_IA32TRAP_DEBUG( NODEVICE )
  472. DbgPrint( "IA32 NoDevice: Eip 0x%p\n", EIP(Frame) );
  473. #endif // IADBG
  474. FcrRegister = __getReg(CV_IA64_AR21);
  475. FsrRegister = __getReg(CV_IA64_AR28);
  476. FirOffset = (ULONG) (__getReg(CV_IA64_AR29) & 0xFFFFFFFF);
  477. FdrOffset = (ULONG) (__getReg(CV_IA64_AR30) & 0xFFFFFFFF);
  478. //
  479. // According to the floating error priority,
  480. // we test what is the cause of the NPX error
  481. // and raise an appropriate exception
  482. //
  483. FpState = (ULONG) (~(FcrRegister &
  484. (FSW_INVALID_OPERATION | FSW_DENORMAL |
  485. FSW_ZERO_DIVIDE | FSW_OVERFLOW |
  486. FSW_UNDERFLOW | FSW_PRECISION)) &
  487. (FsrRegister & FSW_ERR_MASK));
  488. ErrorCode = 0;
  489. if (FpState & FSW_INVALID_OPERATION) {
  490. if (FpState & FSW_STACK_FAULT) {
  491. KiIA32CommonArgs(Frame,
  492. STATUS_FLOAT_STACK_CHECK,
  493. (PVOID) (ULONG_PTR) FirOffset,
  494. 0, FdrOffset, 0);
  495. return TRUE;
  496. } else {
  497. KiIA32CommonArgs(Frame,
  498. STATUS_FLOAT_INVALID_OPERATION,
  499. (PVOID) (ULONG_PTR) FirOffset,
  500. 0, 0, 0);
  501. return TRUE;
  502. }
  503. } else {
  504. //
  505. // Follow the x86 priority of which exception to report if
  506. // multiple bits are set
  507. //
  508. if (FpState & FSW_ZERO_DIVIDE) {
  509. ErrorCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
  510. }
  511. else if (FpState & FSW_DENORMAL) {
  512. ErrorCode = STATUS_FLOAT_INVALID_OPERATION;
  513. }
  514. else if (FpState & FSW_OVERFLOW) {
  515. ErrorCode = STATUS_FLOAT_OVERFLOW;
  516. }
  517. else if (FpState & FSW_UNDERFLOW) {
  518. ErrorCode = STATUS_FLOAT_UNDERFLOW;
  519. }
  520. else if (FpState & FSW_PRECISION) {
  521. ErrorCode = STATUS_FLOAT_INEXACT_RESULT;
  522. }
  523. }
  524. //
  525. // If we get here, we either have the error code, or
  526. // we went through everything and saw nothing
  527. //
  528. if (ErrorCode) {
  529. KiIA32CommonArgs(Frame,
  530. ErrorCode,
  531. (PVOID) (ULONG_PTR) FirOffset,
  532. 0, 0, 0);
  533. return TRUE;
  534. }
  535. //
  536. // FpState indicates no error, then something is wrong
  537. // Panic the system !!!
  538. //
  539. // KeBugCheckEx(TRAP_CAUSE_UNKNOWN, (ULONG_PTR)Frame, 0, 0, 2);
  540. //
  541. // Turns out there is a bug in the chip and it can cause an fp fault even
  542. // with a masked fp exception... So, don't bug check, count it
  543. // as non-error and reset the fsr.es bit to try and avoid getting this
  544. // exception in the future.
  545. //
  546. #if defined(IADBG)
  547. DbgPrint( "IA32 Debug: Saw FP exception when FP exceptions are masked. Reseting fsr.es bit\n");
  548. #endif // IADBG
  549. FsrRegister &= ~((ULONGLONG) FSW_ERROR_SUMMARY);
  550. __setReg(CV_IA64_AR28, FsrRegister);
  551. return FALSE;
  552. }
  553. BOOLEAN
  554. KiIA32ExceptionSegmentNotPresent(
  555. IN PKTRAP_FRAME Frame
  556. )
  557. /*++
  558. Routine Description:
  559. iA-32_Exception(Not Present) - fault
  560. Handle Segment Not Present fault.
  561. ISR.Vector = 11
  562. This exception occurs when the processor finds the P bit 0
  563. when accessing an otherwise valid descriptor that is not to
  564. be loaded in SS register.
  565. Arguments:
  566. Frame - iA32 TrapFrame that was saved in the memory stack
  567. Return Value:
  568. --*/
  569. {
  570. #if defined(IADBG)
  571. IF_IA32TRAP_DEBUG( NOTPRESENT )
  572. DbgPrint( "IA32 NotPresent: Eip 0x%p\n", EIP(Frame) );
  573. #endif // IADBG
  574. //
  575. // Generate Exception for all other errors
  576. //
  577. KiIA32CommonArgs(Frame,
  578. STATUS_ACCESS_VIOLATION,
  579. (PVOID) (ULONG_PTR) EIP(Frame),
  580. 0, ISRCode(Frame) | RPL_MASK, 0);
  581. return TRUE;
  582. }
  583. BOOLEAN
  584. KiIA32ExceptionStack(
  585. IN PKTRAP_FRAME Frame
  586. )
  587. /*++
  588. Routine Description:
  589. iA-32_Exception(Stack) - fault
  590. ISR.Vector = 12
  591. This exception occurs when the processor detects certain problem
  592. with the segment addressed by the SS segment register:
  593. 1. A limit violation in the segment addressed by the SS (error
  594. code = 0)
  595. 2. A limit vioalation in the inner stack during an interlevel
  596. call or interrupt (error code = selector for the inner stack)
  597. 3. If the descriptor to be loaded into SS has its present bit 0
  598. (error code = selector for the not-present segment)
  599. The exception only occurred from user mode
  600. Arguments:
  601. Frame - iA32 TrapFrame that was saved in the memory stack
  602. Return Value:
  603. --*/
  604. {
  605. USHORT Code;
  606. #if defined(IADBG)
  607. IF_IA32TRAP_DEBUG( STACK )
  608. DbgPrint( "IA32 Stack: Eip 0x%p\n", EIP(Frame) );
  609. #endif // IADBG
  610. //
  611. // Dispatch Exception to user
  612. //
  613. Code = ISRCode(Frame);
  614. //
  615. // Code may contain the faulting selector
  616. //
  617. KiIA32CommonArgs(Frame,
  618. STATUS_ACCESS_VIOLATION,
  619. (PVOID) (ULONG_PTR) EIP(Frame),
  620. Code ? (Code | RPL_MASK) : ESP(Frame),
  621. Code ? EXCEPT_UNKNOWN_ACCESS : EXCEPT_LIMIT_ACCESS,
  622. 0);
  623. return TRUE;
  624. }
  625. BOOLEAN
  626. KiIA32ExceptionInvalidOp(
  627. IN PKTRAP_FRAME Frame
  628. )
  629. /*++
  630. Routine Description:
  631. iA-32_Exception(Invalid Opcode) - fault
  632. PKTRAP_FRAME Frame
  633. Eip : virtual iA-32 instruction address
  634. ISR.vector : 6
  635. Note:
  636. Only MMX and KNI instructions can cause this fault based
  637. on values in CR0 and CR4
  638. Arguments:
  639. Frame - iA32 TrapFrame that was saved in the memory stack
  640. Return Value:
  641. --*/
  642. {
  643. #if defined(IADBG)
  644. IF_IA32TRAP_DEBUG( INSTRUCTION )
  645. DbgPrint( "IA32 Invalid Opcode: Eip 0x%p\n", EIP(Frame) );
  646. #endif // IADBG
  647. KiIA32CommonArgs(Frame,
  648. STATUS_ILLEGAL_INSTRUCTION,
  649. (PVOID) (ULONG_PTR) EIP(Frame),
  650. 0, 0, 0);
  651. return TRUE;
  652. }
  653. BOOLEAN
  654. KiIA32ExceptionGPFault(
  655. IN PKTRAP_FRAME Frame
  656. )
  657. /*++
  658. Routine Description:
  659. iA-32_Exception(General Protection) - fault
  660. PKTRAP_FRAME Frame
  661. Eip : virtual iA-32 instruction address
  662. ISR.vector : 13
  663. ISR.code : ErrorCode
  664. Note:
  665. Previlidged instructions are intercepted,
  666. see KiIA32InterceptInstruction
  667. Arguments:
  668. Frame - iA32 TrapFrame that was saved in the memory stack
  669. Return Value:
  670. --*/
  671. {
  672. UCHAR OpCode;
  673. NTSTATUS Status;
  674. #if defined(IADBG)
  675. IF_IA32TRAP_DEBUG( GPFAULT )
  676. DbgPrint( "IA32 GpFault: Eip 0x%p\n", EIP(Frame) );
  677. #endif // IADBG
  678. try {
  679. ProbeForReadSmallStructure((VOID *)Frame->StIIP, sizeof(UCHAR), sizeof(UCHAR));
  680. OpCode = *(UCHAR *)Frame->StIIP;
  681. } except (EXCEPTION_EXECUTE_HANDLER) {
  682. OpCode = 0xcc;
  683. }
  684. // This table comes from the IOInstructionTable in i386\trap.asm
  685. switch (OpCode) {
  686. case CLI_OP:
  687. case STI_OP:
  688. case 0xe4: case 0xe5: case 0xec: case 0xed: // IN
  689. case 0x6c: case 0x6d: // INS
  690. case 0xe6: case 0xe7: case 0xee: case 0xef: // OUT
  691. case 0x6e: case 0x6f: // OUTS
  692. Status = STATUS_PRIVILEGED_INSTRUCTION;
  693. break;
  694. default:
  695. Status = STATUS_ACCESS_VIOLATION;
  696. break;
  697. }
  698. KiIA32CommonArgs(Frame,
  699. Status,
  700. (PVOID) (ULONG_PTR) EIP(Frame),
  701. 0, 0, 0);
  702. return TRUE;
  703. }
  704. BOOLEAN
  705. KiIA32ExceptionKNI(
  706. IN PKTRAP_FRAME Frame
  707. )
  708. /*++
  709. iA32_Exception(KNI) - Fault
  710. Unmasked KNI IA32 Error.
  711. ISR.Vector = 19
  712. --*/
  713. {
  714. NTSTATUS ErrorCode;
  715. ULONG FpState;
  716. ULONGLONG FcrRegister, FsrRegister;
  717. #if defined(IADBG)
  718. IF_IA32TRAP_DEBUG( FPFAULT )
  719. DbgPrint( "IA32 KNI Fault: Eip 0x%p\n", EIP(Frame) );
  720. #endif // IADBG
  721. FcrRegister = __getReg(CV_IA64_AR21);
  722. FsrRegister = __getReg(CV_IA64_AR28);
  723. //
  724. // Get the Katmai error state
  725. // The trick here is that the state is in the same registers as the FP
  726. // state and the bit positions are in the same relative location
  727. // so just need to shift the bits and can use the same constants
  728. // that we had for the x87 case
  729. //
  730. FpState = (ULONG) (~((FcrRegister >> KATMAI_SHIFT_CONTROL) & FSW_ERR_MASK) &
  731. ((FsrRegister >> KATMAI_SHIFT_STATUS) & FSW_ERR_MASK));
  732. //
  733. // FpState now has a 1 for any error that was unmasked
  734. //
  735. //
  736. // Follow the x86 priority of which exception to report if
  737. // multiple bits are set
  738. //
  739. if (FpState & FSW_INVALID_OPERATION) {
  740. ErrorCode = STATUS_FLOAT_MULTIPLE_TRAPS;
  741. }
  742. else if (FpState & FSW_ZERO_DIVIDE) {
  743. ErrorCode = STATUS_FLOAT_MULTIPLE_TRAPS;
  744. }
  745. else if (FpState & FSW_DENORMAL) {
  746. ErrorCode = STATUS_FLOAT_MULTIPLE_TRAPS;
  747. }
  748. else if (FpState & FSW_OVERFLOW) {
  749. ErrorCode = STATUS_FLOAT_MULTIPLE_FAULTS;
  750. }
  751. else if (FpState & FSW_UNDERFLOW) {
  752. ErrorCode = STATUS_FLOAT_MULTIPLE_FAULTS;
  753. }
  754. else if (FpState & FSW_PRECISION) {
  755. ErrorCode = STATUS_FLOAT_MULTIPLE_FAULTS;
  756. }
  757. else {
  758. //
  759. // We have a problem... Shouldn't get here
  760. // as that means we took the exception, but no
  761. // unmasked errors were found...
  762. //
  763. ErrorCode = 0;
  764. }
  765. //
  766. // If we get here, we either have the error code, or
  767. // we went through everything and saw nothing
  768. //
  769. if (ErrorCode) {
  770. KiIA32CommonArgs(Frame,
  771. ErrorCode,
  772. (PVOID) (ULONG_PTR) EIP(Frame),
  773. 0, 0, 0);
  774. return TRUE;
  775. }
  776. //
  777. // FpState indicates no error, then something is wrong
  778. // Panic the system !!!
  779. //
  780. KeBugCheckEx(TRAP_CAUSE_UNKNOWN, (ULONG_PTR)Frame, ISRVector(Frame), 0, 3);
  781. }
  782. BOOLEAN
  783. KiIA32ExceptionFPFault(
  784. IN PKTRAP_FRAME Frame
  785. )
  786. /*++
  787. iA32_Exception(Floating Point) - Fault
  788. Handle Coprocessor Error.
  789. ISR.Vector = 16
  790. This exception is used on 486 or above only. For i386, it uses
  791. IRQ 13 instead.
  792. JMPE instruction should flush all FP delayed exception, and the traps
  793. will goto Device Not Available trap
  794. --*/
  795. {
  796. #if defined(IADBG)
  797. IF_IA32TRAP_DEBUG( FPFAULT )
  798. DbgPrint( "IA32 FpFault: Eip 0x%p\n", EIP(Frame) );
  799. #endif // IADBG
  800. return(KiIA32ExceptionNoDevice(Frame));
  801. }
  802. BOOLEAN
  803. KiIA32ExceptionAlignmentFault(
  804. IN PKTRAP_FRAME Frame
  805. )
  806. /*++
  807. iA32_Exception(Alignment Check) - fault
  808. Handle alignment faults.
  809. ISR.Vector = 17
  810. This exception occurs when an unaligned data access is made by a thread
  811. with alignment checking turned on.
  812. This fault occurred when unaligned access on EM PSR.AC is ON
  813. Note that iA32 EFLAFS.AC, CR0.AM and CPL!=3 does not unmask the fault.
  814. So, for now, let the ia64 alignment handler handle this...
  815. --*/
  816. {
  817. PPSR IntPSR;
  818. #if defined(IADBG)
  819. IF_IA32TRAP_DEBUG( ALIGNMENT )
  820. DbgPrint( "IA32 Alignment: Eip 0x%p\n", EIP(Frame) );
  821. #endif // IADBG
  822. //
  823. // Win32 x86 apps don't expect any alignment faults, so
  824. // let's mask them out.
  825. //
  826. IntPSR = (PPSR)&Frame->StIPSR;
  827. IntPSR->sb.psr_ac = 0;
  828. return FALSE;
  829. }
  830. BOOLEAN
  831. KiIA32InterruptVector(
  832. IN PKTRAP_FRAME Frame
  833. )
  834. /*++
  835. iA32_Interrupt(Vector #) - trap
  836. Handle INTnn trap
  837. Under EM system mode, iA32 INT instruction forces a mandatory iA-32
  838. interrupt trap through iA-32 Interrupt(SoftWare Interrupt)
  839. --*/
  840. {
  841. #if defined(IADBG)
  842. IF_IA32TRAP_DEBUG( INTNN )
  843. DbgPrint( "IA32 Intnn: Eip 0x%p INT 0x%x\n", EIP(Frame), ISRVector(Frame));
  844. #endif // IADBG
  845. KiIA32CommonArgs(Frame,
  846. STATUS_PRIVILEGED_INSTRUCTION,
  847. (PVOID) (ULONG_PTR) EIP(Frame),
  848. 0, 0, 0);
  849. return TRUE;
  850. }
  851. BOOLEAN
  852. KiIA32InterceptGate(
  853. IN PKTRAP_FRAME Frame
  854. )
  855. /*++
  856. Routine Description:
  857. iA32_Intercept(Gate) - trap
  858. If an iA32 control transfer is initiated through a GDT or LDT descriptor
  859. that results in an either a promotion of privilege level (interlevel Call
  860. or Jump Gate and IRET) or an iA32 task switch (TSS segment or Gate),
  861. the intercept trap is generated.
  862. Possible instructions intercepted:
  863. CALL, RET, IRET, IRETD and JMP
  864. Handling
  865. No CaLL, RET, JMP, IRET, IRETD are allowed in any mode,
  866. STATUS_ACCESS_VIOLATION is returned
  867. Arguments:
  868. Frame - iA32 TrapFrame that was saved in the memory stack
  869. Return Value:
  870. --*/
  871. {
  872. #if defined(IADBG)
  873. IF_IA32TRAP_DEBUG( GATE )
  874. DbgPrint( "IA32 Gate: Eip 0x%p GateSelector 0x%x OpcodeId 0x%x\n",
  875. EIP(Frame),
  876. (ULONG) (Frame->StIFA & 0xff),
  877. (ULONG) (ISRCode(Frame) >> 14));
  878. #endif // IADBG
  879. //
  880. // all error fall through here
  881. //
  882. KiIA32CommonArgs(Frame,
  883. STATUS_ILLEGAL_INSTRUCTION,
  884. (PVOID) (ULONG_PTR) EIP(Frame),
  885. 0, 0, 0);
  886. return TRUE;
  887. }
  888. /*++
  889. iA32_intercept(System Flag) - trap
  890. Possible Causes:
  891. 1. if CFLAG.ii==1 and EFLAG.if changes state
  892. 2. Generated after either EFLAG.ac, tf or rf changes state
  893. if no IOPL or CPL to modify bits then no interception.
  894. 3. if CFLG.nm==1 then successful execution of IRET also intercepted
  895. Possible instructions:
  896. CLI, POPF, POFD, STI and IRET
  897. Currently, we set both CFLAG.ii and nm to 0, so that we will only possiblly
  898. get case #2. But in EM/NT, it should always come from user land which
  899. we hard-set EFLAG.IOPL to 0, so there if we do get case #2, then it is user
  900. play around EFLAG.IOPL through JMPE. We should fail it.
  901. --*/
  902. BOOLEAN
  903. KiIA32InterceptSystemFlag(
  904. IN PKTRAP_FRAME Frame
  905. )
  906. {
  907. BOOLEAN TrapFrameModified;
  908. BOOLEAN RestoreIrql;
  909. KIRQL OldIrql;
  910. NTSTATUS NtStatus;
  911. #if defined(IADBG)
  912. IF_IA32TRAP_DEBUG( FLAG )
  913. DbgPrint( "IA32 FLAG: Eip 0x%p Old EFlag: 0x%x OpcodeId 0x%x\n",
  914. EIP(Frame),
  915. (ULONG) (Frame->StIIM & 0xff),
  916. (ULONG) (ISRCode(Frame) >> 14));
  917. #endif // IADBG
  918. //
  919. // Don't trap on POPF/POPFD instructions from ia32 code.
  920. // Allow Eflags.TF and/or Eflags.AC to be changed.
  921. //
  922. if ((ISRCode(Frame) >> 14) == 2)
  923. {
  924. return FALSE;
  925. }
  926. TrapFrameModified = KiIsTrapFrameModifiedAtApcLevel (Frame,
  927. &RestoreIrql,
  928. &OldIrql);
  929. //
  930. // If the frame has been modified, then restart execution.
  931. //
  932. if (TrapFrameModified == TRUE) {
  933. NtStatus = STATUS_SUCCESS;
  934. } else {
  935. //
  936. // Validate the instruction.
  937. //
  938. NtStatus = KiIa32ValidateInstruction (Frame);
  939. }
  940. if (RestoreIrql == TRUE) {
  941. KeLowerIrql (OldIrql);
  942. }
  943. if (NT_SUCCESS (NtStatus))
  944. {
  945. return FALSE;
  946. }
  947. KiIA32CommonArgs(
  948. Frame,
  949. NtStatus,
  950. (PVOID) (ULONG_PTR) EIP(Frame),
  951. 0, 0, 0);
  952. return TRUE;
  953. }
  954. BOOLEAN
  955. KiIA32InterceptLock(
  956. IN PKTRAP_FRAME Frame
  957. )
  958. /*++
  959. Routine Description:
  960. iA32_Intercept(Lock) - trap
  961. Lock intercepts occurred if platform or firmware code has disabled locked
  962. transactions and atomic memory update requires a processor external
  963. indication
  964. Arguments:
  965. Frame - Point to iA32 TrapFrame
  966. Return:
  967. --*/
  968. {
  969. BOOLEAN TrapFrameModified;
  970. BOOLEAN RestoreIrql;
  971. KIRQL OldIrql;
  972. NTSTATUS NtStatus;
  973. #if defined(IADBG)
  974. IF_IA32TRAP_DEBUG( LOCK )
  975. DbgPrint( "IA32 LOCK: Eip 0x%p\n", EIP(Frame) );
  976. #endif // IADBG
  977. TrapFrameModified = KiIsTrapFrameModifiedAtApcLevel (Frame,
  978. &RestoreIrql,
  979. &OldIrql);
  980. //
  981. // If the frame has been modified, then restart execution.
  982. //
  983. if (TrapFrameModified == TRUE) {
  984. NtStatus = STATUS_SUCCESS;
  985. } else {
  986. //
  987. // Emulate the lock prefix
  988. //
  989. NtStatus = KiIa32InterceptUnalignedLock (Frame);
  990. }
  991. if (RestoreIrql == TRUE) {
  992. KeLowerIrql (OldIrql);
  993. }
  994. if (!NT_SUCCESS (NtStatus)) {
  995. KiIA32CommonArgs(
  996. Frame,
  997. NtStatus,
  998. (PVOID) (ULONG_PTR) EIP(Frame),
  999. 0,
  1000. 0,
  1001. 0
  1002. );
  1003. }
  1004. return (!NT_SUCCESS (NtStatus)) ? TRUE : FALSE;
  1005. }
  1006. BOOLEAN
  1007. KiIA32ExceptionPanic(
  1008. IN PKTRAP_FRAME Frame
  1009. )
  1010. {
  1011. //
  1012. // Panic the system
  1013. //
  1014. KeBugCheckEx(TRAP_CAUSE_UNKNOWN,
  1015. (ULONG_PTR)Frame,
  1016. ISRVector(Frame),
  1017. 0,
  1018. 0);
  1019. }
  1020. CONST BOOLEAN (*KiIA32ExceptionDispatchTable[])(PKTRAP_FRAME) = {
  1021. KiIA32ExceptionDivide,
  1022. KiIA32ExceptionDebug,
  1023. KiIA32ExceptionPanic,
  1024. KiIA32ExceptionBreak,
  1025. KiIA32ExceptionOverflow,
  1026. KiIA32ExceptionBound,
  1027. KiIA32ExceptionInvalidOp,
  1028. KiIA32ExceptionNoDevice,
  1029. KiIA32ExceptionPanic,
  1030. KiIA32ExceptionPanic,
  1031. KiIA32ExceptionPanic,
  1032. KiIA32ExceptionSegmentNotPresent,
  1033. KiIA32ExceptionStack,
  1034. KiIA32ExceptionGPFault,
  1035. KiIA32ExceptionPanic,
  1036. KiIA32ExceptionPanic,
  1037. KiIA32ExceptionFPFault,
  1038. KiIA32ExceptionAlignmentFault,
  1039. KiIA32ExceptionPanic,
  1040. KiIA32ExceptionKNI
  1041. };
  1042. CONST BOOLEAN (*KiIA32InterceptionDispatchTable[])(PKTRAP_FRAME) = {
  1043. KiIA32InterceptInstruction,
  1044. KiIA32InterceptGate,
  1045. KiIA32InterceptSystemFlag,
  1046. KiIA32ExceptionPanic,
  1047. KiIA32InterceptLock
  1048. };
  1049. #pragma warning(disable:4702) // unreachable code
  1050. BOOLEAN
  1051. KiIA32InterceptionVectorHandler(
  1052. IN PKTRAP_FRAME Frame
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. KiIA32InterceptionVectorHandler
  1057. Called by first label KiIA32InterceptionVector() to handle further iA32
  1058. interception processing.
  1059. Arguments:
  1060. Frame - iA32 TrapFrame that was saved in the memory stack
  1061. Return Value:
  1062. TRUE - go to dispatch exception
  1063. FALSE - Exception was handled, do an RFI
  1064. --*/
  1065. {
  1066. #if defined(IADBG)
  1067. IF_IA32TRAP_DEBUG( INTERCEPTION )
  1068. DbgPrint("IA32 Interception: ISRVector 0x%x Frame 0x%p\n", ISRVector(Frame), Frame);
  1069. #endif // IADBG
  1070. ASSERT(UserMode == Frame->PreviousMode);
  1071. //
  1072. // Make sure we have an entry in the table for this interception
  1073. //
  1074. if (ISRVector(Frame) <= (sizeof(KiIA32InterceptionDispatchTable) / sizeof(PVOID)))
  1075. return (*KiIA32InterceptionDispatchTable[ISRVector(Frame)])(Frame);
  1076. else
  1077. return (KiIA32ExceptionPanic(Frame));
  1078. }
  1079. #pragma warning(default:4702)
  1080. #pragma warning(disable:4702) // unreachable code
  1081. BOOLEAN
  1082. KiIA32ExceptionVectorHandler(
  1083. IN PKTRAP_FRAME Frame
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. KiIA32ExceptionVectorHandler
  1088. Called by first label KiIA32ExceptionVector() to handle further iA32
  1089. interception processing.
  1090. Arguments:
  1091. Frame - iA32 TrapFrame that was saved in the memory stack
  1092. Return Value:
  1093. TRUE - go to dispatch exception
  1094. FALSE - Exception was handled, do an RFI
  1095. --*/
  1096. {
  1097. #if defined(IADBG)
  1098. IF_IA32TRAP_DEBUG( EXCEPTION )
  1099. DbgPrint("IA32 Exception: ISRVector 0x%x Frame 0x%p\n", ISRVector(Frame), Frame);
  1100. #endif // IADBG
  1101. ASSERT(UserMode == Frame->PreviousMode);
  1102. //
  1103. // Make sure we have an entry in the table for this exception
  1104. //
  1105. if (ISRVector(Frame) <= (sizeof(KiIA32ExceptionDispatchTable) / sizeof(PVOID)))
  1106. return (*KiIA32ExceptionDispatchTable[ISRVector(Frame)])(Frame);
  1107. else
  1108. return(KiIA32ExceptionPanic(Frame));
  1109. }
  1110. #pragma warning(default:4702)
  1111. BOOLEAN
  1112. KiIA32InterruptionVectorHandler(
  1113. IN PKTRAP_FRAME Frame
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. KiIA32InterruptionVectorHandler
  1118. Called by first label KiIA32InterruptionVector() to handle further iA32
  1119. interruption processing. Only get here on INT xx instructions
  1120. Arguments:
  1121. Frame - iA32 TrapFrame that was saved in the memory stack
  1122. Return Value:
  1123. TRUE - go to dispatch exception
  1124. FALSE - Exception was handled, do an RFI
  1125. --*/
  1126. {
  1127. #if defined(IADBG)
  1128. IF_IA32TRAP_DEBUG( INTERRUPT )
  1129. DbgPrint("IA32 Interruption: ISRVector 0x%x Frame 0x%p\n", ISRVector(Frame), Frame);
  1130. #endif // IADBG
  1131. ASSERT(UserMode == Frame->PreviousMode);
  1132. //
  1133. // Follow the ia32 way of INT xx as an Access Violation
  1134. //
  1135. // INT 3 should be handled via a debug exception and should
  1136. // never get here...
  1137. //
  1138. ASSERT(3 != ISRVector(Frame));
  1139. KiIA32CommonArgs(Frame,
  1140. STATUS_ACCESS_VIOLATION,
  1141. (PVOID) (ULONG_PTR) EIP(Frame),
  1142. 0, 0, 0);
  1143. return TRUE;
  1144. }