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.

1919 lines
53 KiB

  1. title "Vdm Instuction Emulation"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; emv86.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module contains the routines for emulating instructions and
  13. ; faults from v86 mode.
  14. ;
  15. ; Author:
  16. ;
  17. ; sudeep bharati (sudeepb) 16-Nov-1992
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Notes:
  24. ;
  25. ;
  26. ; Revision History:
  27. ;
  28. ;--
  29. .386p
  30. .xlist
  31. include ks386.inc
  32. include i386\kimacro.inc
  33. include mac386.inc
  34. include i386\mi.inc
  35. include callconv.inc
  36. include ..\..\vdm\i386\vdm.inc
  37. include vdmtib.inc
  38. include irqli386.inc
  39. .list
  40. extrn VdmOpcode0f:proc
  41. extrn _DbgPrint:proc
  42. extrn _KeI386VirtualIntExtensions:dword
  43. EXTRNP _Ki386VdmDispatchIo,5
  44. EXTRNP _Ki386VdmDispatchStringIo,8
  45. EXTRNP _KiDispatchException,5
  46. EXTRNP _Ki386VdmReflectException,1
  47. EXTRNP _VdmEndExecution,2
  48. EXTRNP _VdmDispatchBop,1
  49. EXTRNP _VdmPrinterStatus,3
  50. EXTRNP _VdmPrinterWriteData, 3
  51. EXTRNP _VdmDispatchInterrupts,2
  52. EXTRNP _KeBugCheck,1
  53. EXTRNP _VdmSkipNpxInstruction,4
  54. EXTRNP _VdmFetchBop1,1
  55. EXTRNP _Ki386AdjustEsp0,1
  56. ifdef VDMDBG
  57. EXTRNP _VdmTraceEvent,4
  58. endif
  59. extrn _ExVdmOpcodeDispatchCounts:dword
  60. extrn OpcodeIndex:byte
  61. extrn _VdmUserCr0MapIn:byte
  62. extrn _MmUserProbeAddress:DWORD
  63. page ,132
  64. ifdef VDMDBG
  65. %out Debugging version
  66. endif
  67. ; Force assume into place
  68. _PAGE SEGMENT DWORD PUBLIC 'CODE'
  69. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  70. _PAGE ENDS
  71. _TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
  72. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  73. _TEXT$00 ENDS
  74. PAGEDATA SEGMENT DWORD PUBLIC 'DATA'
  75. ;
  76. ; Instruction emulation emulates the following instructions.
  77. ; The emulation affects the noted user mode registers.
  78. ;
  79. ;
  80. ; In V86 mode, the following instruction are emulated in the kernel
  81. ;
  82. ; Registers (E)Flags (E)SP SS CS
  83. ; PUSHF X X
  84. ; POPF X X
  85. ; INTnn X X X
  86. ; INTO X X X
  87. ; IRET X X X
  88. ; CLI X
  89. ; STI X
  90. ;
  91. ;
  92. ; INSB
  93. ; INSW
  94. ; OUTSB
  95. ; OUTSW
  96. ; INBimm
  97. ; INWimm
  98. ; OUTBimm
  99. ; OUTWimm
  100. ; INB
  101. ; INW
  102. ; OUTB
  103. ; OUTW
  104. ;
  105. ; WARNING What do we do about 32 bit io instructions??
  106. ; OpcodeDispatchV86 - table of routines used to emulate instructions
  107. ; in v86 mode.
  108. public OpcodeDispatchV86
  109. dtBEGIN OpcodeDispatchV86,OpcodeInvalidV86
  110. dtS VDM_INDEX_0F , Opcode0FV86
  111. dtS VDM_INDEX_ESPrefix , OpcodeESPrefixV86
  112. dtS VDM_INDEX_CSPrefix , OpcodeCSPrefixV86
  113. dtS VDM_INDEX_SSPrefix , OpcodeSSPrefixV86
  114. dtS VDM_INDEX_DSPrefix , OpcodeDSPrefixV86
  115. dtS VDM_INDEX_FSPrefix , OpcodeFSPrefixV86
  116. dtS VDM_INDEX_GSPrefix , OpcodeGSPrefixV86
  117. dtS VDM_INDEX_OPER32Prefix , OpcodeOPER32PrefixV86
  118. dtS VDM_INDEX_ADDR32Prefix , OpcodeADDR32PrefixV86
  119. dtS VDM_INDEX_INSB , OpcodeINSBV86
  120. dtS VDM_INDEX_INSW , OpcodeINSWV86
  121. dtS VDM_INDEX_OUTSB , OpcodeOUTSBV86
  122. dtS VDM_INDEX_OUTSW , OpcodeOUTSWV86
  123. dtS VDM_INDEX_PUSHF , OpcodePUSHFV86
  124. dtS VDM_INDEX_POPF , OpcodePOPFV86
  125. dtS VDM_INDEX_INTnn , OpcodeINTnnV86
  126. dtS VDM_INDEX_INTO , OpcodeINTOV86
  127. dtS VDM_INDEX_IRET , OpcodeIRETV86
  128. dts VDM_INDEX_NPX , OpcodeNPXV86
  129. dtS VDM_INDEX_INBimm , OpcodeINBimmV86
  130. dtS VDM_INDEX_INWimm , OpcodeINWimmV86
  131. dtS VDM_INDEX_OUTBimm , OpcodeOUTBimmV86
  132. dtS VDM_INDEX_OUTWimm , OpcodeOUTWimmV86
  133. dtS VDM_INDEX_INB , OpcodeINBV86
  134. dtS VDM_INDEX_INW , OpcodeINWV86
  135. dtS VDM_INDEX_OUTB , OpcodeOUTBV86
  136. dtS VDM_INDEX_OUTW , OpcodeOUTWV86
  137. dtS VDM_INDEX_LOCKPrefix , OpcodeLOCKPrefixV86
  138. dtS VDM_INDEX_REPNEPrefix , OpcodeREPNEPrefixV86
  139. dtS VDM_INDEX_REPPrefix , OpcodeREPPrefixV86
  140. dtS VDM_INDEX_CLI , OpcodeCLIV86
  141. dtS VDM_INDEX_STI , OpcodeSTIV86
  142. dtS VDM_INDEX_HLT , OpcodeHLTV86
  143. dtEND MAX_VDM_INDEX
  144. PAGEDATA ENDS
  145. _PAGE SEGMENT DWORD USE32 PUBLIC 'CODE'
  146. ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  147. page ,132
  148. subttl "Overide Prefix Macro"
  149. ;++
  150. ;
  151. ; Routine Description:
  152. ;
  153. ; This macro generates the code for handling override prefixes
  154. ; The routine name generated is OpcodeXXXXPrefix, where XXXX is
  155. ; the name used in the macro invocation. The code will set the
  156. ; PREFIX_XXXX bit in the Prefix flags.
  157. ;
  158. ; Arguments
  159. ; name = name of prefix
  160. ; esi = address of reg info
  161. ; edx = opcode
  162. ;
  163. ; Returns
  164. ; user mode Eip advanced
  165. ; eax advanced
  166. ; edx contains next byte of opcode
  167. ;
  168. ; NOTE: This routine exits by dispatching through the table again.
  169. ;--
  170. opPrefix macro name
  171. public Opcode&name&PrefixV86
  172. Opcode&name&PrefixV86 proc
  173. or ebx,PREFIX_&name
  174. ifdef VDMDBG
  175. _DATA segment
  176. Msg&name&Prefix db 'NTVDM: Encountered override prefix &name& %lx at '
  177. db 'address %lx', 0ah, 0dh, 0
  178. _DATA ends
  179. push [ebp].TsEip
  180. push [ebp].TsSegCs
  181. push offset FLAT:Msg&name&Prefix
  182. call _DbgPrint
  183. add esp,12
  184. endif
  185. jmp OpcodeGenericPrefixV86 ; dispatch to next handler
  186. Opcode&name&PrefixV86 endp
  187. endm
  188. irp prefix, <ES, CS, SS, DS, FS, GS, OPER32, ADDR32, LOCK, REPNE, REP>
  189. opPrefix prefix
  190. endm
  191. page ,132
  192. subttl "Instruction Emulation Dispatcher for V86"
  193. ;++
  194. ;
  195. ; Routine Description:
  196. ;
  197. ; This routine dispatches to the opcode specific emulation routine,
  198. ; based on the first byte of the opcode. Two byte opcodes, and prefixes
  199. ; result in another level of dispatching, from the handling routine.
  200. ; This code is called at APC_LEVEL to prevent modifications to the
  201. ; trap frame from NtSetContextThread.
  202. ;
  203. ; Arguments:
  204. ;
  205. ; [esp+4] = pointer to trap frame
  206. ;
  207. ; Returns:
  208. ;
  209. ; EAX = 0 failure
  210. ; 1 success
  211. cPublicProc _Ki386DispatchOpcodeV86,1
  212. push ebp
  213. mov ebp, [esp+8]
  214. movzx esi,word ptr [ebp].TsSegCs
  215. shl esi,4
  216. and dword ptr [ebp].TsEip, 0FFFFH
  217. and dword ptr [ebp].TsHardwareEsp, 0FFFFH
  218. add esi,[ebp].TsEip
  219. ;
  220. ; Probe and fetch the first byte from the instruction stream.
  221. ; Since we should be at APC_LEVEL here the trap frame can't be
  222. ; modified by the set context code. We don't have to capture.
  223. ;
  224. stdCall _VdmFetchBop1, <esi>
  225. movzx edx, OpcodeIndex[eax] ;get opcode index
  226. mov edi,1
  227. xor ebx,ebx
  228. ; All handler routines will get the following on entry
  229. ; ebx -> prefix flags
  230. ; ebp -> trap frame
  231. ; cl -> byte at the faulting address
  232. ; interrupts enabled and Irql at APC level
  233. ; esi -> address of faulting instruction
  234. ; edi -> instruction length count
  235. ; All handler routines return
  236. ; EAX = 0 for failure
  237. ; EAX = 1 for success
  238. if DEVL
  239. inc _ExVdmOpcodeDispatchCounts[edx * type _ExVdmOpcodeDispatchCounts]
  240. endif
  241. ifdef VDMDBG
  242. pushad
  243. stdCall _VdmTraceEvent, <VDMTR_KERNEL_OP_V86,ecx,0,ebp>
  244. popad
  245. endif
  246. call dword ptr OpcodeDispatchV86[edx * type OpcodeDispatchV86]
  247. pop ebp
  248. stdRet _Ki386DispatchOpcodeV86
  249. stdENDP _Ki386DispatchOpcodeV86
  250. page ,132
  251. subttl "Invalid Opcode Handler"
  252. ;++
  253. ;
  254. ; Routine Description:
  255. ;
  256. ; This routine emulates an invalid opcode. It prints the invalid
  257. ; opcode message, and causes a GP fault to be reflected to the
  258. ; debuger
  259. ;
  260. ; Arguments:
  261. ; EBX -> prefix flags
  262. ; EBP -> trap frame
  263. ; CL -> byte at the faulting address
  264. ; interrupts disabled
  265. ; ESI -> address of faulting instruction
  266. ; EDI -> instruction length count
  267. ;
  268. ; Returns:
  269. ; EAX = 0 for failure
  270. ; EAX = 1 for success
  271. ;
  272. ; All registers can be trashed except ebp/esp.
  273. ;
  274. public OpcodeInvalidV86
  275. OpcodeInvalidV86 proc
  276. xor eax,eax ; ret fail
  277. ret
  278. OpcodeInvalidV86 endp
  279. page ,132
  280. subttl "Generic Prefix Handler"
  281. ;++
  282. ;
  283. ; Routine Description:
  284. ;
  285. ; This routine handles the generic portion of all of the prefixes,
  286. ; and dispatches the next byte of the opcode.
  287. ;
  288. ; Arguments:
  289. ;
  290. ; EBX -> prefix flags
  291. ; EBP -> trap frame
  292. ; CL -> byte at the faulting address
  293. ; interrupts disabled
  294. ; ESI -> address of faulting instruction
  295. ; EDI -> instruction length count
  296. ;
  297. ; Returns:
  298. ; EAX = 0 for failure
  299. ; EAX = 1 for success
  300. ;
  301. ; All registers can be trashed except ebp/esp.
  302. ;
  303. public OpcodeGenericPrefixV86
  304. OpcodeGenericPrefixV86 proc
  305. inc esi
  306. inc edi
  307. movzx ecx, byte ptr [esi]
  308. movzx edx, OpcodeIndex[ecx] ;get opcode index
  309. if DEVL
  310. inc _ExVdmOpcodeDispatchCounts[edx * type _ExVdmOpcodeDispatchCounts]
  311. endif
  312. jmp OpcodeDispatchV86[edx * type OpcodeDispatchV86]
  313. OpcodeGenericPrefixV86 endp
  314. page ,132
  315. subttl "Byte string in Opcode Handler"
  316. ;++
  317. ;
  318. ; Routine Description:
  319. ;
  320. ; This routine emulates an INSB opcode. Currently, it prints
  321. ; a message, and ignores the instruction.
  322. ;
  323. ; Arguments:
  324. ; EBX -> prefix flags
  325. ; EBP -> trap frame
  326. ; CL -> byte at the faulting address
  327. ; interrupts disabled
  328. ; ESI -> address of faulting instruction
  329. ; EDI -> instruction length count
  330. ;
  331. ; Returns:
  332. ; EAX = 0 for failure
  333. ; EAX = 1 for success
  334. ;
  335. ; All registers can be trashed except ebp/esp.
  336. ;
  337. ; WARNING size override? ds override?
  338. public OpcodeINSBV86
  339. OpcodeINSBV86 proc
  340. push ebp ; trap frame
  341. push edi ; size of insb
  342. movzx eax,word ptr [ebp].TsV86Es
  343. shl eax,16
  344. movzx ecx,word ptr [ebp].TsEdi
  345. or eax,ecx
  346. push eax ; address
  347. mov eax,1
  348. xor ecx, ecx
  349. test ebx,PREFIX_REP ; prefixREP
  350. jz oisb20
  351. mov ecx, 1
  352. movzx eax,word ptr [ebp].TsEcx
  353. oisb20:
  354. push eax ; number of io ops
  355. push TRUE ; read op
  356. push ecx ; REP prefix ?
  357. push 1 ; byte op
  358. movzx eax,word ptr [ebp].TsEdx
  359. push eax ; port number
  360. ; Ki386VdmDispatchStringIo enables interrupts
  361. call _Ki386VdmDispatchStringIo@32 ; use retval
  362. ret
  363. OpcodeINSBV86 endp
  364. page ,132
  365. subttl "Word String In Opcode Handler"
  366. ;++
  367. ;
  368. ; Routine Description:
  369. ;
  370. ; This routine emulates an INSW opcode. Currently, it prints
  371. ; a message, and ignores the instruction.
  372. ;
  373. ; Arguments:
  374. ;
  375. ; EBX -> prefix flags
  376. ; EBP -> trap frame
  377. ; CL -> byte at the faulting address
  378. ; interrupts disabled
  379. ; ESI -> address of faulting instruction
  380. ; EDI -> instruction length count
  381. ;
  382. ; Returns:
  383. ; EAX = 0 for failure
  384. ; EAX = 1 for success
  385. ;
  386. ; All registers can be trashed except ebp/esp.
  387. ;
  388. public OpcodeINSWV86
  389. OpcodeINSWV86 proc
  390. push ebp ; trap frame
  391. push edi ; size of insw
  392. movzx eax,word ptr [ebp].TsV86Es
  393. shl eax,16
  394. movzx ecx,word ptr [ebp].TsEdi
  395. or eax,ecx
  396. push eax ; address
  397. mov eax,1
  398. xor ecx, ecx
  399. test ebx,PREFIX_REP ; prefixREP
  400. jz oisw20
  401. mov ecx, 1
  402. movzx eax,word ptr [ebp].TsEcx
  403. oisw20:
  404. push eax ; number of io ops
  405. push TRUE ; read op
  406. push ecx ; REP prefix ?
  407. push 2 ; word op
  408. movzx eax,word ptr [ebp].TsEdx
  409. push eax ; port number
  410. ; Ki386VdmDispatchStringIo enables interrupts
  411. call _Ki386VdmDispatchStringIo@32 ; use retval
  412. ret
  413. OpcodeINSWV86 endp
  414. page ,132
  415. subttl "Byte String Out Opcode Handler"
  416. ;++
  417. ;
  418. ; Routine Description:
  419. ;
  420. ; This routine emulates an OUTSB opcode. Currently, it prints
  421. ; a message, and ignores the instruction.
  422. ;
  423. ; Arguments:
  424. ;
  425. ; EBX -> prefix flags
  426. ; EBP -> trap frame
  427. ; CL -> byte at the faulting address
  428. ; interrupts disabled
  429. ; ESI -> address of faulting instruction
  430. ; EDI -> instruction length count
  431. ;
  432. ; Returns:
  433. ; EAX = 0 for failure
  434. ; EAX = 1 for success
  435. ;
  436. ; All registers can be trashed except ebp/esp.
  437. ;
  438. public OpcodeOUTSBV86
  439. OpcodeOUTSBV86 proc
  440. push ebp ; trap frame
  441. push edi ; size of outsb
  442. movzx eax,word ptr [ebp].TsV86Ds
  443. shl eax,16
  444. movzx ecx,word ptr [ebp].TsEsi
  445. or eax,ecx
  446. push eax ; address
  447. mov eax,1
  448. xor ecx, ecx
  449. test ebx,PREFIX_REP ; prefixREP
  450. jz oosb20
  451. mov ecx, 1
  452. movzx eax,word ptr [ebp].TsEcx
  453. oosb20:
  454. push eax ; number of io ops
  455. push FALSE ; write op
  456. push ecx ; REP prefix ?
  457. push 1 ; byte op
  458. movzx eax,word ptr [ebp].TsEdx
  459. push eax ; port number
  460. ; Ki386VdmDispatchStringIo enables interrupts
  461. call _Ki386VdmDispatchStringIo@32 ; use retval
  462. ret
  463. OpcodeOUTSBV86 endp
  464. page ,132
  465. subttl "Word String Out Opcode Handler"
  466. ;++
  467. ;
  468. ; Routine Description:
  469. ;
  470. ; This routine emulates an OUTSW opcode. Currently, it prints
  471. ; a message, and ignores the instruction
  472. ;
  473. ; Arguments:
  474. ;
  475. ; EBX -> prefix flags
  476. ; EBP -> trap frame
  477. ; CL -> byte at the faulting address
  478. ; interrupts disabled
  479. ; ESI -> address of faulting instruction
  480. ; EDI -> instruction length count
  481. ;
  482. ; Returns:
  483. ; EAX = 0 for failure
  484. ; EAX = 1 for success
  485. ;
  486. ; All registers can be trashed except ebp/esp.
  487. ;
  488. public OpcodeOUTSWV86
  489. OpcodeOUTSWV86 proc
  490. push ebp ; trap frame
  491. push edi ; size of outsw
  492. movzx eax,word ptr [ebp].TsV86Ds
  493. shl eax,16
  494. movzx ecx,word ptr [ebp].TsEsi
  495. or eax,ecx
  496. push eax ; address
  497. mov eax,1
  498. xor ecx, ecx
  499. test ebx,PREFIX_REP ; prefixREP
  500. jz oosw20
  501. mov ecx, 1
  502. movzx eax,word ptr [ebp].TsEcx
  503. oosw20:
  504. push eax ; number of io ops
  505. push FALSE ; write op
  506. push ecx ; REP prefix ?
  507. push 2 ; word op
  508. movzx eax,word ptr [ebp].TsEdx
  509. push eax ; port number
  510. ; Ki386VdmDispatchStringIo enables interrupts
  511. call _Ki386VdmDispatchStringIo@32 ; use retval
  512. ret
  513. OpcodeOUTSWV86 endp
  514. page ,132
  515. subttl "PUSHF Opcode Handler"
  516. ;++
  517. ;
  518. ; Routine Description:
  519. ;
  520. ; This routine emulates an PUSHF opcode. Currently, it prints
  521. ; a message, and simulates the instruction.
  522. ;
  523. ; Get SS
  524. ; shift left 4
  525. ; get SP
  526. ; subtract 2
  527. ; get flags
  528. ; put in virtual interrupt flag
  529. ; put on stack
  530. ; update sp
  531. ;
  532. ; Arguments:
  533. ; EBX -> prefix flags
  534. ; EBP -> trap frame
  535. ; CL -> byte at the faulting address
  536. ; interrupts disabled
  537. ; ESI -> address of faulting instruction
  538. ; EDI -> instruction length count
  539. ;
  540. ; Returns:
  541. ; EAX = 0 for failure
  542. ; EAX = 1 for success
  543. ;
  544. ; All registers can be trashed except ebp/esp.
  545. ;
  546. public OpcodePUSHFV86
  547. OpcodePUSHFV86 proc
  548. test _KeI386VirtualIntExtensions, dword ptr V86_VIRTUAL_INT_EXTENSIONS
  549. jz short puf00
  550. mov eax,dword ptr [ebp].TsEFlags
  551. lea ecx,ds:FIXED_NTVDMSTATE_LINEAR
  552. or dword ptr [ecx], VDM_VIRTUAL_INTERRUPTS
  553. test eax, EFLAGS_VIF ; Is vif on
  554. jnz short puf03
  555. and dword ptr [ecx], NOT VDM_VIRTUAL_INTERRUPTS
  556. and eax, NOT EFLAGS_INTERRUPT_MASK
  557. jmp short puf03
  558. puf00:
  559. lea eax,ds:FIXED_NTVDMSTATE_LINEAR
  560. mov edx,dword ptr [ebp].TsEFlags
  561. mov eax, dword ptr [eax] ; get virtual int flag
  562. and edx,NOT EFLAGS_INTERRUPT_MASK
  563. and eax,VDM_VIRTUAL_INTERRUPTS OR VDM_VIRTUAL_AC OR VDM_VIRTUAL_NT
  564. or eax,edx
  565. or eax,EFLAGS_IOPL_MASK
  566. puf03:
  567. movzx ecx,word ptr [ebp].TsHardwareSegSS
  568. movzx edx,word ptr [ebp].TsHardwareEsp
  569. shl ecx,4
  570. sub dx,2
  571. test ebx,PREFIX_OPER32 ; check operand size
  572. jnz puf10
  573. mov [ecx + edx],ax
  574. puf05:
  575. mov word ptr [ebp].TsHardwareEsp,dx ; update client esp
  576. add dword ptr [ebp].TsEip,edi
  577. mov eax, ds:FIXED_NTVDMSTATE_LINEAR
  578. test eax, VDM_VIRTUAL_INTERRUPTS
  579. jz short @f
  580. test eax, VDM_INTERRUPT_PENDING
  581. jz short @f
  582. call VdmDispatchIntAck
  583. @@:
  584. mov eax,1
  585. ret
  586. puf10: sub dx,2
  587. mov [ecx + edx],eax
  588. jmp puf05
  589. OpcodePUSHFV86 endp
  590. page ,132
  591. subttl "POPF Opcode Handler"
  592. ;++
  593. ;
  594. ; Routine Description:
  595. ;
  596. ; This routine emulates an POPF opcode. Currently, it prints
  597. ; a message, and returns to the monitor.
  598. ;
  599. ; Arguments:
  600. ; EBX -> prefix flags
  601. ; EBP -> trap frame
  602. ; CL -> byte at the faulting address
  603. ; interrupts disabled
  604. ; ESI -> address of faulting instruction
  605. ; EDI -> instruction length count
  606. ;
  607. ; Returns:
  608. ; EAX = 0 for failure
  609. ; EAX = 1 for success
  610. ;
  611. ; All registers can be trashed except ebp/esp.
  612. ;
  613. public OpcodePOPFV86
  614. OpcodePOPFV86 proc
  615. if DBG
  616. ; Mods to the trap frame need to be protected from thread context changes
  617. CurrentIrql
  618. cmp al, APC_LEVEL
  619. jge @f
  620. int 3
  621. @@:
  622. endif
  623. lea eax,ds:FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
  624. mov ecx,[ebp].TsHardwareSegSS
  625. movzx edx,word ptr [ebp].TsHardwareEsp
  626. shl ecx,4
  627. mov ecx,[ecx + edx] ; get flags from stack => ecx
  628. add edx,4
  629. test ebx,PREFIX_OPER32 ; check operand size
  630. jnz pof10
  631. and ecx,0ffffh ; only lower 16 bit for 16bit code
  632. sub edx,2
  633. pof10:
  634. mov [ebp].TsHardwareEsp,edx
  635. and ecx, NOT EFLAGS_IOPL_MASK
  636. mov ebx,ecx ; [ebx]=[ecx]=user EFLAGS - IOPL
  637. and ebx, NOT EFLAGS_NT_MASK ; [ebx]=user eflags - iopl - NT
  638. and ecx, (EFLAGS_INTERRUPT_MASK OR EFLAGS_ALIGN_CHECK OR EFLAGS_NT_MASK)
  639. ; [ecx]=IF + AC + NT of User eflgs
  640. ; [ebx]=User eflgs - IOPL - NT
  641. test _KeI386VirtualIntExtensions, dword ptr V86_VIRTUAL_INT_EXTENSIONS
  642. jz short pof15
  643. and ebx, NOT (EFLAGS_VIP + EFLAGS_VIF)
  644. ; [ebx]=UserFlg -IOPL - NT - VIP - VIF
  645. test ebx, EFLAGS_INTERRUPT_MASK
  646. jz short @f
  647. or ebx, EFLAGS_VIF ; [ebx]=UserFlg-IOPL-NT-VIP+VIF
  648. @@:
  649. or ebx, (EFLAGS_INTERRUPT_MASK OR EFLAGS_V86_MASK) ;[ebx]=UserFlg-IOPL-NT-VIP+VIF+IF
  650. push eax
  651. mov eax, [ebp].TsEFlags
  652. push eax
  653. and eax, EFLAGS_VIP
  654. or eax, ebx
  655. mov [ebp].TsEFlags, eax
  656. jmp short pof20
  657. pof15:
  658. push eax
  659. or ebx, (EFLAGS_INTERRUPT_MASK OR EFLAGS_V86_MASK)
  660. push [ebp].TsEFlags
  661. mov [ebp].TsEFlags, ebx
  662. pof20: xor ebx, [esp]
  663. test ebx, EFLAGS_V86_MASK
  664. lea esp, [esp+4]
  665. je @f
  666. stdCall _Ki386AdjustEsp0, <ebp>
  667. @@:
  668. pop eax
  669. MPLOCK and [eax],NOT (EFLAGS_INTERRUPT_MASK OR EFLAGS_ALIGN_CHECK OR EFLAGS_NT_MASK)
  670. MPLOCK or [eax],ecx
  671. add dword ptr [ebp].TsEip,edi
  672. mov eax,dword ptr [eax]
  673. test eax,VDM_INTERRUPT_PENDING
  674. jz pof25
  675. test eax,VDM_VIRTUAL_INTERRUPTS
  676. jz pof25
  677. call VdmDispatchIntAck
  678. pof25:
  679. mov eax,1 ; handled
  680. ret
  681. OpcodePOPFV86 endp
  682. page ,132
  683. subttl "INTnn Opcode Handler"
  684. ;++
  685. ;
  686. ; Routine Description:
  687. ;
  688. ; This routine emulates an INTnn opcode. It retrieves the handler
  689. ; from the IVT, pushes the current cs:ip and flags on the stack,
  690. ; and dispatches to the handler.
  691. ;
  692. ; Arguments:
  693. ; EBX -> prefix flags
  694. ; EBP -> trap frame
  695. ; CL -> byte at the faulting address
  696. ; interrupts disabled
  697. ; ESI -> address of faulting instruction
  698. ; EDI -> instruction length count
  699. ;
  700. ; Returns:
  701. ; EAX = 0 for failure
  702. ; EAX = 1 for success
  703. ;
  704. ; All registers can be trashed except ebp/esp.
  705. ;
  706. public OpcodeINTnnV86
  707. OpcodeINTnnV86 proc
  708. ;
  709. ; Int nn in v86 mode always disables interrupts
  710. ;
  711. mov edx,[ebp].TsEflags
  712. lea eax,ds:FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
  713. mov ecx,dword ptr [eax] ;[ecx]=vdmstate
  714. MPLOCK and [eax],NOT VDM_VIRTUAL_INTERRUPTS
  715. mov eax, edx
  716. and eax, NOT EFLAGS_INTERRUPT_MASK
  717. .errnz (EFLAGS_INTERRUPT_MASK - VDM_VIRTUAL_INTERRUPTS)
  718. and ecx, VDM_VIRTUAL_INTERRUPTS OR VDM_VIRTUAL_AC
  719. ; [edx]=eflags
  720. ; [eax]=eflgs-if
  721. ; [ecx]=IF + AC of vdmstate
  722. test _KeI386VirtualIntExtensions, dword ptr V86_VIRTUAL_INT_EXTENSIONS
  723. jz short oinnv15
  724. ;
  725. ;VIF extension is enabled, we should migrate EFLAGS_VIF instead of
  726. ;VDM_VIRTUAL_INTERRUPT to the iret frame eflags IF.
  727. ;When VIF extension is enabled, RI_BIT_MASK is turned on. This in turn,
  728. ;redirects the FCLI/FSTI macro to execute cli/sti directly instead
  729. ;of simulation. Without this, we might disable v86 mode interrupt
  730. ;without the applications knowing it.
  731. ;
  732. and ecx, VDM_VIRTUAL_AC ;keep VDM_VIRTUAL_AC only
  733. or eax, ecx ;[eax]=eflags + ac -if
  734. mov ecx, edx
  735. and ecx, EFLAGS_VIF
  736. .errnz ((EFLAGS_VIF SHR 10) - EFLAGS_INTERRUPT_MASK)
  737. ror ecx, 10 ;VIF -> IF
  738. oinnv15:
  739. or eax, ecx ;[eax]=eflags +ac +if
  740. oinnv20:
  741. and edx,NOT (EFLAGS_NT_MASK OR EFLAGS_TF_MASK OR EFLAGS_VIF)
  742. mov [ebp].TsEflags,edx
  743. or eax, EFLAGS_IOPL_MASK
  744. movzx ecx,word ptr [ebp].TsHardwareSegSS
  745. shl ecx,4
  746. movzx edx,word ptr [ebp].TsHardwareEsp ; ecx+edx is user stack
  747. sub dx,2
  748. mov word ptr [ecx+edx],ax ; push flags
  749. mov ax,word ptr [ebp].TsSegCS
  750. sub dx,2
  751. mov word ptr [ecx+edx],ax ; push cs
  752. movzx eax,word ptr [ebp].TsEip
  753. add eax, edi
  754. inc eax
  755. sub dx,2
  756. mov word ptr [ecx+edx],ax ; push ip
  757. mov [ebp].TsHardwareEsp,dx ; update sp on trap frame
  758. inc esi
  759. movzx ecx,byte ptr [esi] ; ecx is int#
  760. ;
  761. ; Check if this is a v86 interrupt which must be reflected to a PM handler
  762. ;
  763. call oinnvuserrefs ; do user refs under a try/except block
  764. or eax, eax
  765. je short oinnv30
  766. ;
  767. ; Encode interrupt number in cs
  768. ;
  769. mov eax,ebx
  770. shr eax,16 ; bop cs
  771. sub eax,ecx ; new cs
  772. shl ecx,4
  773. add ebx,ecx ; new ip
  774. jmp short oinnv40
  775. oinnv30:
  776. ;
  777. ; Not hooked, just pick up new vector from RM IVT
  778. ;
  779. mov ebx,[ecx*4]
  780. mov eax,ebx
  781. shr eax,16 ; new cs
  782. oinnv40:
  783. mov word ptr [ebp].TsEip,bx
  784. cmp ax, 8
  785. jae @f
  786. test dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
  787. jnz @f
  788. mov ax, KGDT_R3_CODE OR RPL_MASK
  789. @@:
  790. mov [ebp].TsSegCs,ax ; cs:ip on trap frame is updated
  791. mov eax,1
  792. ret
  793. OpcodeINTnnV86 endp
  794. oinnvuserrefs proc
  795. push ebp
  796. push offset oinnvuserrefs_fault ; Set Handler address
  797. push PCR[PcExceptionList] ; Set next pointer
  798. mov PCR[PcExceptionList],esp ; Link us on
  799. mov eax,PCR[PcTeb]
  800. mov eax,[eax].TeVdm ; get pointer to VdmTib
  801. cmp eax, _MmUserProbeAddress ; Probe the TeVdm
  802. jae short oinnvuserrefs_fault_resume
  803. mov ebx,[eax].VtInterruptTable ;
  804. cmp ebx, 0 ; there is no interrupt table
  805. je short oinnvuserrefs_fault_resume ; so, don't reflect it.
  806. lea ebx,[ebx + ecx*8]
  807. cmp ebx, _MmUserProbeAddress ; Probe the TeVdm
  808. jae short oinnvuserrefs_fault_resume
  809. test [ebx].ViFlags, VDM_INT_HOOKED ; need to reflect to PM?
  810. jz short oinnvuserrefs_fault_resume
  811. lea ebx,[eax].VtDpmiInfo ; point to DpmiInfo
  812. mov ebx,[ebx].VpDosxRmReflector ; bop to reflect to PM
  813. mov eax, 1
  814. pop PCR[PcExceptionList] ; Remove our exception handle
  815. add esp, 4 ; clear stack
  816. pop ebp
  817. ret
  818. oinnvuserrefs_fault_resume:
  819. pop PCR[PcExceptionList] ; Remove our exception handle
  820. add esp, 4 ; clear stack
  821. pop ebp
  822. xor eax, eax
  823. ret
  824. oinnvuserrefs endp
  825. oinnvuserrefs_fault proc
  826. ;
  827. ; WARNING: Here we directly unlink the exception handler from the
  828. ; exception registration chain. NO unwind is performed. We can take
  829. ; this short cut because we know that our handler is a leaf-node.
  830. ;
  831. mov esp, [esp+8] ; (esp)-> ExceptionList
  832. jmp oinnvuserrefs_fault_resume
  833. oinnvuserrefs_fault endp
  834. page ,132
  835. subttl "INTO Opcode Handler"
  836. ;++
  837. ;
  838. ; Routine Description:
  839. ;
  840. ; This routine emulates an INTO opcode. Currently, it prints
  841. ; a message, and reflects a GP fault to the debugger.
  842. ;
  843. ; Arguments:
  844. ; EBX -> prefix flags
  845. ; EBP -> trap frame
  846. ; CL -> byte at the faulting address
  847. ; interrupts disabled
  848. ; ESI -> address of faulting instruction
  849. ; EDI -> instruction length count
  850. ;
  851. ; Returns:
  852. ; EAX = 0 for failure
  853. ; EAX = 1 for success
  854. ;
  855. ; All registers can be trashed except ebp/esp.
  856. ;
  857. public OpcodeINTOV86
  858. OpcodeINTOV86 proc
  859. xor eax,eax ; ret fail
  860. ret
  861. OpcodeINTOV86 endp
  862. page ,132
  863. subttl "IRET Opcode Handler"
  864. ;++
  865. ;
  866. ; Routine Description:
  867. ;
  868. ; This routine emulates an IRET opcode. It retrieves the flags,
  869. ; and new instruction pointer from the stack and puts them into
  870. ; the user context.
  871. ;
  872. ;
  873. ; Arguments:
  874. ; EBX -> prefix flags
  875. ; EBP -> trap frame
  876. ; CL -> byte at the faulting address
  877. ; interrupts disabled
  878. ; ESI -> address of faulting instruction
  879. ; EDI -> instruction length count
  880. ;
  881. ; Returns:
  882. ; EAX = 0 for failure
  883. ; EAX = 1 for success
  884. ;
  885. ; All registers can be trashed except ebp/esp.
  886. ;
  887. ;
  888. public OpcodeIRETV86
  889. OpcodeIRETV86 proc
  890. if DBG
  891. ; Mods to the trap frame need to be protected from thread context changes
  892. CurrentIrql
  893. cmp al, APC_LEVEL
  894. jge @f
  895. int 3
  896. @@:
  897. endif
  898. lea eax,ds:FIXED_NTVDMSTATE_LINEAR
  899. movzx ecx,word ptr [ebp].TsHardwareSegSS
  900. movzx edx,word ptr [ebp].TsHardwareEsp ; ebx+edx is user stack
  901. shl ecx,4
  902. add ecx,edx
  903. test ebx,PREFIX_OPER32
  904. jnz irt50 ; normally not
  905. movzx edi,word ptr [ecx] ; get ip value
  906. mov [ebp].TsEip,edi
  907. movzx esi,word ptr [ecx+2] ; get cs value
  908. add edx,6
  909. movzx ebx,word ptr [ecx+4] ; get flag value
  910. mov [ebp].TsHardwareEsp,edx ; update sp on trap frame
  911. mov [ebp].TsSegCs,esi
  912. irt10: ; [ebx]=UserFlgs
  913. and ebx, NOT (EFLAGS_IOPL_MASK OR EFLAGS_NT_MASK OR EFLAGS_VIP OR EFLAGS_VIF)
  914. mov ecx,ebx ; [ecx]=[ebx]=UserFlgs - IOPL - NT - VIP - VIF
  915. test _KeI386VirtualIntExtensions, dword ptr V86_VIRTUAL_INT_EXTENSIONS
  916. jz short irt15
  917. or ebx, EFLAGS_VIF
  918. test ebx, EFLAGS_INTERRUPT_MASK
  919. jnz irt15
  920. and ebx, NOT EFLAGS_VIF
  921. ; [ebx] = UserFlgs - IOPL - NT - VIP
  922. irt15:
  923. push eax
  924. or ebx, (EFLAGS_V86_MASK OR EFLAGS_INTERRUPT_MASK)
  925. mov eax, dword ptr [ebp].TsEFlags
  926. push eax
  927. and eax, EFLAGS_VIP
  928. or eax, ebx ; update flags in trap frame
  929. mov dword ptr [ebp].TsEFlags, eax
  930. pop ebx
  931. test ebx, EFLAGS_V86_MASK
  932. jne @f
  933. push ecx
  934. push edx
  935. stdCall _Ki386AdjustEsp0, <ebp>
  936. pop edx
  937. pop ecx
  938. @@:
  939. pop eax
  940. and ecx, EFLAGS_INTERRUPT_MASK
  941. MPLOCK and [eax],NOT VDM_VIRTUAL_INTERRUPTS
  942. MPLOCK or [eax],ecx
  943. mov ebx,[eax]
  944. ; at this point esi is the cs and edi is the ip where v86 mode
  945. ; will return. Now we will check if this returning instruction
  946. ; is a bop. if so we will directly dispatch the bop from here
  947. ; saving a full round trip. This will be really helpful to
  948. ; com apps.
  949. shl esi,4
  950. add esi,edi
  951. cmp esi, _MmUserProbeAddress ; Probe 32 bit value
  952. jbe @f
  953. mov esi, _MmUserProbeAddress
  954. @@: mov ax, word ptr [esi]
  955. cmp ax, 0c4c4h
  956. je irtbop
  957. test ebx,VDM_INTERRUPT_PENDING
  958. jz short irt25
  959. test ebx,VDM_VIRTUAL_INTERRUPTS
  960. jz short irt25
  961. call VdmDispatchIntAck ; VdmDispatchIntAck enables interrupts
  962. irt25:
  963. mov eax,1 ; handled
  964. ret
  965. ; ireting to a bop
  966. irtbop:
  967. stdCall _VdmDispatchBop, <ebp>
  968. jmp short irt25
  969. irt50:
  970. mov edi, [ecx] ; get ip value
  971. mov [ebp].TsEip,edi
  972. movzx esi,word ptr [ecx+4] ; get cs value
  973. add edx,12
  974. mov ebx, [ecx+8] ; get flag value
  975. mov [ebp].TsSegCs,esi
  976. mov [ebp].TsHardwareEsp,edx ; update sp on trap frame
  977. jmp irt10 ; rejoin the common path
  978. OpcodeIRETV86 endp
  979. page ,132
  980. subttl "In Byte Immediate Opcode Handler"
  981. ;++
  982. ;
  983. ; Routine Description:
  984. ;
  985. ; This routine emulates an in byte immediate opcode. Currently, it
  986. ; prints a message, and ignores the instruction.
  987. ;
  988. ; Arguments:
  989. ; EBX -> prefix flags
  990. ; EBP -> trap frame
  991. ; CL -> byte at the faulting address
  992. ; interrupts disabled
  993. ; ESI -> address of faulting instruction
  994. ; EDI -> instruction length count
  995. ;
  996. ; Returns:
  997. ; EAX = 0 for failure
  998. ; EAX = 1 for success
  999. ;
  1000. ; All registers can be trashed except ebp/esp.
  1001. ;
  1002. public OpcodeINBimmV86
  1003. OpcodeINBimmV86 proc
  1004. inc esi
  1005. inc edi
  1006. movzx ecx,byte ptr [esi]
  1007. ; Ki386VdmDispatchIo enables interrupts
  1008. stdCall _Ki386VdmDispatchIo, <ecx, 1, TRUE, edi, ebp>
  1009. ret
  1010. OpcodeINBimmV86 endp
  1011. page ,132
  1012. subttl "Word In Immediate Opcode Handler"
  1013. ;++
  1014. ;
  1015. ; Routine Description:
  1016. ;
  1017. ; This routine emulates an in word immediate opcode. Currently, it
  1018. ; prints a message, and ignores the instruction.
  1019. ;
  1020. ; Arguments:
  1021. ; EAX -> pointer to vdm state in DOS arena
  1022. ; EBX -> prefix flags
  1023. ; EBP -> trap frame
  1024. ; CL -> byte at the faulting address
  1025. ; interrupts disabled
  1026. ; ESI -> address of faulting instruction
  1027. ; EDI -> instruction length count
  1028. ;
  1029. ; Returns:
  1030. ; EAX = 0 for failure
  1031. ; EAX = 1 for success
  1032. ;
  1033. ; All registers can be trashed except ebp/esp.
  1034. ;
  1035. public OpcodeINWimmV86
  1036. OpcodeINWimmV86 proc
  1037. inc esi
  1038. inc edi
  1039. movzx ecx,byte ptr [esi]
  1040. ; edi - instruction size
  1041. ; TRUE - read op
  1042. ; 2 - word op
  1043. ; ecx - port number
  1044. ; Ki386VdmDispatchIo enables interrupts
  1045. stdCall _Ki386VdmDispatchIo, <ecx, 2, TRUE, edi, ebp>
  1046. ret
  1047. OpcodeINWimmV86 endp
  1048. page ,132
  1049. subttl "Out Byte Immediate Opcode Handler"
  1050. ;++
  1051. ;
  1052. ; Routine Description:
  1053. ;
  1054. ; This routine emulates an invalid opcode. Currently, it prints
  1055. ; a message, and ignores the instruction.
  1056. ;
  1057. ; Arguments:
  1058. ; EAX -> pointer to vdm state in DOS arena
  1059. ; EBX -> prefix flags
  1060. ; EBP -> trap frame
  1061. ; CL -> byte at the faulting address
  1062. ; interrupts disabled
  1063. ; ESI -> address of faulting instruction
  1064. ; EDI -> instruction length count
  1065. ;
  1066. ; Returns:
  1067. ; EAX = 0 for failure
  1068. ; EAX = 1 for success
  1069. ;
  1070. ; All registers can be trashed except ebp/esp.
  1071. ;
  1072. public OpcodeOUTBimmV86
  1073. OpcodeOUTBimmV86 proc
  1074. inc edi
  1075. inc esi
  1076. movzx ecx,byte ptr [esi]
  1077. ; edi - instruction size
  1078. ; FALSE - write op
  1079. ; 1 - byte op
  1080. ; ecx - port #
  1081. ; Ki386VdmDispatchIo enables interrupts
  1082. stdCall _Ki386VdmDispatchIo, <ecx, 1, FALSE, edi, ebp>
  1083. ret
  1084. OpcodeOUTBimmV86 endp
  1085. page ,132
  1086. subttl "Out Word Immediate Opcode Handler"
  1087. ;++
  1088. ;
  1089. ; Routine Description:
  1090. ;
  1091. ; This routine emulates an out word immediate opcode. Currently,
  1092. ; it prints a message, and ignores the instruction.
  1093. ;
  1094. ; Arguments:
  1095. ; EAX -> pointer to vdm state in DOS arena
  1096. ; EBX -> prefix flags
  1097. ; EBP -> trap frame
  1098. ; CL -> byte at the faulting address
  1099. ; interrupts disabled
  1100. ; ESI -> address of faulting instruction
  1101. ; EDI -> instruction length count
  1102. ;
  1103. ; Returns:
  1104. ; EAX = 0 for failure
  1105. ; EAX = 1 for success
  1106. ;
  1107. ; All registers can be trashed except ebp/esp.
  1108. ;
  1109. ;
  1110. public OpcodeOUTWimmV86
  1111. OpcodeOUTWimmV86 proc
  1112. inc esi
  1113. inc edi
  1114. movzx ecx,byte ptr [esi]
  1115. ; edi - instruction size
  1116. ; FALSE - write op
  1117. ; 2 - word op
  1118. ; ecx - port number
  1119. ; Ki386VdmDispatchIo enables interrupts
  1120. stdCall _Ki386VdmDispatchIo, <ecx, 2, FALSE, edi, ebp>
  1121. ret
  1122. OpcodeOUTWimmV86 endp
  1123. page ,132
  1124. subttl "INB Opcode Handler"
  1125. ;++
  1126. ;
  1127. ; Routine Description:
  1128. ;
  1129. ; This routine emulates an INB opcode. Currently, it prints
  1130. ; a message, and ignores the instruction.
  1131. ;
  1132. ; Arguments:
  1133. ; EAX -> pointer to vdm state in DOS arena
  1134. ; EBX -> prefix flags
  1135. ; EBP -> trap frame
  1136. ; CL -> byte at the faulting address
  1137. ; interrupts disabled
  1138. ; ESI -> address of faulting instruction
  1139. ; EDI -> instruction length count
  1140. ;
  1141. ; Returns:
  1142. ; EAX = 0 for failure
  1143. ; EAX = 1 for success
  1144. ;
  1145. ; All registers can be trashed except ebp/esp.
  1146. ;
  1147. public OpcodeINBV86
  1148. OpcodeINBV86 proc
  1149. movzx ebx,word ptr [ebp].TsEdx
  1150. ; edi - instruction size
  1151. ; TRUE - read op
  1152. ; 1 - byte op
  1153. ; ebx - port number
  1154. cmp ebx, 3bdh
  1155. jz oib_prt1
  1156. cmp ebx, 379h
  1157. jz oib_prt1
  1158. cmp ebx, 279h
  1159. jz oib_prt1
  1160. oib_reflect:
  1161. ; Ki386VdmDispatchIo enables interrupts
  1162. stdCall _Ki386VdmDispatchIo, <ebx, 1, TRUE, edi, ebp>
  1163. ret
  1164. oib_prt1:
  1165. ; call printer status routine with port number, size, trap frame
  1166. stdCall _VdmPrinterStatus, <ebx, edi, ebp>
  1167. or al,al
  1168. jz short oib_reflect
  1169. ret
  1170. OpcodeINBV86 endp
  1171. page ,132
  1172. subttl "INW Opcode Handler"
  1173. ;++
  1174. ;
  1175. ; Routine Description:
  1176. ;
  1177. ; This routine emulates an INW opcode. Currently, it prints
  1178. ; a message, and ignores the instruction.
  1179. ;
  1180. ; Arguments:
  1181. ; EAX -> pointer to vdm state in DOS arena
  1182. ; EBX -> prefix flags
  1183. ; EBP -> trap frame
  1184. ; CL -> byte at the faulting address
  1185. ; interrupts disabled
  1186. ; ESI -> address of faulting instruction
  1187. ; EDI -> instruction length count
  1188. ;
  1189. ; Returns:
  1190. ; EAX = 0 for failure
  1191. ; EAX = 1 for success
  1192. ;
  1193. ; All registers can be trashed except ebp/esp.
  1194. ;
  1195. ;
  1196. public OpcodeINWV86
  1197. OpcodeINWV86 proc
  1198. movzx ebx,word ptr [ebp].TsEdx
  1199. ; edi - instruction size
  1200. ; TRUE - read operation
  1201. ; 2 - word op
  1202. ; ebx - port number
  1203. ; Ki386VdmDispatchIo enables interrupts
  1204. stdCall _Ki386VdmDispatchIo, <ebx, 2, TRUE, edi, ebp>
  1205. ret
  1206. OpcodeINWV86 endp
  1207. page ,132
  1208. subttl "OUTB Opcode Handler"
  1209. ;++
  1210. ;
  1211. ; Routine Description:
  1212. ;
  1213. ; This routine emulates an OUTB opcode. Currently, it prints
  1214. ; a message, and ignores the instruction.
  1215. ;
  1216. ; Arguments:
  1217. ; EAX -> pointer to vdm state in DOS arena
  1218. ; EBX -> prefix flags
  1219. ; EBP -> trap frame
  1220. ; CL -> byte at the faulting address
  1221. ; interrupts disabled
  1222. ; ESI -> address of faulting instruction
  1223. ; EDI -> instruction length count
  1224. ;
  1225. ; Returns:
  1226. ; EAX = 0 for failure
  1227. ; EAX = 1 for success
  1228. ;
  1229. ; All registers can be trashed except ebp/esp.
  1230. ;
  1231. ;
  1232. public OpcodeOUTBV86
  1233. OpcodeOUTBV86 proc
  1234. movzx ebx,word ptr [ebp].TsEdx
  1235. cmp ebx, 3bch
  1236. jz oob_prt1
  1237. cmp ebx, 378h
  1238. jz oob_prt1
  1239. cmp ebx, 278h
  1240. jz oob_prt1
  1241. oob_reflect:
  1242. ; edi - instruction size
  1243. ; FALSE - write op
  1244. ; 1 - byte op
  1245. ; ebx - port number
  1246. ; Ki386VdmDispatchIo enables interrupts
  1247. stdCall _Ki386VdmDispatchIo, <ebx, 1, FALSE, edi, ebp>
  1248. ret
  1249. oob_prt1:
  1250. ; call printer write data routine with port number, size, trap frame
  1251. stdCall _VdmPrinterWriteData, <ebx, edi, ebp>
  1252. or al,al
  1253. jz short oob_reflect
  1254. ;al already has TRUE
  1255. ret
  1256. OpcodeOUTBV86 endp
  1257. page ,132
  1258. subttl "OUTW Opcode Handler"
  1259. ;++
  1260. ;
  1261. ; Routine Description:
  1262. ;
  1263. ; This routine emulates an OUTW opcode. Currently, it prints
  1264. ; a message, and ignores the instruction.
  1265. ;
  1266. ; Arguments:
  1267. ; EAX -> pointer to vdm state in DOS arena
  1268. ; EBX -> prefix flags
  1269. ; EBP -> trap frame
  1270. ; CL -> byte at the faulting address
  1271. ; interrupts disabled
  1272. ; ESI -> address of faulting instruction
  1273. ; EDI -> instruction length count
  1274. ;
  1275. ; Returns:
  1276. ; EAX = 0 for failure
  1277. ; EAX = 1 for success
  1278. ;
  1279. ; All registers can be trashed except ebp/esp.
  1280. ;
  1281. ;
  1282. public OpcodeOUTWV86
  1283. OpcodeOUTWV86 proc
  1284. movzx ebx,word ptr [ebp].TsEdx
  1285. ; edi - instruction size
  1286. ; FALSE - write op
  1287. ; 2 - word op
  1288. ; ebx - port #
  1289. ; Ki386VdmDispatchIo enables interrupts
  1290. stdCall _Ki386VdmDispatchIo, <ebx, 2, FALSE, edi, ebp>
  1291. ret
  1292. OpcodeOUTWV86 endp
  1293. page ,132
  1294. subttl "CLI Opcode Handler"
  1295. ;++
  1296. ;
  1297. ; Routine Description:
  1298. ;
  1299. ; This routine emulates an CLI opcode. Currently, it prints
  1300. ; a message, and clears the virtual interrupt flag in the VdmTeb.
  1301. ;
  1302. ; Arguments:
  1303. ; EAX -> pointer to vdm state in DOS arena
  1304. ; EBX -> prefix flags
  1305. ; EBP -> trap frame
  1306. ; CL -> byte at the faulting address
  1307. ; interrupts disabled
  1308. ; ESI -> address of faulting instruction
  1309. ; EDI -> instruction length count
  1310. ;
  1311. ; Returns:
  1312. ; EAX = 0 for failure
  1313. ; EAX = 1 for success
  1314. ;
  1315. ; All registers can be trashed except ebp/esp.
  1316. ;
  1317. ;
  1318. public OpcodeCLIV86
  1319. OpcodeCLIV86 proc
  1320. lea eax,ds:FIXED_NTVDMSTATE_LINEAR
  1321. test _KeI386VirtualIntExtensions, dword ptr V86_VIRTUAL_INT_EXTENSIONS
  1322. jz short oc50
  1323. mov edx, [ebp].TsEFlags ; redundant code. Just in case
  1324. mov eax,dword ptr [eax]
  1325. and edx, EFLAGS_VIF + EFLAGS_VIP
  1326. cmp edx, EFLAGS_VIF + EFLAGS_VIP
  1327. jnz short oc40
  1328. test eax,VDM_INTERRUPT_PENDING
  1329. jz short oc40
  1330. call VdmDispatchIntAck
  1331. mov eax,1
  1332. ret
  1333. oc40: lea eax,ds:FIXED_NTVDMSTATE_LINEAR
  1334. oc50: MPLOCK and dword ptr [eax],NOT VDM_VIRTUAL_INTERRUPTS
  1335. add dword ptr [ebp].TsEip,edi
  1336. mov eax,1
  1337. ret
  1338. OpcodeCLIV86 endp
  1339. page ,132
  1340. subttl "STI Opcode Handler"
  1341. ;++
  1342. ;
  1343. ; Routine Description:
  1344. ;
  1345. ; This routine emulates an STI opcode. Currently, it prints
  1346. ; a message, and sets the virtual interrupt flag in the VDM teb.
  1347. ;
  1348. ; Arguments:
  1349. ; EAX -> pointer to vdm state in DOS arena
  1350. ; EBX -> prefix flags
  1351. ; EBP -> trap frame
  1352. ; CL -> byte at the faulting address
  1353. ; interrupts disabled
  1354. ; ESI -> address of faulting instruction
  1355. ; EDI -> instruction length count
  1356. ;
  1357. ; Returns:
  1358. ; EAX = 0 for failure
  1359. ; EAX = 1 for success
  1360. ;
  1361. ; All registers can be trashed except ebp/esp.
  1362. ;
  1363. ;
  1364. public OpcodeSTIV86
  1365. OpcodeSTIV86 proc
  1366. lea eax,ds:FIXED_NTVDMSTATE_LINEAR ; get pointer to VDM State
  1367. test _KeI386VirtualIntExtensions, dword ptr V86_VIRTUAL_INT_EXTENSIONS
  1368. jz short os10
  1369. or [ebp].TsEFlags, dword ptr EFLAGS_VIF
  1370. os10: MPLOCK or dword ptr [eax],EFLAGS_INTERRUPT_MASK
  1371. os20: add dword ptr [ebp].TsEip,edi
  1372. mov eax,dword ptr [eax]
  1373. test eax,VDM_INTERRUPT_PENDING
  1374. jz short os30
  1375. call VdmDispatchIntAck
  1376. os30: mov eax,1
  1377. ret
  1378. OpcodeSTIV86 endp
  1379. ;
  1380. ; If we get here, we have executed an NPX instruction in user mode
  1381. ; with the emulator installed. If the EM bit was not set in CR0, the
  1382. ; app really wanted to execute the instruction for detection purposes.
  1383. ; In this case, we need to clear the TS bit, and restart the instruction.
  1384. ; Otherwise we need to reflect the exception
  1385. ;
  1386. ;
  1387. ; Reginfo structure
  1388. ;
  1389. public Opcode0FV86
  1390. Opcode0FV86 proc
  1391. RI equ [ebp - REGINFOSIZE]
  1392. push ebp
  1393. mov ebp,esp
  1394. sub esp,REGINFOSIZE
  1395. push esi
  1396. push edi
  1397. ; Initialize RegInfo
  1398. do10: mov esi,[ebp]
  1399. ; initialize rest of the trap from which was'nt initialized for
  1400. ; v86 mode
  1401. mov eax, [esi].TsV86Es
  1402. mov [esi].TsSegEs,eax
  1403. mov eax, [esi].TsV86Ds
  1404. mov [esi].TsSegDs,eax
  1405. mov eax, [esi].TsV86Fs
  1406. mov [esi].TsSegFs,eax
  1407. mov eax, [esi].TsV86Gs
  1408. mov [esi].TsSegGs,eax
  1409. mov RI.RiTrapFrame,esi
  1410. mov eax,[esi].TsHardwareSegSs
  1411. mov RI.RiSegSs,eax
  1412. mov eax,[esi].TsHardwareEsp
  1413. mov RI.RiEsp,eax
  1414. mov eax,[esi].TsEFlags
  1415. mov RI.RiEFlags,eax
  1416. mov eax,[esi].TsSegCs
  1417. mov RI.RiSegCs,eax
  1418. mov eax,[esi].TsEip
  1419. dec edi
  1420. add eax,edi ; for prefixes
  1421. mov RI.RiEip,eax
  1422. mov RI.RiPrefixFlags,ebx
  1423. lea esi,RI
  1424. CsToLinearV86
  1425. call VdmOpcode0f ; enables interrupts
  1426. test eax,0FFFFh
  1427. jz do20
  1428. mov edi,RI.RiTrapFrame
  1429. mov eax,RI.RiEip ; advance eip
  1430. mov [edi].TsEip,eax
  1431. do19: mov eax,1
  1432. do20:
  1433. pop edi
  1434. pop esi
  1435. mov esp,ebp
  1436. pop ebp
  1437. ret
  1438. Opcode0FV86 endp
  1439. ;++
  1440. ;
  1441. ; Routine Description: VdmDispatchIntAck
  1442. ; pushes stack arguments for VdmDispatchInterrupts
  1443. ; and invokes VdmDispatchInterrupts
  1444. ;
  1445. ; Expects VDM_INTERRUPT_PENDING, and VDM_VIRTUAL_INTERRUPTS
  1446. ;
  1447. ; Arguments:
  1448. ; EBP -> trap frame
  1449. ;
  1450. ; Returns:
  1451. ; nothing
  1452. ;
  1453. ;
  1454. public VdmDispatchIntAck
  1455. VdmDispatchIntAck proc
  1456. push ebp
  1457. push offset diafault ; Set Handler address
  1458. push PCR[PcExceptionList] ; Set next pointer
  1459. mov PCR[PcExceptionList],esp ; Link us on
  1460. test ds:FIXED_NTVDMSTATE_LINEAR, VDM_INT_HARDWARE ; check interrupt int
  1461. mov eax,PCR[PcTeb]
  1462. mov eax,[eax].TeVdm ; get pointer to VdmTib
  1463. jz short dia20
  1464. cmp eax, _MmUserProbeAddress ; check if user address
  1465. jae short dia10 ; if ae, then not user address
  1466. pop PCR[PcExceptionList] ; Remove our exception handle
  1467. add esp, 4 ; clear stack
  1468. pop ebp
  1469. ;
  1470. ; dispatch hardware int directly from kernel
  1471. ;
  1472. stdCall _VdmDispatchInterrupts, <ebp, eax> ; TrapFrame, VdmTib
  1473. ret
  1474. dia10:
  1475. pop PCR[PcExceptionList] ; Remove our exception handle
  1476. add esp, 4 ; clear stack
  1477. pop ebp
  1478. ret
  1479. ;
  1480. ; Switch to monitor context to dispatch timer int
  1481. ;
  1482. dia20:
  1483. cmp eax, _MmUserProbeAddress ; check if user address
  1484. jae dia10 ; if ae, then not user address
  1485. mov dword ptr [eax].VtEIEvent,VdmIntAck ;
  1486. mov dword ptr [eax].VtEIInstSize,0
  1487. mov dword ptr [eax].VtEiIntAckInfo,0
  1488. pop PCR[PcExceptionList] ; Remove our exception handle
  1489. add esp, 4 ; clear stack
  1490. pop ebp
  1491. stdCall _VdmEndExecution, <ebp, eax> ; TrapFrame, VdmTib
  1492. ret
  1493. VdmDispatchIntAck endp
  1494. diafault proc
  1495. ;
  1496. ; WARNING: Here we directly unlink the exception handler from the
  1497. ; exception registration chain. NO unwind is performed. We can take
  1498. ; this short cut because we know that our handler is a leaf-node.
  1499. ;
  1500. mov esp, [esp+8] ; (esp)-> ExceptionList
  1501. pop PCR[PcExceptionList] ; Remove our exception handle
  1502. add esp, 4 ; clear stack
  1503. pop ebp
  1504. ret
  1505. diafault endp
  1506. public vdmDebugPoint
  1507. vdmDebugPoint proc
  1508. ret
  1509. vdmDebugPoint endp
  1510. page ,132
  1511. subttl "HLT Opcode Handler"
  1512. ;++
  1513. ;
  1514. ; Routine Description:
  1515. ;
  1516. ; This routine emulates an HLT opcode. If the halt instruction is
  1517. ; followed by the magic number (to be found in a crackerjack box),
  1518. ; we use the hlt + magic number as a prefix, and emulate the following
  1519. ; instruction. This allows code running in segmented protected mode to
  1520. ; access the virtual interrupt flag.
  1521. ;
  1522. ; Arguments:
  1523. ; EAX -> pointer to vdm state in DOS arena
  1524. ; EBX -> prefix flags
  1525. ; EBP -> trap frame
  1526. ; CL -> byte at the faulting address
  1527. ; interrupts disabled
  1528. ; ESI -> address of faulting instruction
  1529. ; EDI -> instruction length count
  1530. ;
  1531. ; Returns:
  1532. ; EAX = 0 for failure
  1533. ; EAX = 1 for success
  1534. ;
  1535. ; All registers can be trashed except ebp/esp.
  1536. ;
  1537. public OpcodeHLTV86
  1538. OpcodeHLTV86 proc
  1539. add dword ptr [ebp].TsEip,edi
  1540. mov eax,1
  1541. ret
  1542. OpcodeHLTV86 endp
  1543. _PAGE ends
  1544. _TEXT$00 SEGMENT DWORD PUBLIC 'CODE'
  1545. ASSUME DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING
  1546. subttl "NPX Opcode Handler"
  1547. ;++
  1548. ;
  1549. ; Routine Description:
  1550. ;
  1551. ; This routine emulates all NPX opcodes, when the system
  1552. ; has the R3 emulator installed and the c86 apps takes a
  1553. ; trap07.
  1554. ;
  1555. ; Arguments:
  1556. ; EBX -> prefix flags
  1557. ; EBP -> trap frame
  1558. ; CL -> byte at the faulting address
  1559. ; ESI -> address of faulting instruction
  1560. ; EDI -> instruction length count
  1561. ;
  1562. ; Returns:
  1563. ; EAX = 0 for failure
  1564. ; EAX = 1 for success
  1565. ;
  1566. ; All registers can be trashed except ebp/esp.
  1567. ; moved from emv86.asm as it must be non-pagable
  1568. public OpcodeNPXV86
  1569. OpcodeNPXV86 proc
  1570. mov edx, PCR[PcPrcbData+PbCurrentThread] ; get current thread
  1571. mov edx, [edx].ThInitialStack
  1572. mov edx, [edx].FpCr0NpxState-NPX_FRAME_LENGTH
  1573. test edx, CR0_EM ; Does app want NPX traps?
  1574. jnz short onp40
  1575. ; MP bit can never be set while the EM bit is cleared, so we know
  1576. ; the faulting instruction is not an FWAIT
  1577. onp30: and ebx, PREFIX_ADDR32
  1578. stdCall _VdmSkipNpxInstruction, <ebp, ebx, esi, edi>
  1579. or al, al ; was it handled?
  1580. jnz short onp60 ; no, go raise exception to app
  1581. onp40: stdCall _Ki386VdmReflectException, <7> ; trap #
  1582. onp60: mov eax,1
  1583. ret
  1584. OpcodeNPXV86 endp
  1585. ;++ KiVdmSetUserCR0
  1586. ;
  1587. ; eax
  1588. ;
  1589. public KiVdmSetUserCR0
  1590. KiVdmSetUserCR0 proc
  1591. and eax, CR0_MP OR CR0_EM ; Sanitize parameter
  1592. shr eax, 1
  1593. movzx eax, _VdmUserCr0MapIn[eax]
  1594. push ebp ; Pass current Ebp to handler
  1595. push offset scr_fault ; Set Handler address
  1596. push PCR[PcExceptionList] ; Set next pointer
  1597. mov PCR[PcExceptionList],esp ; Link us on
  1598. mov edx,PCR[PcTeb]
  1599. mov edx,[edx].TeVdm ; get pointer to VdmTib
  1600. cmp edx, _MmUserProbeAddress ; probe the pointer
  1601. jbe short @f
  1602. mov edx, _MmUserProbeAddress ; make us AV
  1603. @@: mov [edx].VtVdmContext.CsFloatSave.FpCtxtCr0NpxState, eax
  1604. scr10: pop PCR[PcExceptionList] ; Remove our exception handle
  1605. mov ebx, PCR[PcPrcbData + PbCurrentThread] ; (ebx) = current thread
  1606. add esp, 4 ; Remove Exception Handler
  1607. pop ebp ; restore ebp.
  1608. mov edx, [ebx].ThInitialStack ; Get fp save area
  1609. sub edx, NPX_FRAME_LENGTH
  1610. scr20: cli ; sync with context swap
  1611. and [edx].FpCr0NpxState, NOT (CR0_MP+CR0_EM+CR0_PE)
  1612. or [edx].FpCr0NpxState,eax ; set fp save area bits
  1613. mov eax,cr0
  1614. and eax, NOT (CR0_MP+CR0_EM+CR0_TS) ; turn off bits we will change
  1615. or al, [ebx].ThNpxState ; set scheduler bits
  1616. or eax,[edx].FpCr0NpxState ; set user's bits
  1617. mov cr0,eax
  1618. sti
  1619. ret
  1620. KiVdmSetUserCR0 endp
  1621. scr_fault proc
  1622. ;
  1623. ; WARNING: Here we directly unlink the exception handler from the
  1624. ; exception registration chain. NO unwind is performed. We can take
  1625. ; this short cut because we know that our handler is a leaf-node.
  1626. ;
  1627. mov esp, [esp+8] ; (esp)-> ExceptionList
  1628. jmp short scr10
  1629. scr_fault endp
  1630. _TEXT$00 ENDS
  1631. end