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.

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