Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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