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.

323 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. vdmuserrefs.c
  5. Abstract:
  6. This module contains routines that probe and fetch from the
  7. instruction stream to make the vdm bop support solid.
  8. Author:
  9. Neill Clift (NeillC) 27-Jun-2001
  10. Revision History:
  11. --*/
  12. #include "vdmp.h"
  13. #pragma alloc_text (PAGE, VdmFetchBop1)
  14. #pragma alloc_text (PAGE, VdmFetchBop4)
  15. #pragma alloc_text (PAGE, VdmDispatchOpcodeV86_try)
  16. #pragma alloc_text (PAGE, VdmTibPass1)
  17. #pragma alloc_text (PAGE, VdmDispatchBop)
  18. #pragma alloc_text (PAGE, VdmFetchULONG)
  19. VOID
  20. NTFastDOSIO (
  21. PKTRAP_FRAME TrapFrame,
  22. ULONG IoType
  23. );
  24. ULONG
  25. VdmFetchBop4 (
  26. IN PVOID Pc
  27. )
  28. /*++
  29. Routine Description:
  30. This routine reads up to 4 bytes of bop instruction data
  31. Arguments:
  32. Pc - Program counter fetched from the faulting instruction's trap frame.
  33. Return Value:
  34. ULONG - Up to 4 bytes of instruction stream. Unfetchable bytes are zeroed.
  35. --*/
  36. {
  37. ULONG Value;
  38. ULONG i;
  39. BOOLEAN DidProbe;
  40. DidProbe = FALSE;
  41. try {
  42. ProbeForReadSmallStructure (Pc, sizeof (UCHAR), sizeof (UCHAR));
  43. DidProbe = TRUE;
  44. return *(PULONG)Pc;
  45. } except (EXCEPTION_EXECUTE_HANDLER) {
  46. if (DidProbe == FALSE) {
  47. return 0;
  48. }
  49. }
  50. Value = 0;
  51. try {
  52. for (i = 0; i < sizeof (ULONG); i++) {
  53. Value += (((PUCHAR)Pc)[i])<<(i*8);
  54. }
  55. } except (EXCEPTION_EXECUTE_HANDLER) {
  56. }
  57. return Value;
  58. }
  59. ULONG
  60. VdmFetchULONG (
  61. IN PVOID Pc
  62. )
  63. /*++
  64. Routine Description:
  65. This routine reads 4 bytes from the user address space
  66. Arguments:
  67. Pc - Program counter fetched from the faulting instruction's trap frame.
  68. Return Value:
  69. ULONG - 4 bytes of user mode data
  70. --*/
  71. {
  72. try {
  73. ProbeForReadSmallStructure (Pc, sizeof (ULONG), sizeof (UCHAR));
  74. return *(PULONG)Pc;
  75. } except (EXCEPTION_EXECUTE_HANDLER) {
  76. return 0;
  77. }
  78. }
  79. ULONG
  80. VdmFetchBop1 (
  81. IN PVOID Pc
  82. )
  83. /*++
  84. Routine Description:
  85. This routine reads a single byte of bop instruction data.
  86. Arguments:
  87. Pc - Program counter fetched from the faulting instruction's trap frame
  88. Return Value:
  89. ULONG - 1 byte of instruction stream or zero if unreadable
  90. --*/
  91. {
  92. try {
  93. ProbeForReadSmallStructure (Pc, sizeof (UCHAR), sizeof (UCHAR));
  94. return *(PUCHAR)Pc;
  95. } except (EXCEPTION_EXECUTE_HANDLER) {
  96. return 0;
  97. }
  98. }
  99. ULONG
  100. VdmDispatchOpcodeV86_try (
  101. IN PKTRAP_FRAME TrapFrame
  102. )
  103. /*++
  104. Routine Description:
  105. This routine is just a shell around trap.asm code to handle faulting
  106. instruction stream references. This routines is called at APC_LEVEL
  107. to prevent NtSetContextThread from changing the EIP after its been probed
  108. earlier.
  109. Arguments:
  110. Pc - Program counter fetched from the faulting instructions trap frame
  111. Return Value:
  112. ULONG - 1 byte of instruction stream or zero if unreadable
  113. --*/
  114. {
  115. try {
  116. return Ki386DispatchOpcodeV86 (TrapFrame);
  117. } except (EXCEPTION_EXECUTE_HANDLER) {
  118. return 0;
  119. }
  120. }
  121. PVOID
  122. VdmTibPass1 (
  123. IN ULONG Cs,
  124. IN ULONG Eip,
  125. IN ULONG Ebx
  126. )
  127. {
  128. PVDM_TIB VdmTib;
  129. //
  130. // Copy the specified registers to the VDM Tib communication area,
  131. // using proper probing and exception handling.
  132. //
  133. try {
  134. VdmTib = NtCurrentTeb()->Vdm;
  135. ProbeForWrite (VdmTib, sizeof(VDM_TIB), sizeof(UCHAR));
  136. VdmTib->VdmContext.Ebx = Ebx;
  137. VdmTib->VdmContext.Eip = Eip;
  138. VdmTib->VdmContext.SegCs = Cs;
  139. } except (EXCEPTION_EXECUTE_HANDLER) {
  140. return NULL;
  141. }
  142. return VdmTib;
  143. }
  144. #define BOP_INSTRUCTION 0xC4C4
  145. #define SVC_DEMFASTREAD 0x42
  146. #define SVC_DEMFASTWRITE 0x43
  147. #define DOS_BOP 0x50
  148. extern ULONG VdmBopCount;
  149. LOGICAL
  150. VdmDispatchBop (
  151. IN PKTRAP_FRAME TrapFrame
  152. )
  153. /*++
  154. Routine Description:
  155. This routine attempts to decode and execute the user instruction. If
  156. this cannot be done, FALSE is returned and the ntvdm monitor must handle
  157. it.
  158. Arguments:
  159. TrapFrame - Supplies a pointer to register trapframe.
  160. Return Value:
  161. TRUE if the opcode was handled here.
  162. FALSE if not (ie: the caller must reflect this instruction to ntvdm
  163. to handle on behalf of the 16-bit app).
  164. Environment:
  165. Kernel mode, APC_LEVEL.
  166. --*/
  167. {
  168. LOGICAL RetVal;
  169. BOOLEAN GotSelector;
  170. PVDM_TIB VdmTib;
  171. ULONG SegCs;
  172. ULONG LinearEIP;
  173. ULONG Flags;
  174. ULONG Base;
  175. ULONG Limit;
  176. ULONG IoType;
  177. LOGICAL DoFastIo;
  178. if (TrapFrame->EFlags & EFLAGS_V86_MASK) {
  179. SegCs = TrapFrame->SegCs & 0xFFFF;
  180. LinearEIP = (SegCs << 4) + (TrapFrame->Eip & 0xffff);
  181. }
  182. else {
  183. GotSelector = Ki386GetSelectorParameters ((USHORT) TrapFrame->SegCs,
  184. &Flags,
  185. &Base,
  186. &Limit);
  187. if (GotSelector == FALSE) {
  188. return TRUE;
  189. }
  190. LinearEIP = Base + TrapFrame->Eip;
  191. }
  192. DoFastIo = FALSE;
  193. RetVal = TRUE;
  194. try {
  195. ProbeForReadSmallStructure (LinearEIP, sizeof (UCHAR), sizeof (UCHAR));
  196. if (*(PUSHORT)LinearEIP != BOP_INSTRUCTION) {
  197. RetVal = FALSE;
  198. leave;
  199. }
  200. //
  201. // Check the BOP number.
  202. //
  203. if (*(PUCHAR)(LinearEIP + 2) == DOS_BOP) {
  204. if ((*(PUCHAR)(LinearEIP + 3) == SVC_DEMFASTREAD) ||
  205. (*(PUCHAR)(LinearEIP + 3) == SVC_DEMFASTWRITE)) {
  206. //
  207. // Take the fast I/O path.
  208. //
  209. IoType = (ULONG)(*(PUCHAR)(LinearEIP + 3));
  210. DoFastIo = TRUE;
  211. leave;
  212. }
  213. }
  214. VdmBopCount += 1;
  215. VdmTib = NtCurrentTeb()->Vdm;
  216. ProbeForWrite (VdmTib, sizeof(VDM_TIB), sizeof(UCHAR));
  217. VdmTib->EventInfo.Event = VdmBop;
  218. VdmTib->EventInfo.BopNumber = *(PUCHAR)(LinearEIP + 2);
  219. VdmTib->EventInfo.InstructionSize = 3;
  220. VdmEndExecution (TrapFrame, VdmTib);
  221. } except (EXCEPTION_EXECUTE_HANDLER) {
  222. RetVal = FALSE;
  223. NOTHING; // Fall through
  224. }
  225. if (DoFastIo) {
  226. NTFastDOSIO (TrapFrame, IoType);
  227. }
  228. return RetVal;
  229. }