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.

303 lines
7.6 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Startexec.c
  5. Abstract:
  6. This module contains routines for switching to and from application
  7. mode in a vdm
  8. Author:
  9. Dave Hastings (daveh) 24-Apr-1992
  10. Notes:
  11. This code started out in ke\i386\vdm.c
  12. Revision History:
  13. 23-Sep-1992 sudeepb Formed W_VDMEndExecution from VDMEndExecution
  14. for performance.
  15. 18-Dec-1992 sudeepb Tuned all the routines for performance
  16. 12-Oct-1993 Jonle , removed unneeded endexecution worker functions
  17. --*/
  18. #include "vdmp.h"
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, VdmpStartExecution)
  21. #pragma alloc_text(PAGE, VdmEndExecution)
  22. #endif
  23. NTSTATUS
  24. VdmpStartExecution(
  25. VOID
  26. )
  27. /*++
  28. Routine Description:
  29. This routine causes execution of dos application code to begin. The
  30. Dos application executes on the thread. The Vdms context is loaded
  31. from the VDM_TIB for the thread. The 32 bit context is stored into
  32. the MonitorContext. Execution in the VDM context will continue until
  33. an event occurs that the monitor needs to service. At that point,
  34. the information will be put into the VDM_TIB, and the call will
  35. return.
  36. Arguments:
  37. None.
  38. Return Value:
  39. TrapFrame->Eax for application mode, required for system sevices exit.
  40. --*/
  41. {
  42. PVDM_TIB VdmTib;
  43. PKTRAP_FRAME TrapFrame;
  44. PETHREAD Thread;
  45. KIRQL OldIrql;
  46. BOOLEAN IntsEnabled;
  47. NTSTATUS Status;
  48. CONTEXT VdmContext;
  49. PAGED_CODE();
  50. //
  51. // Form a pointer to the trap frame for the current thread
  52. //
  53. Thread = PsGetCurrentThread ();
  54. TrapFrame = VdmGetTrapFrame (&Thread->Tcb);
  55. //
  56. // Get the VdmTib
  57. //
  58. Status = VdmpGetVdmTib (&VdmTib);
  59. if (!NT_SUCCESS(Status)) {
  60. return STATUS_INVALID_SYSTEM_SERVICE;
  61. }
  62. KeRaiseIrql (APC_LEVEL, &OldIrql);
  63. try {
  64. //
  65. // Determine if interrupts are on or off
  66. //
  67. IntsEnabled = VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK
  68. ? TRUE : FALSE;
  69. //
  70. // Check for timer ints to dispatch, However if interrupts are disabled
  71. // or there are hardware ints pending we postpone dispatching the timer
  72. // interrupt until interrupts are enabled.
  73. //
  74. if ((*FIXED_NTVDMSTATE_LINEAR_PC_AT & VDM_INT_TIMER) &&
  75. IntsEnabled &&
  76. !(*FIXED_NTVDMSTATE_LINEAR_PC_AT & VDM_INT_HARDWARE)) {
  77. VdmTib->EventInfo.Event = VdmIntAck;
  78. VdmTib->EventInfo.InstructionSize = 0;
  79. VdmTib->EventInfo.IntAckInfo = 0;
  80. KeLowerIrql(OldIrql);
  81. return STATUS_SUCCESS;
  82. }
  83. //
  84. // Perform IF to VIF translation if the processor
  85. // supports IF virtualization
  86. //
  87. if (((KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) &&
  88. (VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK)) ||
  89. ((KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) &&
  90. !(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK))) {
  91. //
  92. // Translate IF to VIF
  93. //
  94. if (IntsEnabled) {
  95. VdmTib->VdmContext.EFlags |= EFLAGS_VIF;
  96. } else {
  97. VdmTib->VdmContext.EFlags &= ~EFLAGS_VIF;
  98. VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK;
  99. }
  100. if (*FIXED_NTVDMSTATE_LINEAR_PC_AT & VDM_INT_HARDWARE)
  101. VdmTib->VdmContext.EFlags |= EFLAGS_VIP;
  102. else
  103. VdmTib->VdmContext.EFlags &= ~EFLAGS_VIP;
  104. //
  105. // Else if we are not running in v86 mode, or not using IOPL in
  106. // v86 mode
  107. //
  108. } else if (!(KeI386VdmIoplAllowed) ||
  109. !(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK)) {
  110. //
  111. // Translate the real interrupt flag in the VdmContext to the
  112. // virtual interrupt flag in the VdmTib, and force real
  113. // interrupts enabled.
  114. //
  115. ASSERT(VDM_VIRTUAL_INTERRUPTS == EFLAGS_INTERRUPT_MASK);
  116. if (VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK) {
  117. InterlockedOr (FIXED_NTVDMSTATE_LINEAR_PC_AT, VDM_VIRTUAL_INTERRUPTS);
  118. } else {
  119. InterlockedAnd (FIXED_NTVDMSTATE_LINEAR_PC_AT, ~VDM_VIRTUAL_INTERRUPTS);
  120. }
  121. //
  122. // Insure that real interrupts are always enabled.
  123. //
  124. VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK;
  125. }
  126. //
  127. // Before working on a trap frame, make sure that it's our own structure
  128. //
  129. VdmContext = VdmTib->VdmContext;
  130. if (!(VdmContext.SegCs & FRAME_EDITED)) {
  131. //
  132. // We will crash in KiServiceExit
  133. //
  134. KeLowerIrql(OldIrql);
  135. return(STATUS_INVALID_SYSTEM_SERVICE);
  136. }
  137. //
  138. // Switch from MonitorContext to VdmContext
  139. //
  140. VdmSwapContexts (TrapFrame,
  141. &VdmTib->MonitorContext,
  142. &VdmContext);
  143. //
  144. // Check for pending interrupts
  145. //
  146. if (IntsEnabled && (*FIXED_NTVDMSTATE_LINEAR_PC_AT & VDM_INT_HARDWARE)) {
  147. VdmDispatchInterrupts(TrapFrame, VdmTib);
  148. }
  149. }
  150. except(EXCEPTION_EXECUTE_HANDLER) {
  151. KeLowerIrql (OldIrql);
  152. Status = GetExceptionCode();
  153. return Status;
  154. }
  155. KeLowerIrql(OldIrql);
  156. return (NTSTATUS) TrapFrame->Eax;
  157. }
  158. VOID
  159. VdmEndExecution(
  160. PKTRAP_FRAME TrapFrame,
  161. PVDM_TIB VdmTib
  162. )
  163. /*++
  164. Routine Description:
  165. This routine does the core work to end the execution
  166. Arguments:
  167. None
  168. Return Value:
  169. VOID, but exceptions can be thrown due to the user space accesses.
  170. --*/
  171. {
  172. PAGED_CODE();
  173. ASSERT((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
  174. (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK)) );
  175. //
  176. // The return value must be put into the Monitorcontext, and set,
  177. // since we are probably returning to user mode via EXIT_ALL, and
  178. // the volatile registers will be restored.
  179. //
  180. VdmTib->MonitorContext.Eax = STATUS_SUCCESS;
  181. //
  182. // Switch from MonitorContext to VdmContext
  183. //
  184. VdmSwapContexts(
  185. TrapFrame,
  186. &(VdmTib->VdmContext),
  187. &(VdmTib->MonitorContext)
  188. );
  189. //
  190. // Perform IF to VIF translation
  191. //
  192. //
  193. // If the processor supports IF virtualization
  194. //
  195. if (((KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) &&
  196. (VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK)) ||
  197. ((KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) &&
  198. !(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK))) {
  199. //
  200. // Translate VIF to IF
  201. //
  202. if (VdmTib->VdmContext.EFlags & EFLAGS_VIF) {
  203. VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK;
  204. } else {
  205. VdmTib->VdmContext.EFlags &= ~EFLAGS_INTERRUPT_MASK;
  206. }
  207. //
  208. // Turn off VIP and VIF to insure that nothing strange happens
  209. //
  210. TrapFrame->EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
  211. VdmTib->VdmContext.EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
  212. //
  213. // Else if we are not running in v86 mode, or not using IOPL in
  214. // v86 mode
  215. //
  216. } else if (!(KeI386VdmIoplAllowed) ||
  217. !(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK))
  218. {
  219. //
  220. // Translate the virtual interrupt flag from the VdmTib back to the
  221. // real interrupt flag in the VdmContext
  222. //
  223. VdmTib->VdmContext.EFlags =
  224. (VdmTib->VdmContext.EFlags & ~EFLAGS_INTERRUPT_MASK)
  225. | (*FIXED_NTVDMSTATE_LINEAR_PC_AT & VDM_VIRTUAL_INTERRUPTS);
  226. }
  227. return;
  228. }