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.

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