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.

6774 lines
209 KiB

  1. title "Trap Processing"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989-2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; trap.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to field and process i386
  13. ; trap conditions.
  14. ;
  15. ; Author:
  16. ;
  17. ; Shie-Lin Tzong (shielint) 4-Feb-1990
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Revision History:
  24. ;
  25. ;--
  26. .586p
  27. .xlist
  28. KERNELONLY equ 1
  29. include ks386.inc
  30. include callconv.inc ; calling convention macros
  31. include i386\kimacro.inc
  32. include mac386.inc
  33. include i386\mi.inc
  34. include ..\..\vdm\i386\vdm.inc
  35. include vdmtib.inc
  36. include fastsys.inc
  37. include irqli386.inc
  38. .list
  39. FAST_BOP equ 1
  40. page ,132
  41. extrn _KeI386FxsrPresent:BYTE
  42. extrn ExpInterlockedPopEntrySListFault:DWORD
  43. extrn ExpInterlockedPopEntrySListResume:DWORD
  44. extrn _KeGdiFlushUserBatch:DWORD
  45. extrn _KeTickCount:DWORD
  46. extrn _ExpTickCountMultiplier:DWORD
  47. extrn _KiDoubleFaultTSS:dword
  48. extrn _KeErrorMask:dword
  49. extrn _KiNMITSS:dword
  50. extrn _KeServiceDescriptorTable:dword
  51. if DBG
  52. extrn _MmInjectUserInpageErrors:dword
  53. EXTRNP _MmTrimProcessMemory,1
  54. endif
  55. extrn _KiHardwareTrigger:dword
  56. extrn _KiBugCheckData:dword
  57. extrn _KdpOweBreakpoint:byte
  58. extrn Ki386BiosCallReturnAddress:near
  59. extrn _PoHiberInProgress:byte
  60. extrn _KiI386PentiumLockErrataPresent:BYTE
  61. EXTRNP _KiDeliverApc,3
  62. EXTRNP _PsConvertToGuiThread,0
  63. EXTRNP _ZwUnmapViewOfSection,2
  64. EXTRNP _KiHandleNmi,0
  65. EXTRNP _HalHandleNMI,1,IMPORT
  66. EXTRNP _HalBeginSystemInterrupt,3,IMPORT
  67. EXTRNP _HalEndSystemInterrupt,2,IMPORT
  68. EXTRNP _KiDispatchException,5
  69. EXTRNP _PsWatchWorkingSet,3
  70. extrn _PsWatchEnabled:byte
  71. EXTRNP _MmAccessFault,4
  72. extrn _MmUserProbeAddress:DWORD
  73. EXTRNP _KeBugCheck,1
  74. EXTRNP _KeBugCheckEx,5
  75. EXTRNP _KeTestAlertThread,1
  76. EXTRNP _KiContinue,3
  77. EXTRNP _KiRaiseException,5
  78. EXTRNP _VdmDispatchOpcodeV86_try,1
  79. EXTRNP _VdmDispatchOpcode_try,1
  80. EXTRNP _VdmDispatchPageFault,3
  81. EXTRNP _Ki386VdmReflectException,1
  82. EXTRNP _Ki386VdmSegmentNotPresent,0
  83. extrn _DbgPrint:proc
  84. EXTRNP _KdSetOwedBreakpoints
  85. extrn _KiFreezeFlag:dword
  86. EXTRNP _Ki386CheckDivideByZeroTrap,1
  87. EXTRNP _Ki386CheckDelayedNpxTrap,2
  88. EXTRNP _VdmDispatchIRQ13, 1
  89. EXTRNP _VdmDispatchBop,1
  90. EXTRNP _VdmFetchBop1,1
  91. EXTRNP _VdmFetchBop4,1
  92. EXTRNP _VdmTibPass1,3
  93. extrn _KeI386VirtualIntExtensions:dword
  94. EXTRNP _NTFastDOSIO,2
  95. EXTRNP _NtSetLdtEntries,6
  96. extrn OpcodeIndex:byte
  97. extrn _KeFeatureBits:DWORD
  98. extrn _KeServiceDescriptorTableShadow:dword
  99. extrn _KiIgnoreUnexpectedTrap07:byte
  100. ifndef NT_UP
  101. EXTRNP KiAcquireQueuedSpinLockCheckForFreeze,2,,FASTCALL
  102. EXTRNP KeReleaseQueuedSpinLockFromDpcLevel,1,,FASTCALL
  103. endif
  104. ifdef _CAPKERN
  105. extrn __CAP_SetCPU@0:PROC
  106. extrn __CAP_ThreadID@0:PROC
  107. endif
  108. ;
  109. ; Equates for exceptions which cause system fatal error
  110. ;
  111. EXCEPTION_DIVIDED_BY_ZERO EQU 0
  112. EXCEPTION_DEBUG EQU 1
  113. EXCEPTION_NMI EQU 2
  114. EXCEPTION_INT3 EQU 3
  115. EXCEPTION_BOUND_CHECK EQU 5
  116. EXCEPTION_INVALID_OPCODE EQU 6
  117. EXCEPTION_NPX_NOT_AVAILABLE EQU 7
  118. EXCEPTION_DOUBLE_FAULT EQU 8
  119. EXCEPTION_NPX_OVERRUN EQU 9
  120. EXCEPTION_INVALID_TSS EQU 0AH
  121. EXCEPTION_SEGMENT_NOT_PRESENT EQU 0BH
  122. EXCEPTION_STACK_FAULT EQU 0CH
  123. EXCEPTION_GP_FAULT EQU 0DH
  124. EXCEPTION_RESERVED_TRAP EQU 0FH
  125. EXCEPTION_NPX_ERROR EQU 010H
  126. EXCEPTION_ALIGNMENT_CHECK EQU 011H
  127. ;
  128. ; Exception flags
  129. ;
  130. EXCEPT_UNKNOWN_ACCESS EQU 0H
  131. EXCEPT_LIMIT_ACCESS EQU 10H
  132. ;
  133. ; Equates for some opcodes and instruction prefixes
  134. ;
  135. IOPL_MASK EQU 3000H
  136. IOPL_SHIFT_COUNT EQU 12
  137. ;
  138. ; Debug register 6 (dr6) BS (single step) bit mask
  139. ;
  140. DR6_BS_MASK EQU 4000H
  141. ;
  142. ; EFLAGS overflow bit
  143. ;
  144. EFLAGS_OF_BIT EQU 4000H
  145. ;
  146. ; The mask of selecot's table indicator (ldt or gdt)
  147. ;
  148. TABLE_INDICATOR_MASK EQU 4
  149. ;
  150. ; Opcode for Pop SegReg and iret instructions
  151. ;
  152. POP_DS EQU 1FH
  153. POP_ES EQU 07h
  154. POP_FS EQU 0A10FH
  155. POP_GS EQU 0A90FH
  156. IRET_OP EQU 0CFH
  157. CLI_OP EQU 0FAH
  158. STI_OP EQU 0FBH
  159. PUSHF_OP EQU 9CH
  160. POPF_OP EQU 9DH
  161. INTNN_OP EQU 0CDH
  162. FRSTOR_ECX EQU 021DD9Bh
  163. FWAIT_OP EQU 09bh
  164. ;
  165. ; Force assume into place
  166. ;
  167. _TEXT$00 SEGMENT PARA PUBLIC 'CODE'
  168. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  169. _TEXT$00 ENDS
  170. _DATA SEGMENT DWORD PUBLIC 'DATA'
  171. ;
  172. ; Definitions for gate descriptors
  173. ;
  174. GATE_TYPE_386INT EQU 0E00H
  175. GATE_TYPE_386TRAP EQU 0F00H
  176. GATE_TYPE_TASK EQU 0500H
  177. D_GATE EQU 0
  178. D_PRESENT EQU 8000H
  179. D_DPL_3 EQU 6000H
  180. D_DPL_0 EQU 0
  181. ;
  182. ; Definitions for present x86 trap and interrupt gate attributes
  183. ;
  184. D_TRAP032 EQU D_PRESENT+D_DPL_0+D_GATE+GATE_TYPE_386TRAP
  185. D_TRAP332 EQU D_PRESENT+D_DPL_3+D_GATE+GATE_TYPE_386TRAP
  186. D_INT032 EQU D_PRESENT+D_DPL_0+D_GATE+GATE_TYPE_386INT
  187. D_INT332 EQU D_PRESENT+D_DPL_3+D_GATE+GATE_TYPE_386INT
  188. D_TASK EQU D_PRESENT+D_DPL_0+D_GATE+GATE_TYPE_TASK
  189. ;
  190. ; This is the protected mode interrupt descriptor table.
  191. ;
  192. if DBG
  193. ;
  194. ; NOTE - embedded enlish messages won't fly for NLS! (OK for debug code only)
  195. ;
  196. BadInterruptMessage db 0ah,7,7,'!!! Unexpected Interrupt %02lx !!!',0ah,00
  197. Ki16BitStackTrapMessage db 0ah,'Exception inside of 16bit stack',0ah,00
  198. public KiBiosReenteredAssert
  199. KiBiosReenteredAssert db 0ah,'Bios has been re-entered. Not safe. ',0ah,00
  200. endif
  201. ;
  202. ; NMI only one processor at a time. This is handled in the kernel
  203. ; using a queued spinlock to avoid thrashing the lock in case a
  204. ; crash dump is underway.
  205. ;
  206. KiLockNMI dd 0
  207. ;++
  208. ;
  209. ; DEFINE_SINGLE_EMPTY_VECTOR - helper for DEFINE_EMPTY_VECTORS
  210. ;
  211. ;--
  212. DEFINE_SINGLE_EMPTY_VECTOR macro number
  213. IDTEntry _KiUnexpectedInterrupt&number, D_INT032
  214. _TEXT$00 SEGMENT
  215. public _KiUnexpectedInterrupt&number
  216. _KiUnexpectedInterrupt&number proc
  217. push dword ptr (&number + PRIMARY_VECTOR_BASE)
  218. ;; jmp _KiUnexpectedInterruptTail ; replaced with following jmp which will then jump
  219. jmp _KiAfterUnexpectedRange ; to the _KiUnexpectedInterruptTail location
  220. ; in a manner suitable for BBT, which needs to treat
  221. ; this whole set of KiUnexpectedInterrupt&number
  222. ; vectors as DATA, meaning a relative jmp will not
  223. ; be adjusted properly in the BBT Instrumented or
  224. ; Optimized code.
  225. ;
  226. _KiUnexpectedInterrupt&number endp
  227. _TEXT$00 ENDS
  228. endm
  229. FPOFRAME macro a, b
  230. .FPO ( a, b, 0, 0, 0, FPO_TRAPFRAME )
  231. endm
  232. FXSAVE_ESI macro
  233. db 0FH, 0AEH, 06
  234. endm
  235. FXSAVE_ECX macro
  236. db 0FH, 0AEH, 01
  237. endm
  238. FXRSTOR_ECX macro
  239. db 0FH, 0AEH, 09
  240. endm
  241. ;++
  242. ;
  243. ; DEFINE_EMPTY_VECTORS emits an IDTEntry macro (and thus and IDT entry)
  244. ; into the data segment. It then emits an unexpected interrupt target
  245. ; with push of a constant into the code segment. Labels in the code
  246. ; segment are defined to bracket the unexpected interrupt targets so
  247. ; that KeConnectInterrupt can correctly test for them.
  248. ;
  249. ; Empty vectors will be defined from 30 to ff, which is the hardware
  250. ; vector set.
  251. ;
  252. ;--
  253. NUMBER_OF_IDT_VECTOR EQU 0ffH
  254. DEFINE_EMPTY_VECTORS macro
  255. ;
  256. ; Set up
  257. ;
  258. empty_vector = 00H
  259. _TEXT$00 SEGMENT
  260. public _KiStartUnexpectedRange@0
  261. _KiStartUnexpectedRange@0 equ $
  262. _TEXT$00 ENDS
  263. rept (NUMBER_OF_IDT_VECTOR - (($ - _IDT)/8)) + 1
  264. DEFINE_SINGLE_EMPTY_VECTOR %empty_vector
  265. empty_vector = empty_vector + 1
  266. endm ;; rept
  267. _TEXT$00 SEGMENT
  268. public _KiEndUnexpectedRange@0
  269. _KiEndUnexpectedRange@0 equ $
  270. ;; added by to handle BBT unexpected interrupt problem
  271. ;;
  272. _KiAfterUnexpectedRange equ $ ;; BBT
  273. jmp [KiUnexpectedInterruptTail] ;; BBT
  274. KiUnexpectedInterruptTail dd offset _KiUnexpectedInterruptTail ;; BBT
  275. public _KiBBTUnexpectedRange
  276. _KiBBTUnexpectedRange equ $ ;; BBT
  277. _TEXT$00 ENDS
  278. endm ;; DEFINE_EMPTY_VECTORS macro
  279. IDTEntry macro name,access
  280. dd offset FLAT:name
  281. dw access
  282. dw KGDT_R0_CODE
  283. endm
  284. INIT SEGMENT DWORD PUBLIC 'CODE'
  285. ;
  286. ; The IDT table is put into the INIT code segment so the memory
  287. ; can be reclaimed afer bootup
  288. ;
  289. ALIGN 4
  290. public _IDT, _IDTLEN, _IDTEnd
  291. _IDT label byte
  292. IDTEntry _KiTrap00, D_INT032 ; 0: Divide Error
  293. IDTEntry _KiTrap01, D_INT032 ; 1: DEBUG TRAP
  294. IDTEntry _KiTrap02, D_INT032 ; 2: NMI/NPX Error
  295. IDTEntry _KiTrap03, D_INT332 ; 3: Breakpoint
  296. IDTEntry _KiTrap04, D_INT332 ; 4: INTO
  297. IDTEntry _KiTrap05, D_INT032 ; 5: BOUND/Print Screen
  298. IDTEntry _KiTrap06, D_INT032 ; 6: Invalid Opcode
  299. IDTEntry _KiTrap07, D_INT032 ; 7: NPX Not Available
  300. IDTEntry _KiTrap08, D_INT032 ; 8: Double Exception
  301. IDTEntry _KiTrap09, D_INT032 ; 9: NPX Segment Overrun
  302. IDTEntry _KiTrap0A, D_INT032 ; A: Invalid TSS
  303. IDTEntry _KiTrap0B, D_INT032 ; B: Segment Not Present
  304. IDTEntry _KiTrap0C, D_INT032 ; C: Stack Fault
  305. IDTEntry _KiTrap0D, D_INT032 ; D: General Protection
  306. IDTEntry _KiTrap0E, D_INT032 ; E: Page Fault
  307. IDTEntry _KiTrap0F, D_INT032 ; F: Intel Reserved
  308. IDTEntry _KiTrap10, D_INT032 ;10: 486 coprocessor error
  309. IDTEntry _KiTrap11, D_INT032 ;11: 486 alignment
  310. IDTEntry _KiTrap0F, D_INT032 ;12: Intel Reserved
  311. IDTEntry _KiTrap0F, D_INT032 ;13: XMMI unmasked numeric exception
  312. IDTEntry _KiTrap0F, D_INT032 ;14: Intel Reserved
  313. IDTEntry _KiTrap0F, D_INT032 ;15: Intel Reserved
  314. IDTEntry _KiTrap0F, D_INT032 ;16: Intel Reserved
  315. IDTEntry _KiTrap0F, D_INT032 ;17: Intel Reserved
  316. IDTEntry _KiTrap0F, D_INT032 ;18: Intel Reserved
  317. IDTEntry _KiTrap0F, D_INT032 ;19: Intel Reserved
  318. IDTEntry _KiTrap0F, D_INT032 ;1A: Intel Reserved
  319. IDTEntry _KiTrap0F, D_INT032 ;1B: Intel Reserved
  320. IDTEntry _KiTrap0F, D_INT032 ;1C: Intel Reserved
  321. IDTEntry _KiTrap0F, D_INT032 ;1D: Intel Reserved
  322. IDTEntry _KiTrap0F, D_INT032 ;1E: Intel Reserved
  323. IDTEntry _KiTrap0F, D_INT032 ;1F: Reserved for APIC
  324. ;
  325. ; Note IDTEntry 0x21 is reserved for WOW apps.
  326. ;
  327. rept 2AH - (($ - _IDT)/8)
  328. IDTEntry 0, 0 ;invalid IDT entry
  329. endm
  330. IDTEntry _KiGetTickCount, D_INT332 ;2A: KiGetTickCount service
  331. IDTEntry _KiCallbackReturn, D_INT332 ;2B: KiCallbackReturn
  332. IDTEntry _KiSetLowWaitHighThread, D_INT332 ;2C: KiSetLowWaitHighThread service
  333. IDTEntry _KiDebugService, D_INT332 ;2D: debugger calls
  334. IDTEntry _KiSystemService, D_INT332 ;2E: system service calls
  335. IDTEntry _KiTrap0F, D_INT032 ;2F: Reserved for APIC
  336. ;
  337. ; Generate per-vector unexpected interrupt entries for 30 - ff
  338. ;
  339. DEFINE_EMPTY_VECTORS
  340. _IDTLEN equ $ - _IDT
  341. _IDTEnd equ $
  342. INIT ends
  343. public _KiUnexpectedEntrySize
  344. _KiUnexpectedEntrySize dd _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
  345. ;
  346. ; defines all the possible instruction prefix
  347. ;
  348. PrefixTable label byte
  349. db 0f2h ; rep prefix
  350. db 0f3h ; rep ins/outs prefix
  351. db 67h ; addr prefix
  352. db 0f0h ; lock prefix
  353. db 66h ; operand prefix
  354. db 2eh ; segment override prefix:cs
  355. db 3eh ; ds
  356. db 26h ; es
  357. db 64h ; fs
  358. db 65h ; gs
  359. db 36h ; ss
  360. PREFIX_REPEAT_COUNT EQU 11 ; Prefix table length
  361. ;
  362. ; defines all the possible IO privileged IO instructions
  363. ;
  364. IOInstructionTable label byte
  365. ; db 0fah ; cli
  366. ; db 0fdh ; sti
  367. db 0e4h, 0e5h, 0ech, 0edh ; IN
  368. db 6ch, 6dh ; INS
  369. db 0e6h, 0e7h, 0eeh, 0efh ; OUT
  370. db 6eh, 6fh ; OUTS
  371. IO_INSTRUCTION_TABLE_LENGTH EQU 12
  372. ;
  373. ; definition for floating status word error mask
  374. ;
  375. FSW_INVALID_OPERATION EQU 1
  376. FSW_DENORMAL EQU 2
  377. FSW_ZERO_DIVIDE EQU 4
  378. FSW_OVERFLOW EQU 8
  379. FSW_UNDERFLOW EQU 16
  380. FSW_PRECISION EQU 32
  381. FSW_STACK_FAULT EQU 64
  382. FSW_CONDITION_CODE_0 EQU 100H
  383. FSW_CONDITION_CODE_1 EQU 200H
  384. FSW_CONDITION_CODE_2 EQU 400H
  385. FSW_CONDITION_CODE_3 EQU 4000H
  386. _DATA ENDS
  387. _TEXT$00 SEGMENT
  388. ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  389. page , 132
  390. subttl "Macro to Handle v86 trap d"
  391. ;++
  392. ;
  393. ; Macro Description:
  394. ;
  395. ; This macro is a fast way to handle v86 bop instructions.
  396. ; Note, all the memory write operations in this macro are done in such a
  397. ; way that if a page fault occurs the memory will still be in a consistent
  398. ; state.
  399. ;
  400. ; That is, we must process the trapped instruction in the following order:
  401. ;
  402. ; 1. Read and Write user memory
  403. ; 2. Update VDM state flags
  404. ; 3. Update trap frame
  405. ;
  406. ; Arguments:
  407. ;
  408. ; interrupts disabled
  409. ;
  410. ; Return Value:
  411. ;
  412. ;--
  413. FAST_V86_TRAP_6 MACRO
  414. local DoFastIo, a, b
  415. BOP_FOR_FASTWRITE EQU 4350C4C4H
  416. BOP_FOR_FASTREAD EQU 4250C4C4H
  417. TRAP6_IP EQU 32 ; 8 * 4
  418. TRAP6_CS EQU 36 ; 8 * 4 + 4
  419. TRAP6_FLAGS EQU 40 ; 8 * 4 + 8
  420. TRAP6_SP EQU 44 ; 8 * 4 + 12
  421. TRAP6_SS EQU 48 ; 8 * 4 + 16
  422. TRAP6_ES EQU 52
  423. TRAP6_DS EQU 56
  424. TRAP6_FS EQU 60
  425. TRAP6_GS EQU 64
  426. TRAP6_EAX EQU 28
  427. TRAP6_EDX EQU 20
  428. pushad ;eax, ecx, edx, ebx, old esp, ebp, esi, edi
  429. mov eax, KGDT_R3_DATA OR RPL_MASK
  430. mov ds, ax
  431. mov es, ax
  432. ifndef NT_UP
  433. mov eax, KGDT_R0_PCR
  434. mov fs, ax
  435. endif
  436. mov ax, word ptr [esp+TRAP6_CS] ; [eax] = v86 user cs
  437. shl eax, 4
  438. and dword ptr [esp+TRAP6_IP], 0FFFFH
  439. add eax, [esp+TRAP6_IP]; [eax] = addr of BOP
  440. ;
  441. ; Set the magic PCR bit indicating we are executing VDM management code
  442. ; so faults on potentially invalid or plain bad user addresses do
  443. ; not bugcheck the system. Note both interrupts are disabled and
  444. ; (for performance reasons) we do not have any exception handlers
  445. ; set up.
  446. ;
  447. mov dword ptr PCR[PcVdmAlert], offset FLAT:V86Trap6Recovery
  448. ;
  449. ; Fetch the actual opcode from user space.
  450. ;
  451. mov edx, [eax] ; [edx] = xxxxc4c4 bop + maj bop # + mi #
  452. cmp edx, BOP_FOR_FASTREAD
  453. je DoFastIo
  454. cmp edx, BOP_FOR_FASTWRITE
  455. je DoFastIo
  456. cmp dx, 0c4c4h ; Is it a bop?
  457. jne V86Trap6PassThrough ; It's an error condition
  458. mov eax,PCR[PcTeb]
  459. shr edx, 16
  460. mov eax,[eax].TeVdm
  461. cmp eax, _MmUserProbeAddress ; check if user address
  462. jae V86Trap6PassThrough ; if ae, then not user address
  463. and edx, 0ffh
  464. mov dword ptr [eax].VtEIEvent, VdmBop
  465. mov dword ptr [eax].VtEIBopNumber, edx
  466. mov dword ptr [eax].VtEIInstSize, 3
  467. lea eax, [eax].VtVdmContext
  468. ;
  469. ; Save V86 state to Vdm structure
  470. ;
  471. mov edx, [esp+TRAP6_EDX] ; get edx
  472. cmp eax, _MmUserProbeAddress ; check if user address
  473. jae V86Trap6PassThrough ; if ae, then not user address
  474. mov [eax].CsEcx, ecx
  475. mov [eax].CsEbx, ebx ; Save non-volatile registers
  476. mov [eax].CsEsi, esi
  477. mov [eax].CsEdi, edi
  478. mov ecx, [esp+TRAP6_EAX] ; Get eax
  479. mov [eax].CsEbp, ebp
  480. mov [eax].CsEdx, edx
  481. mov [eax].CsEax, ecx
  482. mov ebx, [esp]+TRAP6_IP ; (ebx) = user ip
  483. mov ecx, [esp]+TRAP6_CS ; (ecx) = user cs
  484. mov esi, [esp]+TRAP6_SP ; (esi) = user esp
  485. mov edi, [esp]+TRAP6_SS ; (edi) = user ss
  486. mov edx, [esp]+TRAP6_FLAGS; (edx) = user eflags
  487. mov [eax].CsEip, ebx
  488. and esi, 0ffffh
  489. mov [eax].CsSegCs, ecx
  490. mov [eax].CsEsp, esi
  491. mov [eax].CsSegSs, edi
  492. test _KeI386VirtualIntExtensions, V86_VIRTUAL_INT_EXTENSIONS
  493. jz short @f
  494. test edx, EFLAGS_VIF
  495. jnz short a
  496. and edx, NOT EFLAGS_INTERRUPT_MASK
  497. jmp short a
  498. @@: test ds:FIXED_NTVDMSTATE_LINEAR, VDM_VIRTUAL_INTERRUPTS ; check interrupt
  499. jnz short a
  500. and edx, NOT EFLAGS_INTERRUPT_MASK
  501. a:
  502. mov [eax].CsEFlags, edx
  503. mov ebx, [esp]+TRAP6_DS ; (ebx) = user ds
  504. mov ecx, [esp]+TRAP6_ES ; (ecx) = user es
  505. mov edx, [esp]+TRAP6_FS ; (edx) = user fs
  506. mov esi, [esp]+TRAP6_GS ; (esi) = user gs
  507. mov [eax].CsSegDs, ebx
  508. mov [eax].CsSegEs, ecx
  509. mov [eax].CsSegFs, edx
  510. mov [eax].CsSegGs, esi
  511. ;
  512. ; Load Monitor context
  513. ;
  514. add eax, VtMonitorContext - VtVdmContext ; (eax)->monitor context
  515. mov ebx, [eax].CsEbx ; We don't need to load volatile registers.
  516. mov esi, [eax].CsEsi ; because monitor uses SystemCall to return
  517. mov edi, [eax].CsEdi ; back to v86. C compiler knows that
  518. mov ebp, [eax].CsEbp ; SystemCall does not preserve volatile
  519. ; registers.
  520. ; es, ds are set up already.
  521. ;
  522. ; Note these push instructions won't fail. Do NOT combine the
  523. ; 'move ebx, [eax].CsEbx' with 'push ebx' to 'push [eax].CsEbx'
  524. ;
  525. push ebx ; note, these push instructions won't fail
  526. push esi
  527. push edi
  528. push ebp
  529. mov dword ptr PCR[PcVdmAlert], offset FLAT:V86Trap6Recovery2
  530. mov ebx, [eax].CsSegSs
  531. mov esi, [eax].CsEsp
  532. mov edi, [eax].CsEFlags
  533. mov edx, [eax].CsSegCs
  534. mov ecx, [eax].CsEip
  535. ;
  536. ; after this point, we don't need to worry about instruction fault
  537. ; Clear magic flag as no more potentially bogus references will be made.
  538. ;
  539. mov dword ptr PCR[PcVdmAlert], 0
  540. and edi, EFLAGS_USER_SANITIZE
  541. or edi, EFLAGS_INTERRUPT_MASK
  542. mov [esp + TRAP6_SS + 16], ebx ; Build Iret frame (can not single step!)
  543. mov [esp + TRAP6_SP + 16], esi
  544. mov [esp + TRAP6_FLAGS + 16], edi
  545. cmp edx, 8
  546. jge @f
  547. test edi, EFLAGS_V86_MASK
  548. jne @f
  549. mov edx, KGDT_R3_CODE OR RPL_MASK
  550. @@: mov [esp + TRAP6_CS + 16], edx
  551. mov [esp + TRAP6_IP + 16], ecx
  552. pop ebp
  553. pop edi
  554. pop esi
  555. pop ebx
  556. add esp, 32
  557. ;
  558. ; Adjust Tss esp0 value and set return value to SUCCESS
  559. ;
  560. mov ecx, PCR[PcPrcbData+PbCurrentThread]
  561. mov ecx, [ecx].thInitialStack
  562. mov edx, PCR[PcTss]
  563. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  564. test byte ptr [esp+8+2],EFLAGS_V86_MASK/010000h ; is this a V86 frame?
  565. jnz short @f
  566. sub ecx, TsV86Gs - TsHardwareSegSs
  567. @@:
  568. sub ecx, NPX_FRAME_LENGTH
  569. xor eax, eax ; ret status = SUCCESS
  570. mov [edx].TssEsp0, ecx
  571. mov edx, KGDT_R3_TEB OR RPL_MASK
  572. mov fs, dx
  573. iretd
  574. DoFastIo:
  575. ;
  576. ; Clear magic flag as no bogus references are going to be made.
  577. ;
  578. mov dword ptr PCR[PcVdmAlert], 0
  579. xor eax, eax
  580. mov edx, [esp]+TRAP6_EDX ; Restore edx
  581. add esp, 7 * 4 ; leave eax in the TsErrCode
  582. xchg [esp], eax ; Restore eax, store a zero errcode
  583. sub esp, TsErrcode ; build a trap frame
  584. mov [esp].TsEbx, ebx
  585. mov [esp].TsEax, eax
  586. mov [esp].TsEbp, ebp
  587. mov [esp].TsEsi, esi
  588. mov [esp].TsEdi, edi
  589. mov [esp].TsEcx, ecx
  590. mov [esp].TsEdx, edx
  591. if DBG
  592. mov [esp].TsPreviousPreviousMode, -1
  593. mov [esp]+TsDbgArgMark, 0BADB0D00h
  594. endif
  595. mov edi, PCR[PcExceptionList]
  596. mov [esp]+TsExceptionList, edi
  597. ifdef NT_UP
  598. mov ebx, KGDT_R0_PCR
  599. mov fs, bx
  600. endif
  601. mov ebx, PCR[PcPrcbData+PbCurrentThread] ; fetch current thread
  602. test [ebx].ThDebugActive, 0ffh ; See if debug registers are active
  603. mov ebp, esp
  604. cld
  605. .errnz (DR7_ACTIVE AND 0FFFFFF00h)
  606. mov [ebp]+TsDr7,0
  607. je short @f
  608. mov ebx,dr0
  609. mov esi,dr1
  610. mov edi,dr2
  611. mov [ebp]+TsDr0,ebx
  612. mov [ebp]+TsDr1,esi
  613. mov [ebp]+TsDr2,edi
  614. mov ebx,dr3
  615. mov esi,dr6
  616. mov edi,dr7
  617. mov [ebp]+TsDr3,ebx
  618. xor ebx, ebx
  619. mov [ebp]+TsDr6,esi
  620. mov [ebp]+TsDr7,edi
  621. mov dr7, ebx ; Clear out control before reloading
  622. ;
  623. ; Load KernelDr* into processor
  624. ;
  625. mov edi,dword ptr PCR[PcPrcb]
  626. mov ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr0
  627. mov esi,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr1
  628. mov dr0,ebx
  629. mov dr1,esi
  630. mov ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr2
  631. mov esi,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr3
  632. mov dr2,ebx
  633. mov dr3,esi
  634. mov ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr6
  635. mov esi,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr7
  636. mov dr6,ebx
  637. mov dr7,esi
  638. @@:
  639. xor edx, edx
  640. mov dx, word ptr [ebp].TsSegCs
  641. shl edx, 4
  642. xor ebx, ebx
  643. add edx, [ebp].TsEip
  644. ;
  645. ; Set the magic PCR bit indicating we are executing VDM management code
  646. ; so faults on potentially invalid or plain bad user addresses do
  647. ; not bugcheck the system. Note both interrupts are disabled and
  648. ; (for performance reasons) we do not have any exception handlers
  649. ; set up.
  650. ;
  651. mov dword ptr PCR[PcVdmAlert], offset FLAT:V86Trap6Recovery1
  652. ;
  653. ; Fetch the actual opcode from user space.
  654. ;
  655. mov bl, [edx+3] ; [bl] = minor BOP code
  656. ;
  657. ; Clear magic flag as no bogus references are going to be made.
  658. ;
  659. mov dword ptr PCR[PcVdmAlert], 0
  660. ;
  661. ; Raise Irql to APC level before enabling interrupts.
  662. ;
  663. RaiseIrql APC_LEVEL
  664. push eax ; Save OldIrql
  665. sti
  666. push ebx
  667. push ebp ; (ebp)->TrapFrame
  668. call _NTFastDOSIO@8
  669. jmp Kt061i
  670. V86Trap6PassThrough:
  671. ;
  672. ; Clear magic flag as no bogus references are going to be made.
  673. ;
  674. mov dword ptr PCR[PcVdmAlert], 0
  675. V86Trap6Recovery:
  676. popad
  677. jmp Kt6SlowBop ; Fall through
  678. V86Trap6Recovery1:
  679. jmp Kt6SlowBop1 ; Fall through
  680. V86Trap6Recovery2:
  681. add esp, 16
  682. popad
  683. jmp Kt6SlowBop ; Fall through
  684. endm
  685. page , 132
  686. subttl "Macro to dispatch user APC"
  687. ;++
  688. ;
  689. ; Macro Description:
  690. ;
  691. ; This macro is called before returning to user mode. It dispatches
  692. ; any pending user mode APCs.
  693. ;
  694. ; Arguments:
  695. ;
  696. ; TFrame - TrapFrame
  697. ; interrupts disabled
  698. ;
  699. ; Return Value:
  700. ;
  701. ;--
  702. DISPATCH_USER_APC macro TFrame, ReturnCurrentEax
  703. local a, b, c
  704. c:
  705. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  706. test byte ptr [TFrame]+TsEflags+2, EFLAGS_V86_MASK/010000h ; is previous mode v86?
  707. jnz short b ; if nz, yes, go check for APC
  708. test byte ptr [TFrame]+TsSegCs,MODE_MASK ; is previous mode user mode?
  709. jz a ; No, previousmode=Kernel, jump out
  710. b: mov ebx, PCR[PcPrcbData+PbCurrentThread]; get addr of current thread
  711. mov byte ptr [ebx]+ThAlerted, 0 ; clear kernel mode alerted
  712. cmp byte ptr [ebx]+ThApcState.AsUserApcPending, 0
  713. je a ; if eq, no user APC pending
  714. mov ebx, TFrame
  715. ifnb <ReturnCurrentEax>
  716. mov [ebx].TsEax, eax ; Store return code in trap frame
  717. mov dword ptr [ebx]+TsSegFs, KGDT_R3_TEB OR RPL_MASK
  718. mov dword ptr [ebx]+TsSegDs, KGDT_R3_DATA OR RPL_MASK
  719. mov dword ptr [ebx]+TsSegEs, KGDT_R3_DATA OR RPL_MASK
  720. mov dword ptr [ebx]+TsSegGs, 0
  721. endif
  722. ;
  723. ; Save previous IRQL and set new priority level
  724. ;
  725. RaiseIrql APC_LEVEL
  726. push eax ; Save OldIrql
  727. sti ; Allow higher priority ints
  728. ;
  729. ; call the APC delivery routine.
  730. ;
  731. ; ebx - Trap frame
  732. ; 0 - Null exception frame
  733. ; 1 - Previous mode
  734. ;
  735. ; call APC deliver routine
  736. ;
  737. CAPSTART <c,_KiDeliverApc@12>
  738. stdCall _KiDeliverApc, <1, 0, ebx>
  739. CAPEND <c>
  740. pop ecx ; (ecx) = OldIrql
  741. LowerIrql ecx
  742. ifnb <ReturnCurrentEax>
  743. mov eax, [ebx].TsEax ; Restore eax, just in case
  744. endif
  745. cli
  746. jmp b
  747. ALIGN 4
  748. a:
  749. endm
  750. if DBG
  751. page ,132
  752. subttl "Processing Exception occurred in a 16 bit stack"
  753. ;++
  754. ;
  755. ; Routine Description:
  756. ;
  757. ; This routine is called after an exception being detected during
  758. ; a 16 bit stack. The system will switch 16 stack to 32 bit
  759. ; stack and bugcheck.
  760. ;
  761. ; Arguments:
  762. ;
  763. ; None.
  764. ;
  765. ; Return value:
  766. ;
  767. ; system stopped.
  768. ;
  769. ;--
  770. align dword
  771. public _Ki16BitStackException
  772. _Ki16BitStackException proc
  773. .FPO (2, 0, 0, 0, 0, FPO_TRAPFRAME)
  774. push ss
  775. push esp
  776. mov eax, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
  777. add esp, [eax]+ThStackLimit ; compute 32-bit stack address
  778. mov eax, KGDT_R0_DATA
  779. mov ss, ax
  780. lea ebp, [esp+8]
  781. cld
  782. SET_DEBUG_DATA
  783. if DBG
  784. push offset FLAT:Ki16BitStackTrapMessage
  785. call _dbgPrint
  786. add esp, 4
  787. endif
  788. stdCall _KeBugCheck, <0F000FFFFh> ; Never return
  789. ret
  790. _Ki16BitStackException endp
  791. endif
  792. page ,132
  793. subttl "System Service Call"
  794. ;++
  795. ;
  796. ; Routine Description:
  797. ;
  798. ; This routine gains control when trap occurs via vector 2EH.
  799. ; INT 2EH is reserved for system service calls.
  800. ;
  801. ; The system service is executed by locating its routine address in
  802. ; system service dispatch table and calling the specified function.
  803. ; On return necessary state is restored.
  804. ;
  805. ; Arguments:
  806. ;
  807. ; eax - System service number.
  808. ; edx - Pointer to arguments
  809. ;
  810. ; Return Value:
  811. ;
  812. ; eax - System service status code.
  813. ;
  814. ;--
  815. if 0
  816. ;
  817. ; Error and exception blocks for KiSystemService
  818. ;
  819. Kss_ExceptionHandler:
  820. ;
  821. ; WARNING: Here we directly unlink the exception handler from the
  822. ; exception registration chain. NO unwind is performed.
  823. ;
  824. mov eax, [esp+4] ; (eax)-> ExceptionRecord
  825. mov eax, [eax].ErExceptionCode ; (eax) = Exception code
  826. mov esp, [esp+8] ; (esp)-> ExceptionList
  827. pop eax
  828. mov PCR[PcExceptionList],eax
  829. add esp, 4
  830. pop ebp
  831. test dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
  832. jnz kss60 ; v86 mode => usermode
  833. test dword ptr [ebp].TsSegCs, MODE_MASK ; if premode=kernel
  834. jnz kss60 ; nz, prevmode=user, go return
  835. ; raise bugcheck if prevmode=kernel
  836. stdCall _KeBugCheck, <KMODE_EXCEPTION_NOT_HANDLED>
  837. endif
  838. ;
  839. ; The specified system service number is not within range. Attempt to
  840. ; convert the thread to a GUI thread if the specified system service is
  841. ; not a base service and the thread has not already been converted to a
  842. ; GUI thread.
  843. ;
  844. Kss_ErrorHandler:
  845. cmp ecx, SERVICE_TABLE_TEST ; test if GUI service
  846. jne short Kss_LimitError ; if ne, not GUI service
  847. push edx ; save argument registers
  848. push ebx ;
  849. stdcall _PsConvertToGuiThread ; attempt to convert to GUI thread
  850. or eax, eax ; check if service was successful
  851. pop eax ; restore argument registers
  852. pop edx ;
  853. mov ebp, esp ; reset trap frame address
  854. mov [esi]+ThTrapFrame, ebp ; save address of trap frame
  855. jz _KiSystemServiceRepeat ; if eq, successful conversion
  856. ;
  857. ; The conversion to a GUI thread failed. The correct return value is encoded
  858. ; in a byte table indexed by the service number that is at the end of the
  859. ; service address table. The encoding is as follows:
  860. ;
  861. ; 0 - return 0.
  862. ; -1 - return -1.
  863. ; 1 - return status code.
  864. ;
  865. lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST ;
  866. mov ecx, [edx]+SdLimit ; get service number limit
  867. mov edx, [edx]+SdBase ; get service table base
  868. lea edx, [edx][ecx*4] ; get ending service table address
  869. and eax, SERVICE_NUMBER_MASK ; isolate service number
  870. add edx, eax ; compute return value address
  871. movsx eax, byte ptr [edx] ; get status byte
  872. or eax, eax ; check for 0 or -1
  873. jle Kss70 ; if le, return value set
  874. Kss_LimitError: ;
  875. mov eax, STATUS_INVALID_SYSTEM_SERVICE ; set return status
  876. jmp kss70 ;
  877. ifndef NT_UP
  878. ENTER_DR_ASSIST kfce_a, kfce_t,NoAbiosAssist,NoV86Assist
  879. endif
  880. ENTER_DR_ASSIST kss_a, kss_t,NoAbiosAssist,NoV86Assist
  881. ;
  882. ; Fast System Call entry point
  883. ;
  884. ; At entry:
  885. ; EAX = service number
  886. ; EDX = Pointer to caller's arguments
  887. ; ECX = unused
  888. ; ESP = DPC stack for this processor
  889. ;
  890. ; Create a stack frame like a call to inner privilege then continue
  891. ; in KiSystemService.
  892. ;
  893. ;
  894. ; Normal entry is at KiFastCallEntry, not KiFastCallEntry2. Entry
  895. ; is via KiFastCallEntry2 if a double fault (trap08) occured and EIP
  896. ; was KiFastCallEntry. This happens if a single step exception occurs
  897. ; on the instruction following SYSENTER instruction because there is
  898. ; no kernel stack fot the debug exception (trap01) to run on.
  899. ;
  900. ; This is NOT a performance path.
  901. PUBLIC _KiFastCallEntry2
  902. _KiFastCallEntry2:
  903. ifndef NT_UP
  904. mov ecx, KGDT_R0_PCR
  905. else
  906. mov ecx, KGDT_R3_TEB OR RPL_MASK
  907. endif
  908. mov fs, ecx
  909. mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
  910. ;
  911. ; Calculate initial stack pointer from thread initial stack.
  912. ; If this isn't the same as esp0 then we are a VX86 thread and we are rejected
  913. ;
  914. mov ecx, [ecx].ThInitialStack
  915. lea esp, [ecx-(NPX_FRAME_LENGTH + (TsV86Gs - TsHardwareSegSS))]
  916. mov ecx, PCR[PcTss]
  917. cmp esp, [ecx].TssEsp0
  918. jne Kfsc90
  919. ; adjust return address in user mode to renable EFLAGS TF so
  920. ; single step is turned back on.
  921. mov ecx, MM_SHARED_USER_DATA_VA+UsSystemCall+fscrOffset+1
  922. jmp short Kfsc10
  923. align 16
  924. PUBLIC _KiFastCallEntry
  925. _KiFastCallEntry proc
  926. ;
  927. ; Return to the instruction immediately following the sysenter
  928. ; instruction which is at a known location in the shared user
  929. ; data structure (this is so we can dynamically place the right
  930. ; code for the processor at system init).
  931. ;
  932. ifndef NT_UP
  933. mov ecx, KGDT_R0_PCR
  934. mov fs, ecx
  935. endif ;; NT_UP
  936. mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
  937. ;
  938. ; Calculate initial stack pointer from thread initial stack.
  939. ; If this isn't the same as esp0 then we are a VX86 thread and we are rejected
  940. ;
  941. mov ecx, [ecx].ThInitialStack
  942. lea esp, [ecx-(NPX_FRAME_LENGTH + (TsV86Gs - TsHardwareSegSS))]
  943. mov ecx, PCR[PcTss]
  944. cmp esp, [ecx].TssEsp0
  945. jne Kfsc90
  946. ;
  947. ; Set ecx to return address in user mode
  948. ;
  949. mov ecx, MM_SHARED_USER_DATA_VA+UsSystemCall+fscrOffset
  950. Kfsc10:
  951. push KGDT_R3_DATA OR RPL_MASK ; Push user SS
  952. push edx ; Push ESP
  953. pushfd
  954. push 2 ; Sanitize eflags
  955. popfd ;
  956. add edx, 8 ; (edx) -> arguments
  957. or dword ptr [esp], EFLAGS_INTERRUPT_MASK ; Enable interrupts
  958. push KGDT_R3_CODE OR RPL_MASK ; Push user CS
  959. push ecx ; push return address
  960. ifndef NT_UP
  961. ; For the MP case, FS is already loaded above
  962. ENTER_SYSCALL kfce_a, kfce_t, NoFSLoad
  963. jmp _KiSystemServiceRepeat
  964. endif ;; NT_UP
  965. _KiFastCallEntry endp
  966. ;
  967. ; General System service entrypoint
  968. ;
  969. PUBLIC _KiSystemService
  970. _KiSystemService proc
  971. ENTER_SYSCALL kss_a, kss_t ; set up trap frame and save state
  972. ?FpoValue = 0
  973. ;
  974. ; (eax) = Service number
  975. ; (edx) = Callers stack pointer
  976. ; (esi) = Current thread address
  977. ;
  978. ; All other registers have been saved and are free.
  979. ;
  980. ; Check if the service number within valid range
  981. ;
  982. _KiSystemServiceRepeat:
  983. mov edi, eax ; copy system service number
  984. shr edi, SERVICE_TABLE_SHIFT ; isolate service table number
  985. and edi, SERVICE_TABLE_MASK ;
  986. mov ecx, edi ; save service table number
  987. add edi, [esi]+ThServiceTable ; compute service descriptor address
  988. mov ebx, eax ; save system service number
  989. and eax, SERVICE_NUMBER_MASK ; isolate service table offset
  990. ;
  991. ; If the specified system service number is not within range, then attempt
  992. ; to convert the thread to a GUI thread and retry the service dispatch.
  993. ;
  994. cmp eax, [edi]+SdLimit ; check if valid service
  995. jae Kss_ErrorHandler ; if ae, try to convert to GUI thread
  996. ;
  997. ; If the service is a GUI service and the GDI user batch queue is not empty,
  998. ; then call the appropriate service to flush the user batch.
  999. ;
  1000. cmp ecx, SERVICE_TABLE_TEST ; test if GUI service
  1001. jne short Kss40 ; if ne, not GUI service
  1002. mov ecx, PCR[PcTeb] ; get current thread TEB address
  1003. xor ebx, ebx ; get number of batched GDI calls
  1004. KiSystemServiceAccessTeb:
  1005. or ebx, [ecx]+TbGdiBatchCount ; may cause an inpage exception
  1006. jz short Kss40 ; if z, no batched calls
  1007. push edx ; save address of user arguments
  1008. push eax ; save service number
  1009. call [_KeGdiFlushUserBatch] ; flush GDI user batch
  1010. pop eax ; restore service number
  1011. pop edx ; restore address of user arguments
  1012. ;
  1013. ; The arguments are passed on the stack. Therefore they always need to get
  1014. ; copied since additional space has been allocated on the stack for the
  1015. ; machine state frame. Note that we don't check for the zero argument case -
  1016. ; copy is always done regardless of the number of arguments because the
  1017. ; zero argument case is very rare.
  1018. ;
  1019. Kss40: inc dword ptr PCR[PcPrcbData+PbSystemCalls] ; system calls
  1020. if DBG
  1021. mov ecx, [edi]+SdCount ; get count table address
  1022. jecxz Kss45 ; if zero, table not specified
  1023. inc dword ptr [ecx+eax*4] ; increment service count
  1024. Kss45: push dword ptr [esi]+ThApcStateIndex ; (ebp-4)
  1025. push dword ptr [esi]+ThCombinedApcDisable ; (ebp-8)
  1026. ;
  1027. ; work around errata 19 which can in some cases cause an
  1028. ; extra dword to be moved in the rep movsd below. In the DBG
  1029. ; build, this will usually case a bugcheck 1 where ebp-8 is no longer
  1030. ; the kernel apc disable count
  1031. ;
  1032. sub esp,4
  1033. ?FpoValue = ?FpoValue+3
  1034. endif
  1035. FPOFRAME ?FpoValue, 0
  1036. mov esi, edx ; (esi)->User arguments
  1037. mov ebx, [edi]+SdNumber ; get argument table address
  1038. xor ecx, ecx
  1039. mov cl, byte ptr [ebx+eax] ; (ecx) = argument size
  1040. mov edi, [edi]+SdBase ; get service table address
  1041. mov ebx, [edi+eax*4] ; (ebx)-> service routine
  1042. sub esp, ecx ; allocate space for arguments
  1043. shr ecx, 2 ; (ecx) = number of argument DWORDs
  1044. mov edi, esp ; (es:edi)->location to receive 1st arg
  1045. cmp esi, _MmUserProbeAddress ; check if user address
  1046. jae kss80 ; if ae, then not user address
  1047. KiSystemServiceCopyArguments:
  1048. rep movsd ; copy the arguments to top of stack.
  1049. ; Since we usually copy more than 3
  1050. ; arguments. rep movsd is faster than
  1051. ; mov instructions.
  1052. if DBG
  1053. ;
  1054. ; Check for user mode call into system at elevated IRQL.
  1055. ;
  1056. test byte ptr [ebp]+TsSegCs,MODE_MASK
  1057. jz short kss50a ; kernel mode, skip test
  1058. CurrentIrql
  1059. or al, al ; bogus irql, go bugcheck
  1060. jnz kss100
  1061. kss50a:
  1062. test _MmInjectUserInpageErrors, 2
  1063. jz short @f
  1064. stdCall _MmTrimProcessMemory, <0>
  1065. jmp short kssdoit
  1066. @@:
  1067. mov eax,PCR[PcPrcbData+PbCurrentThread]
  1068. mov eax,[eax]+ThApcState+AsProcess
  1069. test dword ptr [eax]+PrFlags,0100000h ; is this a inpage-err process?
  1070. je short @f
  1071. stdCall _MmTrimProcessMemory, <0>
  1072. @@:
  1073. endif
  1074. ;
  1075. ; Make actual call to system service
  1076. ;
  1077. kssdoit:
  1078. CAPSTARTX <_KiSystemService,ebx>
  1079. call ebx ; call system service
  1080. CAPENDX <_KiSystemService>
  1081. kss60:
  1082. if DBG
  1083. mov ecx,PCR[PcPrcbData+PbCurrentThread] ; (ecx)-> Current Thread
  1084. ;
  1085. ; Check for return to user mode at elevated IRQL.
  1086. ;
  1087. test byte ptr [ebp]+TsSegCs,MODE_MASK
  1088. jz short kss50b
  1089. mov esi, eax
  1090. CurrentIrql
  1091. or al, al
  1092. jnz kss100 ; bogus irql, go bugcheck
  1093. mov eax, esi
  1094. kss50b:
  1095. ;
  1096. ; Check that APC state has not changed
  1097. ;
  1098. mov edx, [ebp-4]
  1099. cmp dl, [ecx]+ThApcStateIndex
  1100. jne kss120
  1101. mov edx, [ebp-8]
  1102. cmp edx, [ecx]+ThCombinedApcDisable
  1103. jne kss120
  1104. endif
  1105. kss61:
  1106. ;
  1107. ; Upon return, (eax)= status code
  1108. ;
  1109. mov esp, ebp ; deallocate stack space for arguments
  1110. ;
  1111. ; Restore old trap frame address from the current trap frame.
  1112. ;
  1113. kss70: mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
  1114. mov edx, [ebp].TsEdx ; restore previous trap frame address
  1115. mov [ecx].ThTrapFrame, edx ;
  1116. ;
  1117. ; System service's private version of KiExceptionExit
  1118. ; (Also used by KiDebugService)
  1119. ;
  1120. ; Check for pending APC interrupts, if found, dispatch to them
  1121. ; (saving eax in frame first).
  1122. ;
  1123. public _KiServiceExit
  1124. _KiServiceExit:
  1125. cli ; disable interrupts
  1126. DISPATCH_USER_APC ebp, ReturnCurrentEax
  1127. ;
  1128. ; Exit from SystemService
  1129. ;
  1130. EXIT_ALL NoRestoreSegs, NoRestoreVolatile
  1131. ;
  1132. ; The address of the argument list is not a user address. If the previous mode
  1133. ; is user, then return an access violation as the status of the system service.
  1134. ; Otherwise, copy the argument list and execute the system service.
  1135. ;
  1136. kss80: test byte ptr [ebp].TsSegCs, MODE_MASK ; test previous mode
  1137. jz KiSystemServiceCopyArguments ; if z, previous mode kernel
  1138. mov eax, STATUS_ACCESS_VIOLATION ; set service status
  1139. jmp kss60 ;
  1140. ;++
  1141. ;
  1142. ; _KiServiceExit2 - same as _KiServiceExit BUT the full trap_frame
  1143. ; context is restored
  1144. ;
  1145. ;--
  1146. public _KiServiceExit2
  1147. _KiServiceExit2:
  1148. cli ; disable interrupts
  1149. DISPATCH_USER_APC ebp
  1150. ;
  1151. ; Exit from SystemService
  1152. ;
  1153. EXIT_ALL ; RestoreAll
  1154. if DBG
  1155. kss100: push PCR[PcIrql] ; put bogus value on stack for dbg
  1156. ?FpoValue = ?FpoValue + 1
  1157. FPOFRAME ?FpoValue, 0
  1158. mov byte ptr PCR[PcIrql],0 ; avoid recursive trap
  1159. cli
  1160. ;
  1161. ; IRQL_GT_ZERO_AT_SYSTEM_SERVICE Returning to usermode at elevated IRQL.
  1162. ;
  1163. ; KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
  1164. ; System Call Handler (address of system routine),
  1165. ; Irql,
  1166. ; 0,
  1167. ; 0,
  1168. ; );
  1169. ;
  1170. stdCall _KeBugCheckEx,<IRQL_GT_ZERO_AT_SYSTEM_SERVICE, ebx, eax, 0, 0>
  1171. ;
  1172. ; APC_INDEX_MISMATCH This is probably caused by the system call entering
  1173. ; critical regions and not leaving them. This is fatal. Include as
  1174. ; much information in the bugcheck as possible.
  1175. ;
  1176. ; KeBugCheckEx(APC_INDEX_MISMATCH,
  1177. ; System Call Handler (address of system routine),
  1178. ; Thread->ApcStateIndex << 8 | Saved ApcStateIndex,
  1179. ; Thread->CombinedApcDisable,
  1180. ; Saved CombinedApcDisable
  1181. ; );
  1182. ;
  1183. kss120: mov eax, [ebp]-4
  1184. mov ah, [ecx]+ThApcStateIndex
  1185. stdCall _KeBugCheckEx,<APC_INDEX_MISMATCH, ebx, eax, [ecx]+ThCombinedApcDisable, dword ptr [ebp]-8>
  1186. endif
  1187. ret
  1188. ;
  1189. ; If the sysenter instruction was executed in 16 bit mode, generate
  1190. ; an error rather than trying to process the system call. There is
  1191. ; no way to return to the correct code in user mode.
  1192. ;
  1193. Kfsc90:
  1194. mov esp, [ecx].TssEsp0
  1195. push 0 ; save VX86 Es, Ds, Fs, Gs
  1196. push 0
  1197. push 0
  1198. push 0
  1199. push 01bh ; SS
  1200. push 0 ; can't know user esp
  1201. push EFLAGS_INTERRUPT_MASK+EFLAGS_V86_MASK+2h; eflags with VX86 set
  1202. push 01bh ; CS
  1203. push 0 ; don't know original EIP
  1204. jmp _KiTrap06 ; turn exception into illegal op.
  1205. _KiSystemService endp
  1206. ;
  1207. ; BBT cannot instrument code between this label and BBT_Exclude_Trap_Code_End
  1208. ;
  1209. public _BBT_Exclude_Trap_Code_Begin
  1210. _BBT_Exclude_Trap_Code_Begin equ $
  1211. int 3
  1212. ;
  1213. ; Fast path NtGetTickCount
  1214. ;
  1215. align 16
  1216. ENTER_DR_ASSIST kitx_a, kitx_t,NoAbiosAssist
  1217. PUBLIC _KiGetTickCount
  1218. _KiGetTickCount proc
  1219. cmp [esp+4], KGDT_R3_CODE OR RPL_MASK
  1220. jnz short @f
  1221. Kgtc00:
  1222. mov eax,dword ptr cs:[_KeTickCount]
  1223. mul dword ptr cs:[_ExpTickCountMultiplier]
  1224. shrd eax,edx,24 ; compute resultant tick count
  1225. iretd
  1226. @@:
  1227. ;
  1228. ; if v86 mode, we dont handle it
  1229. ;
  1230. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  1231. test byte ptr [esp+8+2], EFLAGS_V86_MASK/010000h
  1232. jnz ktgc20
  1233. ;
  1234. ; if kernel mode, must be get tick count
  1235. ;
  1236. .errnz (MODE_MASK AND 0FFFFFF00h)
  1237. test byte ptr [esp+4], MODE_MASK
  1238. jz short Kgtc00
  1239. ;
  1240. ; else check if the caller is USER16
  1241. ; if eax = ebp = 0xf0f0f0f0 it is get-tick-count
  1242. ; if eax = ebp = 0xf0f0f0f1 it is set-ldt-entry
  1243. ;
  1244. cmp eax, ebp ; if eax != ebp, not USER16
  1245. jne ktgc20
  1246. and eax, 0fffffff0h
  1247. cmp eax, 0f0f0f0f0h
  1248. jne ktgc20
  1249. cmp ebp, 0f0f0f0f0h ; Is it user16 gettickcount?
  1250. je short Kgtc00 ; if z, yes
  1251. cmp ebp, 0f0f0f0f1h ; If this is setldt entry
  1252. jne ktgc20 ; if nz, we don't know what
  1253. ; it is.
  1254. ;
  1255. ; The idea here is that user16 can call 32 bit api to
  1256. ; update LDT entry without going through the penalty
  1257. ; of DPMI. For Daytona beta.
  1258. ;
  1259. push 0 ; push dummy error code
  1260. ENTER_TRAP kitx_a, kitx_t
  1261. sti
  1262. xor eax, eax
  1263. mov ebx, [ebp+TsEbx]
  1264. mov ecx, [ebp+TsEcx]
  1265. mov edx, [ebp+TsEdx]
  1266. stdCall _NtSetLdtEntries <ebx, ecx, edx, eax, eax, eax>
  1267. mov [ebp+TsEax], eax
  1268. and dword ptr [ebp+TsEflags], 0FFFFFFFEH ; clear carry flag
  1269. cmp eax, 0 ; success?
  1270. je short ktgc10
  1271. or dword ptr [ebp+TsEflags], 1 ; set carry flag
  1272. ktgc10:
  1273. jmp _KiExceptionExit
  1274. ktgc20:
  1275. ;
  1276. ; We need to *trap* this int 2a. For exception, the eip should
  1277. ; point to the int 2a instruction not the instruction after it.
  1278. ;
  1279. sub word ptr [esp], 2
  1280. push 0
  1281. jmp _KiTrap0D
  1282. _KiGetTickCount endp
  1283. page ,132
  1284. subttl "Return from User Mode Callback"
  1285. ;++
  1286. ;
  1287. ; NTSTATUS
  1288. ; NtCallbackReturn (
  1289. ; IN PVOID OutputBuffer OPTIONAL,
  1290. ; IN ULONG OutputLength,
  1291. ; IN NTSTATUS Status
  1292. ; )
  1293. ;
  1294. ; Routine Description:
  1295. ;
  1296. ; This function returns from a user mode callout to the kernel mode
  1297. ; caller of the user mode callback function.
  1298. ;
  1299. ; N.B. This service uses a nonstandard calling sequence.
  1300. ;
  1301. ; Arguments:
  1302. ;
  1303. ; OutputBuffer (ecx) - Supplies an optional pointer to an output buffer.
  1304. ;
  1305. ; OutputLength (edx) - Supplies the length of the output buffer.
  1306. ;
  1307. ; Status (esp + 4) - Supplies the status value returned to the caller of
  1308. ; the callback function.
  1309. ;
  1310. ; Return Value:
  1311. ;
  1312. ; If the callback return cannot be executed, then an error status is
  1313. ; returned. Otherwise, the specified callback status is returned to
  1314. ; the caller of the callback function.
  1315. ;
  1316. ; N.B. This function returns to the function that called out to user
  1317. ; mode is a callout is currently active.
  1318. ;
  1319. ;--
  1320. align 16
  1321. PUBLIC _KiCallbackReturn
  1322. _KiCallbackReturn proc
  1323. push fs ; save segment register
  1324. push ecx ; save buffer address and return status
  1325. push eax ;
  1326. mov ecx,KGDT_R0_PCR ; set PCR segment number
  1327. mov fs,cx ;
  1328. mov eax,PCR[PcPrcbData + PbCurrentThread] ; get current thread address
  1329. mov ecx,[eax].ThCallbackStack ; get callback stack address
  1330. test ecx,ecx ; check if callback active
  1331. jz _KiCbExit ; if z, no callback active
  1332. mov edi,[esp] + 4 ; set output buffer address
  1333. mov esi,edx ; set output buffer length
  1334. mov ebp,[esp] + 0 ; set return status
  1335. ;
  1336. ; N.B. The following code is entered with:
  1337. ;
  1338. ; eax - The address of the current thread.
  1339. ; ecx - The callback stack address.
  1340. ; edi - The output buffer address.
  1341. ; esi - The output buffer length.
  1342. ; ebp - The callback service status.
  1343. ;
  1344. ; Restore the trap frame and callback stack addresses,
  1345. ; store the output buffer address and length, and set the service status.
  1346. ;
  1347. cld ; clear the direction flag
  1348. mov ebx,[ecx].CuOutBf ; get address to store output buffer
  1349. mov [ebx],edi ; store output buffer address
  1350. mov ebx,[ecx].CuOutLn ; get address to store output length
  1351. mov [ebx],esi ; store output buffer length
  1352. mov esi,[eax].ThInitialStack ; get source NPX save area address
  1353. mov ebx,[ecx] ; get previous initial stack address
  1354. mov [eax].ThInitialStack,ebx ; restore initial stack address
  1355. sub ebx,NPX_FRAME_LENGTH ; compute destination NPX save area
  1356. sub esi,NPX_FRAME_LENGTH ; compute source NPX save area
  1357. ; All we want to do is to copy ControlWord, StatusWord and TagWord from
  1358. ; the source NPX save area. So we always copy first 3 dwords, irrespective
  1359. ; of the fact whether the save was done using fxsave or fnsave.
  1360. mov edx,[esi].FpControlWord ; copy NPX state to previous frame
  1361. mov [ebx].FpControlWord,edx ;
  1362. mov edx,[esi].FpStatusWord ;
  1363. mov [ebx].FpStatusWord,edx ;
  1364. mov edx,[esi].FpTagWord ;
  1365. mov [ebx].FpTagWord,edx ;
  1366. mov edx,[esi].FxMXCsr ;
  1367. mov [ebx].FxMXCsr,edx ;
  1368. mov edx,[esi].FpCr0NpxState ;
  1369. mov [ebx].FpCr0NpxState,edx ;
  1370. lea esp, [ecx]+4 ; trim stack back to callback frame
  1371. pop edx
  1372. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  1373. test byte ptr [edx]+TsEFlags+2,EFLAGS_V86_MASK/010000h ; is this a V86 frame?
  1374. mov [eax].ThTrapFrame, edx ; restore current trap frame address
  1375. mov edx,PCR[PcTss] ; get address of task switch segment
  1376. jne @f
  1377. sub ebx, TsV86Gs-TsHardwareSegSs ; bias missing V86 fields
  1378. @@: mov [edx].TssEsp0,ebx ; restore kernel entry stack address
  1379. test [eax].ThDebugActive, 0ffh ; Are debug registers active?
  1380. .errnz (DR7_ACTIVE AND 0FFFFFF00h)
  1381. jnz short _KiCbDebugRegs ; restore kernel Debug Registers
  1382. _KiCbRet:
  1383. mov edx, [eax].ThTrapFrame ; Get current trap frame address
  1384. test [edx].TsDr7, DR7_ACTIVE
  1385. setnz byte ptr [eax].ThDebugActive ; Set debug active to match saved DR7
  1386. sti ; enable interrupts
  1387. pop [eax].ThCallbackStack ; restore callback stack address
  1388. mov eax,ebp ; set callback service status
  1389. ;
  1390. ; Restore nonvolatile registers, clean call parameters from stack, and
  1391. ; return to callback caller.
  1392. ;
  1393. pop edi ; restore nonvolatile registers
  1394. pop esi ;
  1395. pop ebx ;
  1396. pop ebp ;
  1397. pop edx ; save return address
  1398. add esp,8 ; remove parameters from stack
  1399. jmp edx ; return to callback caller
  1400. ;
  1401. ; Restore Kernel Mode debug registers.
  1402. ;
  1403. _KiCbDebugRegs:
  1404. mov edi, PCR[PcPrcb]
  1405. xor ecx, ecx ; Make Dr7 safe
  1406. mov dr7, ecx
  1407. mov ebx, [edi].PbProcessorState.PsSpecialRegisters.SrKernelDr0
  1408. mov ecx, [edi].PbProcessorState.PsSpecialRegisters.SrKernelDr1
  1409. mov dr0, ebx
  1410. mov dr1, ecx
  1411. mov ebx, [edi].PbProcessorState.PsSpecialRegisters.SrKernelDr2
  1412. mov ecx, [edi].PbProcessorState.PsSpecialRegisters.SrKernelDr3
  1413. mov dr2, ebx
  1414. mov dr3, ecx
  1415. mov ebx, [edi].PbProcessorState.PsSpecialRegisters.SrKernelDr6
  1416. mov ecx, [edi].PbProcessorState.PsSpecialRegisters.SrKernelDr7
  1417. mov dr6, ebx
  1418. mov dr7, ecx
  1419. jmp short _KiCbRet
  1420. ;
  1421. ; Restore segment register, set systerm service status, and return.
  1422. ;
  1423. _KiCbExit: ;
  1424. add esp, 2 * 4 ; remove saved registers from stack
  1425. pop fs ; restore segment register
  1426. mov eax,STATUS_NO_CALLBACK_ACTIVE ; set service status
  1427. iretd ;
  1428. _KiCallbackReturn endp
  1429. ;
  1430. ; Fast path Nt/Zw SetLowWaitHighThread
  1431. ;
  1432. ENTER_DR_ASSIST kslwh_a, kslwh_t,NoAbiosAssist,NoV86Assist
  1433. align 16
  1434. PUBLIC _KiSetLowWaitHighThread
  1435. _KiSetLowWaitHighThread proc
  1436. ENTER_SYSCALL kslwh_a, kslwh_t ; Set up trap frame
  1437. mov eax,STATUS_NO_EVENT_PAIR ; set service status
  1438. mov edx,[ebp].TsEdx ; restore old trap frame address
  1439. mov [esi].ThTrapFrame,edx ;
  1440. jmp _KiServiceExit
  1441. _KiSetLowWaitHighThread endp
  1442. page ,132
  1443. subttl "Common Trap Exit"
  1444. ;++
  1445. ;
  1446. ; KiUnexpectedInterruptTail
  1447. ;
  1448. ; Routine Description:
  1449. ; This function is jumped to by an IDT entry who has no interrupt
  1450. ; handler.
  1451. ;
  1452. ; Arguments:
  1453. ;
  1454. ; (esp) - Dword, vector
  1455. ; (esp+4) - Processor generated IRet frame
  1456. ;
  1457. ;--
  1458. ENTER_DR_ASSIST kui_a, kui_t
  1459. public _KiUnexpectedInterruptTail
  1460. _KiUnexpectedInterruptTail proc
  1461. ENTER_INTERRUPT kui_a, kui_t, PassDwordParm
  1462. inc dword ptr PCR[PcPrcbData+PbInterruptCount]
  1463. mov ebx, [esp] ; get vector & leave it on the stack
  1464. sub esp, 4 ; make space for OldIrql
  1465. ; esp - ptr to OldIrql
  1466. ; ebx - Vector
  1467. ; HIGH_LEVEL - Irql
  1468. stdCall _HalBeginSystemInterrupt, <HIGH_LEVEL,ebx,esp>
  1469. or eax, eax
  1470. jnz short kui10
  1471. ;
  1472. ; spurious interrupt
  1473. ;
  1474. add esp, 8
  1475. jmp kee99
  1476. kui10:
  1477. if DBG
  1478. push dword ptr [esp+4] ; Vector #
  1479. push offset FLAT:BadInterruptMessage
  1480. call _DbgPrint ; display unexpected interrupt message
  1481. add esp, 8
  1482. endif
  1483. ;
  1484. ; end this interrupt
  1485. ;
  1486. INTERRUPT_EXIT
  1487. _KiUnexpectedInterruptTail endp
  1488. ;++
  1489. ;
  1490. ; N.B. KiExceptionExit and Kei386EoiHelper are identical and have
  1491. ; been combined.
  1492. ;
  1493. ; KiExceptionExit
  1494. ;
  1495. ; Routine Description:
  1496. ;
  1497. ; This code is transfered to at the end of the processing for
  1498. ; an exception. Its function is to restore machine state, and
  1499. ; continue thread execution. If control is returning to user mode
  1500. ; and there is a user APC pending, then control is transfered to
  1501. ; the user APC delivery routine.
  1502. ;
  1503. ; N.B. It is assumed that this code executes at IRQL zero or APC_LEVEL.
  1504. ; Therefore page faults and access violations can be taken.
  1505. ;
  1506. ; NOTE: This code is jumped to, not called.
  1507. ;
  1508. ; Arguments:
  1509. ;
  1510. ; (ebp) -> base of trap frame.
  1511. ;
  1512. ; Return Value:
  1513. ;
  1514. ; None.
  1515. ;
  1516. ;--
  1517. ;++
  1518. ;
  1519. ; Kei386EoiHelper
  1520. ;
  1521. ; Routine Description:
  1522. ;
  1523. ; This code is transfered to at the end of an interrupt. (via the
  1524. ; exit_interrupt macro). It checks for user APC dispatching and
  1525. ; performs the exit_all for the interrupt.
  1526. ;
  1527. ; NOTE: This code is jumped to, not called.
  1528. ;
  1529. ; Arguments:
  1530. ;
  1531. ; (esp) -> base of trap frame.
  1532. ; interrupts are disabled
  1533. ;
  1534. ; Return Value:
  1535. ;
  1536. ; None.
  1537. ;
  1538. ;--
  1539. align 4
  1540. public _KiExceptionExit
  1541. cPublicProc Kei386EoiHelper, 0
  1542. _KiExceptionExit:
  1543. .FPO (0, 0, 0, 0, 0, FPO_TRAPFRAME)
  1544. cli ; disable interrupts
  1545. DISPATCH_USER_APC ebp
  1546. ;
  1547. ; Exit from Exception
  1548. ;
  1549. kee99:
  1550. EXIT_ALL ,,NoPreviousMode
  1551. stdENDP Kei386EoiHelper
  1552. ;
  1553. ; V86ExitHelp
  1554. ;
  1555. ; Restore volatiles for V86 mode, and move seg regs
  1556. ;
  1557. ; Arguments:
  1558. ;
  1559. ; esp = ebp = &TrapFrame
  1560. ;
  1561. ; Return Value:
  1562. ;
  1563. ; None, returns to previous mode using IRETD.
  1564. ;
  1565. align dword
  1566. V86ExitHelp:
  1567. add esp,TsEdx
  1568. pop edx
  1569. pop ecx
  1570. pop eax
  1571. lea esp, [ebp]+TsEdi ; Skip PreMode, ExceptList and fs
  1572. pop edi ; restore non-volatiles
  1573. pop esi
  1574. pop ebx
  1575. pop ebp
  1576. ;
  1577. ; Esp MUST point to the Error Code on the stack. Because we use it to
  1578. ; store the entering esp.
  1579. ;
  1580. cmp word ptr [esp+8], 80h ; check for abios code segment?
  1581. ja AbiosExitHelp
  1582. v86eh90:
  1583. add esp, 4 ; remove error code from trap frame
  1584. iretd ; return
  1585. Abios_ExitHelp_Target2:
  1586. ;
  1587. ; End of ABIOS stack check
  1588. ;
  1589. ;
  1590. ; AbiosExit:
  1591. ;
  1592. ; This routine remaps current 32bit stack to 16bit stack at return
  1593. ; from interrupt time and returns from interrupt.
  1594. ;
  1595. ; Arguments:
  1596. ;
  1597. ; (esp) -> TrapFrame
  1598. ;
  1599. ; Return Value:
  1600. ;
  1601. ; None, returns to previous mode using IRETD.
  1602. ; Note: May use above exit to remove error code from stack.
  1603. ;
  1604. align dword
  1605. AbiosExitHelp:
  1606. cmp word ptr [esp+2], 0 ; (esp+2) = Low word of error code
  1607. jz short v86eh90
  1608. cmp word ptr [esp], 0 ; (esp) = High word of error code
  1609. jnz short v86eh90
  1610. shr dword ptr [esp], 16
  1611. mov word ptr [esp + 2], KGDT_STACK16
  1612. lss sp, dword ptr [esp]
  1613. movzx esp, sp
  1614. iretd ; return
  1615. page , 132
  1616. subttl "trap processing"
  1617. ;++
  1618. ;
  1619. ; Routine Description:
  1620. ;
  1621. ; _KiTrapxx - protected mode trap entry points
  1622. ;
  1623. ; These entry points are for internally generated exceptions,
  1624. ; such as a general protection fault. They do not handle
  1625. ; external hardware interrupts, or user software interrupts.
  1626. ;
  1627. ; Arguments:
  1628. ;
  1629. ; On entry the stack looks like:
  1630. ;
  1631. ; [ss]
  1632. ; [esp]
  1633. ; eflags
  1634. ; cs
  1635. ; eip
  1636. ; ss:sp-> [error]
  1637. ;
  1638. ; The cpu saves the previous SS:ESP, eflags, and CS:EIP on
  1639. ; the new stack if there was a privilige transition. If no
  1640. ; priviledge level transition occurred, then there is no
  1641. ; saved SS:ESP.
  1642. ;
  1643. ; Some exceptions save an error code, others do not.
  1644. ;
  1645. ; Return Value:
  1646. ;
  1647. ; None.
  1648. ;
  1649. ;--
  1650. page , 132
  1651. subttl "Macro to dispatch exception"
  1652. ;++
  1653. ;
  1654. ; Macro Description:
  1655. ;
  1656. ; This macro allocates exception record on stack, sets up exception
  1657. ; record using specified parameters and finally sets up arguments
  1658. ; and calls _KiDispatchException.
  1659. ;
  1660. ; Arguments:
  1661. ;
  1662. ; ExcepCode - Exception code to put into exception record
  1663. ; ExceptFlags - Exception flags to put into exception record
  1664. ; ExceptRecord - Associated exception record
  1665. ; ExceptAddress - Addr of instruction which the hardware exception occurs
  1666. ; NumParms - Number of additional parameters
  1667. ; ParameterList - the additional parameter list
  1668. ;
  1669. ; Return Value:
  1670. ;
  1671. ; None.
  1672. ;
  1673. ;--
  1674. DISPATCH_EXCEPTION macro ExceptCode, ExceptFlags, ExceptRecord, ExceptAddress,\
  1675. NumParms, ParameterList
  1676. local de10, de20
  1677. .FPO ( ExceptionRecordSize/4+NumParms, 0, 0, 0, 0, FPO_TRAPFRAME )
  1678. ; Set up exception record for raising exception
  1679. ?i = 0
  1680. sub esp, ExceptionRecordSize + NumParms * 4
  1681. ; allocate exception record
  1682. mov dword ptr [esp]+ErExceptionCode, ExceptCode
  1683. ; set up exception code
  1684. mov dword ptr [esp]+ErExceptionFlags, ExceptFlags
  1685. ; set exception flags
  1686. mov dword ptr [esp]+ErExceptionRecord, ExceptRecord
  1687. ; set associated exception record
  1688. mov dword ptr [esp]+ErExceptionAddress, ExceptAddress
  1689. mov dword ptr [esp]+ErNumberParameters, NumParms
  1690. ; set number of parameters
  1691. IRP z, <ParameterList>
  1692. mov dword ptr [esp]+(ErExceptionInformation+?i*4), z
  1693. ?i = ?i + 1
  1694. ENDM
  1695. ; set up arguments and call _KiDispatchException
  1696. mov ecx, esp ; (ecx)->exception record
  1697. mov eax,[ebp]+TsSegCs
  1698. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  1699. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  1700. jz de10
  1701. mov eax,0FFFFh
  1702. de10: and eax,MODE_MASK
  1703. ; 1 - first chance TRUE
  1704. ; eax - PreviousMode
  1705. ; ebp - trap frame addr
  1706. ; 0 - Null exception frame
  1707. ; ecx - exception record addr
  1708. ; dispatchexception as appropriate
  1709. stdCall _KiDispatchException, <ecx, 0, ebp, eax, 1>
  1710. mov esp, ebp ; (esp) -> trap frame
  1711. ENDM
  1712. page , 132
  1713. subttl "dispatch exception"
  1714. ;++
  1715. ;
  1716. ; CommonDispatchException
  1717. ;
  1718. ; Routine Description:
  1719. ;
  1720. ; This routine allocates exception record on stack, sets up exception
  1721. ; record using specified parameters and finally sets up arguments
  1722. ; and calls _KiDispatchException.
  1723. ;
  1724. ; NOTE:
  1725. ;
  1726. ; The purpose of this routine is to save code space. Use this routine
  1727. ; only if:
  1728. ; 1. ExceptionRecord is NULL
  1729. ; 2. ExceptionFlags is 0
  1730. ; 3. Number of parameters is less or equal than 3.
  1731. ;
  1732. ; Otherwise, you should use DISPATCH_EXCEPTION macro to set up your special
  1733. ; exception record.
  1734. ;
  1735. ; Arguments:
  1736. ;
  1737. ; (eax) = ExcepCode - Exception code to put into exception record
  1738. ; (ebx) = ExceptAddress - Addr of instruction which the hardware exception occurs
  1739. ; (ecx) = NumParms - Number of additional parameters
  1740. ; (edx) = Parameter1
  1741. ; (esi) = Parameter2
  1742. ; (edi) = Parameter3
  1743. ;
  1744. ; Return Value:
  1745. ;
  1746. ; None.
  1747. ;
  1748. ;--
  1749. CommonDispatchException0Args:
  1750. xor ecx, ecx ; zero arguments
  1751. call CommonDispatchException
  1752. CommonDispatchException1Arg0d:
  1753. xor edx, edx ; zero edx
  1754. CommonDispatchException1Arg:
  1755. mov ecx, 1 ; one argument
  1756. call CommonDispatchException ; there is no return
  1757. CommonDispatchException2Args0d:
  1758. xor edx, edx ; zero edx
  1759. CommonDispatchException2Args:
  1760. mov ecx, 2 ; two arguments
  1761. call CommonDispatchException ; there is no return
  1762. public CommonDispatchException
  1763. align dword
  1764. CommonDispatchException proc
  1765. cPublicFpo 0, ExceptionRecordLength/4
  1766. ;
  1767. ; Set up exception record for raising exception
  1768. ;
  1769. sub esp, ExceptionRecordLength
  1770. ; allocate exception record
  1771. mov dword ptr [esp]+ErExceptionCode, eax
  1772. ; set up exception code
  1773. xor eax, eax
  1774. mov dword ptr [esp]+ErExceptionFlags, eax
  1775. ; set exception flags
  1776. mov dword ptr [esp]+ErExceptionRecord, eax
  1777. ; set associated exception record
  1778. mov dword ptr [esp]+ErExceptionAddress, ebx
  1779. mov dword ptr [esp]+ErNumberParameters, ecx
  1780. ; set number of parameters
  1781. cmp ecx, 0
  1782. je short de00
  1783. lea ebx, [esp + ErExceptionInformation]
  1784. mov [ebx], edx
  1785. mov [ebx+4], esi
  1786. mov [ebx+8], edi
  1787. de00:
  1788. ;
  1789. ; set up arguments and call _KiDispatchException
  1790. ;
  1791. mov ecx, esp ; (ecx)->exception record
  1792. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  1793. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  1794. jz short de10
  1795. mov eax,0FFFFh
  1796. jmp short de20
  1797. de10: mov eax,[ebp]+TsSegCs
  1798. de20: and eax,MODE_MASK
  1799. ; 1 - first chance TRUE
  1800. ; eax - PreviousMode
  1801. ; ebp - trap frame addr
  1802. ; 0 - Null exception frame
  1803. ; ecx - exception record addr
  1804. stdCall _KiDispatchException,<ecx, 0, ebp, eax, 1>
  1805. mov esp, ebp ; (esp) -> trap frame
  1806. jmp _KiExceptionExit
  1807. CommonDispatchException endp
  1808. page , 132
  1809. subttl "Macro to verify base trap frame"
  1810. ;++
  1811. ;
  1812. ; Macro Description:
  1813. ;
  1814. ; This macro verifies the base trap frame is intact.
  1815. ;
  1816. ; It is possible while returning to UserMode that we take an exception.
  1817. ; Any exception which may block, such as not-present, needs to verify
  1818. ; that the base trap frame is not partially dismantled.
  1819. ;
  1820. ; Arguments:
  1821. ; The macro MUST be used directly after ENTER_TRAP macro
  1822. ; as it assumes all sorts of stuff about ESP!
  1823. ;
  1824. ; Return Value:
  1825. ;
  1826. ; If the base frame was incomplete it is totally restored and the
  1827. ; return EIP of the current frame is (virtually) backed up to the
  1828. ; begining of the exit_all - the effect is that the base frame
  1829. ; will be completely exited again. (ie, the exit_all of the base
  1830. ; frame is atomic, if it's interrupted we restore it and do it over).
  1831. ;
  1832. ; None.
  1833. ;
  1834. ;--
  1835. MODIFY_BASE_TRAP_FRAME macro
  1836. local vbfdone
  1837. mov edi, PCR[PcPrcbData+PbCurrentThread] ; Get current thread
  1838. lea eax, [esp]+KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH ; adjust for base frame
  1839. sub eax, [edi].ThInitialStack ; Bias out this stack
  1840. je short vbfdone ; if eq, then this is the base frame
  1841. cmp eax, -TsEflags ; second frame is only this big
  1842. jc short vbfdone ; is stack deeper then 2 frames?
  1843. ; yes, then done
  1844. ;
  1845. ; Stack usage is not exactly one frame, and it's not large enough
  1846. ; to be two complete frames; therefore, we may have a partial base
  1847. ; frame. (unless it's a kernel thread)
  1848. ;
  1849. ; See if this is a kernel thread as kernel threads don't have a base
  1850. ; frame (and therefore don't need correcting).
  1851. ;
  1852. mov eax, PCR[PcTeb]
  1853. or eax, eax ; Any Teb?
  1854. jle short vbfdone ; Br if zero or kernel thread address
  1855. call KiRestoreBaseFrame
  1856. align 4
  1857. vbfdone:
  1858. ENDM
  1859. ;++ KiRestoreBaseFrame
  1860. ;
  1861. ; Routine Description:
  1862. ;
  1863. ; Only to be used from MODIFY_BASE_TRAP_FRAME macro.
  1864. ; Makes lots of assumptions about esp & trap frames
  1865. ;
  1866. ; Arguments:
  1867. ;
  1868. ; Stack:
  1869. ; +-------------------------+
  1870. ; | |
  1871. ; | |
  1872. ; | Npx save area |
  1873. ; | |
  1874. ; | |
  1875. ; +-------------------------+
  1876. ; | (possible mvdm regs) |
  1877. ; +-------------------------+ <- PCR[PcInitialStack]
  1878. ; | |
  1879. ; | Partial base trap frame |
  1880. ; | |
  1881. ; | ------------+
  1882. ; +------------/ | <- Esp @ time of current frame. Location
  1883. ; | | where base trap frame is incomplete
  1884. ; | Completed 'current' |
  1885. ; | trap frame |
  1886. ; | |
  1887. ; | |
  1888. ; | |
  1889. ; | |
  1890. ; +-------------------------+ <- EBP
  1891. ; | return address (dword) |
  1892. ; +-------------------------+ <- current ESP
  1893. ; | |
  1894. ; | |
  1895. ;
  1896. ; Return:
  1897. ;
  1898. ; Stack:
  1899. ; +-------------------------+
  1900. ; | |
  1901. ; | |
  1902. ; | Npx save area |
  1903. ; | |
  1904. ; | |
  1905. ; +-------------------------+
  1906. ; | (possible mvdm regs) |
  1907. ; +-------------------------+ <- PCR[PcInitialStack]
  1908. ; | |
  1909. ; | Base trap frame |
  1910. ; | |
  1911. ; | |
  1912. ; | |
  1913. ; | |
  1914. ; | |
  1915. ; +-------------------------+ <- return esp & ebp
  1916. ; | |
  1917. ; | Current trap frame |
  1918. ; | | EIP set to begining of
  1919. ; | | exit_all code
  1920. ; | |
  1921. ; | |
  1922. ; | |
  1923. ; +-------------------------+ <- EBP, ESP
  1924. ; | |
  1925. ; | |
  1926. ;
  1927. ;--
  1928. KiRestoreBaseFrame proc
  1929. pop ebx ; Get return address
  1930. IF DBG
  1931. mov eax, [esp].TsEip ; EIP of trap
  1932. ;
  1933. ; This code is to handle a very specific problem of a not-present
  1934. ; fault during an exit_all. If it's not this problem then stop.
  1935. ;
  1936. cmp word ptr [eax], POP_GS
  1937. je short @f
  1938. cmp byte ptr [eax], POP_ES
  1939. je short @f
  1940. cmp byte ptr [eax], POP_DS
  1941. je short @f
  1942. cmp word ptr [eax], POP_FS
  1943. je short @f
  1944. cmp byte ptr [eax], IRET_OP
  1945. je short @f
  1946. int 3
  1947. @@:
  1948. ENDIF
  1949. ;
  1950. ; Move current trap frame out of the way to make space for
  1951. ; a full base trap frame
  1952. ;
  1953. mov eax, PCR[PcPrcbData+PbCurrentThread] ; Get current thread
  1954. mov edi, [eax].ThInitialStack
  1955. sub edi, NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + TsEFlags + 4 ; (edi) = bottom of target
  1956. mov esi, esp ; (esi) = bottom of source
  1957. mov esp, edi ; make space before copying the data
  1958. mov ebp, edi ; update location of our trap frame
  1959. push ebx ; put return address back on stack
  1960. mov ecx, (TsEFlags+4)/4 ; # of dword to move
  1961. rep movsd ; Move current trap frame
  1962. ;
  1963. ; Part of the base frame was destroyed when the current frame was
  1964. ; originally pushed. Now that the current frame has been moved out of
  1965. ; the way restore the base frame. We know that any missing data from
  1966. ; the base frame was reloaded into it's corrisponding registers which
  1967. ; were then pushed into the current frame. So we can restore the missing
  1968. ; data from the current frame.
  1969. ;
  1970. mov ecx, esi ; Location of esp at time of fault
  1971. mov edi, [eax].ThInitialStack
  1972. sub edi, NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH ; (edi) = base trap frame
  1973. mov ebx, edi
  1974. sub ecx, edi ; (ecx) = # of bytes which were
  1975. ; removed from base frame before
  1976. ; trap occured
  1977. IF DBG
  1978. test ecx, 3
  1979. jz short @f ; assume dword alignments only
  1980. int 3
  1981. @@:
  1982. ENDIF
  1983. mov esi, ebp ; (esi) = current frame
  1984. shr ecx, 2 ; copy in dwords
  1985. rep movsd
  1986. ;
  1987. ; The base frame is restored. Instead of backing EIP up to the
  1988. ; start of the interrupted EXIT_ALL, we simply move the EIP to a
  1989. ; well known EXIT_ALL. However, this causes a couple of problems
  1990. ; since this exit_all restores every register whereas the original
  1991. ; one may not. So:
  1992. ;
  1993. ; - When exiting from a system call, eax is normally returned by
  1994. ; simply not restoring it. We 'know' that the current trap frame's
  1995. ; EAXs is always the correct one to return. (We know this because
  1996. ; exit_all always restores eax (if it's going to) before any other
  1997. ; instruction which may cause a fault).
  1998. ;
  1999. ; - Not all enter's push the PreviousPreviousMode. Since this is
  2000. ; the base trap frame we know that this must be UserMode.
  2001. ;
  2002. mov eax, [ebp].TsEax ; make sure correct
  2003. mov [ebx].TsEax, eax ; eax is in base frame
  2004. mov byte ptr [ebx].TsPreviousPreviousMode, 1 ; UserMode
  2005. mov [ebp].TsEbp, ebx
  2006. mov [ebp].TsEip, offset _KiServiceExit2 ; ExitAll which
  2007. ; restores everything
  2008. ;
  2009. ; Since we backed up Eip we need to reset some of the kernel selector
  2010. ; values in case they were already restored by the attempted base frame pop
  2011. ;
  2012. mov dword ptr [ebp].TsSegDs, KGDT_R3_DATA OR RPL_MASK
  2013. mov dword ptr [ebp].TsSegEs, KGDT_R3_DATA OR RPL_MASK
  2014. mov dword ptr [ebp].TsSegFs, KGDT_R0_PCR
  2015. ;
  2016. ; The backed up EIP is before interrupts were disabled. Re-enable
  2017. ; interrupts for the current trap frame
  2018. ;
  2019. or [ebp].TsEFlags, EFLAGS_INTERRUPT_MASK
  2020. ret
  2021. KiRestoreBaseFrame endp
  2022. page ,132
  2023. subttl "Divide error processing"
  2024. ;++
  2025. ;
  2026. ; Routine Description:
  2027. ;
  2028. ; Handle divide error fault.
  2029. ;
  2030. ; The divide error fault occurs if a DIV or IDIV instructions is
  2031. ; executed with a divisor of 0, or if the quotient is too big to
  2032. ; fit in the result operand.
  2033. ;
  2034. ; An INTEGER DIVIDED BY ZERO exception will be raised for the fault.
  2035. ; If the fault occurs in kernel mode, the system will be terminated.
  2036. ;
  2037. ; Arguments:
  2038. ;
  2039. ; At entry, the saved CS:EIP point to the faulting instruction.
  2040. ; No error code is provided with the divide error.
  2041. ;
  2042. ; Return value:
  2043. ;
  2044. ; None
  2045. ;
  2046. ;--
  2047. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2048. ENTER_DR_ASSIST kit0_a, kit0_t,NoAbiosAssist
  2049. align dword
  2050. public _KiTrap00
  2051. _KiTrap00 proc
  2052. push 0 ; push dummy error code
  2053. ENTER_TRAP kit0_a, kit0_t
  2054. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2055. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  2056. jnz Kt0040 ; trap occured in V86 mode
  2057. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  2058. jz short Kt0000
  2059. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  2060. jne Kt0020
  2061. ;
  2062. ; Set up exception record for raising Integer_Divided_by_zero exception
  2063. ; and call _KiDispatchException
  2064. ;
  2065. Kt0000:
  2066. if DBG
  2067. test [ebp]+TsEFlags, EFLAGS_INTERRUPT_MASK ; faulted with
  2068. jnz short @f ; interrupts disabled?
  2069. xor eax, eax
  2070. mov esi, [ebp]+TsEip ; [esi] = faulting instruction
  2071. stdCall _KeBugCheckEx,<IRQL_NOT_LESS_OR_EQUAL,eax,-1,eax,esi>
  2072. @@:
  2073. endif
  2074. sti
  2075. ;
  2076. ; Flat mode
  2077. ;
  2078. ; The intel processor raises a divide by zero exception on DIV instructions
  2079. ; which overflow. To be compatible with other processors we want to
  2080. ; return overflows as such and not as divide by zero's. The operand
  2081. ; on the div instruction is tested to see if it's zero or not.
  2082. ;
  2083. stdCall _Ki386CheckDivideByZeroTrap,<ebp>
  2084. mov ebx, [ebp]+TsEip ; (ebx)-> faulting instruction
  2085. jmp CommonDispatchException0Args ; Won't return
  2086. Kt0010:
  2087. ;
  2088. ; 16:16 mode
  2089. ;
  2090. sti
  2091. mov ebx, [ebp]+TsEip ; (ebx)-> faulting instruction
  2092. mov eax, STATUS_INTEGER_DIVIDE_BY_ZERO
  2093. jmp CommonDispatchException0Args ; never return
  2094. Kt0020:
  2095. ; Check to see if this process is a vdm
  2096. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  2097. mov ebx,[ebx]+ThApcState+AsProcess
  2098. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  2099. je Kt0010
  2100. Kt0040:
  2101. stdCall _Ki386VdmReflectException_A, <0>
  2102. or al,al
  2103. jz short Kt0010 ; couldn't reflect, gen exception
  2104. jmp _KiExceptionExit
  2105. _KiTrap00 endp
  2106. page ,132
  2107. subttl "Debug Exception"
  2108. ;++
  2109. ;
  2110. ; Routine Description:
  2111. ;
  2112. ; Handle debug exception.
  2113. ;
  2114. ; The processor triggers this exception for any of the following
  2115. ; conditions:
  2116. ;
  2117. ; 1. Instruction breakpoint fault.
  2118. ; 2. Data address breakpoint trap.
  2119. ; 3. General detect fault.
  2120. ; 4. Single-step trap.
  2121. ; 5. Task-switch breadkpoint trap.
  2122. ;
  2123. ;
  2124. ; Arguments:
  2125. ;
  2126. ; At entry, the values of saved CS and EIP depend on whether the
  2127. ; exception is a fault or a trap.
  2128. ; No error code is provided with the divide error.
  2129. ;
  2130. ; Return value:
  2131. ;
  2132. ; None
  2133. ;
  2134. ;--
  2135. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2136. align dword
  2137. ;
  2138. ; We branch here to handle a trap01 fromt he fast system call entry
  2139. ; we need to propogate the trap bit to the return eflags etc and
  2140. ; continue.
  2141. ;
  2142. Kt0100: mov [ebp].TsEip, _KiFastCallEntry2
  2143. and dword ptr [ebp].TsEflags, NOT EFLAGS_TF
  2144. jmp _KiExceptionExit ; join common code
  2145. ENTER_DR_ASSIST kit1_a, kit1_t, NoAbiosAssist
  2146. align dword
  2147. public _KiTrap01
  2148. _KiTrap01 proc
  2149. ; Set up machine state frame for displaying
  2150. push 0 ; push dummy error code
  2151. ENTER_TRAP kit1_a, kit1_t
  2152. ;
  2153. ; Inspect old EIP in case this is a single stepped
  2154. ; sysenter instruction.
  2155. ;
  2156. mov ecx, [ebp]+TsEip
  2157. cmp ecx, _KiFastCallEntry
  2158. je Kt0100
  2159. ;
  2160. ; See if were doing the fast bap optimization of touching user memory
  2161. ; with ints disabled. If we are then ignore data breakpoints.
  2162. ;
  2163. ;
  2164. if FAST_BOP
  2165. cmp dword ptr PCR[PcVdmAlert], 0
  2166. jne Kt01VdmAlert
  2167. endif
  2168. ;
  2169. ; If caller is user mode, we want interrupts back on.
  2170. ; . all relevent state has already been saved
  2171. ; . user mode code always runs with ints on
  2172. ;
  2173. ; If caller is kernel mode, we want them off!
  2174. ; . some state still in registers, must prevent races
  2175. ; . kernel mode code can run with ints off
  2176. ;
  2177. ;
  2178. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2179. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  2180. jnz kit01_30 ; fault occured in V86 mode => Usermode
  2181. .errnz (MODE_MASK AND 0FFFFFF00h)
  2182. test byte ptr [ebp]+TsSegCs,MODE_MASK
  2183. jz kit01_10
  2184. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  2185. jne kit01_30
  2186. kit01_05:
  2187. sti
  2188. kit01_10:
  2189. ;
  2190. ; Set up exception record for raising single step exception
  2191. ; and call _KiDispatchException
  2192. ;
  2193. kit01_20:
  2194. and dword ptr [ebp]+TsEflags, not EFLAGS_TF
  2195. mov ebx, [ebp]+TsEip ; (ebx)-> faulting instruction
  2196. mov eax, STATUS_SINGLE_STEP
  2197. jmp CommonDispatchException0Args ; Never return
  2198. kit01_30:
  2199. ; Check to see if this process is a vdm
  2200. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  2201. mov ebx,[ebx]+ThApcState+AsProcess
  2202. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  2203. je kit01_05
  2204. stdCall _Ki386VdmReflectException_A, <01h>
  2205. test ax,0FFFFh
  2206. jz Kit01_20
  2207. jmp _KiExceptionExit
  2208. if FAST_BOP
  2209. Kt01VdmAlert:
  2210. ;
  2211. ; If a DEBUG trap occured while we are in VDM alert mode (processing
  2212. ; v86 trap without building trap frame), we will restore all the
  2213. ; registers and return to its recovery routine.
  2214. ;
  2215. mov eax, PCR[PcVdmAlert]
  2216. mov dword ptr PCR[PcVdmAlert], 0
  2217. mov [ebp].TsEip, eax
  2218. mov esp,ebp ; (esp) -> trap frame
  2219. jmp _KiExceptionExit ; join common code
  2220. endif ; FAST_BOP
  2221. _KiTrap01 endp
  2222. page ,132
  2223. subttl "Nonmaskable Interrupt"
  2224. ;++
  2225. ;
  2226. ; Routine Description:
  2227. ;
  2228. ; Handle Nonmaskable interrupt.
  2229. ;
  2230. ; An NMI is typically used to signal serious system conditions
  2231. ; such as bus time-out, memory parity error, and so on.
  2232. ;
  2233. ; Upon detection of the NMI, the system will be terminated, ie a
  2234. ; bugcheck will be raised, no matter what previous mode is.
  2235. ;
  2236. ; Arguments:
  2237. ;
  2238. ; No error code is provided with the error.
  2239. ;
  2240. ; Return value:
  2241. ;
  2242. ; None
  2243. ;
  2244. ;--
  2245. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2246. ; ENTER_DR_ASSIST kit2_a, kit2_t, NoAbiosAssist
  2247. align dword
  2248. public _KiTrap02
  2249. _KiTrap02 proc
  2250. .FPO (1, 0, 0, 0, 0, 2)
  2251. cli
  2252. ;
  2253. ; Set CR3, the I/O map base address, and LDT segment selector
  2254. ; in the old TSS since they are not set on context
  2255. ; switches. These values will be needed to return to the
  2256. ; interrupted task.
  2257. mov eax, PCR[PcTss] ; get old TSS address
  2258. mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get thread address
  2259. mov edi, [ecx].ThApcState.AsProcess ; get process address
  2260. mov ecx, [edi]+PrDirectoryTableBase ; get directory base
  2261. mov [eax]+TssCR3, ecx ; set previous cr3
  2262. mov cx, [edi]+PrIopmOffset ; get IOPM offset
  2263. mov [eax]+TssIoMapBase, cx ; set IOPM offset
  2264. mov ecx, [edi]+PrLdtDescriptor ; get LDT descriptor
  2265. test ecx, ecx ; does task use LDT?
  2266. jz @f
  2267. mov cx, KGDT_LDT
  2268. @@: mov [eax]+TssLDT, cx ; set LDT into old TSS
  2269. ;
  2270. ; Update the TSS pointer in the PCR to point to the NMI TSS
  2271. ; (which is what we're running on, or else we wouldn't be here)
  2272. ;
  2273. push dword ptr PCR[PcTss]
  2274. mov eax, PCR[PcGdt]
  2275. mov ch, [eax+KGDT_NMI_TSS+KgdtBaseHi]
  2276. mov cl, [eax+KGDT_NMI_TSS+KgdtBaseMid]
  2277. shl ecx, 16
  2278. mov cx, [eax+KGDT_NMI_TSS+KgdtBaseLow]
  2279. mov PCR[PcTss], ecx
  2280. ;
  2281. ; Clear Nested Task bit in EFLAGS
  2282. ;
  2283. pushfd
  2284. and [esp], not 04000h
  2285. popfd
  2286. ;
  2287. ; Clear the busy bit in the TSS selector
  2288. ;
  2289. mov ecx, PCR[PcGdt]
  2290. lea eax, [ecx] + KGDT_NMI_TSS
  2291. mov byte ptr [eax+5], 089h ; 32bit, dpl=0, present, TSS32, not busy
  2292. ;
  2293. ; Allow only one processor at a time to enter the NMI path. While
  2294. ; waiting, spin on a LOCAL data structure (to avoid cache thrashing
  2295. ; during a crashdump which can cause the dump to hang), and poll for
  2296. ; Freeze IPI requests so that the correct state for this processor
  2297. ; appears in the crashdump.
  2298. ;
  2299. ;
  2300. ; (1) make a trap frame,
  2301. ; (2) acquire lock
  2302. ; (3) while not lock owner
  2303. ; (4) if (IPI_FREEZE)
  2304. ; (5) KeFreezeExecutionTarget(&TrapFrame, NULL)
  2305. ; (6) let the HAL have it
  2306. ; (7) release lock to next in line
  2307. ;
  2308. ; Build trap frame from the data in the previous TSS.
  2309. ;
  2310. mov eax, [esp] ; get saved TSS address
  2311. push 0 ; build trap frame, starting with
  2312. push 0 ; faked V86Gs thru V86Es
  2313. push 0
  2314. push 0
  2315. push [eax].TssSs ; copy fields from TSS to
  2316. push [eax].TssEsp ; trap frame.
  2317. push [eax].TssEflags
  2318. push [eax].TssCs
  2319. push [eax].TssEip
  2320. push 0
  2321. push [eax].TssEbp
  2322. push [eax].TssEbx
  2323. push [eax].TssEsi
  2324. push [eax].TssEdi
  2325. push [eax].TssFs
  2326. push PCR[PcExceptionList]
  2327. push -1 ; previous mode
  2328. push [eax].TssEax
  2329. push [eax].TssEcx
  2330. push [eax].TssEdx
  2331. push [eax].TssDs
  2332. push [eax].TssEs
  2333. push [eax].TssGs
  2334. push 0 ; fake out the debug registers
  2335. push 0
  2336. push 0
  2337. push 0
  2338. push 0
  2339. push 0
  2340. push 0 ; temp ESP
  2341. push 0 ; temp CS
  2342. push 0
  2343. push 0
  2344. push [eax].TssEip
  2345. push [eax].TssEbp
  2346. mov ebp, esp ; ebp -> TrapFrame
  2347. .FPO ( 0, 0, 0, 0, 0, FPO_TRAPFRAME )
  2348. stdCall _KiHandleNmi ; Rundown the list of NMI handlers
  2349. or al, al ; did someone handle it?
  2350. jne short Kt0210 ; jif handled
  2351. ifndef NT_UP
  2352. ;
  2353. ; Acquire the NMI Lock. If it is not available, check for freeze
  2354. ; execution in case another processor is trying to dump memory.
  2355. ;
  2356. lea eax, KiLockNMI ; build in stack queued spin lock.
  2357. push eax
  2358. push 0
  2359. mov ecx, esp
  2360. mov edx, ebp
  2361. fstCall KiAcquireQueuedSpinLockCheckForFreeze
  2362. endif
  2363. ;
  2364. ; This processor now owns the NMI lock. See if the HAL will
  2365. ; handle the NMI. If the HAL does not handle it, it will NOT
  2366. ; return, so if we get back here, it's handled.
  2367. ;
  2368. stdCall _HalHandleNMI,<0>
  2369. ;
  2370. ; We're back, therefore the Hal has dealt with the NMI.
  2371. ;
  2372. ifndef NT_UP
  2373. mov ecx, esp ; release queued spinlock.
  2374. fstCall KeReleaseQueuedSpinLockFromDpcLevel
  2375. add esp, 8 ; free queued spinlock context
  2376. endif
  2377. Kt0210: add esp, KTRAP_FRAME_LENGTH ; free trap frame and qlock
  2378. pop dword ptr PCR[PcTss] ; restore PcTss
  2379. mov ecx, PCR[PcGdt]
  2380. lea eax, [ecx] + KGDT_TSS
  2381. mov byte ptr [eax+5], 08bh ; 32bit, dpl=0, present, TSS32, *busy*
  2382. pushfd ; Set Nested Task bit in EFLAGS
  2383. or [esp], 04000h ; so iretd will do a task switch
  2384. popfd
  2385. iretd ; Return from NMI
  2386. jmp _KiTrap02 ; in case we NMI again
  2387. _KiTrap02 endp
  2388. page ,132
  2389. subttl "DebugService Breakpoint"
  2390. ;++
  2391. ;
  2392. ; Routine Description:
  2393. ;
  2394. ; Handle INT 2d DebugService
  2395. ;
  2396. ; The trap is caused by an INT 2d. This is used instead of a
  2397. ; BREAKPOINT exception so that parameters can be passed for the
  2398. ; requested debug service. A BREAKPOINT instruction is assumed
  2399. ; to be right after the INT 2d - this allows this code to share code
  2400. ; with the breakpoint handler.
  2401. ;
  2402. ; Arguments:
  2403. ; eax - ServiceClass - which call is to be performed
  2404. ; ecx - Arg1 - generic first argument
  2405. ; edx - Arg2 - generic second argument
  2406. ; ebx - Arg3 - generic third argument
  2407. ;
  2408. ;--
  2409. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2410. ENTER_DR_ASSIST kids_a, kids_t, NoAbiosAssist
  2411. align dword
  2412. public _KiDebugService
  2413. _KiDebugService proc
  2414. push 0 ; push dummy error code
  2415. ENTER_TRAP kids_a, kids_t
  2416. ; sti ; *NEVER sti here*
  2417. inc dword ptr [ebp]+TsEip
  2418. mov eax, [ebp]+TsEax ; ServiceClass
  2419. mov ecx, [ebp]+TsEcx ; Arg1 (already loaded)
  2420. mov edx, [ebp]+TsEdx ; Arg2 (already loaded)
  2421. jmp KiTrap03DebugService
  2422. _KiDebugService endp
  2423. page ,132
  2424. subttl "Single Byte INT3 Breakpoin"
  2425. ;++
  2426. ;
  2427. ; Routine Description:
  2428. ;
  2429. ; Handle INT 3 breakpoint.
  2430. ;
  2431. ; The trap is caused by a single byte INT 3 instruction. A
  2432. ; BREAKPOINT exception with additional parameter indicating
  2433. ; READ access is raised for this trap if previous mode is user.
  2434. ;
  2435. ; Arguments:
  2436. ;
  2437. ; At entry, the saved CS:EIP point to the instruction immediately
  2438. ; following the INT 3 instruction.
  2439. ; No error code is provided with the error.
  2440. ;
  2441. ; Return value:
  2442. ;
  2443. ; None
  2444. ;
  2445. ;--
  2446. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2447. ENTER_DR_ASSIST kit3_a, kit3_t, NoAbiosAssist
  2448. align dword
  2449. public _KiTrap03
  2450. _KiTrap03 proc
  2451. push 0 ; push dummy error code
  2452. ENTER_TRAP kit3_a, kit3_t
  2453. cmp ds:_PoHiberInProgress, 0
  2454. jnz short kit03_01
  2455. lock inc ds:_KiHardwareTrigger ; trip hardware analyzer
  2456. kit03_01:
  2457. mov eax, BREAKPOINT_BREAK
  2458. KiTrap03DebugService:
  2459. ;
  2460. ; If caller is user mode, we want interrupts back on.
  2461. ; . all relevent state has already been saved
  2462. ; . user mode code always runs with ints on
  2463. ;
  2464. ; If caller is kernel mode, we want them off!
  2465. ; . some state still in registers, must prevent races
  2466. ; . kernel mode code can run with ints off
  2467. ;
  2468. ;
  2469. ; Arguments:
  2470. ; eax - ServiceClass - which call is to be performed
  2471. ; ecx - Arg1 - generic first argument
  2472. ; edx - Arg2 - generic second argument
  2473. ;
  2474. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2475. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  2476. jnz kit03_30 ; fault occured in V86 mode => Usermode
  2477. .errnz (MODE_MASK AND 0FFFFFF00h)
  2478. test byte ptr [ebp]+TsSegCs,MODE_MASK
  2479. jz kit03_10
  2480. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  2481. jne kit03_30
  2482. kit03_05:
  2483. sti
  2484. kit03_10:
  2485. ;
  2486. ; Set up exception record and arguments for raising breakpoint exception
  2487. ;
  2488. mov esi, ecx ; ExceptionInfo 2
  2489. mov edi, edx ; ExceptionInfo 3
  2490. mov edx, eax ; ExceptionInfo 1
  2491. mov ebx, [ebp]+TsEip
  2492. dec ebx ; (ebx)-> int3 instruction
  2493. mov ecx, 3
  2494. mov eax, STATUS_BREAKPOINT
  2495. call CommonDispatchException ; Never return
  2496. kit03_30:
  2497. ; Check to see if this process is a vdm
  2498. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  2499. mov ebx,[ebx]+ThApcState+AsProcess
  2500. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  2501. je kit03_05
  2502. stdCall _Ki386VdmReflectException_A, <03h>
  2503. test ax,0FFFFh
  2504. jz Kit03_10
  2505. jmp _KiExceptionExit
  2506. _KiTrap03 endp
  2507. page ,132
  2508. subttl "Integer Overflow"
  2509. ;++
  2510. ;
  2511. ; Routine Description:
  2512. ;
  2513. ; Handle INTO overflow.
  2514. ;
  2515. ; The trap occurs when the processor encounters an INTO instruction
  2516. ; and the OF flag is set.
  2517. ;
  2518. ; An INTEGER_OVERFLOW exception will be raised for this fault.
  2519. ;
  2520. ; N.B. i386 will not generate fault if only OF flag is set.
  2521. ;
  2522. ; Arguments:
  2523. ;
  2524. ; At entry, the saved CS:EIP point to the instruction immediately
  2525. ; following the INTO instruction.
  2526. ; No error code is provided with the error.
  2527. ;
  2528. ; Return value:
  2529. ;
  2530. ; None
  2531. ;
  2532. ;--
  2533. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2534. ENTER_DR_ASSIST kit4_a, kit4_t, NoAbiosAssist
  2535. align dword
  2536. public _KiTrap04
  2537. _KiTrap04 proc
  2538. push 0 ; push dummy error code
  2539. ENTER_TRAP kit4_a, kit4_t
  2540. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2541. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  2542. jnz short Kt0430 ; in a vdm, reflect to vdm
  2543. .errnz (MODE_MASK AND 0FFFFFF00h)
  2544. test byte ptr [ebp]+TsSegCs,MODE_MASK
  2545. jz short Kt0410 ; in kernel mode, gen exception
  2546. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  2547. jne short Kt0420 ; maybe in a vdm
  2548. ; Set up exception record and arguments for raising exception
  2549. Kt0410: sti
  2550. mov ebx, [ebp]+TsEip ; (ebx)-> instr. after INTO
  2551. dec ebx ; (ebx)-> INTO
  2552. mov eax, STATUS_INTEGER_OVERFLOW
  2553. jmp CommonDispatchException0Args ; Never return
  2554. Kt0430:
  2555. stdCall _Ki386VdmReflectException_A, <04h>
  2556. test al,0fh
  2557. jz Kt0410 ; couldn't reflect, gen exception
  2558. jmp _KiExceptionExit
  2559. Kt0420:
  2560. ; Check to see if this process is a vdm
  2561. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  2562. mov ebx,[ebx]+ThApcState+AsProcess
  2563. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  2564. je Kt0410
  2565. jmp Kt0430
  2566. _KiTrap04 endp
  2567. page ,132
  2568. subttl "Bound Check fault"
  2569. ;++
  2570. ;
  2571. ; Routine Description:
  2572. ;
  2573. ; Handle bound check fault.
  2574. ;
  2575. ; The bound check fault occurs if a BOUND instruction finds that
  2576. ; the tested value is outside the specified range.
  2577. ;
  2578. ; For bound check fault, an ARRAY BOUND EXCEEDED exception will be
  2579. ; raised.
  2580. ; For kernel mode exception, it causes system to be terminated.
  2581. ;
  2582. ; Arguments:
  2583. ;
  2584. ; At entry, the saved CS:EIP point to the faulting BOUND
  2585. ; instruction.
  2586. ; No error code is provided with the error.
  2587. ;
  2588. ; Return value:
  2589. ;
  2590. ; None
  2591. ;
  2592. ;--
  2593. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2594. ENTER_DR_ASSIST kit5_a, kit5_t, NoAbiosAssist
  2595. align dword
  2596. public _KiTrap05
  2597. _KiTrap05 proc
  2598. push 0 ; push dummy error code
  2599. ENTER_TRAP kit5_a, kit5_t
  2600. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2601. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  2602. jnz short Kt0530 ; fault in V86 mode
  2603. .errnz (MODE_MASK AND 0FFFFFF00h)
  2604. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  2605. jnz short Kt0500 ; if nz, previous mode = user
  2606. mov eax, EXCEPTION_BOUND_CHECK ; (eax) = exception type
  2607. jmp _KiSystemFatalException ; go terminate the system
  2608. kt0500: cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  2609. jne short Kt0520 ; maybe in a vdm
  2610. ;
  2611. ; set exception record and arguments and call _KiDispatchException
  2612. ;
  2613. Kt0510: sti
  2614. mov ebx, [ebp]+TsEip ; (ebx)->BOUND instruction
  2615. mov eax, STATUS_ARRAY_BOUNDS_EXCEEDED
  2616. jmp CommonDispatchException0Args ; Won't return
  2617. Kt0520:
  2618. ; Check to see if this process is a vdm
  2619. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  2620. mov ebx,[ebx]+ThApcState+AsProcess
  2621. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  2622. je Kt0510
  2623. Kt0530:
  2624. stdCall _Ki386VdmReflectException_A, <05h>
  2625. test al,0fh
  2626. jz Kt0510 ; couldn't reflect, gen exception
  2627. jmp _KiExceptionExit
  2628. _KiTrap05 endp
  2629. page ,132
  2630. subttl "Invalid OP code"
  2631. ;++
  2632. ;
  2633. ; Routine Description:
  2634. ;
  2635. ; Handle invalid op code fault.
  2636. ;
  2637. ; The invalid opcode fault occurs if CS:EIP point to a bit pattern which
  2638. ; is not recognized as an instruction by the x86. This may happen if:
  2639. ;
  2640. ; 1. the opcode is not a valid 80386 instruction
  2641. ; 2. a register operand is specified for an instruction which requires
  2642. ; a memory operand
  2643. ; 3. the LOCK prefix is used on an instruction that cannot be locked
  2644. ;
  2645. ; If fault occurs in USER mode:
  2646. ; an Illegal_Instruction exception will be raised
  2647. ; if fault occurs in KERNEL mode:
  2648. ; system will be terminated.
  2649. ;
  2650. ; Arguments:
  2651. ;
  2652. ; At entry, the saved CS:EIP point to the first byte of the invalid
  2653. ; instruction.
  2654. ; No error code is provided with the error.
  2655. ;
  2656. ; Return value:
  2657. ;
  2658. ; None
  2659. ;
  2660. ;--
  2661. ASSUME DS:FLAT, SS:NOTHING, ES:NOTHING
  2662. ENTER_DR_ASSIST kit6_a, kit6_t, NoAbiosAssist,, kit6_v
  2663. align dword
  2664. public _KiTrap06
  2665. _KiTrap06 proc
  2666. ;
  2667. ; KiTrap06 is performance critical for VDMs and rarely executed in
  2668. ; native mode. So this routine is tuned for the VDM case.
  2669. ;
  2670. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2671. test byte ptr [esp]+8h+2,EFLAGS_V86_MASK/010000h
  2672. jz Kt060i
  2673. if FAST_BOP
  2674. FAST_V86_TRAP_6
  2675. endif
  2676. Kt6SlowBop:
  2677. push 0 ; push dummy error code
  2678. ENTER_TRAPV86 kit6_a, kit6_v
  2679. Kt6SlowBop1:
  2680. Kt06VMpf:
  2681. ;
  2682. ; If the current process is NOT a VDM just hand it an
  2683. ; illegal instruction exception.
  2684. ;
  2685. mov ecx,PCR[PcPrcbData+PbCurrentThread]
  2686. mov ecx,[ecx]+ThApcState+AsProcess
  2687. cmp dword ptr [ecx]+PrVdmObjects,0 ; if not a vdm process,
  2688. je Kt0635 ; then deliver exception
  2689. ;
  2690. ; Raise Irql to APC level before enabling interrupts to prevent
  2691. ; a setcontext from editing the trapframe.
  2692. ;
  2693. RaiseIrql APC_LEVEL
  2694. push eax ; Save OldIrql
  2695. if DBG
  2696. cmp eax, PASSIVE_LEVEL
  2697. je @f
  2698. int 3
  2699. @@:
  2700. endif
  2701. sti
  2702. ;
  2703. ; Call VdmDispatchBop to try and handle the opcode immediately.
  2704. ; If it returns FALSE (meaning too complicated for us to quickly parse)
  2705. ; then reflect the opcode off to the ntvdm monitor to handle it.
  2706. ;
  2707. stdCall _VdmDispatchBop, <ebp>
  2708. ;
  2709. ; If the operation was processed directly above then return back now.
  2710. ;
  2711. test al,0fh
  2712. jnz short Kt061i
  2713. ;
  2714. ; The operation could not be processed directly above so reflect it
  2715. ; back to the ntvdm monitor now.
  2716. ;
  2717. stdCall _Ki386VdmReflectException,<6>
  2718. test al,0fh
  2719. jnz Kt061i
  2720. pop ecx ; (TOS) = OldIrql
  2721. LowerIrql ecx
  2722. jmp Kt0635
  2723. Kt061i:
  2724. pop ecx ; (TOS) = OldIrql
  2725. LowerIrql ecx
  2726. cli
  2727. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  2728. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  2729. jz Kt062i
  2730. ;
  2731. ; EXIT_TRAPv86 does not exit if a user mode apc has switched
  2732. ; the context from V86 mode to flat mode (VDM monitor context)
  2733. ;
  2734. EXIT_TRAPV86
  2735. Kt062i:
  2736. jmp _KiExceptionExit
  2737. Kt060i:
  2738. ;
  2739. ; Non-v86 (user or kernel) executing code arrives here for
  2740. ; invalid opcode traps.
  2741. ;
  2742. push 0 ; Push dummy error code
  2743. ENTER_TRAP kit6_a, kit6_t
  2744. Kt06pf:
  2745. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  2746. jz short Kt0635 ; if z, kernel mode - go dispatch exception
  2747. ;
  2748. ; UserMode. Did the fault happen in a vdm running in protected mode?
  2749. ;
  2750. cmp word ptr [ebp]+TsSegCs, KGDT_R3_CODE OR RPL_MASK
  2751. jz short kt0605 ; normal 32-bit mode so give exception
  2752. ;
  2753. ; The code segment is not a normal flat 32-bit entity, so see if
  2754. ; this process is a vdm. If so, then try to handle it. If not,
  2755. ; give this process an exception.
  2756. ;
  2757. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  2758. mov ebx,[ebx]+ThApcState+AsProcess
  2759. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  2760. jne Kt0650
  2761. kt0605:
  2762. ;
  2763. ; Invalid Opcode exception could be either INVALID_LOCK_SEQUENCE or
  2764. ; ILLEGAL_INSTRUCTION.
  2765. ;
  2766. mov eax, [ebp]+TsSegCs
  2767. mov esi, [ebp]+TsEip
  2768. sti
  2769. mov ecx, MAX_INSTRUCTION_PREFIX_LENGTH
  2770. ;
  2771. ; Set up an exception handler in case we fault
  2772. ; while reading the user mode instruction.
  2773. ;
  2774. push es
  2775. push ebp ; pass trapframe to handler
  2776. push offset FLAT:Kt6_ExceptionHandler
  2777. ; set up exception registration record
  2778. push PCR[PcExceptionList]
  2779. mov PCR[PcExceptionList], esp
  2780. ; (es:esi) -> address of faulting instruction
  2781. mov es, ax
  2782. @@:
  2783. mov al, byte ptr es:[esi] ; (al)= instruction byte
  2784. cmp al, MI_LOCK_PREFIX ; Is it a lock prefix?
  2785. je short Kt0640 ; Yes, raise Invalid_lock exception
  2786. add esi, 1
  2787. loop short @b ; keep on looping
  2788. pop PCR[PcExceptionList]
  2789. add esp, 8 ; clear stack
  2790. Kt0630:
  2791. pop es
  2792. ;
  2793. ; Set up exception record for raising Illegal instruction exception
  2794. ;
  2795. Kt0635:
  2796. sti
  2797. mov ebx, [ebp]+TsEip ; (ebx)-> invalid instruction
  2798. mov eax, STATUS_ILLEGAL_INSTRUCTION
  2799. jmp CommonDispatchException0Args ; Won't return
  2800. ;
  2801. ; Set up exception record for raising Invalid lock sequence exception
  2802. ;
  2803. Kt0640:
  2804. pop PCR[PcExceptionList]
  2805. add esp, 8 ; clear stack
  2806. pop es
  2807. mov ebx, [ebp]+TsEip ; (ebx)-> invalid instruction
  2808. mov eax, STATUS_INVALID_LOCK_SEQUENCE
  2809. jmp CommonDispatchException0Args ; Won't return
  2810. Kt0650:
  2811. ; Raise Irql to APC level before enabling interrupts
  2812. RaiseIrql APC_LEVEL
  2813. push eax ; SaveOldIrql
  2814. sti
  2815. stdCall _VdmDispatchBop, <ebp>
  2816. test al,0fh
  2817. jnz short Kt0660
  2818. stdCall _Ki386VdmReflectException,<6>
  2819. test al,0fh
  2820. jnz Kt0660
  2821. pop ecx ; (TOS) = OldIrql
  2822. LowerIrql ecx
  2823. jmp short Kt0635
  2824. Kt0660:
  2825. pop ecx ; (TOS) = OldIrql
  2826. LowerIrql ecx
  2827. jmp _KiExceptionExit
  2828. _KiTrap06 endp
  2829. ;
  2830. ; Error and exception blocks for KiTrap06
  2831. ;
  2832. Kt6_ExceptionHandler proc
  2833. ;
  2834. ; WARNING: Here we directly unlink the exception handler from the
  2835. ; exception registration chain. NO unwind is performed.
  2836. ;
  2837. mov esp, [esp+8] ; (esp)-> ExceptionList
  2838. pop PCR[PcExceptionList]
  2839. add esp, 4 ; pop out except handler
  2840. pop ebp ; (ebp)-> trap frame
  2841. test dword ptr [ebp].TsSegCs, MODE_MASK ; if premode=kernel
  2842. jnz Kt0630 ; nz, prevmode=user, go return
  2843. ;
  2844. ; Raise bugcheck if prevmode=kernel
  2845. ;
  2846. stdCall _KeBugCheck, <KMODE_EXCEPTION_NOT_HANDLED>
  2847. Kt6_ExceptionHandler endp
  2848. page ,132
  2849. subttl "Coprocessor Not Avalaible"
  2850. ;++
  2851. ;
  2852. ; Routine Description:
  2853. ;
  2854. ; Handle Coprocessor not available exception.
  2855. ;
  2856. ; If we are REALLY emulating the FPU, the trap 07 vector is edited
  2857. ; to point directly at the emulator's entry point. So this code is
  2858. ; only hit when FPU hardware DOES exist.
  2859. ;
  2860. ; The current thread's coprocessor state is loaded into the
  2861. ; coprocessor. If the coprocessor has a different thread's state
  2862. ; in it (UP only) it is first saved away. The thread is then continued.
  2863. ; Note: the thread's state may contian the TS bit - In this case the
  2864. ; code loops back to the top of the Trap07 handler. (which is where
  2865. ; we would end up if we let the thread return to user code anyway).
  2866. ;
  2867. ; If the thread's NPX context is in the coprocessor and we hit a Trap07
  2868. ; there is an NPX error which needs to be processed. If the trap was
  2869. ; from usermode the error is dispatched. If the trap was from kernelmode
  2870. ; the error is remembered, but we clear CR0 so the kernel code can
  2871. ; continue. We can do this because the kernel mode code will restore
  2872. ; CR0 (and set TS) to signal a delayed error for this thread.
  2873. ;
  2874. ; Arguments:
  2875. ;
  2876. ; At entry, the saved CS:EIP point to the first byte of the faulting
  2877. ; instruction.
  2878. ; No error code is provided with the error.
  2879. ;
  2880. ; Return value:
  2881. ;
  2882. ; None
  2883. ;
  2884. ;--
  2885. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  2886. ENTER_DR_ASSIST kit7_a, kit7_t, NoAbiosAssist
  2887. align dword
  2888. public _KiTrap07
  2889. _KiTrap07 proc
  2890. push 0 ; push dummy error code
  2891. ENTER_TRAP kit7_a, kit7_t
  2892. Kt0700:
  2893. mov eax, PCR[PcPrcbData+PbCurrentThread]
  2894. mov ecx, [eax].ThInitialStack ; (ecx) -> top of kernel stack
  2895. sub ecx, NPX_FRAME_LENGTH
  2896. cli ; don't context switch
  2897. .errnz (CR0_EM AND 0FFFFFF00h)
  2898. test byte ptr [ecx].FpCr0NpxState,CR0_EM
  2899. jnz Kt07140
  2900. Kt0701: cmp byte ptr [eax].ThNpxState, NPX_STATE_LOADED
  2901. mov ebx, cr0
  2902. je Kt0710
  2903. ;
  2904. ; Trap occured and this thread's NPX state is not loaded. Load it now
  2905. ; and resume the application. If someone else's state is in the coprocessor
  2906. ; (uniprocessor implementation only) then save it first.
  2907. ;
  2908. and ebx, NOT (CR0_MP+CR0_TS+CR0_EM)
  2909. mov cr0, ebx ; allow frstor (& fnsave) to work
  2910. ifdef NT_UP
  2911. Kt0702:
  2912. mov edx, PCR[PcPrcbData+PbNpxThread] ; Owner of NPX state
  2913. or edx, edx ; NULL?
  2914. jz Kt0704 ; Yes - skip save
  2915. ;
  2916. ; Due to an hardware errata we need to know that the coprocessor
  2917. ; doesn't generate an error condition once interrupts are disabled and
  2918. ; trying to perform an fnsave which could wait for the error condition
  2919. ; to be handled.
  2920. ;
  2921. ; The fix for this errata is that we "know" that the coprocessor is
  2922. ; being used by a different thread then the one which may have caused
  2923. ; the error condition. The round trip time to swap to a new thread
  2924. ; is longer then ANY floating point instruction. We therefore know
  2925. ; that any possible coprocessor error has already occured and been
  2926. ; handled.
  2927. ;
  2928. mov esi,[edx].ThInitialStack
  2929. sub esi, NPX_FRAME_LENGTH ; Space for NPX_FRAME
  2930. test byte ptr _KeI386FxsrPresent, 1 ; Is FXSR feature present
  2931. jz short Kt0703a
  2932. FXSAVE_ESI
  2933. jmp short Kt0703b
  2934. Kt0703a:
  2935. fnsave [esi] ; Save thread's coprocessor state
  2936. Kt0703b:
  2937. mov byte ptr [edx].ThNpxState, NPX_STATE_NOT_LOADED
  2938. Kt0704:
  2939. endif
  2940. ;
  2941. ; Load current thread's coprocessor state into the coprocessor
  2942. ;
  2943. ; (eax) - CurrentThread
  2944. ; (ecx) - CurrentThread's NPX save area
  2945. ; (ebx) - CR0
  2946. ; (ebp) - trap frame
  2947. ; Interrupts disabled
  2948. ;
  2949. ;
  2950. ; frstor might generate a NPX exception if there's an error image being
  2951. ; loaded. The handler will simply set the TS bit for this context an iret.
  2952. ;
  2953. test byte ptr _KeI386FxsrPresent, 1 ; Is FXSR feature present
  2954. jz short Kt0704b
  2955. ifndef NT_UP
  2956. if 0 ; FpNpxSavedCpu is broken - disable it
  2957. ;
  2958. ; We need not load the NPX state if
  2959. ; - PCR[PbNpxThread] matches new thread AND
  2960. ; - FpNpxSavedCpu matches the current processor
  2961. mov edx, PCR[PcSelfPcr]
  2962. cmp [edx+PcPrcbData+PbNpxThread], eax
  2963. jne Kt0704a
  2964. cmp dword ptr [ecx].FpNpxSavedCpu, edx
  2965. jne short Kt0704a
  2966. jmp short Kt0704c
  2967. Kt0704a:
  2968. mov dword ptr [ecx].FpNpxSavedCpu, edx ; Remember processor
  2969. endif
  2970. endif
  2971. FXRSTOR_ECX ; reload NPX context
  2972. jmp short Kt0704c
  2973. Kt0704b:
  2974. frstor [ecx] ; reload NPX context
  2975. Kt0704c:
  2976. mov byte ptr [eax].ThNpxState, NPX_STATE_LOADED
  2977. mov PCR[PcPrcbData+PbNpxThread], eax ; owner of coprocessors state
  2978. sti ; Allow interrupts & context switches
  2979. nop ; sti needs one cycle
  2980. cmp dword ptr [ecx].FpCr0NpxState, 0
  2981. jz _KiExceptionExit ; nothing to set, skip CR0 reload
  2982. ;
  2983. ; Note: we have to get the CR0 value again to insure that we have the
  2984. ; correct state for TS. We may have context switched since
  2985. ; the last move from CR0, and our npx state may have been moved off
  2986. ; of the npx.
  2987. ;
  2988. cli
  2989. if DBG
  2990. test dword ptr [ecx].FpCr0NpxState, NOT (CR0_MP+CR0_EM+CR0_TS)
  2991. jnz short Kt07dbg1
  2992. endif
  2993. mov ebx,CR0
  2994. or ebx, [ecx].FpCr0NpxState
  2995. mov cr0, ebx ; restore thread's CR0 NPX state
  2996. sti
  2997. .errnz (CR0_TS AND 0FFFFFF00h)
  2998. test bl, CR0_TS ; Setting TS? (delayed error)
  2999. jz _KiExceptionExit ; No - continue
  3000. clts
  3001. jmp Kt0700 ; Dispatch delayed exception
  3002. if DBG
  3003. Kt07dbg1: int 3
  3004. Kt07dbg2: int 3
  3005. Kt07dbg3: int 3
  3006. sti
  3007. jmp short $-2
  3008. endif
  3009. Kt0705:
  3010. ;
  3011. ; A Trap07 or Trap10 has occured from a ring 0 ESCAPE instruction. This
  3012. ; may occur when trying to load the coprocessors state. These
  3013. ; code paths rely on Cr0NpxState to signal a delayed error (not CR0) - we
  3014. ; set CR0_TS in Cr0NpxState to get a delayed error, and make sure CR0 CR0_TS
  3015. ; is not set so the R0 ESC instruction(s) can complete.
  3016. ;
  3017. ; (ecx) - CurrentThread's NPX save area
  3018. ; (ebp) - trap frame
  3019. ; Interrupts disabled
  3020. ;
  3021. if DBG
  3022. mov eax, cr0 ; Did we fault because some bit in CR0
  3023. test eax, (CR0_TS+CR0_MP+CR0_EM)
  3024. jnz short Kt07dbg3
  3025. endif
  3026. or dword ptr [ecx].FpCr0NpxState, CR0_TS ; signal a delayed error
  3027. cmp dword ptr [ebp]+TsEip, Kt0704b ; Is this fault on reload a thread's context?
  3028. jne short Kt0716 ; No, dispatch exception
  3029. add dword ptr [ebp]+TsEip, 3 ; Skip frstor ecx instruction
  3030. jmp _KiExceptionExit
  3031. Kt0710:
  3032. .errnz (CR0_TS AND 0FFFFFF00h)
  3033. test bl, CR0_TS ; check for task switch
  3034. jnz Kt07150
  3035. ;
  3036. ; WARNING: May enter here from the trap 10 handler.
  3037. ;
  3038. Kt0715:
  3039. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  3040. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  3041. jnz Kt07110 ; v86 mode
  3042. .errnz (MODE_MASK AND 0FFFFFF00h)
  3043. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previousMode=USER?
  3044. jz Kt0705 ; if z, previousmode=SYSTEM
  3045. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  3046. jne Kt07110
  3047. ;
  3048. ; We are about to dispatch a floating point exception to user mode.
  3049. ; We need to check to see if the user's NPX instruction is supposed to
  3050. ; cause an exception or not.
  3051. ;
  3052. ; (ecx) - CurrentThread's NPX save area
  3053. ;
  3054. Kt0716: stdCall _Ki386CheckDelayedNpxTrap,<ebp,ecx>
  3055. or al, al
  3056. jnz _KiExceptionExit ; Already handled
  3057. mov eax, PCR[PcPrcbData+PbCurrentThread]
  3058. mov ecx, [eax].ThInitialStack ; (ecx) -> top of kernel stack
  3059. sub ecx, NPX_FRAME_LENGTH
  3060. Kt0720:
  3061. ;
  3062. ; Some type of coprocessor exception has occured for the current thread.
  3063. ;
  3064. ; (eax) - CurrentThread
  3065. ; (ecx) - CurrentThread's NPX save area
  3066. ; (ebp) - TrapFrame
  3067. ; Interrupts disabled
  3068. ;
  3069. mov ebx, cr0
  3070. and ebx, NOT (CR0_MP+CR0_EM+CR0_TS)
  3071. mov cr0, ebx ; Clear MP+TS+EM to do fnsave & fwait
  3072. ;
  3073. ; Save the faulting state so we can inspect the cause of the floating
  3074. ; point fault
  3075. ;
  3076. test byte ptr _KeI386FxsrPresent, 1 ; Is FXSR feature present
  3077. jz short Kt0725a
  3078. FXSAVE_ECX
  3079. jmp short Kt0725b
  3080. Kt0725a:
  3081. fnsave [ecx] ; Save thread's coprocessor state
  3082. fwait ; in case fnsave hasn't finished yet
  3083. Kt0725b:
  3084. if DBG
  3085. test dword ptr [ecx].FpCr0NpxState, NOT (CR0_MP+CR0_EM+CR0_TS)
  3086. jnz Kt07dbg2
  3087. endif
  3088. or ebx, NPX_STATE_NOT_LOADED
  3089. or ebx,[ecx]+FpCr0NpxState ; restore this thread's CR0 NPX state
  3090. mov cr0, ebx ; set TS so next ESC access causes trap
  3091. ;
  3092. ; Clear TS bit in Cr0NpxFlags in case it was set to trigger this trap.
  3093. ;
  3094. and dword ptr [ecx].FpCr0NpxState, NOT CR0_TS
  3095. ;
  3096. ; The state is no longer in the coprocessor. Clear ThNpxState and
  3097. ; re-enable interrupts to allow context switching.
  3098. ;
  3099. mov byte ptr [eax].ThNpxState, NPX_STATE_NOT_LOADED
  3100. mov dword ptr PCR[PcPrcbData+PbNpxThread], 0 ; No state in coprocessor
  3101. Kt0726: sti
  3102. ;
  3103. ; According to the floating error priority, we test what is the cause of
  3104. ; the NPX error and raise an appropriate exception.
  3105. ;
  3106. test byte ptr _KeI386FxsrPresent, 1 ; Is FXSR feature present
  3107. jz short Kt0727a
  3108. mov ebx, [ecx] + FxErrorOffset
  3109. movzx eax, word ptr [ecx] + FxControlWord
  3110. movzx edx, word ptr [ecx] + FxStatusWord
  3111. mov esi, [ecx] + FxDataOffset ; (esi) = operand addr
  3112. jmp short Kt0727b
  3113. Kt0727a:
  3114. mov ebx, [ecx] + FpErrorOffset
  3115. movzx eax, word ptr [ecx] + FpControlWord
  3116. movzx edx, word ptr [ecx] + FpStatusWord
  3117. mov esi, [ecx] + FpDataOffset ; (esi) = operand addr
  3118. Kt0727b:
  3119. and eax, FSW_INVALID_OPERATION + FSW_DENORMAL + FSW_ZERO_DIVIDE + FSW_OVERFLOW + FSW_UNDERFLOW + FSW_PRECISION
  3120. not eax ; ax = mask of enabled exceptions
  3121. and eax, edx
  3122. .errnz (FSW_INVALID_OPERATION AND 0FFFFFF00h)
  3123. test al, FSW_INVALID_OPERATION ; Is it an invalid op exception?
  3124. jz short Kt0740 ; if z, no, go Kt0740
  3125. .errnz (FSW_STACK_FAULT AND 0FFFFFF00h)
  3126. test al, FSW_STACK_FAULT ; Is it caused by stack fault?
  3127. jnz short Kt0730 ; if nz, yes, go Kt0730
  3128. ; Raise Floating reserved operand exception
  3129. ;
  3130. mov eax, STATUS_FLOAT_INVALID_OPERATION
  3131. jmp CommonDispatchException1Arg0d ; Won't return
  3132. Kt0730:
  3133. ;
  3134. ; Raise Access Violation exception for stack overflow/underflow
  3135. ;
  3136. mov eax, STATUS_FLOAT_STACK_CHECK
  3137. jmp CommonDispatchException2Args0d ; Won't return
  3138. Kt0740:
  3139. ; Check for floating zero divide exception
  3140. .errnz (FSW_ZERO_DIVIDE AND 0FFFFFF00h)
  3141. test al, FSW_ZERO_DIVIDE ; Is it a zero divide error?
  3142. jz short Kt0750 ; if z, no, go Kt0750
  3143. ; Raise Floating divided by zero exception
  3144. mov eax, STATUS_FLOAT_DIVIDE_BY_ZERO
  3145. jmp CommonDispatchException1Arg0d ; Won't return
  3146. Kt0750:
  3147. ; Check for denormal error
  3148. .errnz (FSW_DENORMAL AND 0FFFFFF00h)
  3149. test al, FSW_DENORMAL ; Is it a denormal error?
  3150. jz short Kt0760 ; if z, no, go Kt0760
  3151. ; Raise floating reserved operand exception
  3152. mov eax, STATUS_FLOAT_INVALID_OPERATION
  3153. jmp CommonDispatchException1Arg0d ; Won't return
  3154. Kt0760:
  3155. ; Check for floating overflow error
  3156. .errnz (FSW_OVERFLOW AND 0FFFFFF00h)
  3157. test al, FSW_OVERFLOW ; Is it an overflow error?
  3158. jz short Kt0770 ; if z, no, go Kt0770
  3159. ; Raise floating overflow exception
  3160. mov eax, STATUS_FLOAT_OVERFLOW
  3161. jmp CommonDispatchException1Arg0d ; Won't return
  3162. Kt0770:
  3163. ; Check for floating underflow error
  3164. .errnz (FSW_UNDERFLOW AND 0FFFFFF00h)
  3165. test al, FSW_UNDERFLOW ; Is it a underflow error?
  3166. jz short Kt0780 ; if z, no, go Kt0780
  3167. ; Raise floating underflow exception
  3168. mov eax, STATUS_FLOAT_UNDERFLOW
  3169. jmp CommonDispatchException1Arg0d ; Won't return
  3170. Kt0780:
  3171. ; Check for precision (IEEE inexact) error
  3172. .errnz (FSW_PRECISION AND 0FFFFFF00h)
  3173. test al, FSW_PRECISION ; Is it a precision error
  3174. jz short Kt07100 ; if z, no, go Kt07100
  3175. mov eax, STATUS_FLOAT_INEXACT_RESULT
  3176. jmp CommonDispatchException1Arg0d ; Won't return
  3177. Kt07100:
  3178. ; If status word does not indicate error, then something is wrong...
  3179. ;
  3180. ; There is a known bug on Cyrix processors, upto and including
  3181. ; the MII that causes Trap07 for no real reason (INTR is asserted
  3182. ; during an FP instruction and is held high too long, we end up
  3183. ; in the Trap07 handler with not exception set). Bugchecking seems
  3184. ; a little heavy handed, if this is a Cyrix processor, just ignore
  3185. ; the error.
  3186. cmp _KiIgnoreUnexpectedTrap07, 0
  3187. jnz _KiExceptionExit
  3188. ; stop the system
  3189. sti
  3190. stdCall _KeBugCheckEx, <TRAP_CAUSE_UNKNOWN, 1, eax, 0, 0>
  3191. Kt07110:
  3192. ; Check to see if this process is a vdm
  3193. mov eax,PCR[PcPrcbData+PbCurrentThread]
  3194. mov ebx,[eax]+ThApcState+AsProcess
  3195. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  3196. je Kt0720 ; no, dispatch exception
  3197. Kt07130:
  3198. clts ; Turn off TS
  3199. and dword ptr [ecx]+FpCr0NpxState,NOT CR0_TS
  3200. ; Reflect the exception to the vdm, the VdmHandler enables interrupts
  3201. ; Raise Irql to APC level before enabling interrupts
  3202. RaiseIrql APC_LEVEL
  3203. push eax ; Save OldIrql
  3204. sti
  3205. stdCall _VdmDispatchIRQ13, <ebp> ; ebp - Trapframe
  3206. test al,0fh
  3207. jnz Kt07135
  3208. pop ecx ; (TOS) = OldIrql
  3209. LowerIrql ecx
  3210. ; Could not reflect, generate exception.
  3211. ;
  3212. ; FP context may or may not still be loaded. If loaded, it needs to
  3213. ; be saved now, if not loaded, skip save.
  3214. mov eax, PCR[PcPrcbData+PbCurrentThread]
  3215. mov ecx, [eax].ThInitialStack ; ecx -> top of kernel stack
  3216. sub ecx, NPX_FRAME_LENGTH ; ecx -> NPX save area
  3217. cli
  3218. cmp byte ptr [eax].ThNpxState, NPX_STATE_LOADED
  3219. je Kt0720 ; jif NPX state needs to be saved
  3220. jmp Kt0726 ; NPX state already saved
  3221. Kt07135:
  3222. pop ecx ; (TOS) = OldIrql
  3223. LowerIrql ecx
  3224. jmp _KiExceptionExit
  3225. Kt07140:
  3226. ;
  3227. ; Insure that this is not an NPX instruction in the kernel. (If
  3228. ; an app, such as C7, sets the EM bit after executing NPX instructions,
  3229. ; the fsave in SwapContext will catch an NPX exception
  3230. ;
  3231. cmp [ebp].TsSegCS, word ptr KGDT_R0_CODE
  3232. je Kt0701
  3233. ;
  3234. ; Check to see if it really is a VDM
  3235. ;
  3236. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  3237. mov ebx,[ebx]+ThApcState+AsProcess
  3238. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  3239. je Kt07100
  3240. ; A vdm is emulating NPX instructions on a machine with an NPX.
  3241. stdCall _Ki386VdmReflectException_A, <07h>
  3242. test al,0fh
  3243. jnz _KiExceptionExit
  3244. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  3245. mov eax, STATUS_ACCESS_VIOLATION
  3246. mov esi, -1
  3247. jmp CommonDispatchException2Args0d ; Won't return
  3248. ;
  3249. ; If the processor took an NMI (or other task switch) CR0_TS will have
  3250. ; been set. If this occured while the FP state was loaded it would
  3251. ; appear that it is no longer valid. This is not actually true, the
  3252. ; state is perfectly valid.
  3253. ;
  3254. ; Sanity: make sure CR0_MP is clear, if the OS had set CR0_TS, then
  3255. ; CR0_MP should also be set.
  3256. ;
  3257. Kt07150:
  3258. .errnz (CR0_MP AND 0FFFFFF00h)
  3259. test bl, CR0_MP
  3260. jnz short Kt07151
  3261. clts ; clear CR0_TS and continue
  3262. jmp _KiExceptionExit
  3263. Kt07151:
  3264. stdCall _KeBugCheckEx, <TRAP_CAUSE_UNKNOWN, 2, ebx, 0, 0>
  3265. jmp short Kt07151
  3266. _KiTrap07 endp
  3267. page ,132
  3268. subttl "Double Fault"
  3269. ;++
  3270. ;
  3271. ; Routine Description:
  3272. ;
  3273. ; Handle double exception fault.
  3274. ;
  3275. ; Normally, when the processor detects an exception while trying to
  3276. ; invoke the handler for a prior exception, the two exception can be
  3277. ; handled serially. If, however, the processor cannot handle them
  3278. ; serially, it signals the double-fault exception instead.
  3279. ;
  3280. ; If double exception is detected, no matter previous mode is USER
  3281. ; or kernel, a bugcheck will be raised and the system will be terminated.
  3282. ;
  3283. ;
  3284. ; Arguments:
  3285. ;
  3286. ; error code, which is always zero, is pushed on stack.
  3287. ;
  3288. ; Return value:
  3289. ;
  3290. ; None
  3291. ;
  3292. ;--
  3293. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  3294. public _KiTrap08
  3295. _KiTrap08 proc
  3296. .FPO (0, 0, 0, 0, 0, 2)
  3297. cli
  3298. ;
  3299. ; Set CR3, the I/O map base address, and LDT segment selector
  3300. ; in the old TSS since they are not set on context
  3301. ; switches. These values will be needed to return to the
  3302. ; interrupted task.
  3303. mov eax, PCR[PcTss] ; get old TSS address
  3304. mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get thread address
  3305. mov edi, [ecx].ThApcState.AsProcess ; get process address
  3306. mov ecx, [edi]+PrDirectoryTableBase ; get directory base
  3307. mov [eax]+TssCR3, ecx ; set previous cr3
  3308. mov cx, [edi]+PrIopmOffset ; get IOPM offset
  3309. mov [eax]+TssIoMapBase, cx ; set IOPM offset
  3310. mov ecx, [edi]+PrLdtDescriptor ; get LDT descriptor
  3311. test ecx, ecx ; does task use LDT?
  3312. jz @f
  3313. mov cx, KGDT_LDT
  3314. @@: mov [eax]+TssLDT, cx ; set LDT into old TSS
  3315. ;
  3316. ; Clear the busy bit in the TSS selector
  3317. ;
  3318. mov ecx, PCR[PcGdt]
  3319. lea eax, [ecx] + KGDT_DF_TSS
  3320. mov byte ptr [eax+5], 089h ; 32bit, dpl=0, present, TSS32, not busy
  3321. ;
  3322. ; Clear Nested Task bit in EFLAGS
  3323. ;
  3324. pushfd
  3325. and [esp], not 04000h
  3326. popfd
  3327. ;
  3328. ; Get address of the double-fault TSS which we are now running on.
  3329. ;
  3330. mov eax, PCR[PcGdt]
  3331. mov ch, [eax+KGDT_DF_TSS+KgdtBaseHi]
  3332. mov cl, [eax+KGDT_DF_TSS+KgdtBaseMid]
  3333. shl ecx, 16
  3334. mov cx, [eax+KGDT_DF_TSS+KgdtBaseLow]
  3335. ;
  3336. ; Update the TSS pointer in the PCR to point to the double-fault TSS
  3337. ; (which is what we're running on, or else we wouldn't be here)
  3338. ;
  3339. mov eax, PCR[PcTss]
  3340. mov PCR[PcTss], ecx
  3341. ;
  3342. ; The original machine context is in original task's TSS
  3343. ;
  3344. @@: stdCall _KeBugCheckEx,<UNEXPECTED_KERNEL_MODE_TRAP,8,eax,0,0>
  3345. jmp short @b ; do not remove - for debugger
  3346. _KiTrap08 endp
  3347. page ,132
  3348. subttl "Coprocessor Segment Overrun"
  3349. ;++
  3350. ;
  3351. ; Routine Description:
  3352. ;
  3353. ; Handle Coprocessor Segment Overrun exception.
  3354. ;
  3355. ; This exception only occurs on the 80286 (it's a trap 0d on the 80386),
  3356. ; so choke if we get here.
  3357. ;
  3358. ; Arguments:
  3359. ;
  3360. ; At entry, the saved CS:EIP point to the aborted instruction.
  3361. ; No error code is provided with the error.
  3362. ;
  3363. ; Return value:
  3364. ;
  3365. ; None
  3366. ;
  3367. ;--
  3368. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  3369. ENTER_DR_ASSIST kit9_a, kit9_t, NoAbiosAssist
  3370. align dword
  3371. public _KiTrap09
  3372. _KiTrap09 proc
  3373. push 0 ; push dummy error code
  3374. ENTER_TRAP kit9_a, kit9_t
  3375. sti
  3376. mov eax, EXCEPTION_NPX_OVERRUN ; (eax) = exception type
  3377. jmp _KiSystemFatalException ; go terminate the system
  3378. _KiTrap09 endp
  3379. page ,132
  3380. subttl "Invalid TSS exception"
  3381. ;++
  3382. ;
  3383. ; Routine Description:
  3384. ;
  3385. ; Handle Invalid TSS fault.
  3386. ;
  3387. ; This exception occurs if a segment exception other than the
  3388. ; not-present exception is detected when loading a selector
  3389. ; from the TSS.
  3390. ;
  3391. ; If the exception is caused as a result of the kernel, device
  3392. ; drivers, or user incorrectly setting the NT bit in the flags
  3393. ; while the back-link selector in the TSS is invalid and the
  3394. ; IRET instruction being executed, in this case, this routine
  3395. ; will clear the NT bit in the trap frame and restart the iret
  3396. ; instruction. For other causes of the fault, the user process
  3397. ; will be terminated if previous mode is user and the system
  3398. ; will stop if the exception occurs in kernel mode. No exception
  3399. ; is raised.
  3400. ;
  3401. ; Arguments:
  3402. ;
  3403. ; At entry, the saved CS:EIP point to the faulting instruction or
  3404. ; the first instruction of the task if the fault occurs as part of
  3405. ; a task switch.
  3406. ; Error code containing the segment causing the exception is provided.
  3407. ;
  3408. ; NT386 does not use TSS for context switching. So, the invalid tss
  3409. ; fault should NEVER occur. If it does, something is wrong with
  3410. ; the kernel. We simply shutdown the system.
  3411. ;
  3412. ; Return value:
  3413. ;
  3414. ; None
  3415. ;
  3416. ;--
  3417. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  3418. ENTER_DR_ASSIST kita_a, kita_t, NoAbiosAssist
  3419. align dword
  3420. public _KiTrap0A
  3421. _KiTrap0A proc
  3422. ENTER_TRAP kita_a, kita_t
  3423. ; We can not enable interrupt here. If we came here because DOS/WOW
  3424. ; iret with NT bit set, it is possible that vdm will swap the trap frame
  3425. ; with their monitor context. If this happen before we check the NT bit
  3426. ; we will bugcheck.
  3427. ; sti
  3428. ;
  3429. ; If the trap occur in USER mode and is caused by iret instruction with
  3430. ; OF bit set, we simply clear the OF bit and restart the iret.
  3431. ; Any other causes of Invalid TSS cause system to be shutdown.
  3432. ;
  3433. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  3434. test byte ptr [ebp]+TsEFlags+2, EFLAGS_V86_MASK/010000h
  3435. jnz short Kt0a10
  3436. .errnz (MODE_MASK AND 0FFFFFF00h)
  3437. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  3438. jz short Kt0a20
  3439. Kt0a10:
  3440. .errnz (EFLAGS_OF_BIT AND 0FFFF00FFh)
  3441. test byte ptr [ebp]+TsEFlags+1, EFLAGS_OF_BIT/0100h
  3442. sti
  3443. jz short Kt0a20
  3444. and dword ptr [ebp]+TsEFlags, NOT EFLAGS_OF_BIT
  3445. jmp _KiExceptionExit ; restart the instruction
  3446. Kt0a20:
  3447. mov eax, EXCEPTION_INVALID_TSS ; (eax) = trap type
  3448. jmp _KiSystemFatalException ; go terminate the system
  3449. _KiTrap0A endp
  3450. page ,132
  3451. subttl "Segment Not Present"
  3452. ;++
  3453. ;
  3454. ; Routine Description:
  3455. ;
  3456. ; Handle Segment Not Present fault.
  3457. ;
  3458. ; This exception occurs when the processor finds the P bit 0
  3459. ; when accessing an otherwise valid descriptor that is not to
  3460. ; be loaded in SS register.
  3461. ;
  3462. ; The only place the fault can occur (in kernel mode) is Trap/Exception
  3463. ; exit code. Otherwise, this exception causes system to be terminated.
  3464. ; NT386 uses flat mode, the segment not present fault in Kernel mode
  3465. ; indicates system malfunction.
  3466. ;
  3467. ; Arguments:
  3468. ;
  3469. ; At entry, the saved CS:EIP point to the faulting instruction or
  3470. ; the first instruction of the task if the fault occurs as part of
  3471. ; a task switch.
  3472. ; Error code containing the segment causing the exception is provided.
  3473. ;
  3474. ; Return value:
  3475. ;
  3476. ; None
  3477. ;
  3478. ;--
  3479. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  3480. ENTER_DR_ASSIST kitb_a, kitb_t, NoAbiosAssist
  3481. align dword
  3482. public _KiTrap0B
  3483. _KiTrap0B proc
  3484. ; Set up machine state frame for displaying
  3485. ENTER_TRAP kitb_a, kitb_t
  3486. ;
  3487. ; Did the trap occur in a VDM?
  3488. ;
  3489. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  3490. jz Kt0b30
  3491. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  3492. je Kt0b20
  3493. Kt0b10:
  3494. ; Check to see if this process is a vdm
  3495. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  3496. mov ebx,[ebx]+ThApcState+AsProcess
  3497. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  3498. je short Kt0b20
  3499. ; Raise Irql to APC level before enabling interrupts
  3500. RaiseIrql APC_LEVEL
  3501. push eax ; Save OldIrql
  3502. sti
  3503. stdCall _Ki386VdmSegmentNotPresent
  3504. test eax, 0ffffh
  3505. jz short Kt0b15
  3506. pop ecx ; (TOS) = OldIrql
  3507. LowerIrql ecx
  3508. jmp _KiExceptionExit
  3509. Kt0b15:
  3510. pop ecx ; (TOS) = OldIrql
  3511. LowerIrql ecx
  3512. Kt0b20: sti
  3513. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  3514. mov esi, [ebp]+TsErrCode
  3515. and esi, 0FFFFh
  3516. or esi, RPL_MASK
  3517. mov eax, STATUS_ACCESS_VIOLATION
  3518. jmp CommonDispatchException2Args0d ; Won't return
  3519. Kt0b30:
  3520. ;
  3521. ; Check if the exception is caused by pop SegmentRegister.
  3522. ; We need to deal with the case that user puts a NP selector in fs, ds, cs
  3523. ; or es through kernel debugger. (kernel will trap while popping segment
  3524. ; registers in trap exit code.)
  3525. ; Note: We assume if the faulted instruction is pop segreg. It MUST be
  3526. ; in trap exit code. So there MUST be a valid trap frame for the trap exit.
  3527. ;
  3528. mov eax, [ebp]+TsEip ; (eax)->faulted Instruction
  3529. mov eax, [eax] ; (eax)= opcode of faulted instruction
  3530. mov edx, [ebp]+TsEbp ; (edx)->previous trap exit trapframe
  3531. add edx, TsSegDs ; [edx] = prev trapframe + TsSegDs
  3532. cmp al, POP_DS ; Is it pop ds instruction?
  3533. jz Kt0b90 ; if z, yes, go Kt0b90
  3534. add edx, TsSegEs - TsSegDs ; [edx] = prev trapframe + TsSegEs
  3535. cmp al, POP_ES ; Is it pop es instruction?
  3536. jz Kt0b90 ; if z, yes, go Kt0b90
  3537. add edx, TsSegFs - TsSegEs ; [edx] = prev trapframe + TsSegFs
  3538. cmp ax, POP_FS ; Is it pop fs (2-byte) instruction?
  3539. jz Kt0b90 ; If z, yes, go Kt0b90
  3540. add edx, TsSegGs - TsSegFs ; [edx] = prev trapframe + TsSegGs
  3541. cmp ax, POP_GS ; Is it pop gs (2-byte) instruction?
  3542. jz Kt0b90 ; If z, yes, go Kt0b90
  3543. ;
  3544. ; The exception is not caused by pop instruction. We still need to check
  3545. ; if it is caused by iret (to user mode.) Because user may have a NP
  3546. ; cs and we will trap at iret in trap exit code.
  3547. ;
  3548. cmp al, IRET_OP ; Is it an iret instruction?
  3549. jne Kt0b199 ; if ne, not iret, go bugcheck
  3550. lea edx, [ebp]+TsHardwareEsp ; (edx)->trapped iret frame
  3551. .errnz (RPL_MASK AND 0FFFFFF00h)
  3552. test byte ptr [edx]+4, RPL_MASK ; Check CS of iret addr
  3553. ; Does the iret have ring transition?
  3554. jz Kt0b199 ; if z, it's a real fault
  3555. ;
  3556. ; Before enabling interrupts we need to save off any debug registers again
  3557. ; and build a good trap frame.
  3558. ;
  3559. lea ecx, [ebp+12] ; get original trap frame address
  3560. call SaveDebugReg
  3561. ;
  3562. ; we trapped at iret while returning back to user mode. We will dispatch
  3563. ; the exception back to user program.
  3564. ;
  3565. mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
  3566. lea edx, [ebp]+TsErrCode
  3567. Kt0b40:
  3568. mov eax, [edx]
  3569. mov [edx+12], eax
  3570. sub edx, 4
  3571. loop Kt0b40
  3572. sti
  3573. add esp, 12 ; adjust esp and ebp
  3574. add ebp, 12
  3575. jmp Kt0b10
  3576. ; mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  3577. ; xor edx, edx
  3578. ; mov esi, [ebp]+TsErrCode
  3579. ; or esi, RPL_MASK
  3580. ; and esi, 0FFFFh
  3581. ; mov ecx, 2
  3582. ; mov eax, STATUS_ACCESS_VIOLATION
  3583. ; call CommonDispatchException ; WOn't return
  3584. ;
  3585. ; The faulted instruction is pop seg
  3586. ;
  3587. Kt0b90:
  3588. if DBG
  3589. lea eax, [ebp].TsHardwareEsp
  3590. cmp eax, edx
  3591. je @f
  3592. int 3
  3593. @@:
  3594. endif
  3595. mov dword ptr [edx], 0 ; set the segment reg to 0 such that
  3596. ; we will trap in user mode.
  3597. jmp Kt0d01 ; continue in common code
  3598. Kt0b199:
  3599. sti
  3600. mov eax, EXCEPTION_SEGMENT_NOT_PRESENT ; (eax) = exception type
  3601. jmp _KiSystemFatalException ; terminate the system
  3602. _KiTrap0B endp
  3603. SaveDebugReg:
  3604. push ebx
  3605. mov ebx, dr7
  3606. test bl, DR7_ACTIVE
  3607. mov [ebp]+TsDr7,ebx
  3608. je @f
  3609. push edi
  3610. push esi
  3611. mov ebx,dr0
  3612. mov esi,dr1
  3613. mov edi,dr2
  3614. mov [ebp]+TsDr0,ebx
  3615. mov [ebp]+TsDr1,esi
  3616. mov [ebp]+TsDr2,edi
  3617. mov ebx,dr3
  3618. mov esi,dr6
  3619. mov [ebp]+TsDr3,ebx
  3620. xor ebx, ebx
  3621. mov [ebp]+TsDr6,esi
  3622. mov dr7, ebx
  3623. ;
  3624. ; Load KernelDr* into processor
  3625. ;
  3626. mov edi,dword ptr PCR[PcPrcb]
  3627. mov ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr0
  3628. mov esi,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr1
  3629. mov dr0,ebx
  3630. mov dr1,esi
  3631. mov ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr2
  3632. mov esi,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr3
  3633. mov dr2,ebx
  3634. mov dr3,esi
  3635. mov ebx,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr6
  3636. mov esi,[edi].PbProcessorState.PsSpecialRegisters.SrKernelDr7
  3637. mov dr6,ebx
  3638. mov dr7,esi
  3639. pop esi
  3640. pop edi
  3641. @@: pop ebx
  3642. ret
  3643. page ,132
  3644. subttl "Stack segment fault"
  3645. ;++
  3646. ;
  3647. ; Routine Description:
  3648. ;
  3649. ; Handle Stack Segment fault.
  3650. ;
  3651. ; This exception occurs when the processor detects certain problem
  3652. ; with the segment addressed by the SS segment register:
  3653. ;
  3654. ; 1. A limit violation in the segment addressed by the SS (error
  3655. ; code = 0)
  3656. ; 2. A limit violation in the inner stack during an interlevel
  3657. ; call or interrupt (error code = selector for the inner stack)
  3658. ; 3. If the descriptor to be loaded into SS has its present bit 0
  3659. ; (error code = selector for the not-present segment)
  3660. ;
  3661. ; The exception should never occur in kernel mode except when we
  3662. ; perform the iret back to user mode.
  3663. ;
  3664. ; Arguments:
  3665. ;
  3666. ; At entry, the saved CS:EIP point to the faulting instruction or
  3667. ; the first instruction of the task if the fault occurs as part of
  3668. ; a task switch.
  3669. ; Error code (whose value depends on detected condition) is provided.
  3670. ;
  3671. ; Return value:
  3672. ;
  3673. ; None
  3674. ;
  3675. ;--
  3676. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  3677. ENTER_DR_ASSIST kitc_a, kitc_t, NoAbiosAssist
  3678. align dword
  3679. public _KiTrap0C
  3680. _KiTrap0C proc
  3681. ENTER_TRAP kitc_a, kitc_t
  3682. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  3683. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  3684. jnz Kt0c20
  3685. .errnz (MODE_MASK AND 0FFFFFF00h)
  3686. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  3687. jz Kt0c10
  3688. cmp word ptr [ebp]+TsSegCs, KGDT_R3_CODE OR RPL_MASK
  3689. jne Kt0c20 ; maybe in a vdm
  3690. Kt0c00: sti
  3691. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  3692. mov edx, EXCEPT_LIMIT_ACCESS; assume it is limit violation
  3693. mov esi, [ebp]+TsHardwareEsp; (ecx) = User Stack pointer
  3694. cmp word ptr [ebp]+TsErrCode, 0 ; Is errorcode = 0?
  3695. jz short kt0c05 ; if z, yes, go dispatch exception
  3696. mov esi, [ebp]+TsErrCode ; Otherwise, set SS segment value
  3697. ; to be the address causing the fault
  3698. mov edx, EXCEPT_UNKNOWN_ACCESS
  3699. or esi, RPL_MASK
  3700. and esi, 0FFFFh
  3701. kt0c05: mov eax, STATUS_ACCESS_VIOLATION
  3702. jmp CommonDispatchException2Args ; Won't return
  3703. kt0c10:
  3704. ;
  3705. ; Check if the exception is caused by kernel mode iret to user code.
  3706. ; We need to deal with the case that user puts a bogus value in ss
  3707. ; through SetContext call. (kernel will trap while iret to user code
  3708. ; in trap exit code.)
  3709. ; Note: We assume if the faulted instruction is iret. It MUST be in
  3710. ; trap/exception exit code. So there MUST be a valid trap frame for
  3711. ; the trap exit.
  3712. ;
  3713. mov eax, [ebp]+TsEip ; (eax)->faulted Instruction
  3714. ;
  3715. ; Note the eip is captured above before enabling interrupts to
  3716. ; prevent a setcontext from editing a bogus eip into our trapframe.
  3717. ;
  3718. movzx eax, byte ptr[eax]
  3719. ; (eax)= opcode of faulted instruction
  3720. ;
  3721. ; Check if the exception is caused by iret (to user mode.)
  3722. ; Because user may have a NOT PRESENT ss and we will trap at iret
  3723. ; in trap exit code. (If user put a bogus/not valid SS in trap frame, we
  3724. ; will catch it in trap 0D handler.
  3725. ;
  3726. cmp al, IRET_OP ; Is it an iret instruction?
  3727. jne Kt0c15 ; if ne, not iret, go bugcheck
  3728. ;
  3729. ; Before enabling interrupts we need to save off any debug registers again
  3730. ;
  3731. lea ecx, [ebp+12] ; get original trap frame address
  3732. call SaveDebugReg
  3733. lea edx, [ebp]+TsHardwareEsp ; (edx)->trapped iret frame
  3734. test dword ptr [edx]+4, RPL_MASK ; Check CS of iret addr
  3735. ; Does the iret have ring transition?
  3736. jz Kt0c15 ; if z, no SS involved, it's a real fault
  3737. ;
  3738. ; we trapped at iret while returning back to user mode. We will dispatch
  3739. ; the exception back to user program.
  3740. ;
  3741. mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
  3742. lea edx, [ebp]+TsErrCode
  3743. @@:
  3744. mov eax, [edx]
  3745. mov [edx+12], eax
  3746. sub edx, 4
  3747. loop @b
  3748. sti
  3749. add esp, 12 ; adjust esp and ebp
  3750. add ebp, 12
  3751. ;
  3752. ; Now, we have user mode trap frame set up
  3753. ;
  3754. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  3755. mov edx, EXCEPT_LIMIT_ACCESS; assume it is limit violation
  3756. mov esi, [ebp]+TsHardwareEsp; (ecx) = User Stack pointer
  3757. cmp word ptr [ebp]+TsErrCode, 0 ; Is errorcode = 0?
  3758. jz short @f ; if z, yes, go dispatch exception
  3759. mov esi, [ebp]+TsErrCode ; Otherwise, set SS segment value
  3760. ; to be the address causing the fault
  3761. and esi, 0FFFFh
  3762. mov edx, EXCEPT_UNKNOWN_ACCESS
  3763. or esi, RPL_MASK
  3764. @@:
  3765. mov eax, STATUS_ACCESS_VIOLATION
  3766. jmp CommonDispatchException2Args ; Won't return
  3767. Kt0c15:
  3768. sti
  3769. mov eax, EXCEPTION_STACK_FAULT ; (eax) = trap type
  3770. jmp _KiSystemFatalException
  3771. Kt0c20:
  3772. ; Check to see if this process is a vdm
  3773. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  3774. mov ebx,[ebx]+ThApcState+AsProcess
  3775. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  3776. je Kt0c00
  3777. Kt0c30:
  3778. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  3779. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  3780. jnz short @f
  3781. ;
  3782. ; Raise Irql to APC level before enabling interrupt
  3783. ;
  3784. RaiseIrql APC_LEVEL
  3785. sti
  3786. mov edi, eax ; [edi] = OldIrql
  3787. call VdmFixEspEbp
  3788. push eax
  3789. mov ecx, edi
  3790. LowerIrql ecx
  3791. cli
  3792. pop eax
  3793. test al, 0fh
  3794. jz short @f
  3795. jmp _KiExceptionExit
  3796. @@:
  3797. stdCall _Ki386VdmReflectException_A,<0ch>
  3798. test al,0fh
  3799. jz Kt0c00
  3800. jmp _KiExceptionExit
  3801. _KiTrap0C endp
  3802. page ,132
  3803. subttl "TrapC handler for NTVDM"
  3804. ;++
  3805. ;
  3806. ; Routine Description:
  3807. ;
  3808. ; Some protected dos games (ex, Duke3D) while running in a BIG code
  3809. ; segment with SMALL Stack segment will hit trap c with higher 16bit
  3810. ; of esp containing kernel esp higher 16 bit. The question it should
  3811. ; not trapped because cpu should only look at sp. So, here we try
  3812. ; to deal with this problem.
  3813. ;
  3814. ; Arguments:
  3815. ;
  3816. ; EBP - Trap frame
  3817. ;
  3818. ; Return value:
  3819. ;
  3820. ; None
  3821. ;
  3822. ;--
  3823. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  3824. public VdmFixEspEbp
  3825. VdmFixEspEbp proc
  3826. ;
  3827. ; First check if user SS is small. If it is big, do nothing
  3828. ;
  3829. mov eax, [ebp].TsHardwareSegSs
  3830. lar eax, eax ; [eax]= ss access right
  3831. jnz Vth_err
  3832. test eax, 400000h ; is SS a big segment?
  3833. jnz Vth_err ; nz, yes, do nothing
  3834. xor edx, edx ; [edx] = 0 no need to update tframe
  3835. mov eax, esp
  3836. and eax, 0ffff0000h ; [eax]=kernel esp higher 16bit
  3837. mov ecx, [ebp].TsHardwareEsp
  3838. and ecx, 0ffff0000h ; [ecx]=user esp higher 16bit
  3839. cmp ecx, eax ; are they the same
  3840. jnz short @f ; if nz, no, go check ebp
  3841. and dword ptr [ebp].TsHardwareEsp, 0ffffH ; zero higher 16 bit of user esp
  3842. mov edx, 1 ; [edx]=1 indicates we need to update trap frame
  3843. @@:
  3844. mov ecx, [ebp].TsEbp
  3845. and ecx, 0ffff0000h ; [ecx]=user ebp higher 16bit
  3846. cmp ecx, eax ; are they the same as kernel's
  3847. jnz short @f ; if nz, no, go check if we need to update tframe
  3848. and dword ptr [ebp].TsEbp, 0ffffH ; zero higher 16bit of user ebp
  3849. mov edx, 1 ; update kernel trap frame
  3850. @@: cmp edx, 1 ; do we need to update trap frame?
  3851. jnz short Vth_err ; if nz, no, do nothing
  3852. Vth_ok:
  3853. ;
  3854. ; copy user's cs:eip and ss:esp to vdmtib, note this needs to be done
  3855. ; with proper probing and exception handling.
  3856. ;
  3857. mov ebx, PCR[PcTeb]
  3858. mov eax, [ebp].TsSegCs
  3859. mov ecx, [ebp].TsEip
  3860. mov edx, [ebp].TsEbx
  3861. stdCall _VdmTibPass1, <eax,ecx,edx>
  3862. ; eax now points at the VDM tib (or NULL if anything went wrong)
  3863. ;
  3864. ; Move the vdmtib to the trap frame such that we return back to ntvdm
  3865. ; [ebx]->vdmtib
  3866. ;
  3867. mov [ebp].TsEbx, eax
  3868. ;
  3869. ; dispatch control to ntvdm trapc handler which will load ss:esp
  3870. ; and jump to the trapped cs:eip
  3871. ;
  3872. mov eax,PCR[PcPrcbData+PbCurrentThread]
  3873. mov eax,[eax]+ThApcState+AsProcess
  3874. mov eax,[eax]+PrVdmTrapcHandler
  3875. mov dword ptr [ebp].TsSegCs, KGDT_R3_CODE OR RPL_MASK
  3876. mov dword ptr [ebp].TsEip, eax
  3877. mov eax, 1
  3878. ret
  3879. Vth_err:
  3880. xor eax, eax
  3881. ret
  3882. VdmFixEspEbp endp
  3883. page ,132
  3884. subttl "General Protection Fault"
  3885. ;++
  3886. ;
  3887. ; Routine Description:
  3888. ;
  3889. ; Handle General protection fault.
  3890. ;
  3891. ; First, check to see if the fault occured in kernel mode with
  3892. ; incorrect selector values. If so, this is a lazy segment load.
  3893. ; Correct the selector values and restart the instruction. Otherwise,
  3894. ; parse out various kinds of faults and report as exceptions.
  3895. ;
  3896. ; All protection violations that do not cause another exception
  3897. ; cause a general exception. If the exception indicates a violation
  3898. ; of the protection model by an application program executing a
  3899. ; previleged instruction or I/O reference, a PRIVILEGED INSTRUCTION
  3900. ; exception will be raised. All other causes of general protection
  3901. ; fault cause a ACCESS VIOLATION exception to be raised.
  3902. ;
  3903. ; If previous mode = Kernel;
  3904. ; the system will be terminated (assuming not lazy segment load)
  3905. ; Else previous mode = USER
  3906. ; the process will be terminated if the exception was not caused
  3907. ; by privileged instruction.
  3908. ;
  3909. ; Arguments:
  3910. ;
  3911. ; At entry, the saved CS:EIP point to the faulting instruction or
  3912. ; the first instruction of the task if the fault occurs as part of
  3913. ; a task switch.
  3914. ; Error code (whose value depends on detected condition) is provided.
  3915. ;
  3916. ; Return value:
  3917. ;
  3918. ; None
  3919. ;
  3920. ;--
  3921. ASSUME DS:FLAT, SS:NOTHING, ES:FLAT
  3922. ;
  3923. ; Error and exception blocks for KiTrap0d
  3924. ;
  3925. Ktd_ExceptionHandler proc
  3926. ;
  3927. ; WARNING: Here we directly unlink the exception handler from the
  3928. ; exception registration chain. NO unwind is performed.
  3929. ;
  3930. mov esp, [esp+8] ; (esp)-> ExceptionList
  3931. pop PCR[PcExceptionList]
  3932. add esp, 4 ; pop out except handler
  3933. pop ebp ; (ebp)-> trap frame
  3934. test dword ptr [ebp].TsSegCs, MODE_MASK ; if premode=kernel
  3935. jnz Kt0d103 ; nz, prevmode=user, go return
  3936. ; raise bugcheck if prevmode=kernel
  3937. stdCall _KeBugCheck, <KMODE_EXCEPTION_NOT_HANDLED>
  3938. Ktd_ExceptionHandler endp
  3939. ENTER_DR_ASSIST kitd_a, kitd_t, NoAbiosAssist,, kitd_v
  3940. align dword
  3941. public _KiTrap0D
  3942. _KiTrap0D proc
  3943. ;
  3944. ; Did the trap occur in a VDM in V86 mode? Trap0d is not critical from
  3945. ; performance point of view to native NT, but it's super critical to
  3946. ; VDMs. So here we are doing every thing to make v86 mode most
  3947. ; efficient.
  3948. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  3949. test byte ptr [esp]+0ch+2,EFLAGS_V86_MASK/010000h
  3950. jz Ktdi
  3951. KtdV86Slow:
  3952. ENTER_TRAPV86 kitd_a, kitd_v
  3953. KtdV86Slow2:
  3954. mov ecx,PCR[PcPrcbData+PbCurrentThread]
  3955. mov ecx,[ecx]+ThApcState+AsProcess
  3956. cmp dword ptr [ecx]+PrVdmObjects,0 ; is this a vdm process?
  3957. jnz short @f ; if nz, yes
  3958. sti ; else, enable ints
  3959. jmp Kt0d105 ; and dispatch exception
  3960. @@:
  3961. ; Raise Irql to APC level, before enabling interrupts
  3962. RaiseIrql APC_LEVEL
  3963. push eax ; Save OldIrql
  3964. sti
  3965. stdCall _VdmDispatchOpcodeV86_try,<ebp>
  3966. KtdV86Exit:
  3967. test al,0FFh
  3968. jnz short Ktdi2
  3969. stdCall _Ki386VdmReflectException,<0dh>
  3970. test al,0fh
  3971. jnz short Ktdi2
  3972. pop ecx ; (TOS) = OldIrql
  3973. LowerIrql ecx
  3974. jmp Kt0d105
  3975. Ktdi2:
  3976. pop ecx ; (TOS) = OldIrql
  3977. LowerIrql ecx
  3978. cli
  3979. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  3980. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  3981. jz Ktdi3
  3982. EXIT_TRAPV86
  3983. ;
  3984. ; EXIT_TRAPv86 does not exit if a user mode apc has switched
  3985. ; the context from V86 mode to flat mode (VDM monitor context)
  3986. ;
  3987. Ktdi3:
  3988. jmp _KiExceptionExit
  3989. Ktdi:
  3990. ENTER_TRAP kitd_a, kitd_t
  3991. ;
  3992. ; DO NOT TURN INTERRUPTS ON! If we're doing a lazy segment load,
  3993. ; could be in an ISR or other code that needs ints off!
  3994. ;
  3995. ;
  3996. ; Is this just a lazy segment load? First make sure the exception occurred
  3997. ; in kernel mode.
  3998. ;
  3999. test dword ptr [ebp]+TsSegCs,MODE_MASK
  4000. jnz Kt0d02 ; not kernel mode, go process normally
  4001. ;
  4002. ; Before handling kernel mode trap0d, we need to do some checks to make
  4003. ; sure the kernel mode code is the one to blame.
  4004. ;
  4005. if FAST_BOP
  4006. cmp dword ptr PCR[PcVdmAlert], 0
  4007. jne Kt0eVdmAlert
  4008. endif
  4009. ;
  4010. ; Check if the exception is caused by the handler trying to examine offending
  4011. ; instruction. If yes, we raise exception to user mode program. This occurs
  4012. ; when user cs is bogus. Note if cs is valid and eip is bogus, the exception
  4013. ; will be caught by page fault and out Ktd_ExceptionHandler will be invoked.
  4014. ; Both cases, the exception is dispatched back to user mode.
  4015. ;
  4016. mov eax, [ebp]+TsEip
  4017. cmp eax, offset FLAT:Kt0d03
  4018. jbe short Kt0d000
  4019. cmp eax, offset FLAT:Kt0d60
  4020. jae short Kt0d000
  4021. sti
  4022. mov ebp, [ebp]+TsEbp ; remove the current trap frame
  4023. mov esp, ebp ; set ebp, esp to previous trap frame
  4024. jmp Kt0d105 ; and dispatch exception to user mode.
  4025. ;
  4026. ; Check if the exception is caused by pop SegmentRegister.
  4027. ; We need to deal with the case that user puts a bogus value in fs, ds,
  4028. ; or es through kernel debugger. (kernel will trap while popping segment
  4029. ; registers in trap exit code.)
  4030. ; Note: We assume if the faulted instruction is pop segreg. It MUST be
  4031. ; in trap exit code. So there MUST be a valid trap frame for the trap exit.
  4032. ;
  4033. Kt0d000:
  4034. mov eax, [ebp]+TsEip ; (eax)->faulted Instruction
  4035. mov eax, [eax] ; (eax)= opcode of faulted instruction
  4036. mov edx, [ebp]+TsEbp ; (edx)->previous trap exit trapframe
  4037. add edx, TsSegDs ; [edx] = prev trapframe + TsSegDs
  4038. cmp al, POP_DS ; Is it pop ds instruction?
  4039. jz Kt0d005 ; if z, yes, go Kt0d005
  4040. add edx, TsSegEs - TsSegDs ; [edx] = prev trapframe + TsSegEs
  4041. cmp al, POP_ES ; Is it pop es instruction?
  4042. jz Kt0d005 ; if z, yes, go Kt0d005
  4043. add edx, TsSegFs - TsSegEs ; [edx] = prev trapframe + TsSegFs
  4044. cmp ax, POP_FS ; Is it pop fs (2-byte) instruction?
  4045. jz Kt0d005 ; If z, yes, go Kt0d005
  4046. add edx, TsSegGs - TsSegFs ; [edx] = prev trapframe + TsSegGs
  4047. cmp ax, POP_GS ; Is it pop gs (2-byte) instruction?
  4048. jz Kt0d005 ; If z, yes, go Kt0d005
  4049. ;
  4050. ; The exception is not caused by pop instruction. We still need to check
  4051. ; if it is caused by iret (to user mode.) Because user may have a bogus
  4052. ; ss and we will trap at iret in trap exit code.
  4053. ;
  4054. cmp al, IRET_OP ; Is it an iret instruction?
  4055. jne Kt0d002 ; if ne, not iret, go check lazy load
  4056. lea edx, [ebp]+TsHardwareEsp ; (edx)->trapped iret frame
  4057. mov ax, [ebp]+TsErrCode ; (ax) = Error Code
  4058. and ax, NOT RPL_MASK ; No need to do this ...
  4059. mov cx, word ptr [edx]+4 ; [cx] = cs selector
  4060. and cx, NOT RPL_MASK
  4061. cmp cx, ax ; is it faulted in CS?
  4062. jne short Kt0d0008 ; No
  4063. ;
  4064. ; Check if this is the code which we use to return to Ki386CallBios
  4065. ; (see biosa.asm):
  4066. ; cs should be KGDT_R0_CODE OR RPL_MASK
  4067. ; eip should be Ki386BiosCallReturnAddress
  4068. ; esi should be the esp of function Ki386SetUpAndExitToV86Code
  4069. ; (edx) -> trapped iret frame
  4070. ;
  4071. mov eax, OFFSET FLAT:Ki386BiosCallReturnAddress
  4072. cmp eax, [edx] ; [edx]= trapped eip
  4073. ; Is eip what we're expecting?
  4074. jne short Kt0d0005 ; No, continue
  4075. mov eax, [edx]+4 ; (eax) = trapped cs
  4076. cmp ax, KGDT_R0_CODE OR RPL_MASK ; Is Cs what we're exptecting?
  4077. jne short Kt0d0005 ; No
  4078. jmp Ki386BiosCallReturnAddress ; with interrupts off
  4079. Kt0d0005:
  4080. ;
  4081. ; Since the CS is bogus, we cannot tell if we are going back to user mode...
  4082. ;
  4083. mov ebx,PCR[PcPrcbData+PbCurrentThread] ; if previous mode is
  4084. test byte ptr [ebx]+ThPreviousMode, 0ffh ; kernel, we bugcheck
  4085. jz Kt0d02
  4086. or word ptr [edx]+4, RPL_MASK
  4087. Kt0d0008:
  4088. test dword ptr [edx]+4, RPL_MASK ; Check CS of iret addr
  4089. ; Does the iret have ring transition?
  4090. jz Kt0d02 ; if z, no SS involed, it's a real fault
  4091. ;
  4092. ; Before enabling interrupts we need to save off any debug registers again
  4093. ;
  4094. lea ecx, [ebp+12] ; get original trap frame address
  4095. call SaveDebugReg
  4096. ;
  4097. ; we trapped at iret while returning back to user mode. We will dispatch
  4098. ; the exception back to user program.
  4099. ;
  4100. mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4
  4101. lea edx, [ebp]+TsErrCode
  4102. Kt0d001:
  4103. mov eax, [edx]
  4104. mov [edx+12], eax
  4105. sub edx, 4
  4106. loop Kt0d001
  4107. sti
  4108. add esp, 12 ; adjust esp and ebp
  4109. add ebp, 12
  4110. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  4111. mov esi, [ebp]+TsErrCode
  4112. and esi, 0FFFFh
  4113. mov eax, STATUS_ACCESS_VIOLATION
  4114. jmp CommonDispatchException2Args0d ; Won't return
  4115. ;
  4116. ; Kernel mode, first opcode byte is 0f, check for rdmsr or wrmsr instruction
  4117. ;
  4118. Kt0d001a:
  4119. shr eax, 8
  4120. cmp al, 30h
  4121. je short Kt0d001b
  4122. cmp al, 32h
  4123. jne short Kt0d002a
  4124. Kt0d001b:
  4125. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  4126. mov eax, STATUS_ACCESS_VIOLATION
  4127. jmp CommonDispatchException0Args ; Won't return
  4128. ;
  4129. ; The Exception is not caused by pop instruction. Check to see
  4130. ; if the instruction is a rdmsr or wrmsr
  4131. ;
  4132. Kt0d002:
  4133. cmp al, 0fh
  4134. je short Kt0d001a
  4135. ;
  4136. ; We now check if DS and ES contain correct value. If not, this is lazy
  4137. ; segment load, we simply set them to valid selector.
  4138. ;
  4139. Kt0d002a:
  4140. cmp word ptr [ebp]+TsSegDs, KGDT_R3_DATA OR RPL_MASK
  4141. je short Kt0d003
  4142. mov dword ptr [ebp]+TsSegDs, KGDT_R3_DATA OR RPL_MASK
  4143. jmp short Kt0d01
  4144. Kt0d003:
  4145. cmp word ptr [ebp]+TsSegEs, KGDT_R3_DATA OR RPL_MASK
  4146. je Kt0d02 ; Real fault, go process it
  4147. mov dword ptr [ebp]+TsSegEs, KGDT_R3_DATA OR RPL_MASK
  4148. jmp short Kt0d01
  4149. ;
  4150. ; The faulted instruction is pop seg
  4151. ;
  4152. Kt0d005:
  4153. if DBG
  4154. lea eax, [ebp].TsHardwareEsp
  4155. cmp edx, eax
  4156. je @f
  4157. int 3
  4158. @@:
  4159. endif
  4160. xor eax, eax
  4161. mov dword ptr [edx], eax ; set the segment reg to 0 such that
  4162. ; we will trap in user mode.
  4163. Kt0d01:
  4164. EXIT_ALL NoRestoreSegs,,NoPreviousMode ; RETURN
  4165. ;
  4166. ; Caller is not kernel mode, or DS and ES are OK. Therefore this
  4167. ; is a real fault rather than a lazy segment load. Process as such.
  4168. ; Since this is not a lazy segment load is now safe to turn interrupts on.
  4169. ;
  4170. Kt0d02: mov eax, EXCEPTION_GP_FAULT ; (eax) = trap type
  4171. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is prevmode=User?
  4172. jz _KiSystemFatalException ; If z, prevmode=kernel, stop...
  4173. ; preload pointer to process
  4174. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  4175. mov ebx,[ebx]+ThApcState+AsProcess
  4176. ; flat or protect mode ?
  4177. cmp word ptr [ebp]+TsSegCs, KGDT_R3_CODE OR RPL_MASK
  4178. jz kt0d0201
  4179. ;
  4180. ; if vdm running in protected mode, handle instruction
  4181. ;
  4182. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  4183. jne Kt0d110
  4184. sti
  4185. cmp word ptr [ebp]+TsErrCode, 0 ; if errcode<>0, raise access
  4186. ; violation exception
  4187. jnz Kt0d105 ; if nz, raise access violation
  4188. jmp short Kt0d03
  4189. ;
  4190. ; if vdm running in flat mode, handle pop es,fs,gs by setting to Zero
  4191. ;
  4192. kt0d0202:
  4193. add dword ptr [ebp].TsEip, 1
  4194. kt0d02021:
  4195. mov dword ptr [edx], 0
  4196. add dword ptr [ebp].TsEip, 1
  4197. add dword ptr [ebp].TsHardwareEsp, 4
  4198. jmp _KiExceptionExit
  4199. kt0d0201:
  4200. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  4201. je short Kt0d03
  4202. sti
  4203. mov eax, [ebp]+TsEip ; (eax)->faulted Instruction
  4204. stdCall _VdmFetchBop4, <eax> ; (eax)= opcode of faulted instruction
  4205. mov edx, ebp ; (edx)-> trap frame
  4206. add edx, TsSegEs ; [edx] = prev trapframe + TsSegEs
  4207. cmp al, POP_ES ; Is it pop es instruction?
  4208. jz short Kt0d02021
  4209. @@:
  4210. add edx, TsSegFs - TsSegEs ; [edx] = prev trapframe + TsSegFs
  4211. cmp ax, POP_FS ; Is it pop fs (2-byte) instruction?
  4212. jz short kt0d0202
  4213. add edx, TsSegGs - TsSegFs ; [edx] = prev trapframe + TsSegGs
  4214. cmp ax, POP_GS ; Is it pop gs (2-byte) instruction?
  4215. jz short kt0d0202
  4216. ;
  4217. ; we need to determine if the trap0d was caused by privileged instruction.
  4218. ; First, we need to skip all the instruction prefix bytes
  4219. ;
  4220. Kt0d03: sti
  4221. ;
  4222. ; First we need to set up an exception handler to handle the case that
  4223. ; we fault while reading user mode instruction.
  4224. ;
  4225. push ebp ; pass trapframe to handler
  4226. push offset FLAT:Ktd_ExceptionHandler
  4227. ; set up exception registration record
  4228. push PCR[PcExceptionList]
  4229. mov PCR[PcExceptionList], esp
  4230. mov esi, [ebp]+TsEip ; (esi) -> flat address of faulting instruction
  4231. cmp esi, _MmUserProbeAddress ; Probe captured EIP
  4232. jb short @f
  4233. mov esi, _MmUserProbeAddress ; Use address of the GAP to force exception
  4234. @@: mov ecx, MAX_INSTRUCTION_LENGTH
  4235. @@:
  4236. push ecx ; save ecx for loop count
  4237. lods byte ptr [esi] ; (al)= instruction byte
  4238. mov ecx, PREFIX_REPEAT_COUNT
  4239. mov edi, offset FLAT:PrefixTable ; (ES:EDI)->prefix table
  4240. repnz scasb ; search for matching (al)
  4241. pop ecx ; restore loop count
  4242. jnz short Kt0d10 ; (al) not a prefix byte, go kt0d10
  4243. loop short @b ; go check for prefix byte again
  4244. pop PCR[PcExceptionList]
  4245. add esp, 8 ; clear stack
  4246. jmp Kt0635 ; exceed max instruction length,
  4247. ; raise ILLEGALINSTRUCTION exception
  4248. ;
  4249. ; (al) = first opcode which is NOT prefix byte
  4250. ; (ds:esi)= points to the first opcode which is not prefix byte + 1
  4251. ; We need to check if it is one of the privileged instructions
  4252. ;
  4253. Kt0d10: cmp al, MI_HLT ; Is it a HLT instruction?
  4254. je Kt0d80 ; if e, yes, go kt0d80
  4255. cmp al, MI_TWO_BYTE ; Is it a two-byte instruction?
  4256. jne short Kt0d50 ; if ne, no, go check for IO inst.
  4257. lods byte ptr [esi] ; (al)= next instruction byte
  4258. cmp al, MI_LTR_LLDT ; Is it a LTR or LLDT ?
  4259. jne short Kt0d20 ; if ne, no, go kt0d20
  4260. lods byte ptr [esi] ; (al)= ModRM byte of instruction
  4261. and al, MI_MODRM_MASK ; (al)= bit 3-5 of ModRM byte
  4262. cmp al, MI_LLDT_MASK ; Is it a LLDT instruction?
  4263. je Kt0d80 ; if e, yes, go Kt0d80
  4264. cmp al, MI_LTR_MASK ; Is it a LTR instruction?
  4265. je Kt0d80 ; if e, yes, go Kt0d80
  4266. jmp Kt0d100 ; if ne, go raise access vioalation
  4267. Kt0d20: cmp al, MI_LGDT_LIDT_LMSW ; Is it one of these instructions?
  4268. jne short Kt0d30 ; if ne, no, go check special mov inst.
  4269. lods byte ptr [esi] ; (al)= ModRM byte of instruction
  4270. and al, MI_MODRM_MASK ; (al)= bit 3-5 of ModRM byte
  4271. cmp al, MI_LGDT_MASK ; Is it a LGDT instruction?
  4272. je Kt0d80 ; if e, yes, go Kt0d80
  4273. cmp al, MI_LIDT_MASK ; Is it a LIDT instruction?
  4274. je Kt0d80 ; if e, yes, go Kt0d80
  4275. cmp al, MI_LMSW_MASK ; Is it a LMSW instruction?
  4276. je Kt0d80 ; if e, yes, go Kt0d80
  4277. jmp Kt0d100 ; else, raise access violation except
  4278. Kt0d30:
  4279. ;
  4280. ; Check some individual privileged instructions
  4281. ;
  4282. cmp al, MI_INVD
  4283. je kt0d80
  4284. cmp al, MI_WBINVD
  4285. je kt0d80
  4286. cmp al, MI_SYSEXIT
  4287. je short kt0d80
  4288. cmp al, MI_MOV_TO_TR ; mov tx, rx
  4289. je short kt0d80
  4290. cmp al, MI_CLTS
  4291. je short kt0d80
  4292. ;
  4293. ; Test ordering of these compares
  4294. ;
  4295. if MI_MOV_FROM_CR GT MI_WRMSR
  4296. .err
  4297. endif
  4298. ;
  4299. ; Test for the mov instructions as a block with a single unused gap
  4300. ;
  4301. .errnz (MI_MOV_FROM_CR + 1 - MI_MOV_FROM_DR)
  4302. .errnz (MI_MOV_FROM_DR + 1 - MI_MOV_TO_CR)
  4303. .errnz (MI_MOV_TO_CR + 1 - MI_MOV_TO_DR)
  4304. .errnz (MI_MOV_TO_DR + 1 - MI_MOV_FROM_TR)
  4305. cmp al, MI_MOV_FROM_CR ; See if we are a mov rx, cx
  4306. jb Kt0d100 ; mov cx, rx
  4307. cmp al, MI_MOV_FROM_TR ; mov rx, dx
  4308. jbe short kt0d80 ; mov dx, rx
  4309. ; mov rx, tx
  4310. ;
  4311. ; Test the counter instructions as a block
  4312. ;
  4313. .errnz (MI_WRMSR + 1 - MI_RDTSC)
  4314. .errnz (MI_RDTSC + 1 - MI_RDMSR)
  4315. .errnz (MI_RDMSR + 1 - MI_RDPMC)
  4316. cmp al, MI_WRMSR
  4317. jb Kt0d100
  4318. cmp al, MI_RDPMC
  4319. jbe short kt0d80
  4320. jmp Kt0d100 ; else, no, raise access violation
  4321. ;
  4322. ; Now, we need to check if the trap 0d was caused by IO privileged instruct.
  4323. ; (al) = first opcode which is NOT prefix byte
  4324. ; Also note, if we come here, the instruction has 1 byte opcode (still need to
  4325. ; check REP case.)
  4326. ;
  4327. Kt0d50: mov ebx, [ebp]+TsEflags ; (ebx) = client's eflags
  4328. and ebx, IOPL_MASK ;
  4329. shr ebx, IOPL_SHIFT_COUNT ; (ebx) = client's IOPL
  4330. mov ecx, [ebp]+TsSegCs
  4331. and ecx, RPL_MASK ; RPL_MASK NOT MODE_MASK!!!
  4332. ; (ecx) = CPL, 1/2 of computation of
  4333. ; whether IOPL applies.
  4334. cmp ebx,ecx ; compare IOPL with CPL of caller
  4335. jge short Kt0d100 ; if ge, not IO privileged,
  4336. ; go raise access violation
  4337. Kt0d60: cmp al, CLI_OP ; Is it a CLI instruction
  4338. je short Kt0d80 ; if e, yes. Report it.
  4339. cmp al, STI_OP ; Is it a STI?
  4340. je short Kt0d80 ; if e, yes, report it.
  4341. mov ecx, IO_INSTRUCTION_TABLE_LENGTH
  4342. mov edi, offset FLAT:IOInstructionTable
  4343. repnz scasb ; Is it a IO instruction?
  4344. jnz short Kt0d100 ; if nz, not io instrct.
  4345. ;
  4346. ; We know the instr is an IO instr without IOPL. But, this doesn't mean
  4347. ; this is a privileged instruction exception. We need to make sure the
  4348. ; IO port access is not granted in the bit map
  4349. ;
  4350. mov edi, PCR[PcSelfPcr] ; (edi)->Pcr
  4351. mov esi, [edi]+PcGdt ; (esi)->Gdt addr
  4352. add esi, KGDT_TSS
  4353. movzx ebx, word ptr [esi] ; (ebx) = Tss limit
  4354. mov edx, [ebp].TsEdx ; [edx] = port addr
  4355. mov ecx, edx
  4356. and ecx, 07 ; [ecx] = Bit position
  4357. shr edx, 3 ; [edx] = offset to the IoMap
  4358. mov edi, [edi]+PcTss ; (edi)->TSS
  4359. movzx eax, word ptr [edi + TssIoMapBase] ; [eax] = Iomap offset
  4360. add edx, eax
  4361. cmp edx, ebx ; is the offset addr beyond tss limit?
  4362. ja short Kt0d80 ; yes, no I/O priv.
  4363. add edi, edx ; (edi)-> byte correspons to the port addr
  4364. mov edx, 1
  4365. shl edx, cl
  4366. test dword ptr [edi], edx ; Is the bit of the port disabled?
  4367. jz short Kt0d100 ; if z, no, then it is access violation
  4368. Kt0d80:
  4369. pop PCR[PcExceptionList]
  4370. add esp, 8 ; clear stack
  4371. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  4372. mov eax, STATUS_PRIVILEGED_INSTRUCTION
  4373. jmp CommonDispatchException0Args ; Won't return
  4374. ;
  4375. ; NOTE All the GP fault (except the ones we can
  4376. ; easily detect now) will cause access violation exception
  4377. ; AND, all the access violation will be raised with additional
  4378. ; parameters set to "read" and "virtual address which caused
  4379. ; the violation = unknown (-1)"
  4380. ;
  4381. Kt0d100:
  4382. pop PCR[PcExceptionList]
  4383. add esp, 8 ; clear stack
  4384. Kt0d103:
  4385. Kt0d105:
  4386. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  4387. mov esi, -1
  4388. mov eax, STATUS_ACCESS_VIOLATION
  4389. jmp CommonDispatchException2Args0d ; Won't return
  4390. Kt0d110:
  4391. ; Raise Irql to APC level, before enabling interrupts
  4392. RaiseIrql APC_LEVEL
  4393. push eax ; Save OldIrql
  4394. sti
  4395. stdCall _VdmDispatchOpcode_try <ebp>
  4396. test eax,0FFFFh
  4397. jnz short Kt0d120
  4398. stdCall _Ki386VdmReflectException,<0dh>
  4399. test al,0fh
  4400. jnz short Kt0d120
  4401. pop ecx ; (TOS) = OldIrql
  4402. LowerIrql ecx
  4403. jmp short Kt0d105
  4404. Kt0d120:
  4405. pop ecx ; (TOS) = OldIrql
  4406. LowerIrql ecx
  4407. jmp _KiExceptionExit
  4408. _KiTrap0D endp
  4409. page ,132
  4410. subttl "Page faults on invalid addresses allowed in certain instances"
  4411. ;++
  4412. ; BOOLEAN
  4413. ; FASTCALL
  4414. ; KeInvalidAccessAllowed (
  4415. ; IN PVOID TrapInformation
  4416. ; )
  4417. ;
  4418. ;
  4419. ; Routine Description:
  4420. ;
  4421. ; Mm will pass a pointer to a trap frame prior to issuing a bug check on
  4422. ; a pagefault. This routine lets Mm know if it is ok to bugcheck. The
  4423. ; specific case we must protect are the interlocked pop sequences which can
  4424. ; blindly access memory that may have been freed and/or reused prior to the
  4425. ; access. We don't want to bugcheck the system in these cases, so we check
  4426. ; the instruction pointer here.
  4427. ;
  4428. ; Arguments:
  4429. ;
  4430. ; (ecx) - Trap frame pointer. NULL means return False.
  4431. ;
  4432. ; Return value:
  4433. ;
  4434. ; True if the invalid access should be ignored.
  4435. ; False which will usually trigger a bugcheck.
  4436. ;
  4437. ;--
  4438. cPublicFastCall KeInvalidAccessAllowed, 1
  4439. cPublicFpo 0,0
  4440. cmp ecx, 0 ; caller gave us a trap frame?
  4441. jne Ktia01 ; yes, so examine the frame
  4442. mov al, 0
  4443. jmp Ktia02 ; no frame, go bugcheck
  4444. Ktia01:
  4445. mov edx, offset FLAT:ExpInterlockedPopEntrySListFault
  4446. cmp [ecx].TsEip, edx ; check if fault at pop code address
  4447. sete al ; if yes, then don't bugcheck
  4448. Ktia02:
  4449. fstRET KeInvalidAccessAllowed
  4450. fstENDP KeInvalidAccessAllowed
  4451. ;
  4452. ; The following code it to fix a bug in the Pentium Proccesor dealing with
  4453. ; Invalid Opcodes.
  4454. ;
  4455. PentiumTest: ; Is this access to the write protect
  4456. ; IDT page?
  4457. test [ebp]+TsErrCode, 04h ; Do not allow user mode access to trap 6
  4458. jne NoPentiumFix ; vector. Let page fault code deal with it
  4459. mov eax, PCR[PcIDT] ; Get address of trap 6 IDT entry
  4460. add eax, (6 * 8)
  4461. cmp eax, edi ; Is that the faulting address?
  4462. jne NoPentiumFix ; No. Back to page fault code
  4463. ; Yes. We have accessed the write
  4464. ; protect page of the IDT
  4465. mov [ebp]+TsErrCode, 0 ; Overwrite error code
  4466. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  4467. test byte ptr [ebp]+TsEFlags+2, EFLAGS_V86_MASK/010000h ; Was it a VM?
  4468. jne Kt06VMpf ; Yes. Go to VM part of trap 6
  4469. jmp Kt06pf ; Not from a VM
  4470. page ,132
  4471. subttl "Page fault processing"
  4472. ;++
  4473. ;
  4474. ; Routine Description:
  4475. ;
  4476. ; Handle page fault.
  4477. ;
  4478. ; The page fault occurs if paging is enabled and any one of the
  4479. ; conditions is true:
  4480. ;
  4481. ; 1. page not present
  4482. ; 2. the faulting procedure does not have sufficient privilege to
  4483. ; access the indicated page.
  4484. ;
  4485. ; For case 1, the referenced page will be loaded to memory and
  4486. ; execution continues.
  4487. ; For case 2, registered exception handler will be invoked with
  4488. ; appropriate error code (in most cases STATUS_ACCESS_VIOLATION)
  4489. ;
  4490. ; N.B. It is assumed that no page fault is allowed during task
  4491. ; switches.
  4492. ;
  4493. ; N.B. INTERRUPTS MUST REMAIN OFF UNTIL AFTER CR2 IS CAPTURED.
  4494. ;
  4495. ; Arguments:
  4496. ;
  4497. ; Error code left on stack.
  4498. ; CR2 contains faulting address.
  4499. ; Interrupts are turned off at entry by use of an interrupt gate.
  4500. ;
  4501. ; Return value:
  4502. ;
  4503. ; None
  4504. ;
  4505. ;--
  4506. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  4507. ENTER_DR_ASSIST kite_a, kite_t, NoAbiosAssist
  4508. align dword
  4509. public _KiTrap0E
  4510. _KiTrap0E proc
  4511. ENTER_TRAP kite_a, kite_t
  4512. if FAST_BOP
  4513. cmp dword ptr PCR[PcVdmAlert], 0
  4514. jne Kt0eVdmAlert
  4515. endif
  4516. MODIFY_BASE_TRAP_FRAME
  4517. mov edi,cr2
  4518. ;
  4519. ; Now that everything is in a sane state check for rest of the Pentium
  4520. ; Processor bug work around for illegal operands
  4521. ;
  4522. cmp _KiI386PentiumLockErrataPresent, 0
  4523. jne PentiumTest ; Check for special problems
  4524. NoPentiumFix: ; No. Skip it
  4525. sti
  4526. test [ebp]+TsEFlags, EFLAGS_INTERRUPT_MASK ; faulted with
  4527. jz Kt0e12b ; interrupts disabled?
  4528. Kt0e01:
  4529. ;
  4530. ; call _MmAccessFault to page in the not present page. If the cause
  4531. ; of the fault is 2, _MmAccessFault will return approriate error code
  4532. ;
  4533. push ebp ; set trap frame address
  4534. mov eax, [ebp]+TsSegCs ; set previous mode
  4535. and eax, MODE_MASK ;
  4536. push eax ;
  4537. push edi ; set virtual address of page fault
  4538. mov eax, [ebp]+TsErrCode ; set load/store indicator
  4539. shr eax, 1 ;
  4540. and eax, _KeErrorMask ;
  4541. push eax ;
  4542. CAPSTART <_KiTrap0E,_MmAccessFault@16>
  4543. call _MmAccessFault@16
  4544. CAPEND <_KiTrap0E>
  4545. test eax, eax ; check if page fault resolved
  4546. jl short Kt0e05 ; if l, page fault not resolved
  4547. cmp _PsWatchEnabled, 0 ; check if working set watch enabled
  4548. je short @f ; if e, working set watch not enabled
  4549. mov ebx, [ebp]+TsEip ; set exception address
  4550. stdCall _PsWatchWorkingSet, <eax, ebx, edi> ; record working set information
  4551. @@: cmp _KdpOweBreakpoint, 0 ; check for owed breakpoints
  4552. je _KiExceptionExit ; if e, no owed breakpoints
  4553. stdCall _KdSetOwedBreakpoints ; notify the debugger
  4554. jmp _KiExceptionExit ; join common code
  4555. ;
  4556. ; Memory management could not resolve the page fault.
  4557. ;
  4558. ; Check to determine if the fault occured in the interlocked pop entry slist
  4559. ; code. There is a case where a fault may occur in this code when the right
  4560. ; set of circumstances occurs. The fault can be ignored by simply skipping
  4561. ; the faulting instruction.
  4562. ;
  4563. Kt0e05: mov ecx, offset FLAT:ExpInterlockedPopEntrySListFault ; get pop code address
  4564. cmp [ebp].TsEip, ecx ; check if fault at pop code address
  4565. je Kt0e10a ; if eq, skip faulting instruction
  4566. ;
  4567. ; Did the fault occur in KiSystemService while copying arguments from
  4568. ; user stack to kernel stack?
  4569. ;
  4570. mov ecx, offset FLAT:KiSystemServiceCopyArguments
  4571. cmp [ebp].TsEip, ecx
  4572. je short Kt0e06
  4573. mov ecx, offset FLAT:KiSystemServiceAccessTeb
  4574. cmp [ebp].TsEip, ecx
  4575. jne short Kt0e07
  4576. mov ecx, [ebp].TsEbp ; (eax)->TrapFrame of SysService
  4577. test [ecx].TsSegCs, MODE_MASK
  4578. jz short Kt0e07 ; caller of SysService is k mode, we
  4579. ; will let it bugcheck.
  4580. mov [ebp].TsEip, offset FLAT:kss61
  4581. mov eax, STATUS_ACCESS_VIOLATION
  4582. mov [ebp].TsEax, eax
  4583. jmp _KiExceptionExit
  4584. Kt0e06:
  4585. mov ecx, [ebp].TsEbp ; (eax)->TrapFrame of SysService
  4586. test [ecx].TsSegCs, MODE_MASK
  4587. jz short Kt0e07 ; caller of SysService is k mode, we
  4588. ; will let it bugcheck.
  4589. mov [ebp].TsEip, offset FLAT:kss60
  4590. mov eax, STATUS_ACCESS_VIOLATION
  4591. mov [ebp].TsEax, eax
  4592. jmp _KiExceptionExit
  4593. Kt0e07:
  4594. mov ecx, [ebp]+TsErrCode ; (ecx) = error code
  4595. shr ecx, 1 ; isolate read/write bit
  4596. and ecx, _KeErrorMask ;
  4597. ;
  4598. ; Did the fault occur in a VDM?
  4599. ;
  4600. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  4601. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  4602. jnz Kt0e7
  4603. ;
  4604. ; Did the fault occur in a VDM while running in protected mode?
  4605. ;
  4606. mov esi,PCR[PcPrcbData+PbCurrentThread]
  4607. mov esi,[esi]+ThApcState+AsProcess
  4608. cmp dword ptr [esi]+PrVdmObjects,0 ; is this a vdm process?
  4609. je short Kt0e9 ; z -> not vdm
  4610. .errnz (MODE_MASK AND 0FFFFFF00h)
  4611. test byte ptr [ebp]+TsSegCs, MODE_MASK
  4612. jz short Kt0e9 ; kernel mode, just dispatch exception.
  4613. cmp word ptr [ebp]+TsSegCs, KGDT_R3_CODE OR RPL_MASK
  4614. jz kt0e9 ; z -> not vdm
  4615. Kt0e7: mov esi, eax
  4616. stdCall _VdmDispatchPageFault, <ebp,ecx,edi>
  4617. test al,0fh ; returns TRUE, if success
  4618. jnz Kt0e11 ; Exit,No need to call the debugger
  4619. mov eax, esi
  4620. Kt0e9:
  4621. ; Set up exception record and arguments and call _KiDispatchException
  4622. mov esi, [ebp]+TsEip ; (esi)-> faulting instruction
  4623. cmp eax, STATUS_ACCESS_VIOLATION ; dispatch access violation or
  4624. je short Kt0e9b ; or in_page_error?
  4625. cmp eax, STATUS_GUARD_PAGE_VIOLATION
  4626. je short Kt0e9b
  4627. cmp eax, STATUS_STACK_OVERFLOW
  4628. je short Kt0e9b
  4629. ;
  4630. ; test to see if davec's reserved status code bit is set. If so, then bugchecka
  4631. ;
  4632. cmp eax, STATUS_IN_PAGE_ERROR or 10000000h
  4633. je Kt0e12 ; bugchecka
  4634. ;
  4635. ; (ecx) = ExceptionInfo 1
  4636. ; (edi) = ExceptionInfo 2
  4637. ; (eax) = ExceptionInfo 3
  4638. ; (esi) -> Exception Addr
  4639. ;
  4640. mov edx, ecx
  4641. mov ebx, esi
  4642. mov esi, edi
  4643. mov ecx, 3
  4644. mov edi, eax
  4645. mov eax, STATUS_IN_PAGE_ERROR
  4646. call CommonDispatchException ; Won't return
  4647. Kt0e9b:
  4648. mov ebx, esi
  4649. mov edx, ecx
  4650. mov esi, edi
  4651. jmp CommonDispatchException2Args ; Won't return
  4652. .FPO ( 0, 0, 0, 0, 0, FPO_TRAPFRAME )
  4653. ;
  4654. ; The fault occured in the interlocked pop slist function and the faulting
  4655. ; instruction should be skipped.
  4656. ;
  4657. Kt0e10a:mov ecx, offset FLAT:ExpInterlockedPopEntrySListResume ; get resume address
  4658. mov [ebp].TsEip, ecx ; set continuation address
  4659. Kt0e10:
  4660. mov esp,ebp ; (esp) -> trap frame
  4661. test _KdpOweBreakpoint, 1 ; do we have any owed breakpoints?
  4662. jz _KiExceptionExit ; No, all done
  4663. stdCall _KdSetOwedBreakpoints ; notify the debugger
  4664. Kt0e11: mov esp,ebp ; (esp) -> trap frame
  4665. jmp _KiExceptionExit ; join common code
  4666. Kt0e12:
  4667. CurrentIrql ; (eax) = OldIrql
  4668. Kt0e12a:
  4669. lock inc ds:_KiHardwareTrigger ; trip hardware analyzer
  4670. ;
  4671. ; bugcheck a, addr, irql, load/store, pc
  4672. ;
  4673. mov ecx, [ebp]+TsErrCode ; (ecx)= error code
  4674. shr ecx, 1 ; isolate read/write bit
  4675. and ecx, _KeErrorMask ;
  4676. mov esi, [ebp]+TsEip ; [esi] = faulting instruction
  4677. stdCall _KeBugCheckEx,<IRQL_NOT_LESS_OR_EQUAL,edi,eax,ecx,esi>
  4678. Kt0e12b:cmp _KiFreezeFlag,0 ; during boot we can take
  4679. jnz Kt0e01 ; 'transition faults' on the
  4680. ; debugger before it's been locked
  4681. cmp _KiBugCheckData, 0 ; If crashed, handle trap in
  4682. jnz Kt0e01 ; normal manner
  4683. mov eax, 0ffh ; OldIrql = -1
  4684. jmp short Kt0e12a
  4685. if FAST_BOP
  4686. Kt0eVdmAlert:
  4687. ;
  4688. ; If a page fault occured while we are in VDM alert mode (processing
  4689. ; v86 trap without building trap frame), we will restore all the
  4690. ; registers and return to its recovery routine which is stored in
  4691. ; the TsSegGs of original trap frame.
  4692. ;
  4693. mov eax, PCR[PcVdmAlert]
  4694. mov dword ptr PCR[PcVdmAlert], 0
  4695. mov [ebp].TsEip, eax
  4696. mov esp,ebp ; (esp) -> trap frame
  4697. jmp _KiExceptionExit ; join common code
  4698. endif ; FAST_BOP
  4699. _KiTrap0E endp
  4700. page ,132
  4701. subttl "Trap0F -- Intel Reserved"
  4702. ;++
  4703. ;
  4704. ; Routine Description:
  4705. ;
  4706. ; The trap 0F should never occur. If, however, the exception occurs in
  4707. ; USER mode, the current process will be terminated. If the exception
  4708. ; occurs in KERNEL mode, a bugcheck will be raised. NO registered
  4709. ; handler, if any, will be invoked to handle the exception.
  4710. ;
  4711. ; Arguments:
  4712. ;
  4713. ; None
  4714. ; Return value:
  4715. ;
  4716. ; None
  4717. ;
  4718. ;--
  4719. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  4720. ENTER_DR_ASSIST kitf_a, kitf_t, NoAbiosAssist
  4721. align dword
  4722. public _KiTrap0F
  4723. _KiTrap0F proc
  4724. push 0 ; push dummy error code
  4725. ENTER_TRAP kitf_a, kitf_t
  4726. sti
  4727. mov eax, EXCEPTION_RESERVED_TRAP ; (eax) = trap type
  4728. jmp _KiSystemFatalException ; go terminate the system
  4729. _KiTrap0F endp
  4730. page ,132
  4731. subttl "Coprocessor Error"
  4732. ;++
  4733. ;
  4734. ; Routine Description:
  4735. ;
  4736. ; Handle Coprocessor Error.
  4737. ;
  4738. ; This exception is used on 486 or above only. For i386, it uses
  4739. ; IRQ 13 instead.
  4740. ;
  4741. ; Arguments:
  4742. ;
  4743. ; At entry, the saved CS:EIP point to the aborted instruction.
  4744. ; No error code is provided with the error.
  4745. ;
  4746. ; Return value:
  4747. ;
  4748. ; None
  4749. ;
  4750. ;--
  4751. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  4752. ENTER_DR_ASSIST kit10_a, kit10_t, NoAbiosAssist
  4753. align dword
  4754. public _KiTrap10
  4755. _KiTrap10 proc
  4756. push 0 ; push dummy error code
  4757. ENTER_TRAP kit10_a, kit10_t
  4758. mov eax, PCR[PcPrcbData+PbCurrentThread] ; Correct context for
  4759. cmp eax, PCR[PcPrcbData+PbNpxThread] ; fault?
  4760. mov ecx, [eax].ThInitialStack
  4761. lea ecx, [ecx]-NPX_FRAME_LENGTH
  4762. je Kt0715 ; Yes - go try to dispatch it
  4763. ;
  4764. ; We are in the wrong NPX context and can not dispatch the exception right now.
  4765. ; Set up the target thread for a delay exception.
  4766. ;
  4767. ; Note: we don't think this is a possible case, but just to be safe...
  4768. ;
  4769. or dword ptr [ecx].FpCr0NpxState, CR0_TS ; Set for delayed error
  4770. jmp _KiExceptionExit
  4771. _KiTrap10 endp
  4772. page ,132
  4773. subttl "Alignment fault"
  4774. ;++
  4775. ;
  4776. ; Routine Description:
  4777. ;
  4778. ; Handle alignment faults.
  4779. ;
  4780. ; This exception occurs when an unaligned data access is made by a thread
  4781. ; with alignment checking turned on.
  4782. ;
  4783. ; The x86 will not do any alignment checking. Only threads which have
  4784. ; the appropriate bit set in EFLAGS will generate alignment faults.
  4785. ;
  4786. ; The exception will never occur in kernel mode. (hardware limitation)
  4787. ;
  4788. ; Arguments:
  4789. ;
  4790. ; At entry, the saved CS:EIP point to the faulting instruction.
  4791. ; Error code is provided.
  4792. ;
  4793. ; Return value:
  4794. ;
  4795. ; None
  4796. ;
  4797. ;--
  4798. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  4799. ENTER_DR_ASSIST kit11_a, kit11_t, NoAbiosAssist
  4800. align dword
  4801. public _KiTrap11
  4802. _KiTrap11 proc
  4803. ENTER_TRAP kit11_a, kit11_t
  4804. sti
  4805. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  4806. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  4807. jnz Kt11_01 ; v86 mode => usermode
  4808. .errnz (MODE_MASK AND 0FFFFFF00h)
  4809. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previous mode = USER
  4810. jz Kt11_10
  4811. ;
  4812. ; Check to make sure that the AutoAlignment state of this thread is FALSE.
  4813. ; If not, this fault occurred because the thread messed with its own EFLAGS.
  4814. ; In order to "fixup" this fault, we just clear the ALIGN_CHECK bit in the
  4815. ; EFLAGS and restart the instruction. Exceptions will only be generated if
  4816. ; AutoAlignment is FALSE.
  4817. ;
  4818. Kt11_01:
  4819. mov ebx,PCR[PcPrcbData+PbCurrentThread] ; (ebx)-> Current Thread
  4820. test byte ptr [ebx].ThAutoAlignment, -1
  4821. jz kt11_00
  4822. ;
  4823. ; This fault was generated even though the thread had AutoAlignment set to
  4824. ; TRUE. So we fix it up by setting the correct state in his EFLAGS and
  4825. ; restarting the instruction.
  4826. ;
  4827. and dword ptr [ebp]+TsEflags, NOT EFLAGS_ALIGN_CHECK
  4828. jmp _KiExceptionExit
  4829. kt11_00:
  4830. mov ebx, [ebp]+TsEip ; (ebx)->faulting instruction
  4831. mov edx, EXCEPT_LIMIT_ACCESS; assume it is limit violation
  4832. mov esi, [ebp]+TsHardwareEsp; (esi) = User Stack pointer
  4833. cmp word ptr [ebp]+TsErrCode, 0 ; Is errorcode = 0?
  4834. jz short kt11_05 ; if z, yes, go dispatch exception
  4835. mov edx, EXCEPT_UNKNOWN_ACCESS
  4836. kt11_05:
  4837. mov eax, STATUS_DATATYPE_MISALIGNMENT
  4838. jmp CommonDispatchException2Args ; Won't return
  4839. kt11_10:
  4840. ;
  4841. ; We should never be here, since the 486 will not generate alignment faults
  4842. ; in kernel mode.
  4843. ;
  4844. mov eax, EXCEPTION_ALIGNMENT_CHECK ; (eax) = trap type
  4845. jmp _KiSystemFatalException
  4846. _KiTrap11 endp
  4847. ;++
  4848. ;
  4849. ; Routine Description:
  4850. ;
  4851. ; Handle XMMI Exception.
  4852. ;;
  4853. ; Arguments:
  4854. ;
  4855. ; At entry, the saved CS:EIP point to the aborted instruction.
  4856. ; No error code is provided with the error.
  4857. ;
  4858. ; Return value:
  4859. ;
  4860. ; None
  4861. ;
  4862. ;--
  4863. ASSUME DS:NOTHING, SS:NOTHING, ES:NOTHING
  4864. ENTER_DR_ASSIST kit13_a, kit13_t, NoAbiosAssist
  4865. align dword
  4866. public _KiTrap13
  4867. _KiTrap13 proc
  4868. push 0 ; push dummy error code
  4869. ENTER_TRAP kit13_a, kit13_t
  4870. mov eax, PCR[PcPrcbData+PbNpxThread] ; Correct context for fault?
  4871. cmp eax, PCR[PcPrcbData+PbCurrentThread]
  4872. je Kt13_10 ; Yes - go try to dispatch it
  4873. ;
  4874. ; Katmai New Instruction exceptions are precise and occur immediately.
  4875. ; if we are in the wrong NPX context, bugcheck the system.
  4876. ;
  4877. ; stop the system
  4878. stdCall _KeBugCheckEx,<TRAP_CAUSE_UNKNOWN,13,eax,0,0>
  4879. Kt13_10:
  4880. mov ecx, [eax].ThInitialStack ; (ecx) -> top of kernel stack
  4881. sub ecx, NPX_FRAME_LENGTH
  4882. ;
  4883. ; TrapFrame is built by ENTER_TRAP.
  4884. ; XMMI are accessible from all IA execution modes:
  4885. ; Protected Mode, Real address mode, Virtual 8086 mode
  4886. ;
  4887. Kt13_15:
  4888. .errnz (EFLAGS_V86_MASK AND 0FF00FFFFh)
  4889. test byte ptr [ebp]+TsEFlags+2,EFLAGS_V86_MASK/010000h
  4890. jnz Kt13_130 ; v86 mode
  4891. ;
  4892. ; eflags.vm=0 (not v86 mode)
  4893. ;
  4894. .errnz (MODE_MASK AND 0FFFFFF00h)
  4895. test byte ptr [ebp]+TsSegCs, MODE_MASK ; Is previousMode=USER?
  4896. jz Kt13_05 ; if z, previousmode=SYSTEM
  4897. ;
  4898. ; eflags.vm=0 (not v86 mode)
  4899. ; previousMode=USER
  4900. ;
  4901. cmp word ptr [ebp]+TsSegCs,KGDT_R3_CODE OR RPL_MASK
  4902. jne Kt13_110 ; May still be a vdm...
  4903. ;
  4904. ; eflags.vm=0 (not v86 mode)
  4905. ; previousMode=USER
  4906. ; Cs=00011011
  4907. ;
  4908. ; We are about to dispatch a XMMI floating point exception to user mode.
  4909. ;
  4910. ; (ebp) - Trap frame
  4911. ; (ecx) - CurrentThread's NPX save area (PCR[PcInitialStack])
  4912. ; (eax) - CurrentThread
  4913. ; Dispatch
  4914. Kt13_20:
  4915. ;
  4916. ; Some type of coprocessor exception has occured for the current thread.
  4917. ;
  4918. ; Interrupts disabled
  4919. ;
  4920. mov ebx, cr0
  4921. and ebx, NOT (CR0_MP+CR0_EM+CR0_TS)
  4922. mov cr0, ebx ; Clear MP+TS+EM to do fxsave
  4923. ;
  4924. ; Save the faulting state so we can inspect the cause of the floating
  4925. ; point fault
  4926. ;
  4927. FXSAVE_ECX
  4928. if DBG
  4929. test dword ptr [ecx].FpCr0NpxState, NOT (CR0_MP+CR0_EM+CR0_TS)
  4930. jnz Kt13_dbg2
  4931. endif
  4932. or ebx, NPX_STATE_NOT_LOADED ; CR0_TS | CR0_MP
  4933. or ebx,[ecx]+FpCr0NpxState ; restore this thread's CR0 NPX state
  4934. mov cr0, ebx ; set TS so next ESC access causes trap
  4935. ;
  4936. ; Clear TS bit in Cr0NpxFlags in case it was set to trigger this trap.
  4937. ;
  4938. and dword ptr [ecx].FpCr0NpxState, NOT CR0_TS
  4939. ;
  4940. ; The state is no longer in the coprocessor. Clear ThNpxState and
  4941. ; re-enable interrupts to allow context switching.
  4942. ;
  4943. mov byte ptr [eax].ThNpxState, NPX_STATE_NOT_LOADED
  4944. mov dword ptr PCR[PcPrcbData+PbNpxThread], 0 ; No state in coprocessor
  4945. sti
  4946. ; (eax) = ExcepCode - Exception code to put into exception record
  4947. ; (ebx) = ExceptAddress - Addr of instruction which the hardware exception occurs
  4948. ; (ecx) = NumParms - Number of additional parameters
  4949. ; (edx) = Parameter1
  4950. ; (esi) = Parameter2
  4951. ; (edi) = Parameter3
  4952. mov ebx, [ebp].TsEip ; Eip is from trap frame, not from FxErrorOffset
  4953. movzx eax, word ptr [ecx] + FxMXCsr
  4954. mov edx, eax
  4955. shr edx, 7 ; get the mask
  4956. not edx
  4957. mov esi, 0 ; (esi) = operand addr, addr is computed from
  4958. ; trap frame, not from FxDataOffset
  4959. ;
  4960. ; Exception will be handled in user's handler if there is one declared.
  4961. ;
  4962. and eax, FSW_INVALID_OPERATION + FSW_DENORMAL + FSW_ZERO_DIVIDE + FSW_OVERFLOW + FSW_UNDERFLOW + FSW_PRECISION
  4963. and eax, edx
  4964. .errnz (FSW_INVALID_OPERATION AND 0FFFFFF00h)
  4965. test al, FSW_INVALID_OPERATION ; Is it an invalid op exception?
  4966. jz short Kt13_40 ; if z, no, go Kt13_40
  4967. ;
  4968. ; Invalid Operation Exception - Invalid arithmetic operand
  4969. ; Raise exception
  4970. ;
  4971. mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
  4972. jmp CommonDispatchException1Arg0d ; Won't return
  4973. Kt13_40:
  4974. ; Check for floating zero divide exception
  4975. ;
  4976. .errnz (FSW_ZERO_DIVIDE AND 0FFFFFF00h)
  4977. test al, FSW_ZERO_DIVIDE ; Is it a zero divide error?
  4978. jz short Kt13_50 ; if z, no, go Kt13_50
  4979. ;
  4980. ; Division-By-Zero Exception
  4981. ; Raise exception
  4982. ;
  4983. mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
  4984. jmp CommonDispatchException1Arg0d ; Won't return
  4985. Kt13_50:
  4986. ; Check for denormal error
  4987. ;
  4988. .errnz (FSW_DENORMAL AND 0FFFFFF00h)
  4989. test al, FSW_DENORMAL ; Is it a denormal error?
  4990. jz short Kt13_60 ; if z, no, go Kt13_60
  4991. ;
  4992. ; Denormal Operand Excpetion
  4993. ; Raise exception
  4994. ;
  4995. mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
  4996. jmp CommonDispatchException1Arg0d ; Won't return
  4997. Kt13_60:
  4998. ; Check for floating overflow error
  4999. ;
  5000. .errnz (FSW_OVERFLOW AND 0FFFFFF00h)
  5001. test al, FSW_OVERFLOW ; Is it an overflow error?
  5002. jz short Kt13_70 ; if z, no, go Kt13_70
  5003. ;
  5004. ; Numeric Overflow Exception
  5005. ; Raise exception
  5006. ;
  5007. mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
  5008. jmp CommonDispatchException1Arg0d ; Won't return
  5009. Kt13_70:
  5010. ; Check for floating underflow error
  5011. ;
  5012. .errnz (FSW_UNDERFLOW AND 0FFFFFF00h)
  5013. test al, FSW_UNDERFLOW ; Is it a underflow error?
  5014. jz short Kt13_80 ; if z, no, go Kt13_80
  5015. ;
  5016. ; Numeric Underflow Exception
  5017. ; Raise exception
  5018. ;
  5019. mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
  5020. jmp CommonDispatchException1Arg0d ; Won't return
  5021. Kt13_80:
  5022. ; Check for precision (IEEE inexact) error
  5023. ;
  5024. .errnz (FSW_PRECISION AND 0FFFFFF00h)
  5025. test al, FSW_PRECISION ; Is it a precision error
  5026. jz short Kt13_100 ; if z, no, go Kt13_100
  5027. ;
  5028. ; Inexact-Result (Precision) Exception
  5029. ; Raise exception
  5030. ;
  5031. mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
  5032. jmp CommonDispatchException1Arg0d ; Won't return
  5033. ; Huh?
  5034. Kt13_100:
  5035. ; If status word does not indicate error, then something is wrong...
  5036. ; (Note: that we have done a sti, before the status is examined)
  5037. sti
  5038. ; stop the system
  5039. stdCall _KeBugCheckEx,<TRAP_CAUSE_UNKNOWN,13,eax,0,1>
  5040. ;
  5041. ; eflags.vm=0 (not v86 mode)
  5042. ; previousMode=USER
  5043. ; Cs=!00011011
  5044. ; (We should have (eax) -> CurrentThread)
  5045. ;
  5046. Kt13_110:
  5047. ; Check to see if this process is a vdm
  5048. mov ebx,PCR[PcPrcbData+PbCurrentThread] ; (ebx) -> CurrentThread
  5049. mov ebx,[ebx]+ThApcState+AsProcess ; (ebx) -> CurrentProcess
  5050. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  5051. je Kt13_20 ; no, dispatch exception
  5052. ; yes, drop down to v86 mode
  5053. ;
  5054. ; eflags.vm=1 (v86 mode)
  5055. ;
  5056. Kt13_130:
  5057. ; Turn off TS
  5058. mov ebx,CR0
  5059. and ebx,NOT CR0_TS
  5060. mov CR0,ebx
  5061. and dword ptr [ecx]+FpCr0NpxState,NOT CR0_TS
  5062. ;
  5063. ; Reflect the exception to the vdm, the VdmHandler enables interrupts
  5064. ;
  5065. ; Raise Irql to APC level before enabling interrupts
  5066. RaiseIrql APC_LEVEL
  5067. push eax ; Save OldIrql
  5068. sti
  5069. stdCall _VdmDispatchIRQ13, <ebp> ; ebp - Trapframe
  5070. test al,0fh
  5071. jnz Kt13_135
  5072. pop ecx ; (TOS) = OldIrql
  5073. LowerIrql ecx
  5074. jmp Kt13_20 ; could not reflect, gen exception
  5075. Kt13_135:
  5076. pop ecx ; (TOS) = OldIrql
  5077. LowerIrql ecx
  5078. jmp _KiExceptionExit
  5079. ;
  5080. ; eflags.vm=0 (not v86 mode)
  5081. ; previousMode=SYSTEM
  5082. ;
  5083. Kt13_05:
  5084. ; stop the system
  5085. stdCall _KeBugCheckEx,<TRAP_CAUSE_UNKNOWN,13,0,0,2>
  5086. if DBG
  5087. Kt13_dbg1: int 3
  5088. Kt13_dbg2: int 3
  5089. Kt13_dbg3: int 3
  5090. sti
  5091. jmp short $-2
  5092. endif
  5093. _KiTrap13 endp
  5094. page ,132
  5095. subttl "Coprocessor Error Handler"
  5096. ;++
  5097. ;
  5098. ; Routine Description:
  5099. ;
  5100. ; When the FPU detects an error, it raises its error line. This
  5101. ; was supposed to be routed directly to the x86 to cause a trap 16
  5102. ; (which would actually occur when the x86 encountered the next FP
  5103. ; instruction).
  5104. ;
  5105. ; However, the ISA design routes the error line to IRQ13 on the
  5106. ; slave 8259. So an interrupt will be generated whenever the FPU
  5107. ; discovers an error. Unfortunately, we could be executing system
  5108. ; code at the time, in which case we can't dispatch the exception.
  5109. ;
  5110. ; So we force emulation of the intended behaviour. This interrupt
  5111. ; handler merely sets TS and Cr0NpxState TS and dismisses the interrupt.
  5112. ; Then, on the next user FP instruction, a trap 07 will be generated, and
  5113. ; the exception can be dispatched then.
  5114. ;
  5115. ; Note that we don't have to clear the FP exeception here,
  5116. ; since that will be done in the trap 07 handler. The x86 will
  5117. ; generate the trap 07 before the FPU gets a chance to raise another
  5118. ; error interrupt. We'll want to save the FPU state in the trap 07
  5119. ; handler WITH the error information.
  5120. ;
  5121. ; Note the caller must clear the FPU error latch. (this is done in
  5122. ; the hal).
  5123. ;
  5124. ; Arguments:
  5125. ;
  5126. ; None
  5127. ;
  5128. ; Return value:
  5129. ;
  5130. ; None
  5131. ;
  5132. ;--
  5133. ASSUME DS:FLAT, SS:NOTHING, ES:NOTHING
  5134. align dword
  5135. cPublicProc _KiCoprocessorError ,0
  5136. ;
  5137. ; Set TS in Cr0NpxState - the next time this thread runs an ESC
  5138. ; instruction the error will be dispatched. We also need to set TS
  5139. ; in CR0 in case the owner of the NPX is currently running.
  5140. ;
  5141. ; Bit must be set in FpCr0NpxState before CR0.
  5142. ;
  5143. mov eax, PCR[PcPrcbData+PbNpxThread]
  5144. mov eax, [eax].ThInitialStack
  5145. sub eax, NPX_FRAME_LENGTH ; Space for NPX_FRAME
  5146. or dword ptr [eax].FpCr0NpxState, CR0_TS
  5147. mov eax, cr0
  5148. or eax, CR0_TS
  5149. mov cr0, eax
  5150. stdRET _KiCoprocessorError
  5151. stdENDP _KiCoprocessorError
  5152. ;
  5153. ; BBT cannot instrument code between BBT_Exclude_Trap_Code_Begin and this label
  5154. ;
  5155. public _BBT_Exclude_Trap_Code_End
  5156. _BBT_Exclude_Trap_Code_End equ $
  5157. int 3
  5158. ;++
  5159. ;
  5160. ; VOID
  5161. ; KiFlushNPXState (
  5162. ; PFLOATING_SAVE_AREA SaveArea
  5163. ; )
  5164. ;
  5165. ; Routine Description:
  5166. ;
  5167. ; When a thread's NPX context is requested (most likely by a debugger)
  5168. ; this function is called to flush the thread's NPX context out of the
  5169. ; compressor if required.
  5170. ;
  5171. ; Arguments:
  5172. ;
  5173. ; Pointer to a location where this function must do fnsave for the
  5174. ; current thread.
  5175. ;
  5176. ; NOTE that this pointer can be NON-NULL only if KeI386FxsrPresent is
  5177. ; set (FXSR feature is present)
  5178. ;
  5179. ; Return value:
  5180. ;
  5181. ; None
  5182. ;
  5183. ;--
  5184. ASSUME DS:FLAT, SS:NOTHING, ES:NOTHING
  5185. align dword
  5186. SaveArea equ [esp + 20]
  5187. cPublicProc _KiFlushNPXState ,1
  5188. cPublicFpo 1, 4
  5189. push esi
  5190. push edi
  5191. push ebx
  5192. pushfd
  5193. cli ; don't context switch
  5194. mov edi, PCR[PcSelfPcr]
  5195. mov esi, [edi].PcPrcbData+PbCurrentThread
  5196. cmp byte ptr [esi].ThNpxState, NPX_STATE_LOADED
  5197. je short fnpx20
  5198. fnpx00:
  5199. ; NPX state is not loaded. If SaveArea is non-null, we need to return
  5200. ; the saved FP state in fnsave format.
  5201. cmp dword ptr SaveArea, 0
  5202. je fnpx70
  5203. if DBG
  5204. ;
  5205. ; SaveArea can be NON-NULL ONLY when FXSR feature is present
  5206. ;
  5207. test byte ptr _KeI386FxsrPresent, 1
  5208. jnz @f
  5209. int 3
  5210. @@:
  5211. endif
  5212. ;
  5213. ; Need to convert the (not loaded) NPX state of the current thread
  5214. ; to FNSAVE format into the SaveArea
  5215. ;
  5216. mov ebx, cr0
  5217. .errnz ((CR0_MP+CR0_TS+CR0_EM) AND 0FFFFFF00h)
  5218. test bl, CR0_MP+CR0_TS+CR0_EM
  5219. jz short fnpx07
  5220. and ebx, NOT (CR0_MP+CR0_TS+CR0_EM)
  5221. mov cr0, ebx ; allow frstor (& fnsave) to work
  5222. fnpx07:
  5223. ;
  5224. ; If NPX state is for some other thread, save it away
  5225. ;
  5226. mov eax, [edi].PcPrcbData+PbNpxThread ; Owner of NPX state
  5227. or eax, eax
  5228. jz short fnpx10 ; no - skip save
  5229. cmp byte ptr [eax].ThNpxState, NPX_STATE_LOADED
  5230. jne short fnpx10 ; not loaded, skip save
  5231. ifndef NT_UP
  5232. if DBG
  5233. ; This can only happen UP where the context is not unloaded on a swap
  5234. int 3
  5235. endif
  5236. endif
  5237. ;
  5238. ; Save current owners NPX state
  5239. ;
  5240. mov ecx, [eax].ThInitialStack
  5241. sub ecx, NPX_FRAME_LENGTH ; Space for NPX_FRAME
  5242. FXSAVE_ECX
  5243. mov byte ptr [eax].ThNpxState, NPX_STATE_NOT_LOADED
  5244. fnpx10:
  5245. ;
  5246. ; Load current thread's NPX state
  5247. ;
  5248. mov ecx, [edi].PcPrcbData+PbCurrentThread
  5249. mov ecx, [ecx].ThInitialStack ; (ecx) -> top of kernel stack
  5250. sub ecx, NPX_FRAME_LENGTH
  5251. FXRSTOR_ECX ; reload NPX context
  5252. mov ecx, SaveArea
  5253. jmp short fnpx40
  5254. fnpx20:
  5255. ;
  5256. ; Current thread has NPX state in the coprocessor, flush it
  5257. ;
  5258. mov ebx, cr0
  5259. .errnz ((CR0_MP+CR0_TS+CR0_EM) AND 0FFFFFF00h)
  5260. test bl, CR0_MP+CR0_TS+CR0_EM
  5261. jz short fnpx30
  5262. and ebx, NOT (CR0_MP+CR0_TS+CR0_EM)
  5263. mov cr0, ebx ; allow frstor (& fnsave) to work
  5264. fnpx30:
  5265. mov ecx, [edi].PcPrcbData+PbCurrentThread
  5266. mov ecx, [ecx].ThInitialStack ; (ecx) -> top of kernel stack
  5267. sub ecx, NPX_FRAME_LENGTH
  5268. test byte ptr _KeI386FxsrPresent, 1
  5269. jz short fnpx40
  5270. FXSAVE_ECX
  5271. ; Do fnsave to SaveArea if it is non-null
  5272. mov ecx, SaveArea
  5273. jecxz short fnpx50
  5274. fnpx40:
  5275. fnsave [ecx] ; NPX state to save area
  5276. fwait ; Make sure data is in save area
  5277. fnpx50:
  5278. xor eax, eax
  5279. mov ecx, [edi].PcPrcbData+PbCurrentThread
  5280. mov ecx, [ecx].ThInitialStack ; (ecx) -> top of kernel stack
  5281. sub ecx, NPX_FRAME_LENGTH
  5282. mov byte ptr [esi].ThNpxState, NPX_STATE_NOT_LOADED
  5283. mov [edi].PcPrcbData+PbNpxThread, eax ; clear npx owner
  5284. ;; mov [ecx].FpNpxSavedCpu, eax ; clear last npx processor
  5285. or ebx, NPX_STATE_NOT_LOADED ; or in new thread's cr0
  5286. or ebx, [ecx]+FpCr0NpxState ; merge new thread setable state
  5287. mov cr0, ebx
  5288. fnpx70:
  5289. popfd ; enable interrupts
  5290. pop ebx
  5291. pop edi
  5292. pop esi
  5293. stdRET _KiFlushNPXState
  5294. stdENDP _KiFlushNPXState
  5295. ;++
  5296. ;
  5297. ; VOID
  5298. ; KiSetHardwareTrigger (
  5299. ; VOID
  5300. ; )
  5301. ;
  5302. ; Routine Description:
  5303. ;
  5304. ; This function sets KiHardwareTrigger such that an analyzer can sniff
  5305. ; for this access. It needs to occur with a lock cycle such that
  5306. ; the processor won't speculatively read this value. Interlocked
  5307. ; functions can't be used as in a UP build they do not use a
  5308. ; lock prefix.
  5309. ;
  5310. ; Arguments:
  5311. ;
  5312. ; None
  5313. ;
  5314. ; Return value:
  5315. ;
  5316. ; None
  5317. ;
  5318. ;--
  5319. ASSUME DS:FLAT, SS:NOTHING, ES:NOTHING
  5320. cPublicProc _KiSetHardwareTrigger,0
  5321. lock inc ds:_KiHardwareTrigger ; trip hardware analyzer
  5322. stdRet _KiSetHardwareTrigger
  5323. stdENDP _KiSetHardwareTrigger
  5324. page ,132
  5325. subttl "Processing System Fatal Exceptions"
  5326. ;++
  5327. ;
  5328. ; Routine Description:
  5329. ;
  5330. ; This routine processes the system fatal exceptions.
  5331. ; The machine state and trap type will be displayed and
  5332. ; System will be stopped.
  5333. ;
  5334. ; Arguments:
  5335. ;
  5336. ; (eax) = Trap type
  5337. ; (ebp) -> machine state frame
  5338. ;
  5339. ; Return value:
  5340. ;
  5341. ; system stopped.
  5342. ;
  5343. ;--
  5344. assume ds:nothing, es:nothing, ss:nothing, fs:nothing, gs:nothing
  5345. align dword
  5346. public _KiSystemFatalException
  5347. _KiSystemFatalException proc
  5348. .FPO (0, 0, 0, 0, 0, FPO_TRAPFRAME)
  5349. stdCall _KeBugCheckEx,<UNEXPECTED_KERNEL_MODE_TRAP, eax, 0, 0, 0>
  5350. ret
  5351. _KiSystemFatalException endp
  5352. page
  5353. subttl "Continue Execution System Service"
  5354. ;++
  5355. ;
  5356. ; NTSTATUS
  5357. ; NtContinue (
  5358. ; IN PCONTEXT ContextRecord,
  5359. ; IN BOOLEAN TestAlert
  5360. ; )
  5361. ;
  5362. ; Routine Description:
  5363. ;
  5364. ; This routine is called as a system service to continue execution after
  5365. ; an exception has occurred. Its function is to transfer information from
  5366. ; the specified context record into the trap frame that was built when the
  5367. ; system service was executed, and then exit the system as if an exception
  5368. ; had occurred.
  5369. ;
  5370. ; WARNING - Do not call this routine directly, always call it as
  5371. ; ZwContinue!!! This is required because it needs the
  5372. ; trapframe built by KiSystemService.
  5373. ;
  5374. ; Arguments:
  5375. ;
  5376. ; KTrapFrame (ebp+0: after setup) -> base of KTrapFrame
  5377. ;
  5378. ; ContextRecord (ebp+8: after setup) = Supplies a pointer to a context rec.
  5379. ;
  5380. ; TestAlert (esp+12: after setup) = Supplies a boolean value that specifies
  5381. ; whether alert should be tested for the previous processor mode.
  5382. ;
  5383. ; Return Value:
  5384. ;
  5385. ; Normally there is no return from this routine. However, if the specified
  5386. ; context record is misaligned or is not accessible, then the appropriate
  5387. ; status code is returned.
  5388. ;
  5389. ;--
  5390. NcTrapFrame equ [ebp + 0]
  5391. NcContextRecord equ [ebp + 8]
  5392. NcTestAlert equ [ebp + 12]
  5393. align dword
  5394. cPublicProc _NtContinue ,2
  5395. push ebp
  5396. ;
  5397. ; Restore old trap frame address since this service exits directly rather
  5398. ; than returning.
  5399. ;
  5400. mov ebx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
  5401. mov edx, [ebp].TsEdx ; restore old trap frame address
  5402. mov [ebx].ThTrapFrame, edx ;
  5403. ;
  5404. ; Call KiContinue to load ContextRecord into TrapFrame. On x86 TrapFrame
  5405. ; is an atomic entity, so we don't need to allocate any other space here.
  5406. ;
  5407. ; KiContinue(NcContextRecord, 0, NcTrapFrame)
  5408. ;
  5409. mov ebp,esp
  5410. mov eax, NcTrapFrame
  5411. mov ecx, NcContextRecord
  5412. CAPSTART <_NtContinue,_KiContinue@12>
  5413. stdCall _KiContinue, <ecx, 0, eax>
  5414. CAPEND <_NtContinue>
  5415. or eax,eax ; return value 0?
  5416. jnz short Nc20 ; KiContinue failed, go report error
  5417. ;
  5418. ; Check to determine if alert should be tested for the previous processor mode.
  5419. ;
  5420. cmp byte ptr NcTestAlert,0 ; Check test alert flag
  5421. je short Nc10 ; if z, don't test alert, go Nc10
  5422. mov al,byte ptr [ebx]+ThPreviousMode ; No need to xor eax, eax.
  5423. CAPSTART <_NtContinue,_KeTestAlertThread@4>
  5424. stdCall _KeTestAlertThread, <eax> ; test alert for current thread
  5425. CAPEND <_NtContinue>
  5426. Nc10: CAPEND <_KiSystemService>
  5427. pop ebp ; (ebp) -> TrapFrame
  5428. mov esp,ebp ; (esp) = (ebp) -> trapframe
  5429. jmp _KiServiceExit2 ; common exit
  5430. Nc20: pop ebp ; (ebp) -> TrapFrame
  5431. mov esp,ebp ; (esp) = (ebp) -> trapframe
  5432. jmp _KiServiceExit ; common exit
  5433. stdENDP _NtContinue
  5434. page
  5435. subttl "Raise Exception System Service"
  5436. ;++
  5437. ;
  5438. ; NTSTATUS
  5439. ; NtRaiseException (
  5440. ; IN PEXCEPTION_RECORD ExceptionRecord,
  5441. ; IN PCONTEXT ContextRecord,
  5442. ; IN BOOLEAN FirstChance
  5443. ; )
  5444. ;
  5445. ; Routine Description:
  5446. ;
  5447. ; This routine is called as a system service to raise an exception. Its
  5448. ; function is to transfer information from the specified context record
  5449. ; into the trap frame that was built when the system service was executed.
  5450. ; The exception may be raised as a first or second chance exception.
  5451. ;
  5452. ; WARNING - Do not call this routine directly, always call it as
  5453. ; ZwRaiseException!!! This is required because it needs the
  5454. ; trapframe built by KiSystemService.
  5455. ;
  5456. ; NOTE - KiSystemService will terminate the ExceptionList, which is
  5457. ; not what we want for this case, so we will fish it out of
  5458. ; the trap frame and restore it.
  5459. ;
  5460. ; Arguments:
  5461. ;
  5462. ; TrapFrame (ebp+0: before setup) -> System trap frame for this call
  5463. ;
  5464. ; ExceptionRecord (ebp+8: after setup) -> An exception record.
  5465. ;
  5466. ; ContextRecord (ebp+12: after setup) -> Points to a context record.
  5467. ;
  5468. ; FirstChance (ebp+16: after setup) -> Supplies a boolean value that
  5469. ; specifies whether the exception is to be raised as a first (TRUE)
  5470. ; or second chance (FALSE) exception.
  5471. ;
  5472. ; Return Value:
  5473. ;
  5474. ; None.
  5475. ;--
  5476. align dword
  5477. cPublicProc _NtRaiseException ,3
  5478. NtRaiseException:
  5479. push ebp
  5480. ;
  5481. ; Restore old trap frame address since this service exits directly rather
  5482. ; than returning.
  5483. ;
  5484. mov ebx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
  5485. mov edx, [ebp].TsEdx ; restore old trap frame address
  5486. mov [ebx].ThTrapFrame, edx ;
  5487. ;
  5488. ; Put back the ExceptionList so the exception can be properly
  5489. ; dispatched.
  5490. ;
  5491. mov ebp,esp ; [ebp+0] -> TrapFrame
  5492. mov ebx, [ebp+0] ; (ebx)->TrapFrame
  5493. mov edx, [ebp+16] ; (edx) = First chance indicator
  5494. mov eax, [ebx]+TsExceptionList ; Old exception list
  5495. mov ecx, [ebp+12] ; (ecx)->ContextRecord
  5496. mov PCR[PcExceptionList],eax
  5497. mov eax, [ebp+8] ; (eax)->ExceptionRecord
  5498. ;
  5499. ; KiRaiseException(ExceptionRecord, ContextRecord, ExceptionFrame,
  5500. ; TrapFrame, FirstChance)
  5501. ;
  5502. CAPSTART <NtRaiseException,_KiRaiseException@20>
  5503. stdCall _KiRaiseException,<eax, ecx, 0, ebx, edx>
  5504. CAPEND <NtRaiseException>
  5505. pop ebp
  5506. mov esp,ebp ; (esp) = (ebp) -> trap frame
  5507. ;
  5508. ; If the exception was handled, then the trap frame has been edited to
  5509. ; reflect new state, and we'll simply exit the system service to get
  5510. ; the effect of a continue.
  5511. ;
  5512. ; If the exception was not handled, exit via KiServiceExit so the
  5513. ; return status is propagated back to the caller.
  5514. ;
  5515. or eax, eax ; test exception handled
  5516. jnz _KiServiceExit ; if exception not handled
  5517. jmp _KiServiceExit2
  5518. stdENDP _NtRaiseException
  5519. page
  5520. subttl "Reflect Exception to a Vdm"
  5521. ;++
  5522. ;
  5523. ; Routine Description:
  5524. ; Local stub which reflects an exception to a VDM using
  5525. ; Ki386VdmReflectException,
  5526. ;
  5527. ; Arguments:
  5528. ;
  5529. ; ebp -> Trap frame
  5530. ; ss:esp + 4 = trap number
  5531. ;
  5532. ; Returns
  5533. ; ret value from Ki386VdmReflectException
  5534. ; interrupts are disabled uppon return
  5535. ;
  5536. cPublicProc _Ki386VdmReflectException_A, 1
  5537. sub esp, 4*2
  5538. RaiseIrql APC_LEVEL
  5539. sti
  5540. mov [esp+4], eax ; Save OldIrql
  5541. mov eax, [esp+12] ; Pick up trap number
  5542. mov [esp+0], eax
  5543. call _Ki386VdmReflectException@4 ; pops one dword
  5544. mov ecx, [esp+0] ; (ecx) = OldIrql
  5545. mov [esp+0], eax ; Save return code
  5546. LowerIrql ecx
  5547. pop eax ; pops second dword
  5548. ret 4
  5549. stdENDP _Ki386VdmReflectException_A
  5550. page
  5551. subttl "Fast System Call code templates"
  5552. ;++
  5553. ;
  5554. ; Routine Description:
  5555. ;
  5556. ; One of the following sets of code will be copied to
  5557. ; SharedUserData->SystemCall to be executed for system
  5558. ; calls from user mode.
  5559. ;
  5560. ; In the fast call case, if an attempt is made to single
  5561. ; step over the system call instruction, the processor
  5562. ; will double fault because no valid stack address is
  5563. ; set on which to handle the debug exception. The double
  5564. ; fault handler will arrange to return one byte later
  5565. ; than normal allowing the following code to re-enable
  5566. ; single step mode.
  5567. ;
  5568. ; Arguments:
  5569. ;
  5570. ;
  5571. ; Returns
  5572. ;
  5573. ;--
  5574. public _KiDefaultSystemCall, _KiDefaultSystemCallEnd
  5575. _KiDefaultSystemCall:
  5576. lea edx, [esp]+8 ; (edx) -> arguments
  5577. int 2eh
  5578. ret
  5579. _KiDefaultSystemCallEnd:
  5580. public _KiFastSystemCallIa32, _KiFastSystemCallIa32End
  5581. _KiFastSystemCallIa32:
  5582. mov edx, esp ; (edx) -> arguments-8
  5583. iSYSENTER
  5584. fscrr0: ret
  5585. pushfd ; reset single step mode
  5586. or [esp], EFLAGS_TF_MASK
  5587. popfd
  5588. ret
  5589. _KiFastSystemCallIa32End:
  5590. public _KiFastSystemCallAmdK6, _KiFastSystemCallAmdK6End
  5591. _KiFastSystemCallAmdK6:
  5592. mov edx, esp ; (edx) -> arguments-8
  5593. iSYSCALL
  5594. fscrr1: ret
  5595. pushfd ; reset single step mode
  5596. or [esp], EFLAGS_TF_MASK
  5597. popfd
  5598. ret
  5599. _KiFastSystemCallAmdK6End:
  5600. ;
  5601. ; For Fast System Call return, the EIP saved in the trap frame should
  5602. ; correspond to the RET instruction in the above two syscall sequences.
  5603. ; Note: It is much faster to return to the return instruction than to
  5604. ; pop the return address off the stack and use that because doing so
  5605. ; unbalances the call/return stack the processor uses for branch prediction.
  5606. ;
  5607. fscrOffset EQU fscrr0-_KiFastSystemCallIa32
  5608. fscrOffset2 EQU fscrr1-_KiFastSystemCallAmdK6
  5609. .errnz fscrOffset2-fscrOffset
  5610. _TEXT$00 ends
  5611. end