Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3034 lines
82 KiB

  1. title "Vdm Instuction Emulation"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; instemul.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module contains the routines for emulating instructions and
  13. ; faults to a VDM.
  14. ;
  15. ; Author:
  16. ;
  17. ; Dave Hastings (daveh) 29-March-1991
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Notes:
  24. ;
  25. ;
  26. ;sudeepb 09-Dec-1992 Very Sonn this file will be deleted and protected
  27. ; mode instruction emulation will be merged in
  28. ; emv86.asm. Particularly following routines will
  29. ; simply become OpcodeInvalid.
  30. ; OpcodeIret
  31. ; OpcodePushf
  32. ; OpcodePopf
  33. ; OpcodeHlt
  34. ; Other routines such as
  35. ; OpcodeCli
  36. ; OpcodeSti
  37. ; OpcodeIN/OUT/SB/Immb etc
  38. ; will map exactly like emv86.asm
  39. ; OpcodeInt will be the main differeing routine.
  40. ;
  41. ; OpcodeDispatch Table will be deleted.
  42. ;
  43. ; So before making any major changes in this file please see
  44. ; Sudeepb or Daveh.
  45. ;
  46. ;neilsa 19-Oct-1993 Size and performance enhancements
  47. ;jonle 15-Nov-1993 - The Debug messages for each opcode may no longer work
  48. ; correctly, because interrupts may not have been enabled
  49. ;
  50. ;
  51. ;
  52. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  53. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  54. ;
  55. ; Revision History:
  56. ;
  57. ;--
  58. .386p
  59. .xlist
  60. include ks386.inc
  61. include i386\kimacro.inc
  62. include mac386.inc
  63. include i386\mi.inc
  64. include callconv.inc
  65. include ..\..\vdm\i386\vdm.inc
  66. include vdmtib.inc
  67. include irqli386.inc
  68. .list
  69. extrn VdmOpcode0f:proc
  70. extrn OpcodeNPXV86:proc
  71. extrn VdmDispatchIntAck:proc ;; only OpcodeSti uses this
  72. ifdef VDMDBG
  73. EXTRNP _VdmTraceEvent,4
  74. endif
  75. extrn CommonDispatchException:proc ;; trap.asm
  76. extrn _DbgPrint:proc
  77. extrn _KeI386VirtualIntExtensions:dword
  78. extrn _MmHighestUserAddress:dword
  79. EXTRNP _Ki386GetSelectorParameters,4
  80. EXTRNP _Ki386VdmDispatchIo,5
  81. EXTRNP _Ki386VdmDispatchStringIo,8
  82. EXTRNP _KiDispatchException,5
  83. EXTRNP _VdmPrinterStatus,3
  84. EXTRNP _VdmPrinterWriteData, 3
  85. EXTRNP _VdmClearPMCliTimeStamp, 0
  86. EXTRNP _VdmSetPMCliTimeStamp, 1
  87. extrn _MmUserProbeAddress:DWORD
  88. EXTRNP _VdmFetchULONG,1
  89. EXTRNP _Ki386AdjustEsp0,1
  90. page ,132
  91. ifdef VDMDBG
  92. %out Debugging version
  93. endif
  94. ;
  95. ; Force assume into place
  96. ;
  97. _PAGE SEGMENT DWORD PUBLIC 'CODE'
  98. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  99. _PAGE ENDS
  100. _TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
  101. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  102. _TEXT$00 ENDS
  103. PAGECONST SEGMENT DWORD PUBLIC 'DATA'
  104. ;
  105. ; Instruction emulation emulates the following instructions.
  106. ; The emulation affects the noted user mode registers.
  107. ;
  108. ; In protected mode, the following instructions are emulated in the kernel
  109. ;
  110. ; Registers (E)Flags (E)SP SS CS
  111. ; INTnn X X X X
  112. ; INTO X X X X
  113. ; CLI X
  114. ; STI X
  115. ;
  116. ; The following instructions are always emulated by reflection to the
  117. ; Usermode VDM monitor
  118. ;
  119. ; INSB
  120. ; INSW
  121. ; OUTSB
  122. ; OUTSW
  123. ; INBimm
  124. ; INWimm
  125. ; OUTBimm
  126. ; OUTWimm
  127. ; INB
  128. ; INW
  129. ; OUTB
  130. ; OUTW
  131. ;
  132. ; WARNING What do we do about 32 bit io instructions??
  133. ;
  134. ; OpcodeIndex - packed 1st level table to index OpcodeDispatch table
  135. ;
  136. public OpcodeIndex
  137. diBEGIN OpcodeIndex,VDM_INDEX_Invalid
  138. dtI 0fh, VDM_INDEX_0F
  139. dtI 26h, VDM_INDEX_ESPrefix
  140. dtI 2eh, VDM_INDEX_CSPrefix
  141. dtI 36h, VDM_INDEX_SSPrefix
  142. dtI 3eh, VDM_INDEX_DSPrefix
  143. dtI 64h, VDM_INDEX_FSPrefix
  144. dtI 65h, VDM_INDEX_GSPrefix
  145. dtI 66h, VDM_INDEX_OPER32Prefix
  146. dtI 67h, VDM_INDEX_ADDR32Prefix
  147. dtI 6ch, VDM_INDEX_INSB
  148. dtI 6dh, VDM_INDEX_INSW
  149. dtI 6eh, VDM_INDEX_OUTSB
  150. dtI 6fh, VDM_INDEX_OUTSW
  151. dtI 9bh, VDM_INDEX_NPX
  152. dtI 9ch, VDM_INDEX_PUSHF
  153. dtI 9dh, VDM_INDEX_POPF
  154. dtI 0cdh, VDM_INDEX_INTnn
  155. dtI 0ceh, VDM_INDEX_INTO
  156. dtI 0cfh, VDM_INDEX_IRET
  157. dtI 0d8h, VDM_INDEX_NPX
  158. dtI 0d9h, VDM_INDEX_NPX
  159. dtI 0dah, VDM_INDEX_NPX
  160. dtI 0dbh, VDM_INDEX_NPX
  161. dtI 0dch, VDM_INDEX_NPX
  162. dtI 0ddh, VDM_INDEX_NPX
  163. dtI 0deh, VDM_INDEX_NPX
  164. dtI 0dfh, VDM_INDEX_NPX
  165. dtI 0e4h, VDM_INDEX_INBimm
  166. dtI 0e5h, VDM_INDEX_INWimm
  167. dtI 0e6h, VDM_INDEX_OUTBimm
  168. dtI 0e7h, VDM_INDEX_OUTWimm
  169. dtI 0ech, VDM_INDEX_INB
  170. dtI 0edh, VDM_INDEX_INW
  171. dtI 0eeh, VDM_INDEX_OUTB
  172. dtI 0efh, VDM_INDEX_OUTW
  173. dtI 0f0h, VDM_INDEX_LOCKPrefix
  174. dtI 0f2h, VDM_INDEX_REPNEPrefix
  175. dtI 0f3h, VDM_INDEX_REPPrefix
  176. dtI 0f4h, VDM_INDEX_HLT
  177. dtI 0fah, VDM_INDEX_CLI
  178. dtI 0fbh, VDM_INDEX_STI
  179. diEND NUM_OPCODE
  180. ;
  181. ; OpcodeDispatch - table of routines used to emulate instructions
  182. ;
  183. public OpcodeDispatch
  184. dtBEGIN OpcodeDispatch,OpcodeInvalid
  185. dtS VDM_INDEX_0F , Opcode0F
  186. dtS VDM_INDEX_ESPrefix , OpcodeESPrefix
  187. dtS VDM_INDEX_CSPrefix , OpcodeCSPrefix
  188. dtS VDM_INDEX_SSPrefix , OpcodeSSPrefix
  189. dtS VDM_INDEX_DSPrefix , OpcodeDSPrefix
  190. dtS VDM_INDEX_FSPrefix , OpcodeFSPrefix
  191. dtS VDM_INDEX_GSPrefix , OpcodeGSPrefix
  192. dtS VDM_INDEX_OPER32Prefix, OpcodeOPER32Prefix
  193. dtS VDM_INDEX_ADDR32Prefix, OpcodeADDR32Prefix
  194. dtS VDM_INDEX_INSB , OpcodeINSB
  195. dtS VDM_INDEX_INSW , OpcodeINSW
  196. dtS VDM_INDEX_OUTSB , OpcodeOUTSB
  197. dtS VDM_INDEX_OUTSW , OpcodeOUTSW
  198. dtS VDM_INDEX_INTnn , OpcodeINTnn
  199. dtS VDM_INDEX_INTO , OpcodeINTO
  200. dtS VDM_INDEX_INBimm , OpcodeINBimm
  201. dtS VDM_INDEX_INWimm , OpcodeINWimm
  202. dtS VDM_INDEX_OUTBimm , OpcodeOUTBimm
  203. dtS VDM_INDEX_OUTWimm , OpcodeOUTWimm
  204. dtS VDM_INDEX_INB , OpcodeINB
  205. dtS VDM_INDEX_INW , OpcodeINW
  206. dtS VDM_INDEX_OUTB , OpcodeOUTB
  207. dtS VDM_INDEX_OUTW , OpcodeOUTW
  208. dtS VDM_INDEX_LOCKPrefix , OpcodeLOCKPrefix
  209. dtS VDM_INDEX_REPNEPrefix , OpcodeREPNEPrefix
  210. dtS VDM_INDEX_REPPrefix , OpcodeREPPrefix
  211. dtS VDM_INDEX_CLI , OpcodeCLI
  212. dtS VDM_INDEX_STI , OpcodeSTI
  213. dtEND MAX_VDM_INDEX
  214. PAGECONST ENDS
  215. PAGEDATA SEGMENT DWORD PUBLIC 'DATA'
  216. public _ExVdmOpcodeDispatchCounts,_ExVdmSegmentNotPresent
  217. _ExVdmOpcodeDispatchCounts dd MAX_VDM_INDEX dup(0)
  218. _ExVdmSegmentNotPresent dd 0
  219. PAGEDATA ENDS
  220. _PAGE SEGMENT DWORD PUBLIC 'CODE'
  221. ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  222. page ,132
  223. subttl "Overide Prefix Macro"
  224. ;++
  225. ;
  226. ; Routine Description:
  227. ;
  228. ; This macro generates the code for handling override prefixes
  229. ; The routine name generated is OpcodeXXXXPrefix, where XXXX is
  230. ; the name used in the macro invocation. The code will set the
  231. ; PREFIX_XXXX bit in the Prefix flags.
  232. ;
  233. ; Arguments
  234. ; name = name of prefix
  235. ; EBP -> trap frame
  236. ; EBX -> prefix flags, BL = instruction length count
  237. ; ECX -> byte at the faulting address
  238. ; EDX -> pointer to vdm state in DOS arena
  239. ; ESI -> Reginfo struct
  240. ; EDI -> address of faulting instruction
  241. ;
  242. ; Returns
  243. ; user mode Eip advanced
  244. ; eax advanced
  245. ; edx contains next byte of opcode
  246. ;
  247. ; NOTE: This routine exits by dispatching through the table again.
  248. ;--
  249. opPrefix macro name
  250. public Opcode&name&Prefix
  251. Opcode&name&Prefix proc
  252. or [esi].RiPrefixFlags,PREFIX_&name
  253. jmp OpcodeGenericPrefix ; dispatch to next handler
  254. Opcode&name&Prefix endp
  255. endm
  256. irp prefix, <ES, CS, SS, DS, FS, GS, OPER32, ADDR32, LOCK, REPNE, REP>
  257. opPrefix prefix
  258. endm
  259. page ,132
  260. subttl "Instruction Emulation Dispatcher"
  261. ;++
  262. ;
  263. ; Routine Description:
  264. ;
  265. ; This routine dispatches to the opcode specific emulation routine,
  266. ; based on the first byte of the opcode. Two byte opcodes, and prefixes
  267. ; result in another level of dispatching, from the handling routine.
  268. ;
  269. ; Arguments:
  270. ;
  271. ; [esp+4] = pointer to trap frame
  272. ;
  273. ; Returns:
  274. ;
  275. ; Nothing
  276. ;
  277. ;
  278. cPublicProc _Ki386DispatchOpcode,1
  279. push ebp
  280. mov ebp, [esp+8]
  281. sub esp,REGINFOSIZE
  282. mov esi, esp ; scratch area
  283. CsToLinearPM [ebp].TsSegCs, doerr ; initialize reginfo
  284. mov edi,[ebp].TsEip ; get fault instruction address
  285. cmp edi,[esi].RiCsLimit ; check eip
  286. ja doerr
  287. add edi,[esi].RiCsBase
  288. cmp edi, _MmUserProbeAddress
  289. ja doerr
  290. movzx ecx,byte ptr [edi] ; get faulting opcode
  291. mov eax,ecx
  292. and eax,0F8h ; check for npx instr
  293. cmp eax,0D8h
  294. je do30 ; dispatch
  295. movzx eax, OpcodeIndex[ecx]
  296. mov ebx,1 ; length count, flags
  297. ; All handler routines will get the following on entry
  298. ; ebp -> trap frame
  299. ; ebx -> prefix flags, instruction length count
  300. ; ecx -> byte at the faulting address
  301. ; edx -> pointer to vdm state in DOS arena
  302. ; interrupts enabled and Irql at APC level
  303. ; edi -> address of faulting instruction
  304. ; esi -> reginfo struct
  305. ; All handler routines will return
  306. ; EAX = 0 for failure
  307. ; EAX = 1 for success
  308. if DEVL
  309. inc _ExVdmOpcodeDispatchCounts[eax * type _ExVdmOpcodeDispatchCounts]
  310. endif
  311. ifdef VDMDBG
  312. pushad
  313. stdCall _VdmTraceEvent, <VDMTR_KERNEL_OP_PM,ecx,0,ebp>
  314. popad
  315. endif
  316. call OpcodeDispatch[eax * type OpcodeDispatch]
  317. do20:
  318. add esp,REGINFOSIZE
  319. pop ebp
  320. stdRET _Ki386DispatchOpcode
  321. doerr: xor eax,eax
  322. jmp do20
  323. ;
  324. ; If we get here, we have executed an NPX instruction in user mode
  325. ; with the emulator installed. If the EM bit was not set in CR0, the
  326. ; app really wanted to execute the instruction for detection purposes.
  327. ; In this case, we need to clear the TS bit, and restart the instruction.
  328. ; Otherwise we need to reflect the exception
  329. ;
  330. do30:
  331. call OpcodeNPXV86
  332. jmp short do20
  333. stdENDP _Ki386DispatchOpcode
  334. page ,132
  335. subttl "Invalid Opcode Handler"
  336. ;++
  337. ;
  338. ; Routine Description:
  339. ;
  340. ; This routine causes a GP fault to be reflected to the vdm
  341. ;
  342. ; Arguments:
  343. ; EBP -> trap frame
  344. ; EBX -> prefix flags, BL = instruction length count
  345. ; ECX -> byte at the faulting address
  346. ; EDX -> pointer to vdm state in DOS arena
  347. ; ESI -> Reginfo struct
  348. ; EDI -> address of faulting instruction
  349. ;
  350. ; Returns:
  351. ;
  352. ; nothing
  353. ;
  354. public OpcodeInvalid
  355. OpcodeInvalid proc
  356. xor eax,eax ; ret fail
  357. ret
  358. OpcodeInvalid endp
  359. page ,132
  360. subttl "Generic Prefix Handler"
  361. ;++
  362. ;
  363. ; Routine Description:
  364. ;
  365. ; This routine handles the generic portion of all of the prefixes,
  366. ; and dispatches the next byte of the opcode.
  367. ;
  368. ; Arguments:
  369. ; EBP -> trap frame
  370. ; EBX -> prefix flags, BL = instruction length count
  371. ; ECX -> byte at the faulting address
  372. ; EDX -> pointer to vdm state in DOS arena
  373. ; ESI -> Reginfo struct
  374. ; EDI -> address of faulting instruction
  375. ;
  376. ; Returns:
  377. ;
  378. ; user mode Eip advanced
  379. ; edx contains next byte of opcode
  380. ;
  381. public OpcodeGenericPrefix
  382. OpcodeGenericPrefix proc
  383. inc edi ; increment eip
  384. inc ebx ; increment size
  385. cmp bl, 128 ; set arbitrary inst size limit
  386. ja ogperr ; in case of pointless prefixes
  387. mov eax,edi ; current linear address
  388. sub eax,[esi].RiCsBase ; make address eip
  389. cmp eax,[esi].RiCsLimit ; check eip
  390. ja ogperr
  391. cmp edi, [_MmHighestUserAddress]
  392. ja ogperr
  393. mov cl,byte ptr [edi] ; get next opcode
  394. movzx eax, OpcodeIndex[ecx]
  395. if DEVL
  396. inc _ExVdmOpcodeDispatchCounts[eax * type _ExVdmOpcodeDispatchCounts]
  397. endif
  398. jmp OpcodeDispatch[eax * type OpcodeDispatch]
  399. ogperr:
  400. xor eax,eax ; opcode was NOT handled
  401. ret
  402. OpcodeGenericPrefix endp
  403. page ,132
  404. subttl "0F Opcode Handler"
  405. ;++
  406. ;
  407. ; Routine Description:
  408. ;
  409. ; This routine emulates a 0Fh opcode.
  410. ;
  411. ; Arguments:
  412. ; EBP -> trap frame
  413. ; EBX -> prefix flags, BL = instruction length count
  414. ; ECX -> byte at the faulting address
  415. ; EDX -> pointer to vdm state in DOS arena
  416. ; ESI -> Reginfo struct
  417. ; EDI -> address of faulting instruction
  418. ;
  419. ; Returns:
  420. ;
  421. ; nothing
  422. ;
  423. public Opcode0F
  424. Opcode0F proc
  425. mov eax,[ebp].TsEip ; get fault instruction address
  426. mov [esi].RiEip,eax
  427. mov [esi].RiTrapFrame,ebp
  428. mov [esi].RiPrefixFlags,ebx
  429. mov eax,dword ptr [ebp].TsEFlags
  430. mov [esi].RiEFlags,eax
  431. call VdmOpcode0F ; enables interrupts
  432. test eax,0FFFFh
  433. jz o0f20
  434. mov eax,[esi].RiEip
  435. mov [ebp].TsEip,eax
  436. mov eax,1
  437. o0f20:
  438. ret
  439. Opcode0F endp
  440. page ,132
  441. subttl "Byte string in Opcode Handler"
  442. ;++
  443. ;
  444. ; Routine Description:
  445. ;
  446. ; This routine emulates an INSB opcode.
  447. ;
  448. ; Arguments:
  449. ; EBP -> trap frame
  450. ; EBX -> prefix flags, BL = instruction length count
  451. ; ECX -> byte at the faulting address
  452. ; EDX -> pointer to vdm state in DOS arena
  453. ; ESI -> Reginfo struct
  454. ; EDI -> address of faulting instruction
  455. ;
  456. ; Returns:
  457. ;
  458. ; nothing
  459. ;
  460. ; WARNING what to do about size override? ds override?
  461. public OpcodeINSB
  462. OpcodeINSB proc
  463. push ebp ; Trap Frame
  464. push ebx ; size of insb
  465. movzx eax,word ptr [ebp].TsSegEs
  466. shl eax,16
  467. ; WARNING no support for 32bit edi
  468. mov ax,word ptr [ebp].TsEdi ; don't support 32bit'ness
  469. push eax ; address
  470. xor eax, eax
  471. mov ecx,1
  472. test ebx,PREFIX_REP
  473. jz @f
  474. mov eax, 1
  475. ; WARNING no support for 32bit ecx
  476. movzx ecx,word ptr [ebp].TsEcx
  477. @@:
  478. push ecx ; number of io ops
  479. push TRUE ; read op
  480. push eax ; REP prefix
  481. push 1 ; byte op
  482. movzx edx,word ptr [ebp].TsEdx
  483. push edx ; port number
  484. call _Ki386VdmDispatchStringIo@32 ; use retval
  485. ret
  486. OpcodeINSB endp
  487. page ,132
  488. subttl "Word String In Opcode Handler"
  489. ;++
  490. ;
  491. ; Routine Description:
  492. ;
  493. ; This routine emulates an INSW opcode.
  494. ;
  495. ; Arguments:
  496. ; EBP -> trap frame
  497. ; EBX -> prefix flags, BL = instruction length count
  498. ; ECX -> byte at the faulting address
  499. ; EDX -> pointer to vdm state in DOS arena
  500. ; ESI -> Reginfo struct
  501. ; EDI -> address of faulting instruction
  502. ;
  503. ; Returns:
  504. ;
  505. ; nothing
  506. ;
  507. public OpcodeINSW
  508. OpcodeINSW proc
  509. push ebp ; Trap frame
  510. push ebx ; sizeof insw
  511. movzx eax,word ptr [ebp].TsSegEs
  512. shl eax,16
  513. ; WARNING no support for 32bit edi
  514. mov ax,word ptr [ebp].TsEdi
  515. push eax ; address
  516. xor eax, eax
  517. mov ecx,1
  518. test ebx,PREFIX_REP
  519. jz @f
  520. mov eax, 1
  521. ; WARNING no support for 32bit ecx
  522. movzx ecx,word ptr [ebp].TsEcx
  523. @@:
  524. movzx edx,word ptr [ebp].TsEdx
  525. push ecx ; number of io ops
  526. push TRUE ; read op
  527. push eax ; REP prefix
  528. push 2 ; word size
  529. push edx ; port number
  530. call _Ki386VdmDispatchStringIo@32 ; use retval
  531. ret
  532. OpcodeINSW endp
  533. page ,132
  534. subttl "Byte String Out Opcode Handler"
  535. ;++
  536. ;
  537. ; Routine Description:
  538. ;
  539. ; This routine emulates an OUTSB opcode.
  540. ;
  541. ; Arguments:
  542. ; EBP -> trap frame
  543. ; EBX -> prefix flags, BL = instruction length count
  544. ; ECX -> byte at the faulting address
  545. ; EDX -> pointer to vdm state in DOS arena
  546. ; ESI -> Reginfo struct
  547. ; EDI -> address of faulting instruction
  548. ;
  549. ; Returns:
  550. ;
  551. ; nothing
  552. ;
  553. public OpcodeOUTSB
  554. OpcodeOUTSB proc
  555. push ebp ; Trap Frame
  556. push ebx ; size of outsb
  557. movzx eax,word ptr [ebp].TsSegDs
  558. shl eax,16
  559. ; WARNING don't support 32bit'ness, esi
  560. mov ax,word ptr [ebp].TsEsi
  561. push eax ; address
  562. xor eax, eax
  563. mov ecx,1
  564. test ebx,PREFIX_REP
  565. jz @f
  566. mov eax, 1
  567. ; WARNING don't support 32bit'ness ecx
  568. movzx ecx,word ptr [ebp].TsEcx
  569. @@:
  570. movzx edx,word ptr [ebp].TsEdx
  571. push ecx ; number of io ops
  572. push FALSE ; write op
  573. push eax ; REP prefix
  574. push 1 ; byte op
  575. push edx ; port number
  576. call _Ki386VdmDispatchStringIo@32 ; use retval
  577. ret
  578. OpcodeOUTSB endp
  579. page ,132
  580. subttl "Word String Out Opcode Handler"
  581. ;++
  582. ;
  583. ; Routine Description:
  584. ;
  585. ; This routine emulates an OUTSW opcode.
  586. ;
  587. ; Arguments:
  588. ; EBP -> trap frame
  589. ; EBX -> prefix flags, BL = instruction length count
  590. ; ECX -> byte at the faulting address
  591. ; EDX -> pointer to vdm state in DOS arena
  592. ; ESI -> Reginfo struct
  593. ; EDI -> address of faulting instruction
  594. ;
  595. ; Returns:
  596. ;
  597. ; nothing
  598. ;
  599. public OpcodeOUTSW
  600. OpcodeOUTSW proc
  601. push ebp ; Trap Frame
  602. push ebx ; size of outsb
  603. movzx eax,word ptr [ebp].TsSegDs
  604. shl eax,16
  605. ; WARNING don't support 32bit'ness esi
  606. mov ax,word ptr [ebp].TsEsi
  607. push eax ; address
  608. xor eax, eax
  609. mov ecx,1
  610. test ebx,PREFIX_REP
  611. jz @f
  612. mov eax, 1
  613. ; WARNING don't support 32bit'ness ecx
  614. movzx ecx,word ptr [ebp].TsEcx
  615. @@:
  616. movzx edx,word ptr [ebp].TsEdx
  617. push ecx ; number of io ops
  618. push FALSE ; write op
  619. push eax ; REP prefix
  620. push 2 ; byte op
  621. push edx ; port number
  622. call _Ki386VdmDispatchStringIo@32 ; use retval
  623. ret
  624. OpcodeOUTSW endp
  625. page ,132
  626. subttl "INTnn Opcode Handler"
  627. ;++
  628. ;
  629. ; Routine Description:
  630. ;
  631. ; This routine emulates an INTnn opcode. It retrieves the handler
  632. ; from the IVT, pushes the current cs:ip and flags on the stack,
  633. ; and dispatches to the handler.
  634. ;
  635. ; Arguments:
  636. ; EBP -> trap frame
  637. ; EBX -> prefix flags, BL = instruction length count
  638. ; ECX -> byte at the faulting address
  639. ; EDX -> pointer to vdm state in DOS arena
  640. ; ESI -> Reginfo struct
  641. ; EDI -> address of faulting instruction
  642. ;
  643. ; Returns:
  644. ;
  645. ; Current CS:IP on user stack
  646. ; RiCs:RiEip -> handler from IVT
  647. ;
  648. public OpcodeINTnn
  649. OpcodeINTnn proc
  650. mov eax, ds:FIXED_NTVDMSTATE_LINEAR
  651. and eax, (VDM_INTERRUPT_PENDING + VDM_VIRTUAL_INTERRUPTS)
  652. cmp eax, (VDM_INTERRUPT_PENDING + VDM_VIRTUAL_INTERRUPTS)
  653. jnz short oi10
  654. call VdmDispatchIntAck
  655. jmp oi99
  656. oi10:
  657. mov eax,dword ptr [ebp].TsEFlags
  658. call GetVirtualBits ; set interrupt flag
  659. mov [esi].RiEFlags,eax
  660. movzx eax,word ptr [ebp].TsHardwareSegSs
  661. call SsToLinear
  662. test al,0FFh
  663. jz oinerr
  664. inc edi ; point to int #
  665. mov eax,edi ; current linear address
  666. sub eax,[esi].RiCsBase ; make address eip
  667. cmp eax,[esi].RiCsLimit ; check eip
  668. ja oinerr
  669. cmp edi, [_MmHighestUserAddress]
  670. ja oinerr
  671. movzx ecx,byte ptr [edi] ; get int #
  672. inc eax ; inc past end of instruction
  673. mov [esi].RiEip,eax ; save for pushint's benefit
  674. call PushInt ; will return retcode in al
  675. test al,0FFh
  676. jz oinerr ; error!
  677. mov eax,[esi].RiEsp
  678. mov [ebp].TsHardwareEsp,eax
  679. mov ax,word ptr [esi].RiSegCs
  680. or ax, 7 ; R3 LDT selectors only
  681. cmp ax, 8
  682. jge short @f
  683. test dword ptr [ebp]+TsEFlags, EFLAGS_V86_MASK
  684. jnz short @f
  685. mov ax, KGDT_R3_DATA OR RPL_MASK
  686. @@: mov word ptr [ebp].TsSegCs,ax
  687. mov eax,[esi].RiEFlags
  688. push [ebp].TsEFlags
  689. mov [ebp].TsEFlags,eax
  690. or [ebp].TsEFlags, EFLAGS_INTERRUPT_MASK
  691. xor eax, [esp]
  692. test eax, EFLAGS_V86_MASK
  693. pop eax
  694. je short @f
  695. stdCall _Ki386AdjustEsp0, <ebp>
  696. @@: mov eax,[esi].RiEip
  697. mov [ebp].TsEip,eax
  698. oi99:
  699. mov eax,1
  700. ret
  701. oinerr:
  702. xor eax,eax
  703. ret
  704. OpcodeINTnn endp
  705. page ,132
  706. subttl "INTO Opcode Handler"
  707. ;++
  708. ;
  709. ; Routine Description:
  710. ;
  711. ; This routine emulates an INTO opcode.
  712. ;
  713. ; Arguments:
  714. ; EBP -> trap frame
  715. ; EBX -> prefix flags, BL = instruction length count
  716. ; ECX -> byte at the faulting address
  717. ; EDX -> pointer to vdm state in DOS arena
  718. ; ESI -> Reginfo struct
  719. ; EDI -> address of faulting instruction
  720. ;
  721. ; Returns:
  722. ;
  723. ; nothing
  724. ;
  725. public OpcodeINTO
  726. OpcodeINTO proc
  727. xor eax,eax
  728. ret
  729. OpcodeINTO endp
  730. page ,132
  731. subttl "In Byte Immediate Opcode Handler"
  732. ;++
  733. ;
  734. ; Routine Description:
  735. ;
  736. ; This routine emulates an in byte immediate opcode.
  737. ;
  738. ; Arguments:
  739. ; EBP -> trap frame
  740. ; EBX -> prefix flags, BL = instruction length count
  741. ; ECX -> byte at the faulting address
  742. ; EDX -> pointer to vdm state in DOS arena
  743. ; ESI -> Reginfo struct
  744. ; EDI -> address of faulting instruction
  745. ;
  746. ; Returns:
  747. ;
  748. ; nothing
  749. ;
  750. public OpcodeINBimm
  751. OpcodeINBimm proc
  752. inc ebx ; length count
  753. inc edi
  754. mov eax,edi ; current linear address
  755. sub eax,[esi].RiCsBase ; make address eip
  756. cmp eax,[esi].RiCsLimit ; check eip
  757. ja oibi20
  758. cmp edi, [_MmHighestUserAddress]
  759. ja oibi20
  760. movzx ecx,byte ptr [edi]
  761. ; (eax) = inst. size
  762. ; read op
  763. ; I/O size = 1
  764. ; (ecx) = port number
  765. stdCall _Ki386VdmDispatchIo, <ecx, 1, TRUE, ebx, ebp>
  766. ret
  767. oibi20:
  768. xor eax, eax ; not handled
  769. ret
  770. OpcodeINBimm endp
  771. page ,132
  772. subttl "Word In Immediate Opcode Handler"
  773. ;++
  774. ;
  775. ; Routine Description:
  776. ;
  777. ; This routine emulates an in word immediate opcode.
  778. ;
  779. ; Arguments:
  780. ; EBP -> trap frame
  781. ; EBX -> prefix flags, BL = instruction length count
  782. ; ECX -> byte at the faulting address
  783. ; EDX -> pointer to vdm state in DOS arena
  784. ; ESI -> Reginfo struct
  785. ; EDI -> address of faulting instruction
  786. ;
  787. ; Returns:
  788. ;
  789. ; nothing
  790. ;
  791. public OpcodeINWimm
  792. OpcodeINWimm proc
  793. inc ebx ; length count
  794. inc edi
  795. mov eax,edi ; current linear address
  796. sub eax,[esi].RiCsBase ; make address eip
  797. cmp eax,[esi].RiCsLimit ; check eip
  798. ja oiwi20
  799. cmp edi, [_MmHighestUserAddress]
  800. ja oiwi20
  801. movzx ecx,byte ptr [edi]
  802. ; TRUE - read op
  803. ; 2 - word op
  804. ; ecx - port number
  805. stdCall _Ki386VdmDispatchIo, <ecx, 2, TRUE, ebx, ebp>
  806. ret
  807. oiwi20:
  808. xor eax, eax ; not handled
  809. ret
  810. OpcodeINWimm endp
  811. page ,132
  812. subttl "Out Byte Immediate Opcode Handler"
  813. ;++
  814. ;
  815. ; Routine Description:
  816. ;
  817. ; This routine emulates an invalid opcode.
  818. ;
  819. ; Arguments:
  820. ; EBP -> trap frame
  821. ; EBX -> prefix flags, BL = instruction length count
  822. ; ECX -> byte at the faulting address
  823. ; EDX -> pointer to vdm state in DOS arena
  824. ; ESI -> Reginfo struct
  825. ; EDI -> address of faulting instruction
  826. ;
  827. ; Returns:
  828. ;
  829. ; nothing
  830. ;
  831. public OpcodeOUTBimm
  832. OpcodeOUTBimm proc
  833. inc ebx ; length count
  834. inc edi
  835. mov eax,edi ; current linear address
  836. sub eax,[esi].RiCsBase ; make address eip
  837. cmp eax,[esi].RiCsLimit ; check eip
  838. ja oobi20
  839. cmp edi, [_MmHighestUserAddress]
  840. ja oobi20
  841. movzx ecx,byte ptr [edi]
  842. ; FALSE - write op
  843. ; 1 - byte op
  844. ; ecx - port #
  845. stdCall _Ki386VdmDispatchIo, <ecx, 1, FALSE, ebx, ebp>
  846. ret
  847. oobi20:
  848. xor eax, eax ; not handled
  849. ret
  850. OpcodeOUTBimm endp
  851. page ,132
  852. subttl "Out Word Immediate Opcode Handler"
  853. ;++
  854. ;
  855. ; Routine Description:
  856. ;
  857. ; This routine emulates an out word immediate opcode.
  858. ;
  859. ; Arguments:
  860. ; EBP -> trap frame
  861. ; EBX -> prefix flags, BL = instruction length count
  862. ; ECX -> byte at the faulting address
  863. ; EDX -> pointer to vdm state in DOS arena
  864. ; ESI -> Reginfo struct
  865. ; EDI -> address of faulting instruction
  866. ;
  867. ; Returns:
  868. ;
  869. ; nothing
  870. ;
  871. public OpcodeOUTWimm
  872. OpcodeOUTWimm proc
  873. inc ebx ; length count
  874. inc edi
  875. mov eax,edi ; current linear address
  876. sub eax,[esi].RiCsBase ; make address eip
  877. cmp eax,[esi].RiCsLimit ; check eip
  878. ja oowi20
  879. cmp edi, [_MmHighestUserAddress]
  880. ja oowi20
  881. movzx ecx,byte ptr [edi]
  882. ; FALSE - write op
  883. ; 2 - word op
  884. ; ecx - port number
  885. stdCall _Ki386VdmDispatchIo, <ecx, 2, FALSE, ebx, ebp>
  886. ret
  887. oowi20:
  888. xor eax, eax ; not handled
  889. ret
  890. OpcodeOUTWimm endp
  891. page ,132
  892. subttl "INB Opcode Handler"
  893. ;++
  894. ;
  895. ; Routine Description:
  896. ;
  897. ; This routine emulates an INB opcode.
  898. ;
  899. ; Arguments:
  900. ; EBP -> trap frame
  901. ; EBX -> prefix flags, BL = instruction length count
  902. ; ECX -> byte at the faulting address
  903. ; EDX -> pointer to vdm state in DOS arena
  904. ; ESI -> Reginfo struct
  905. ; EDI -> address of faulting instruction
  906. ;
  907. ; Returns:
  908. ;
  909. ; nothing
  910. ;
  911. public OpcodeINB
  912. OpcodeINB proc
  913. movzx eax,word ptr [ebp].TsEdx
  914. ; TRUE - read op
  915. ; 1 - byte op
  916. ; eax - port number
  917. cmp eax, 3bdh
  918. jz oib_prt1
  919. cmp eax, 379h
  920. jz oib_prt1
  921. cmp eax, 279h
  922. jz oib_prt1
  923. oib_reflect:
  924. stdCall _Ki386VdmDispatchIo, <eax, 1, TRUE, ebx, ebp>
  925. ret
  926. oib_prt1:
  927. ; call printer status routine with port number, size, trap frame
  928. movzx ebx, bl ;clear prefix flags
  929. push eax
  930. stdCall _VdmPrinterStatus, <eax, ebx, ebp>
  931. or al,al
  932. pop eax
  933. jz short oib_reflect
  934. mov al, 1
  935. ret
  936. OpcodeINB endp
  937. page ,132
  938. subttl "INW Opcode Handler"
  939. ;++
  940. ;
  941. ; Routine Description:
  942. ;
  943. ; This routine emulates an INW opcode.
  944. ;
  945. ; Arguments:
  946. ; EBP -> trap frame
  947. ; EBX -> prefix flags, BL = instruction length count
  948. ; ECX -> byte at the faulting address
  949. ; EDX -> pointer to vdm state in DOS arena
  950. ; ESI -> Reginfo struct
  951. ; EDI -> address of faulting instruction
  952. ;
  953. ; Returns:
  954. ;
  955. ; nothing
  956. ;
  957. public OpcodeINW
  958. OpcodeINW proc
  959. movzx eax,word ptr [ebp].TsEdx
  960. ; TRUE - read operation
  961. ; 2 - word op
  962. ; eax - port number
  963. stdCall _Ki386VdmDispatchIo, <eax, 2, TRUE, ebx, ebp>
  964. ret
  965. OpcodeINW endp
  966. page ,132
  967. subttl "OUTB Opcode Handler"
  968. ;++
  969. ;
  970. ; Routine Description:
  971. ;
  972. ; This routine emulates an OUTB opcode.
  973. ;
  974. ; Arguments:
  975. ; EBP -> trap frame
  976. ; EBX -> prefix flags, BL = instruction length count
  977. ; ECX -> byte at the faulting address
  978. ; EDX -> pointer to vdm state in DOS arena
  979. ; ESI -> Reginfo struct
  980. ; EDI -> address of faulting instruction
  981. ;
  982. ; Returns:
  983. ;
  984. ; nothing
  985. ;
  986. public OpcodeOUTB
  987. OpcodeOUTB proc
  988. movzx eax,word ptr [ebp].TsEdx
  989. cmp eax, 03BCh
  990. je short oob_printerVDD
  991. cmp eax, 0378h
  992. je short oob_printerVDD
  993. cmp eax, 0278h
  994. jz short oob_printerVDD
  995. oob_reflect:
  996. ; FALSE - write op
  997. ; 1 - byte op
  998. ; eax - port number
  999. stdCall _Ki386VdmDispatchIo, <eax, 1, FALSE, ebx, ebp>
  1000. ret
  1001. oob_printerVDD:
  1002. movzx ebx, bl ; instruction size
  1003. push eax ; save port address
  1004. stdCall _VdmPrinterWriteData, <eax, ebx, ebp>
  1005. or al,al ;
  1006. pop eax
  1007. jz short oob_reflect
  1008. mov al, 1
  1009. ret
  1010. OpcodeOUTB endp
  1011. page ,132
  1012. subttl "OUTW Opcode Handler"
  1013. ;++
  1014. ;
  1015. ; Routine Description:
  1016. ;
  1017. ; This routine emulates an OUTW opcode.
  1018. ;
  1019. ; Arguments:
  1020. ; EBP -> trap frame
  1021. ; EBX -> prefix flags, BL = instruction length count
  1022. ; ECX -> byte at the faulting address
  1023. ; EDX -> pointer to vdm state in DOS arena
  1024. ; ESI -> Reginfo struct
  1025. ; EDI -> address of faulting instruction
  1026. ;
  1027. ; Returns:
  1028. ;
  1029. ; nothing
  1030. ;
  1031. public OpcodeOUTW
  1032. OpcodeOUTW proc
  1033. movzx eax,word ptr [ebp].TsEdx
  1034. ; FALSE - write op
  1035. ; 2 - word op
  1036. ; edi - port #
  1037. stdCall _Ki386VdmDispatchIo, <eax, 2, FALSE, ebx, ebp>
  1038. ret
  1039. OpcodeOUTW endp
  1040. page ,132
  1041. subttl "CLI Opcode Handler"
  1042. ;++
  1043. ;
  1044. ; Routine Description:
  1045. ;
  1046. ; This routine emulates an CLI opcode. It clears the virtual
  1047. ; interrupt flag in the VdmTeb.
  1048. ;
  1049. ; Arguments:
  1050. ; EBP -> trap frame
  1051. ; EBX -> prefix flags, BL = instruction length count
  1052. ; ECX -> byte at the faulting address
  1053. ; EDX -> pointer to vdm state in DOS arena
  1054. ; ESI -> Reginfo struct
  1055. ; EDI -> address of faulting instruction
  1056. ;
  1057. ; Returns:
  1058. ;
  1059. ; nothing
  1060. ;
  1061. public OpcodeCLI
  1062. OpcodeCLI proc
  1063. mov eax, ds:FIXED_NTVDMSTATE_LINEAR
  1064. and eax, (VDM_INTERRUPT_PENDING + VDM_VIRTUAL_INTERRUPTS)
  1065. cmp eax, (VDM_INTERRUPT_PENDING + VDM_VIRTUAL_INTERRUPTS)
  1066. jnz short oc50
  1067. call VdmDispatchIntAck
  1068. jmp short oc99
  1069. oc50:
  1070. mov eax,[ebp].TsEFlags
  1071. and eax,NOT EFLAGS_INTERRUPT_MASK
  1072. call SetVirtualBits
  1073. inc dword ptr [ebp].TsEip
  1074. stdCall _VdmSetPMCliTimeStamp, <0>
  1075. oc99:
  1076. mov eax,1
  1077. ret
  1078. OpcodeCLI endp
  1079. page ,132
  1080. subttl "STI Opcode Handler"
  1081. ;++
  1082. ;
  1083. ; Routine Description:
  1084. ;
  1085. ; This routine emulates an STI opcode. It sets the virtual
  1086. ; interrupt flag in the VDM teb.
  1087. ;
  1088. ; Arguments:
  1089. ; EBP -> trap frame
  1090. ; EBX -> prefix flags, BL = instruction length count
  1091. ; ECX -> byte at the faulting address
  1092. ; EDX -> pointer to vdm state in DOS arena
  1093. ; ESI -> Reginfo struct
  1094. ; EDI -> address of faulting instruction
  1095. ;
  1096. ; Returns:
  1097. ;
  1098. ; nothing
  1099. ;
  1100. public OpcodeSTI
  1101. OpcodeSTI proc
  1102. stdCall _VdmClearPMCliTimeStamp
  1103. mov eax,[ebp].TsEFlags
  1104. or eax,EFLAGS_INTERRUPT_MASK
  1105. call SetVirtualBits
  1106. inc dword ptr [ebp].TsEip
  1107. mov eax, ds:FIXED_NTVDMSTATE_LINEAR
  1108. test eax,VDM_INTERRUPT_PENDING
  1109. jz os10
  1110. call VdmDispatchIntAck
  1111. os10:
  1112. mov eax,1
  1113. ret
  1114. OpcodeSTI endp
  1115. page ,132
  1116. subttl "Check Vdm Flags"
  1117. ;++
  1118. ;
  1119. ; Routine Description:
  1120. ;
  1121. ; This routine checks the flags that are going to be used for the
  1122. ; dos or windows application.
  1123. ;
  1124. ; Arguments:
  1125. ;
  1126. ; ecx = EFlags to be set
  1127. ; esi = address of reg info
  1128. ;
  1129. ; Returns:
  1130. ;
  1131. ; ecx = fixed flags
  1132. ;
  1133. CheckVdmFlags proc
  1134. mov eax,[esi].RiEFlags
  1135. and eax,EFLAGS_V86_MASK
  1136. ;
  1137. ; [eax] = V86 mode bit
  1138. ; [ecx] = Flags to be fixed
  1139. ;
  1140. test eax,EFLAGS_V86_MASK ; Is V86 Mode?
  1141. jz short cvf10 ; No, enable IF
  1142. test _KeI386VirtualIntExtensions, V86_VIRTUAL_INT_EXTENSIONS
  1143. jz short cvf10
  1144. ;
  1145. ; Convert EFLAGS_INTERRUPT_MASK to VIF flags
  1146. ;
  1147. mov edx, ecx
  1148. and edx,EFLAGS_INTERRUPT_MASK
  1149. shl edx,0ah
  1150. or eax,edx
  1151. cvf10: or ecx,EFLAGS_INTERRUPT_MASK
  1152. cvf20: and ecx,NOT (EFLAGS_IOPL_MASK OR EFLAGS_NT_MASK OR EFLAGS_V86_MASK OR EFLAGS_VIF OR EFLAGS_VIP)
  1153. or ecx,eax ; restore original v86 bit
  1154. ret
  1155. CheckVdmFlags endp
  1156. page ,132
  1157. subttl "Get Virtual Interrupt Flag"
  1158. ;++
  1159. ;
  1160. ; Routine Description:
  1161. ;
  1162. ; This routine correctly gets the VDMs virtual interrupt flag and
  1163. ; puts it into an EFlags image to be put on the stack.
  1164. ;
  1165. ; Arguments:
  1166. ;
  1167. ; eax = EFlags value
  1168. ;
  1169. ; Returns:
  1170. ;
  1171. ; eax = EFlags value with correct setting for IF
  1172. ;
  1173. ; Uses:
  1174. ; ecx
  1175. ;
  1176. public GetVirtualBits
  1177. GetVirtualBits proc
  1178. push ebp
  1179. push edx
  1180. push ebx
  1181. push esi
  1182. push edi
  1183. test eax, EFLAGS_V86_MASK
  1184. jz short gvb10
  1185. test _KeI386VirtualIntExtensions, V86_VIRTUAL_INT_EXTENSIONS
  1186. jz short gvb10
  1187. mov ecx,eax
  1188. and ecx,EFLAGS_VIF
  1189. shr ecx,0ah ; mov vif to if posn
  1190. and eax,NOT EFLAGS_INTERRUPT_MASK
  1191. or eax,ecx
  1192. call gvbGetFixedStateLinear ; after return [ecx] = content of 0x417
  1193. and ecx,VDM_VIRTUAL_AC
  1194. and eax,NOT EFLAGS_ALIGN_CHECK
  1195. or eax,ecx
  1196. jmp short gbvexit
  1197. gvb10: and eax,NOT EFLAGS_INTERRUPT_MASK
  1198. call gvbGetFixedStateLinear ; after return [ecx] = content of 0x417
  1199. and ecx,VDM_VIRTUAL_INTERRUPTS OR VDM_VIRTUAL_AC
  1200. or eax,ecx ; put virtual int flag into flags
  1201. gbvexit:
  1202. or eax,EFLAGS_IOPL_MASK ; make it look like a 386
  1203. pop edi
  1204. pop esi
  1205. pop ebx
  1206. pop edx
  1207. pop ebp
  1208. ret
  1209. gvbGetFixedStateLinear:
  1210. push eax
  1211. push offset GetVirtualBits_Handler
  1212. push PCR[PcExceptionList]
  1213. mov PCR[PcExceptionList], esp
  1214. mov ecx, ds:FIXED_NTVDMSTATE_LINEAR
  1215. gvbexit1:
  1216. pop PCR[PcExceptionList]
  1217. add esp, 4 ; pop out except handler
  1218. pop eax
  1219. ret
  1220. GetVirtualBits endp
  1221. GetVirtualBits_Handler proc
  1222. mov esp, [esp+8] ; (esp)-> ExceptionList
  1223. xor ecx, ecx
  1224. jmp gvbexit1
  1225. GetVirtualBits_Handler endp
  1226. page ,132
  1227. subttl "Set Virtual Interrupt Flag"
  1228. ;++
  1229. ;
  1230. ; Routine Description:
  1231. ;
  1232. ; This routine correctly sets the VDMs virtual interrupt flag.
  1233. ;
  1234. ; Arguments:
  1235. ;
  1236. ; eax = EFlags value
  1237. ;
  1238. ; Returns:
  1239. ;
  1240. ; Virtual interrupt flag set
  1241. ;
  1242. SetVirtualBits proc
  1243. Flags equ [ebp - 4]
  1244. ;
  1245. ; IMPORTANT: shielint - save ALL the non-volatile registers in case of exception
  1246. ;
  1247. push ebp
  1248. push edx
  1249. push ebx
  1250. push esi
  1251. push edi
  1252. push offset SetVirtualBits_Handler
  1253. push PCR[PcExceptionList]
  1254. mov PCR[PcExceptionList], esp
  1255. mov ebp,esp
  1256. sub esp,4
  1257. mov Flags,eax
  1258. lea edx,ds:FIXED_NTVDMSTATE_LINEAR
  1259. and eax,EFLAGS_INTERRUPT_MASK ; isolate int flag
  1260. MPLOCK and [edx],NOT VDM_VIRTUAL_INTERRUPTS
  1261. MPLOCK or [edx],eax ; place virtual int flag value
  1262. svb20:
  1263. ; WARNING 32 bit support!
  1264. test ebx,PREFIX_OPER32
  1265. jz short svb30 ; 16 bit instr
  1266. mov eax,Flags
  1267. and eax,EFLAGS_ALIGN_CHECK
  1268. MPLOCK and dword ptr [edx],NOT EFLAGS_ALIGN_CHECK
  1269. MPLOCK or [edx],eax
  1270. svb30:
  1271. mov esp,ebp
  1272. svbexit:
  1273. pop PCR[PcExceptionList] ; Remove handler
  1274. lea esp, [esp+4]
  1275. pop edi
  1276. pop esi
  1277. pop ebx
  1278. pop edx
  1279. pop ebp
  1280. ret
  1281. SetVirtualBits endp
  1282. SetVirtualBits_Handler proc
  1283. mov esp, [esp+8] ; (esp)-> ExceptionList
  1284. jmp svbexit
  1285. SetVirtualBits_Handler endp
  1286. page ,132
  1287. subttl "Reflect Exception to a Vdm"
  1288. ;++
  1289. ;
  1290. ; Routine Description:
  1291. ;
  1292. ; This routine reflects an exception to a VDM. It uses the information
  1293. ; in the trap frame to determine what exception to reflect, and updates
  1294. ; the trap frame with the new CS, EIP, SS, and SP values
  1295. ;
  1296. ; Arguments:
  1297. ;
  1298. ; ebp -> Trap frame
  1299. ; ss:esp + 4 = trap number
  1300. ;
  1301. ; Returns
  1302. ;
  1303. ; Nothing
  1304. ;
  1305. ; Notes:
  1306. ; Interrupts are enabled upon entry, Irql is at APC level
  1307. ; This routine may not preserve all of the non-volatile registers if
  1308. ; a fault occurs.
  1309. ;
  1310. cPublicProc _Ki386VdmReflectException,1
  1311. RI equ [ebp - REGINFOSIZE]
  1312. ;
  1313. ; First make sure this is for us to handle
  1314. ;
  1315. mov eax,PCR[PcPrcbData+PbCurrentThread]
  1316. mov eax,[eax]+ThApcState+AsProcess
  1317. cmp dword ptr [eax]+PrVdmObjects,0 ; is this a vdm process?
  1318. jne short @f
  1319. xor eax, eax ; not handled
  1320. stdRET _Ki386VdmReflectException
  1321. @@:
  1322. push ebp
  1323. mov ebp,esp
  1324. sub esp,REGINFOSIZE
  1325. pushad
  1326. lea esi,ds:FIXED_NTVDMSTATE_LINEAR
  1327. ;
  1328. ; Look to see if the debugger wants exceptions
  1329. ;
  1330. stdCall _VdmFetchULONG, <esi>
  1331. test eax,VDM_BREAK_EXCEPTIONS
  1332. jz vredbg ; no, check for debug events
  1333. mov ebx,DBG_STACKFAULT
  1334. cmp word ptr [ebp + 8],0ch ; stack fault?
  1335. jz @f ; yes, check dbg flag
  1336. mov ebx,DBG_GPFAULT
  1337. cmp word ptr [ebp + 8],0dh ; gp fault?
  1338. jne vredbg ; no, continue
  1339. @@:
  1340. test eax,VDM_USE_DBG_VDMEVENT
  1341. jnz vrexc_event
  1342. jmp vrexcd ; reflect the exception to 32
  1343. ;
  1344. ; Look to see if the debugger wants debug events
  1345. ;
  1346. vredbg:
  1347. test eax,VDM_BREAK_DEBUGGER
  1348. jz vrevdm ; no debug events, reflect to vdm
  1349. mov ebx,DBG_SINGLESTEP
  1350. cmp word ptr [ebp + 8],1
  1351. jnz @f
  1352. test eax,VDM_USE_DBG_VDMEVENT
  1353. jnz vrexc_event
  1354. jmp vrexc1
  1355. @@:
  1356. mov ebx,DBG_BREAK
  1357. cmp word ptr [ebp + 8],3
  1358. jnz vrevdm
  1359. test eax,VDM_USE_DBG_VDMEVENT
  1360. jnz vrexc_event
  1361. jmp vrexc3
  1362. ;
  1363. ; Reflect the exception to the VDM
  1364. ;
  1365. vrevdm:
  1366. mov esi,[ebp]
  1367. cmp word ptr [esi].TsSegCs, KGDT_R3_CODE OR RPL_MASK ; int sim after fault?
  1368. je vre28
  1369. if DEVL
  1370. cmp word ptr [ebp + 8],11
  1371. jne @f
  1372. inc _ExVdmSegmentNotPresent
  1373. @@:
  1374. endif
  1375. if DBG
  1376. CurrentIrql
  1377. cmp al, APC_LEVEL
  1378. jge @f
  1379. int 3
  1380. @@:
  1381. endif
  1382. mov RI.RiTrapFrame,esi
  1383. mov eax,[esi].TsHardwareSegSs
  1384. mov RI.RiSegSs,eax
  1385. mov eax,[esi].TsHardwareEsp
  1386. mov RI.RiEsp,eax
  1387. mov eax,[esi].TsEFlags
  1388. mov RI.RiEFlags,eax
  1389. mov eax,[esi].TsEip
  1390. mov RI.RiEip,eax
  1391. mov eax,[esi].TsSegCs
  1392. mov RI.RiSegCs,eax
  1393. lea esi,RI
  1394. call CsToLinear ; uses eax as selector
  1395. test al,0FFh
  1396. jz vrerr
  1397. mov eax,[esi].RiSegSs
  1398. call SsToLinear
  1399. test al,0FFh
  1400. jz vrerr
  1401. mov ecx,[ebp + 8]
  1402. call PushException
  1403. test al,0FFh
  1404. jz vrerr
  1405. mov esi,RI.RiTrapFrame
  1406. mov eax,RI.RiEsp
  1407. mov [esi].TsHardwareEsp,eax
  1408. xor bl, bl ; R3 mask. 0 on V86 mode
  1409. test dword ptr [esi].TsEFlags, EFLAGS_V86_MASK ;
  1410. jnz @F ;
  1411. mov bl, 7 ; protected mode, R3 LDT selectors only
  1412. @@:
  1413. mov eax,RI.RiSegSs
  1414. or al, bl
  1415. mov [esi].TsHardwareSegSs,eax
  1416. mov eax,RI.RiEFlags
  1417. push [esi].TsEFlags
  1418. mov [esi].TsEFlags,eax
  1419. xor eax, [esp]
  1420. test eax, EFLAGS_V86_MASK ;
  1421. pop eax
  1422. je @f
  1423. stdCall _Ki386AdjustEsp0, <esi>
  1424. @@:
  1425. mov eax,RI.RiSegCs
  1426. or al, bl
  1427. cmp eax, 8
  1428. jae @f
  1429. test dword ptr [esi].TsEFlags, EFLAGS_V86_MASK ;
  1430. jnz @f ;
  1431. mov eax, KGDT_R3_CODE OR RPL_MASK
  1432. @@: mov [esi].TsSegCs,eax
  1433. mov eax,RI.RiEip
  1434. mov [esi].TsEip,eax
  1435. cmp word ptr [ebp + 8],1
  1436. jne vre28
  1437. and dword ptr [esi].TsEFlags, NOT EFLAGS_TF_MASK
  1438. vre28:
  1439. popad
  1440. mov eax,1 ; handled
  1441. vre30:
  1442. mov esp,ebp
  1443. pop ebp
  1444. stdRET _Ki386VdmReflectException
  1445. vrerr:
  1446. popad
  1447. xor eax,eax
  1448. jmp vre30
  1449. vrexc1:
  1450. mov eax, [ebp]
  1451. and dword ptr [eax]+TsEflags, not EFLAGS_TF_MASK
  1452. mov eax, [ebp]+TsEip ; (eax)-> faulting instruction
  1453. stdCall _VdmDispatchException <[ebp],STATUS_SINGLE_STEP,eax,0,0,0,0>
  1454. jmp vre28
  1455. vrexc3:
  1456. mov eax,BREAKPOINT_BREAK
  1457. mov ebx, [ebp]
  1458. mov ebx, [ebx]+TsEip
  1459. dec ebx ; (eax)-> int3 instruction
  1460. stdCall _VdmDispatchException <[ebp],STATUS_BREAKPOINT,ebx,3,eax,ecx,edx>
  1461. jmp vre28
  1462. vrexcd:
  1463. mov eax, [ebp]
  1464. mov eax, [eax]+TsEip
  1465. stdCall _VdmDispatchException <[ebp],STATUS_ACCESS_VIOLATION,eax,2,0,-1,0>
  1466. jmp vre28
  1467. vrexc_event:
  1468. mov eax, [ebp]
  1469. cmp ebx, DBG_SINGLESTEP
  1470. jnz vrexc_event2
  1471. and dword ptr [eax]+TsEflags, not EFLAGS_TF_MASK
  1472. vrexc_event2:
  1473. mov eax, [eax]+TsEip
  1474. stdCall _VdmDispatchException <[ebp],STATUS_VDM_EVENT,eax,1,ebx,0,0>
  1475. jmp vre28
  1476. stdENDP _Ki386VdmReflectException
  1477. page ,132
  1478. subttl "Reflect Segment Not Present Exception to a Vdm"
  1479. ;++
  1480. ;
  1481. ; Routine Description:
  1482. ;
  1483. ; This routine reflects an TRAP B to a VDM. It uses the information
  1484. ; in the trap frame to determine what exception to reflect, and updates
  1485. ; the trap frame with the new CS, EIP, SS, and SP values
  1486. ;
  1487. ; Arguments:
  1488. ;
  1489. ; ebp -> Trap frame
  1490. ;
  1491. ; Returns
  1492. ;
  1493. ; 0 is returned if the reflection fails.
  1494. ;
  1495. cPublicProc _Ki386VdmSegmentNotPresent,0
  1496. mov edi,PCR[PcTeb]
  1497. mov ecx,VDM_FAULT_HANDLER_SIZE * 0Bh
  1498. ;
  1499. ; Set up an exception handler in case we fault
  1500. ; during the user-space accesses below.
  1501. ;
  1502. push ebp
  1503. push offset FLAT:VdmSegNotPres_ExceptionHandler
  1504. ; set up exception registration record
  1505. push PCR[PcExceptionList]
  1506. mov PCR[PcExceptionList], esp
  1507. mov edi,[edi].TeVdm
  1508. xor ebx, ebx
  1509. cmp edi, _MmUserProbeAddress ; probe the TeVdm
  1510. jae short reflect
  1511. lea esi,[edi].VtDpmiInfo ; (esi)->dpmi info struct
  1512. mov edi, [edi].VtFaultTable ;
  1513. lea edi,[edi+ecx] ; (edi)->FaultHandler
  1514. cmp edi, _MmUserProbeAddress ; probe the table address
  1515. jae short reflect
  1516. cmp word ptr [esi].VpLockCount, 0 ; switching stacks?
  1517. jz short seg_not_pres ; yes, we can handle it
  1518. ; no, let normal code check
  1519. ; for stack faults
  1520. reflect:
  1521. ;
  1522. ; WARNING: Here we directly unlink the exception handler from the
  1523. ; exception registration chain. NO unwind is performed.
  1524. ;
  1525. pop PCR[PcExceptionList]
  1526. add esp, 4 ; pop out except handler
  1527. pop ebp
  1528. ;
  1529. ; Reflect the failure (or exception) back to the usermode ntvdm
  1530. ; to handle.
  1531. ;
  1532. pop eax ; (eax) = return addr
  1533. push 0bh
  1534. push eax
  1535. jmp _Ki386VdmReflectException
  1536. reflect_1:
  1537. add esp, REGINFOSIZE + 4 ; plus the "push esi" 4 bytes
  1538. jmp short reflect
  1539. seg_not_pres:
  1540. if DEVL
  1541. inc _ExVdmSegmentNotPresent
  1542. endif
  1543. inc word ptr [esi].VpLockCount
  1544. ;
  1545. ; (esi)->dpmi info struct
  1546. ; (edi)->FaultHandler
  1547. ; (ebp)->TrapFrame
  1548. ;
  1549. ; save stuff just like SwitchToHandlerStack does
  1550. ;
  1551. mov eax, [ebp].TsEip
  1552. mov [esi].VpSaveEip, eax
  1553. mov eax, [ebp].TsHardwareEsp
  1554. mov [esi].VpSaveEsp, eax
  1555. mov ax, [ebp].TsHardwareSegSs
  1556. mov [esi].VpSaveSsSelector, ax
  1557. movzx eax,word ptr [esi].VpSsSelector ; (eax) = PM stack selector
  1558. sub esp, REGINFOSIZE ; allocate reginfo table on stack
  1559. push esi ; save dpmi info
  1560. mov esi, esp
  1561. add esi, 4 ; (esi)->RegInfo
  1562. mov ecx, dword ptr [ebp].TsEFlags
  1563. mov [esi].RiEFlags,ecx ; initialize the reginfo table
  1564. call SsToLinear ; with eax and esi
  1565. test al,0FFh ; is al == 0?
  1566. jz short reflect_1 ; yes, failed
  1567. mov ebx, [esi].RiSsBase ; (ebx) = Base of PM Stack
  1568. pop esi ; (esi)->dpmi info
  1569. add esp, REGINFOSIZE ; remove RegInfo from stack
  1570. cmp ebx, _MmUserProbeAddress ; probe the PM stack base addr
  1571. jae short reflect ; make sure it is not Kmode addr
  1572. mov eax, [ebp].TsEFlags
  1573. call GetVirtualBits ; (eax) = app's eflags
  1574. push esi
  1575. mov edx, 0fe0h ; dpmistack offset (per win31)
  1576. test word ptr [esi].VpFlags, 1 ; 32-bit frame?
  1577. jz short @f
  1578. sub edx, 8 * 4
  1579. add edx, ebx
  1580. mov esi, [ebp].TsHardwareEsp
  1581. mov ecx, [ebp].TsHardwareSegSs
  1582. mov [edx + 20], eax ; push flags
  1583. mov [edx + 24], esi ; put esp on new stack
  1584. mov [edx + 28], ecx ; put ss on new stack
  1585. mov ecx, [ebp].TsSegCs
  1586. mov eax, [ebp].TsEip
  1587. mov esi, [ebp].TsErrCode
  1588. mov [edx + 16], ecx ; push cs
  1589. mov [edx + 12], eax ; push ip
  1590. mov [edx + 8], esi ; push error code
  1591. pop esi
  1592. mov ecx, [esi].VpDosxFaultIretD
  1593. mov eax, ecx
  1594. shr eax, 16
  1595. and ecx, 0ffffh
  1596. mov [edx + 4], eax ; push fault iret seg
  1597. mov [edx], ecx ; push fault iret offset
  1598. jmp short vsnp_update
  1599. @@:
  1600. sub edx, 8 * 2
  1601. add edx, ebx
  1602. mov esi, [ebp].TsHardwareEsp
  1603. mov ecx, [ebp].TsHardwareSegSs
  1604. mov [edx + 10], ax ; push flags
  1605. mov [edx + 12], si ; put esp on new stack
  1606. mov [edx + 14], cx ; put ss on new stack
  1607. mov ecx, [ebp].TsSegCs
  1608. mov eax, [ebp].TsEip
  1609. mov esi, [ebp].TsErrCode
  1610. mov [edx + 8], cx ; push cs
  1611. mov [edx + 6], ax ; push ip
  1612. mov [edx + 4], si ; push error code
  1613. pop esi
  1614. mov ecx, [esi].VpDosxFaultIret
  1615. mov eax, ecx
  1616. shr eax, 16
  1617. mov [edx + 2], ax ; push fault iret seg
  1618. mov [edx], cx ; push fault iret offset
  1619. vsnp_update:
  1620. mov eax,[edi].VfEip
  1621. sub edx, ebx
  1622. mov cx, word ptr [edi].VfCsSelector
  1623. mov bx, word ptr [esi].VpSsSelector
  1624. test dword ptr [edi].VfFlags, VDM_INT_INT_GATE
  1625. jz short @f
  1626. lea esi,ds:FIXED_NTVDMSTATE_LINEAR
  1627. MPLOCK and [esi],NOT VDM_VIRTUAL_INTERRUPTS
  1628. and dword ptr [ebp].TsEflags, 0FFF7FFFFH ; clear VIF
  1629. @@:
  1630. or cx, 7 ; R3 LDT selectors only
  1631. or bx, 7 ; R3 LDT selectors only
  1632. test dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
  1633. jnz short @f
  1634. cmp cx, 8
  1635. jge short @f
  1636. mov cx, KGDT_R3_CODE OR RPL_MASK
  1637. @@: mov [ebp].TsSegCs, cx
  1638. mov [ebp].TsEip, eax
  1639. mov [ebp].TsHardwareEsp,edx
  1640. mov [ebp].TsHardwareSegSs,bx
  1641. ;
  1642. ; WARNING: Here we directly unlink the exception handler from the
  1643. ; exception registration chain. NO unwind is performed.
  1644. ;
  1645. pop PCR[PcExceptionList]
  1646. add esp, 4 ; pop out except handler
  1647. pop ebp
  1648. mov eax, 1
  1649. stdRET _Ki386VdmSegmentNotPresent
  1650. stdENDP _Ki386VdmSegmentNotPresent
  1651. ;
  1652. ; Error and exception blocks for Ki386VdmSegmentNoPresent
  1653. ;
  1654. VdmSegNotPres_ExceptionHandler proc
  1655. ;
  1656. ; WARNING: Here we directly unlink the exception handler from the
  1657. ; exception registration chain. NO unwind is performed.
  1658. ;
  1659. mov esp, [esp+8] ; (esp)-> ExceptionList
  1660. jmp reflect
  1661. VdmSegNotPres_ExceptionHandler endp
  1662. page ,132
  1663. subttl "Dispatch UserMode Exception to a Vdm"
  1664. ;++
  1665. ;
  1666. ; Routine Description:
  1667. ;
  1668. ; Dispatches exception for vdm from in the kernel, by invoking
  1669. ; CommonDispatchException.
  1670. ;
  1671. ; Arguments: See CommonDispatchException for parameter description
  1672. ;
  1673. ; VOID
  1674. ; VdmDispatchException(
  1675. ; PKTRAP_FRAME TrapFrame,
  1676. ; NTSTATUS ExcepCode,
  1677. ; PVOID ExcepAddr,
  1678. ; ULONG NumParms,
  1679. ; ULONG Parm1,
  1680. ; ULONG Parm2,
  1681. ; ULONG Parm3
  1682. ; )
  1683. ;
  1684. ; Returns
  1685. ;
  1686. ; Nothing
  1687. ;
  1688. ; Notes:
  1689. ;
  1690. ; This routine may not preserve all of the non-volatile registers if
  1691. ; a fault occurs.
  1692. ;
  1693. cPublicProc _VdmDispatchException,7
  1694. TrapFrame equ [ebp+8]
  1695. ExcepCode equ [ebp+12]
  1696. ExcepAddr equ [ebp+16]
  1697. NumParms equ [ebp+20]
  1698. Parm1 equ [ebp+24]
  1699. Parm2 equ [ebp+28]
  1700. Parm3 equ [ebp+32]
  1701. push ebp
  1702. mov ebp,esp
  1703. pushad
  1704. LowerIrql 0 ; lower irql to 0
  1705. ; allow APCs and debuggers in!
  1706. mov eax, ExcepCode
  1707. mov ebx, ExcepAddr
  1708. mov ecx, NumParms
  1709. mov edx, Parm1
  1710. mov esi, Parm2
  1711. mov edi, Parm3
  1712. mov ebp, TrapFrame
  1713. call CommonDispatchException
  1714. popad
  1715. pop ebp
  1716. stdRET _VdmDispatchException
  1717. stdENDP _VdmDispatchException
  1718. page ,132
  1719. subttl "Push Interrupt frame on user stack"
  1720. ;++
  1721. ;
  1722. ; Routine Description:
  1723. ;
  1724. ; This routine pushes an interrupt frame on the user stack
  1725. ;
  1726. ; Arguments:
  1727. ;
  1728. ; ecx = interrupt #
  1729. ; esi = address of reg info
  1730. ; Returns:
  1731. ;
  1732. ; interrupt frame pushed on stack
  1733. ; reg info updated
  1734. ;
  1735. public PushInt
  1736. PushInt proc
  1737. push ebx
  1738. push edi
  1739. ;
  1740. ; Handle dispatching interrupts directly to the handler, rather than
  1741. ; to the dos extender
  1742. ;
  1743. ;
  1744. ; Get the information on the interrupt handler
  1745. ;
  1746. .errnz (VDM_INTERRUPT_HANDLER_SIZE - 8)
  1747. mov eax,PCR[PcTeb]
  1748. ;
  1749. ; Set up an exception handler in case we fault
  1750. ; during the user-space accesses below.
  1751. ; Note, we must preserve esi if exception does occur, all non-volatile registers are destroyed
  1752. ;
  1753. push esi
  1754. push ebp
  1755. push offset FLAT:PushIntExceptionHandler ; set up exception registration record
  1756. push PCR[PcExceptionList]
  1757. mov PCR[PcExceptionList], esp
  1758. mov eax,[eax].TbVdm
  1759. cmp eax, _MmUserProbeAddress
  1760. jae pierr
  1761. mov eax, [eax].VtInterruptTable
  1762. lea eax,[eax + ecx*8]
  1763. cmp eax, _MmUserProbeAddress
  1764. jae pierr
  1765. ;
  1766. ; Get SP
  1767. ;
  1768. mov edi,[ebp].TsHardwareEsp
  1769. test [esi].RiSsFlags,SEL_TYPE_BIG
  1770. jnz short @f
  1771. movzx edi,di ; zero high bits for 64k stack
  1772. ;
  1773. ; Update SP
  1774. ;
  1775. @@: test [eax].ViFlags,dword ptr VDM_INT_32
  1776. jz short @f
  1777. ;
  1778. ; 32 bit iret frame
  1779. ;
  1780. cmp edi,12 ; enough space on stack?
  1781. jb pierr ; no, go fault
  1782. sub edi,12
  1783. mov [esi].RiEsp,edi
  1784. jmp short pi130
  1785. ;
  1786. ; 16 bit iret frame
  1787. ;
  1788. @@: cmp edi,6 ; enough space on stack?
  1789. jb pierr ; no, go fault
  1790. sub edi,6
  1791. mov [esi].RiEsp,edi
  1792. ;
  1793. ; Check limit
  1794. ;
  1795. pi130: test [esi].RiSsFlags,SEL_TYPE_ED
  1796. jz short pi140
  1797. ;
  1798. ; Expand down, Sp must be above limit
  1799. ;
  1800. cmp edi,[esi].RiSsLimit
  1801. jna pierr
  1802. jmp short pi150
  1803. ;
  1804. ; Normal, Sp must be below limit
  1805. ;
  1806. pi140: cmp edi,[esi].RiSsLimit
  1807. jnb pierr
  1808. ;
  1809. ; Get base of ss
  1810. ;
  1811. pi150: mov ebx,[esi].RiSsBase
  1812. test [eax].ViFlags,dword ptr VDM_INT_32
  1813. jz short pi160
  1814. ;
  1815. ; "push" 32 bit iret frame
  1816. ;
  1817. mov edx,[esi].RiEip
  1818. mov [edi + ebx],edx
  1819. mov dx,word ptr [ebp].TsSegCs
  1820. mov [edi + ebx] + 4,edx
  1821. push eax
  1822. mov eax,[esi].RiEFlags
  1823. call GetVirtualBits
  1824. mov [edi + ebx] + 8,eax
  1825. pop eax
  1826. jmp short pi170
  1827. ;
  1828. ; push 16 bit iret frame
  1829. ;
  1830. pi160: mov dx,word ptr [esi].RiEip
  1831. mov [edi + ebx],dx
  1832. mov dx,word ptr [ebp].TsSegCs
  1833. mov [edi + ebx] + 2,dx
  1834. push eax
  1835. mov eax,[esi].RiEFlags
  1836. call GetVirtualBits
  1837. mov [edi + ebx] + 4,ax
  1838. pop eax
  1839. ;
  1840. ; Update CS and IP
  1841. ;
  1842. pi170: mov ebx,eax ; save int info
  1843. mov dx,[eax].ViCsSelector
  1844. mov word ptr [esi].RiSegCs,dx
  1845. mov edx,[eax].ViEip
  1846. mov [esi].RiEip,edx
  1847. movzx eax, word ptr [esi].RiSegCs
  1848. call CsToLinear ; uses eax as selector
  1849. test al,0ffh
  1850. jnz short pi175
  1851. ;
  1852. ; Check for destination not present
  1853. ;
  1854. test [esi].RiCsFlags,SEL_TYPE_NP
  1855. jz pierr
  1856. mov al,0ffh ; succeeded
  1857. jmp short pi180
  1858. ;
  1859. ; Check handler address
  1860. ;
  1861. pi175: mov edx,[esi].RiEip
  1862. cmp edx,[esi].RiCsLimit
  1863. jnb short pierr
  1864. ;
  1865. ; Turn off the trap flag
  1866. ;
  1867. pi180: and [esi].RiEFlags,NOT EFLAGS_TF_MASK
  1868. ;
  1869. ; Turn off virtual interrupts if necessary
  1870. ;
  1871. test [ebx].ViFlags,dword ptr VDM_INT_INT_GATE
  1872. ; n.b. We know al is non-zero, because we succeeded in cstolinear
  1873. jz short pi80
  1874. pi75: lea ebx,ds:FIXED_NTVDMSTATE_LINEAR
  1875. MPLOCK and [ebx], NOT EFLAGS_INTERRUPT_MASK
  1876. pi80: and [esi].RiEFlags,NOT (EFLAGS_IOPL_MASK OR EFLAGS_NT_MASK OR EFLAGS_V86_MASK)
  1877. or [esi].RiEFlags,EFLAGS_INTERRUPT_MASK
  1878. pi90:
  1879. ;
  1880. ; WARNING: Here we directly unlink the exception handler from the
  1881. ; exception registration chain. NO unwind is performed.
  1882. ;
  1883. pop PCR[PcExceptionList]
  1884. add esp, 4 ; pop out except handler
  1885. pop ebp
  1886. pop esi
  1887. pop edi
  1888. pop ebx
  1889. ret
  1890. pierr: xor eax,eax
  1891. jmp short pi90
  1892. PushInt endp
  1893. PushIntExceptionHandler proc
  1894. mov esp, [esp+8] ; (esp)-> ExceptionList
  1895. xor eax,eax
  1896. jmp pi90
  1897. PushIntExceptionHandler endp
  1898. page ,132
  1899. subttl "Convert CS Segment or selector to linear address"
  1900. ;++
  1901. ;
  1902. ; Routine Description:
  1903. ;
  1904. ; Convert CS segment or selector to linear address as appropriate
  1905. ; for the current user mode processor mode.
  1906. ;
  1907. ; Arguments:
  1908. ;
  1909. ; esi = reg info
  1910. ;
  1911. ; Returns:
  1912. ;
  1913. ; reg info updated
  1914. ;
  1915. public CsToLinear
  1916. CsToLinear proc
  1917. test [esi].RiEFlags,EFLAGS_V86_MASK
  1918. jz ctl10
  1919. shl eax,4
  1920. mov [esi].RiCsBase,eax
  1921. mov [esi].RiCsLimit,0FFFFh
  1922. mov [esi].RiCsFlags,0
  1923. mov eax,1
  1924. ret
  1925. ctl10:
  1926. push edx ; WARNING volatile regs!!!
  1927. lea edx,[esi].RiCsLimit
  1928. push edx
  1929. lea edx,[esi].RiCsBase
  1930. push edx
  1931. lea edx,[esi].RiCsFlags
  1932. push edx
  1933. push eax ; push selector
  1934. call _Ki386GetSelectorParameters@16
  1935. pop edx
  1936. or al,al
  1937. jz ctlerr
  1938. test [esi].RiCsFlags,SEL_TYPE_EXECUTE
  1939. jz ctlerr
  1940. test [esi].RiCsFlags,SEL_TYPE_2GIG
  1941. jz ctl30
  1942. ; Correct limit value for granularity
  1943. shl [esi].RiCsLimit,12
  1944. or [esi].RiCsLimit,0FFFh
  1945. ctl30:
  1946. mov eax,1
  1947. ret
  1948. ctlerr: xor eax,eax
  1949. ret
  1950. CsToLinear endp
  1951. page ,132
  1952. subttl "Verify that EIP is still valid"
  1953. ;++
  1954. ;
  1955. ; Routine Description:
  1956. ;
  1957. ; Verify that Eip is still valid and put it into the trap frame
  1958. ;
  1959. ; Arguments:
  1960. ;
  1961. ; esi = address of reg info
  1962. ;
  1963. ; Returns:
  1964. ;
  1965. ;
  1966. public CheckEip
  1967. CheckEip proc
  1968. mov eax,[esi].RiEip
  1969. test [esi].RiEFlags,EFLAGS_V86_MASK
  1970. jz ce20
  1971. and eax,[esi].RiCsLimit
  1972. mov [esi].RiEip,eax
  1973. jmp ce40
  1974. ce20: cmp eax,[esi].RiCsLimit
  1975. ja ceerr
  1976. ce40: mov eax,1
  1977. ce50: ret
  1978. ceerr: xor eax,eax
  1979. jmp ce50
  1980. CheckEip endp
  1981. page ,132
  1982. subttl "Convert Ss Segment or selector to linear address"
  1983. ;++
  1984. ;
  1985. ; Routine Description:
  1986. ;
  1987. ; Convert Ss segment or selector to linear address as appropriate
  1988. ; for the current user mode processor mode.
  1989. ;
  1990. ; Arguments:
  1991. ;
  1992. ; eax = selector to convert
  1993. ; esi = address of reg info
  1994. ;
  1995. ; Returns:
  1996. ;
  1997. ; reg info updated
  1998. ;
  1999. public SsToLinear
  2000. SsToLinear proc
  2001. test [esi].RiEFlags,EFLAGS_V86_MASK
  2002. jz stl10
  2003. shl eax,4
  2004. mov [esi].RiSsBase,eax
  2005. mov [esi].RiSsLimit,0FFFFh
  2006. mov [esi].RiSsFlags,0
  2007. mov eax,1
  2008. ret
  2009. stl10: push ecx
  2010. lea ecx,[esi].RiSsLimit
  2011. push ecx
  2012. lea ecx,[esi].RiSsBase
  2013. push ecx
  2014. lea ecx,[esi].RiSsFlags
  2015. push ecx
  2016. push eax ;selector
  2017. call _Ki386GetSelectorParameters@16
  2018. pop ecx
  2019. or al,al
  2020. jz stlerr
  2021. test [esi].RiSsFlags,SEL_TYPE_WRITE
  2022. jz stlerr
  2023. test [esi].RiSsFlags,SEL_TYPE_2GIG
  2024. jz stl30
  2025. ; Correct limit value for granularity
  2026. mov eax,[esi].RiSsLimit
  2027. shl eax,12
  2028. or eax,0FFFh
  2029. mov [esi].RiSsLimit,eax
  2030. stl30:
  2031. mov eax,1
  2032. stl40: ret
  2033. stlerr: xor eax,eax
  2034. jmp stl40
  2035. SsToLinear endp
  2036. page ,132
  2037. subttl "Verify that Esp is still valid"
  2038. ;++
  2039. ;
  2040. ; Routine Description:
  2041. ;
  2042. ; Verify that Esp is still valid
  2043. ;
  2044. ; Arguments:
  2045. ;
  2046. ; ecx = # of bytes needed for stack frame
  2047. ; esi = address of reg info
  2048. ;
  2049. ; Returns:
  2050. ;
  2051. ;
  2052. ;
  2053. public CheckEsp
  2054. CheckEsp proc
  2055. mov eax,[esi].RiEsp
  2056. test [esi].RiEFlags,EFLAGS_V86_MASK
  2057. jz cs20
  2058. and eax,[esi].RiSsLimit
  2059. mov [esi].RiEsp,eax
  2060. jmp cs40
  2061. cs20: test [esi].RiSsFlags,SEL_TYPE_BIG
  2062. jnz cs25
  2063. and eax,0FFFFh ; only use 16 bit for 16 bit
  2064. cs25:
  2065. cmp ecx, eax ; StackOffset > SP?
  2066. ja cserr ; yes error
  2067. dec eax ; make limit checks work
  2068. test [esi].RiSsFlags,SEL_TYPE_ED ; Expand down?
  2069. jz cs30 ; jif no
  2070. ;
  2071. ; Expand Down
  2072. ;
  2073. sub eax, ecx ; New SP
  2074. cmp eax,[esi].RiSsLimit ; NewSp < Limit?
  2075. jb cserr
  2076. jmp cs40
  2077. ;
  2078. ; Not Expand Down
  2079. ;
  2080. cs30: cmp eax,[esi].RiSsLimit
  2081. ja cserr
  2082. cs40: mov eax,1
  2083. cs50: ret
  2084. cserr: xor eax,eax
  2085. jmp cs50
  2086. CheckEsp endp
  2087. page ,132
  2088. subttl "Switch to protected mode interrupt stack"
  2089. ;++
  2090. ;
  2091. ; Routine Description:
  2092. ;
  2093. ; Switch to protected mode interrupt handler stack
  2094. ;
  2095. ; Arguments:
  2096. ;
  2097. ; ecx = interrupt number
  2098. ; esi = address of reg info
  2099. ; edi = address of PM Stack info
  2100. ;
  2101. ; Returns:
  2102. ;
  2103. ; reg info updated
  2104. ;
  2105. public SwitchToHandlerStack
  2106. SwitchToHandlerStack proc
  2107. ;
  2108. ; We must preserve non-volatile registers across exception
  2109. ;
  2110. push ebx
  2111. push esi
  2112. push edi
  2113. ;
  2114. ; Install exception handler
  2115. ;
  2116. push ebp
  2117. push offset SwitchToHandlerStack_fault ; Set Handler address
  2118. push PCR[PcExceptionList] ; Set next pointer
  2119. mov PCR[PcExceptionList],esp ; Link us on
  2120. cmp word ptr [edi].VpLockCount, 0 ; already switched?
  2121. jnz short @f ; yes
  2122. mov eax, [esi].RiEip
  2123. mov [edi].VpSaveEip, eax
  2124. mov eax, [esi].RiEsp
  2125. mov [edi].VpSaveEsp, eax
  2126. mov eax, [esi].RiSegSs
  2127. mov [edi].VpSaveSsSelector, ax
  2128. movzx eax,word ptr [edi].VpSsSelector
  2129. pop PCR[PcExceptionList] ; Remove our exception handle
  2130. add esp, 4 ; clear stack
  2131. pop ebp
  2132. mov [esi].RiSegSs,eax
  2133. mov dword ptr [esi].RiEsp,1000h ; dpmi stack offset
  2134. movzx eax, word ptr [esi].RiSegSs
  2135. push ecx
  2136. call SsToLinear ; compute new base
  2137. pop ecx
  2138. test al,0FFh
  2139. jz short shserr
  2140. push ebp
  2141. push offset SwitchToHandlerStack_fault ; Set Handler address
  2142. push PCR[PcExceptionList] ; Set next pointer
  2143. mov PCR[PcExceptionList],esp ; Link us on
  2144. @@:
  2145. inc word ptr [edi].VpLockCount ; maintain lock count
  2146. pop PCR[PcExceptionList] ; Remove our exception handle
  2147. add esp, 4 ; clear stack
  2148. pop ebp
  2149. mov eax,1
  2150. jmp short shsexit
  2151. shserr:
  2152. xor eax,eax
  2153. shsexit:
  2154. pop edi
  2155. pop esi
  2156. pop ebx
  2157. ret
  2158. SwitchToHandlerStack endp
  2159. SwitchToHandlerStack_fault proc
  2160. mov esp, [esp+8]
  2161. pop PCR[PcExceptionList] ; Remove our exception handle
  2162. add esp, 4 ; clear stack
  2163. pop ebp
  2164. jmp short shserr
  2165. SwitchToHandlerStack_fault endp
  2166. page ,132
  2167. subttl "Get protected mode interrupt handler address"
  2168. ;++
  2169. ;
  2170. ; Routine Description:
  2171. ;
  2172. ; Get the address of the interrupt handler for the specified interrupt
  2173. ;
  2174. ; Arguments:
  2175. ;
  2176. ; ecx = interrupt number
  2177. ; esi = address of reg info
  2178. ;
  2179. ; Returns:
  2180. ;
  2181. ; reg info updated
  2182. ;
  2183. public GetHandlerAddress
  2184. GetHandlerAddress proc
  2185. push ebp
  2186. push ebx
  2187. push esi
  2188. push edi
  2189. push ecx
  2190. push edx
  2191. push offset GetHandlerAddress_fault ; Set Handler address
  2192. push PCR[PcExceptionList] ; Set next pointer
  2193. mov PCR[PcExceptionList],esp ; Link us on
  2194. mov eax,VDM_FAULT_HANDLER_SIZE
  2195. mul ecx
  2196. mov edi,PCR[PcTeb]
  2197. mov edi,[edi].TeVdm
  2198. cmp edi, _MmUserProbeAddress ; Probe the VMD structure
  2199. jae short GetHandlerAddress_fault_resume
  2200. mov edi,[edi].VtFaultTable
  2201. cmp edi, _MmUserProbeAddress
  2202. jae short GetHandlerAddress_fault_resume
  2203. movzx ecx,word ptr [edi + eax].VfCsSelector
  2204. mov [esi].RiSegCs,ecx
  2205. mov ecx,[edi + eax].VfEip
  2206. mov [esi].RiEip,ecx
  2207. mov eax,1
  2208. jmp short GetHandlerAddress_Exit
  2209. GetHandlerAddress_fault_resume:
  2210. xor eax, eax
  2211. GethandlerAddress_Exit:
  2212. pop PCR[PcExceptionList] ; Remove our exception handle
  2213. add esp, 4 ; clear stack
  2214. pop edx
  2215. pop ecx
  2216. pop edi
  2217. pop esi
  2218. pop ebx
  2219. pop ebp
  2220. ret
  2221. GetHandlerAddress endp
  2222. GetHandlerAddress_fault proc
  2223. mov esp, [esp+8]
  2224. jmp short GetHandlerAddress_fault_resume
  2225. GetHandlerAddress_fault endp
  2226. page ,132
  2227. subttl "Push processor exception"
  2228. ;++
  2229. ;
  2230. ; Routine Description:
  2231. ;
  2232. ; Update the stack and registers to emulate the specified exception
  2233. ;
  2234. ; Arguments:
  2235. ;
  2236. ; ecx = interrupt number
  2237. ; esi = address of reg info
  2238. ;
  2239. ; Returns:
  2240. ;
  2241. ; reg info updated
  2242. ;
  2243. public PushException
  2244. PushException Proc
  2245. push ebx
  2246. push edi
  2247. push esi
  2248. test [esi].RiEflags,EFLAGS_V86_MASK
  2249. jz pe40
  2250. ;
  2251. ; Push V86 mode exception
  2252. ;
  2253. cmp ecx, 7 ; device not available fault
  2254. ja peerr ; per win3.1, no exceptions
  2255. ; above 7 for v86 mode
  2256. mov edx,[esi].RiEsp
  2257. mov ebx,[esi].RiSsBase
  2258. and edx,0FFFFh ; only use a 16 bit sp
  2259. sub dx,2
  2260. mov eax,[esi].RiEFlags
  2261. push ecx
  2262. call GetVirtualBits
  2263. pop ecx
  2264. ;
  2265. ; Install exception handler
  2266. ;
  2267. push ebp
  2268. push esp ; Pass current Esp to handler
  2269. push offset perr_fault ; Set Handler address
  2270. push PCR[PcExceptionList] ; Set next pointer
  2271. mov PCR[PcExceptionList],esp ; Link us on
  2272. mov [ebx+edx],ax ; push flags
  2273. sub dx,2
  2274. mov ax,word ptr [esi].RiSegCs
  2275. mov [ebx+edx],ax ; push cs
  2276. sub dx,2
  2277. mov ax,word ptr [esi].RiEip
  2278. mov [ebx+edx],ax ; push ip
  2279. mov eax,[ecx*4] ; get new cs:ip value
  2280. pop PCR[PcExceptionList] ; Remove our exception handle
  2281. add esp, 8 ; clear stack
  2282. pop ebp
  2283. push eax
  2284. movzx eax,ax
  2285. mov [esi].RiEip,eax
  2286. pop eax
  2287. shr eax,16
  2288. mov [esi].RiSegCs,eax
  2289. mov word ptr [esi].RiEsp,dx
  2290. jmp pe60
  2291. ;
  2292. ; Push PM exception
  2293. ;
  2294. pe40:
  2295. push [esi].RiEsp ; save for stack frame
  2296. push [esi].RiSegSs
  2297. ;
  2298. ; Install exception handler
  2299. ;
  2300. push ebp
  2301. push esp ; Pass current Esp to handler
  2302. push offset perr1_fault ; Set Handler address
  2303. push PCR[PcExceptionList] ; Set next pointer
  2304. mov PCR[PcExceptionList],esp ; Link us on
  2305. mov edi,PCR[PcTeb]
  2306. mov edi, [edi].TeVdm
  2307. pop PCR[PcExceptionList] ; Remove our exception handle
  2308. add esp, 8 ; clear stack
  2309. pop ebp
  2310. cmp edi, _MmUserProbeAddress
  2311. jae peerr1
  2312. lea edi,[edi].VtDpmiInfo
  2313. call SwitchToHandlerStack
  2314. test al,0FFh
  2315. jz peerr1 ; pop off stack and exit
  2316. sub [esi].RiEsp, 20h ; win31 undocumented feature
  2317. mov ebx,[esi].RiSsBase
  2318. mov edx,[esi].RiEsp
  2319. test [esi].RiSsFlags,SEL_TYPE_BIG
  2320. jnz short @f
  2321. movzx edx,dx ; zero high bits for 64k stack
  2322. @@:
  2323. ;
  2324. ; Install exception handler
  2325. ;
  2326. push ebp
  2327. push esp ; Pass current Esp to handler
  2328. push offset perr1_fault ; Set Handler address
  2329. push PCR[PcExceptionList] ; Set next pointer
  2330. mov PCR[PcExceptionList],esp ; Link us on
  2331. test word ptr [edi].VpFlags, 1 ; 32 bit app?
  2332. pop PCR[PcExceptionList] ; Remove our exception handle
  2333. lea esp, [esp+8] ; clear stack
  2334. pop ebp
  2335. jnz pe45 ; yes
  2336. ;
  2337. ; push 16-bit frame
  2338. ;
  2339. push ecx
  2340. mov ecx, 8*2 ; room for 8 words?
  2341. call CheckEsp
  2342. pop ecx
  2343. test al,0FFh
  2344. jz peerr1 ; pop off stack and exit
  2345. sub edx,8*2
  2346. mov [esi].RiEsp,edx
  2347. ;
  2348. ; Install exception handler
  2349. ;
  2350. push ebp
  2351. push esp ; Pass current Esp to handler
  2352. push offset perr1_fault ; Set Handler address
  2353. push PCR[PcExceptionList] ; Set next pointer
  2354. mov PCR[PcExceptionList],esp ; Link us on
  2355. mov eax, [esp+4*4]
  2356. mov [ebx+edx+14], ax
  2357. mov eax, [esp+4*5]
  2358. mov [ebx+edx+12], ax
  2359. pop PCR[PcExceptionList] ; Remove our exception handle
  2360. lea esp, [esp+8] ; clear stack
  2361. pop ebp
  2362. lea esp, [esp+8] ; clear stack
  2363. mov eax,[esi].RiEFlags
  2364. push ecx
  2365. call GetVirtualBits
  2366. pop ecx
  2367. ;
  2368. ; Install exception handler
  2369. ;
  2370. push ebp
  2371. push esp ; Pass current Esp to handler
  2372. push offset perr_fault ; Set Handler address
  2373. push PCR[PcExceptionList] ; Set next pointer
  2374. mov PCR[PcExceptionList],esp ; Link us on
  2375. mov [ebx+edx+10],ax ; push flags
  2376. movzx eax,word ptr [esi].RiSegCs
  2377. mov [ebx+edx+8],ax ; push cs
  2378. mov eax,[esi].RiEip
  2379. mov [ebx+edx+6],ax ; push ip
  2380. mov eax,RI.RiTrapFrame
  2381. mov eax,[eax].TsErrCode
  2382. mov [ebx+edx+4],ax ; push error code
  2383. mov eax,[edi].VpDosxFaultIret
  2384. mov [ebx+edx],eax ; push iret address
  2385. pop PCR[PcExceptionList] ; Remove our exception handle
  2386. add esp, 8 ; clear stack
  2387. pop ebp
  2388. jmp pe50
  2389. pe45:
  2390. ;
  2391. ; push 32-bit frame
  2392. ;
  2393. push ecx
  2394. mov ecx, 8*4 ; room for 8 dwords?
  2395. call CheckEsp
  2396. pop ecx
  2397. test al,0FFh
  2398. jz peerr1 ; pop off stack and exit
  2399. sub edx,8*4
  2400. mov [esi].RiEsp,edx
  2401. push ebp
  2402. push esp ; Pass current Esp to handler
  2403. push offset perr1_fault ; Set Handler address
  2404. push PCR[PcExceptionList] ; Set next pointer
  2405. mov PCR[PcExceptionList],esp ; Link us on
  2406. mov eax, [esp+4*4]
  2407. mov [ebx+edx+28], eax
  2408. mov eax, [esp+4*5]
  2409. mov [ebx+edx+24], eax
  2410. pop PCR[PcExceptionList] ; Remove our exception handle
  2411. add esp, 8 ; clear stack
  2412. pop ebp
  2413. lea esp, [esp+8] ; drop ss etc
  2414. mov eax,[esi].RiEFlags
  2415. push ecx
  2416. call GetVirtualBits
  2417. pop ecx
  2418. push ebp
  2419. push esp ; Pass current Esp to handler
  2420. push offset perr_fault ; Set Handler address
  2421. push PCR[PcExceptionList] ; Set next pointer
  2422. mov PCR[PcExceptionList],esp ; Link us on
  2423. mov [ebx+edx+20],eax ; push flags
  2424. movzx eax,word ptr [esi].RiSegCs
  2425. mov [ebx+edx+16],eax ; push cs
  2426. mov eax,[esi].RiEip
  2427. mov [ebx+edx+12],eax ; push ip
  2428. mov eax,RI.RiTrapFrame
  2429. mov eax,[eax].TsErrCode
  2430. mov [ebx+edx+8],eax ; push error code
  2431. mov eax,[edi].VpDosxFaultIretD
  2432. shr eax, 16
  2433. mov [ebx+edx+4],eax ; push iret seg
  2434. mov eax,[edi].VpDosxFaultIretD
  2435. and eax, 0ffffh
  2436. mov [ebx+edx],eax ; push iret offset
  2437. pop PCR[PcExceptionList] ; Remove our exception handle
  2438. add esp, 8 ; clear stack
  2439. pop ebp
  2440. pe50:
  2441. call GetHandlerAddress
  2442. test al,0FFh
  2443. jz peerr
  2444. pe60: push ecx
  2445. movzx eax,word ptr [esi].RiSegCs
  2446. call CsToLinear ; uses eax as selector
  2447. pop ecx
  2448. test al,0FFh
  2449. jz peerr
  2450. mov eax,[esi].RiEip
  2451. cmp eax,[esi].RiCsLimit
  2452. ja peerr
  2453. mov eax,VDM_FAULT_HANDLER_SIZE
  2454. push edx
  2455. mul ecx
  2456. pop edx
  2457. push ebp
  2458. push esp ; Pass current Esp to handler
  2459. push offset perr_fault ; Set Handler address
  2460. push PCR[PcExceptionList] ; Set next pointer
  2461. mov PCR[PcExceptionList],esp ; Link us on
  2462. mov edi,PCR[PcTeb]
  2463. mov edi,[edi].TbVdm
  2464. cmp edi, _MmUserProbeAddress
  2465. jb @f
  2466. mov edi, _MmUserProbeAddress
  2467. @@: mov edi,[edi].VtFaultTable
  2468. add edi,eax
  2469. cmp edi, _MmUserProbeAddress
  2470. jb @f
  2471. mov edi, _MmUserProbeAddress
  2472. @@: mov eax,[esi].RiEFlags ;WARNING 16 vs 32
  2473. test dword ptr [edi].VfFlags,VDM_INT_INT_GATE
  2474. pop PCR[PcExceptionList] ; Remove our exception handle
  2475. lea esp, [esp+8] ; clear stack
  2476. pop ebp
  2477. jz pe70
  2478. and eax,NOT (EFLAGS_INTERRUPT_MASK OR EFLAGS_TF_MASK)
  2479. push eax
  2480. xor ebx, ebx ; clear prefix flags
  2481. call SetVirtualBits
  2482. pop eax
  2483. pe70: push ecx
  2484. mov ecx,eax
  2485. call CheckVdmFlags
  2486. and ecx,NOT EFLAGS_TF_MASK
  2487. mov [esi].RiEFlags,ecx
  2488. pop ecx
  2489. mov eax,1 ; success
  2490. pe80: pop esi
  2491. pop edi
  2492. pop ebx
  2493. ret
  2494. peerr1: add esp, 8 ;throw away esp, ss
  2495. peerr: xor eax,eax
  2496. jmp pe80
  2497. PushException endp
  2498. perr1_fault proc
  2499. mov esp, [esp+8] ; (esp)-> ExceptionList
  2500. pop PCR[PcExceptionList] ; Remove our exception handle
  2501. add esp, 8 ; clear stack
  2502. pop ebp
  2503. jmp peerr1
  2504. perr1_fault endp
  2505. perr_fault proc
  2506. mov esp, [esp+8] ; (esp)-> ExceptionList
  2507. pop PCR[PcExceptionList] ; Remove our exception handle
  2508. add esp, 8 ; clear stack
  2509. pop ebp
  2510. jmp peerr
  2511. perr_fault endp
  2512. _PAGE ends
  2513. _TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
  2514. ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  2515. ;
  2516. ; Non-pagable code
  2517. ;
  2518. page ,132
  2519. subttl "Ipi worker for enabling Pentium extensions"
  2520. ;++
  2521. ;
  2522. ; Routine Description:
  2523. ;
  2524. ; This routine sets or resets the VME bit in CR4 for each processor
  2525. ;
  2526. ; Arguments:
  2527. ;
  2528. ; [esp + 4] -- 1 if VME is to be set, 0 if it is to be reset
  2529. ; Returns:
  2530. ;
  2531. ; 0
  2532. ;
  2533. cPublicProc _Ki386VdmEnablePentiumExtentions, 1
  2534. Enable equ [ebp + 8]
  2535. push ebp
  2536. mov ebp,esp
  2537. ;
  2538. ; Insure we do not get an interrupt in here. We may
  2539. ; be called at IPI_LEVEL - 1 by KiIpiGenericCall.
  2540. ;
  2541. pushf
  2542. cli
  2543. ; mov eax,cr4
  2544. db 0fh, 020h,0e0h
  2545. test Enable,1
  2546. je vepe20
  2547. or eax,CR4_VME
  2548. jmp vepe30
  2549. vepe20: and eax,NOT CR4_VME
  2550. ; mov cr4,eax
  2551. vepe30: db 0fh,022h,0e0h
  2552. popf
  2553. xor eax,eax
  2554. mov esp,ebp
  2555. pop ebp
  2556. stdRET _Ki386VdmEnablePentiumExtentions
  2557. stdENDP _Ki386VdmEnablePentiumExtentions
  2558. _TEXT$00 ends
  2559. end