ReactOS  r75907
v86vdm.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: ntoskrnl/ke/i386/v86vdm.c
5  * PURPOSE: V8086 and VDM Trap Emulation
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  * Alex Ionescu (alex.ionescu@reactos.org)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 #define KiVdmGetInstructionSize(x) ((x) & 0xFF)
17 #define KiVdmGetPrefixFlags(x) ((x) & 0xFFFFFF00)
18 
19 /* GLOBALS ********************************************************************/
20 
26 
27 /* UNHANDLED OPCODES **********************************************************/
28 
35 KiVdmUnhandledOpcode(INBimm);
36 KiVdmUnhandledOpcode(INWimm);
37 KiVdmUnhandledOpcode(OUTBimm);
38 KiVdmUnhandledOpcode(OUTWimm);
46 
47 /* OPCODE HANDLERS ************************************************************/
48 
49 BOOLEAN
52  IN ULONG Flags)
53 {
54  ULONG Esp, V86EFlags, TrapEFlags;
55 
56  /* Get current V8086 flags and mask out interrupt flag */
57  V86EFlags = *KiNtVdmState;
58  V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
59 
60  /* Get trap frame EFLags */
61  TrapEFlags = TrapFrame->EFlags;
62  /* Check for VME support */
64  {
65  /* Copy the virtual interrupt flag to the interrupt flag */
66  TrapEFlags &= ~EFLAGS_INTERRUPT_MASK;
67  if(TrapEFlags & EFLAGS_VIF)
68  TrapEFlags |= EFLAGS_INTERRUPT_MASK;
69  }
70  /* Leave only align, nested task and interrupt */
72 
73  /* Add in those flags if they exist, and add in the IOPL flag */
74  V86EFlags |= TrapEFlags;
75  V86EFlags |= EFLAGS_IOPL;
76 
77  /* Build flat ESP */
78  Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
79 
80  /* Check for OPER32 */
82  {
83  /* Save EFlags */
84  Esp -= 4;
85  *(PULONG)Esp = V86EFlags;
86  }
87  else
88  {
89  /* Save EFLags */
90  Esp -= 2;
91  *(PUSHORT)Esp = (USHORT)V86EFlags;
92  }
93 
94  /* Set new ESP and EIP */
95  TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
96  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
97 
98  /* We're done */
99  return TRUE;
100 }
101 
102 BOOLEAN
103 FASTCALL
105  IN ULONG Flags)
106 {
107  ULONG Esp, V86EFlags, EFlags, TrapEFlags;
108 
109  /* Build flat ESP */
110  Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
111 
112  /* Check for OPER32 */
114  {
115  /* Read EFlags */
116  EFlags = *(PULONG)Esp;
117  Esp += 4;
118  }
119  else
120  {
121  /* Read EFlags */
122  EFlags = *(PUSHORT)Esp;
123  Esp += 2;
124  }
125 
126  /* Set new ESP */
127  TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
128 
129  /* Mask out IOPL from the flags */
130  EFlags &= ~EFLAGS_IOPL;
131 
132  /* Save the V86 flags, but mask out the nested task flag */
133  V86EFlags = EFlags & ~EFLAGS_NESTED_TASK;
134 
135  /* Now leave only alignment, nested task and interrupt flag */
137 
138  /* Get trap EFlags */
139  TrapEFlags = TrapFrame->EFlags;
140 
141  /* Check for VME support */
143  {
144  /* Copy the IF flag into the VIF one */
145  V86EFlags &= ~EFLAGS_VIF;
146  if(V86EFlags & EFLAGS_INTERRUPT_MASK)
147  {
148  V86EFlags |= EFLAGS_VIF;
149  /* Don't set the interrupt flag */
150  V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
151  }
152  }
153 
154  /* Add V86 flag */
155  V86EFlags |= EFLAGS_V86_MASK;
156 
157  /* Update EFlags in trap frame */
158  TrapFrame->EFlags |= V86EFlags;
159 
160  /* Check if ESP0 needs to be fixed up */
161  if (TrapEFlags & EFLAGS_V86_MASK) Ki386AdjustEsp0(TrapFrame);
162 
163  /* Update the V8086 EFlags state */
165  KiVdmSetVdmEFlags(EFlags);
166 
167  /* FIXME: Check for VDM interrupts */
168 
169  /* Update EIP */
170  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
171 
172  /* We're done */
173  return TRUE;
174 }
175 
176 BOOLEAN
177 FASTCALL
179  IN ULONG Flags)
180 {
181  ULONG Esp, V86EFlags, TrapEFlags, Eip, Interrupt;
182 
183  /* Read trap frame EFlags */
184  TrapEFlags = TrapFrame->EFlags;
185 
186  /* Remove interrupt flag from V8086 EFlags */
187  V86EFlags = *KiNtVdmState;
189 
190  /* Keep only alignment and interrupt flag from the V8086 state */
191  V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_INTERRUPT_MASK);
192 
193  /* Check for VME support */
195 
196  /* Mask in the relevant V86 EFlags into the trap flags */
197  V86EFlags |= (TrapEFlags & ~EFLAGS_INTERRUPT_MASK);
198 
199  /* And mask out the VIF, nested task and TF flag from the trap flags */
200  TrapFrame->EFlags = TrapEFlags &~ (EFLAGS_VIF | EFLAGS_NESTED_TASK | EFLAGS_TF);
201 
202  /* Add the IOPL flag to the local trap flags */
203  V86EFlags |= EFLAGS_IOPL;
204 
205  /* Build flat ESP */
206  Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp;
207 
208  /* Push EFlags */
209  Esp -= 2;
210  *(PUSHORT)(Esp) = (USHORT)V86EFlags;
211 
212  /* Push CS */
213  Esp -= 2;
214  *(PUSHORT)(Esp) = (USHORT)TrapFrame->SegCs;
215 
216  /* Push IP */
217  Esp -= 2;
218  *(PUSHORT)(Esp) = (USHORT)TrapFrame->Eip + KiVdmGetInstructionSize(Flags) + 1;
219 
220  /* Update ESP */
221  TrapFrame->HardwareEsp = (USHORT)Esp;
222 
223  /* Get flat EIP */
224  Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
225 
226  /* Now get the *next* EIP address (current is original + the count - 1) */
227  Eip += KiVdmGetInstructionSize(Flags);
228 
229  /* Now read the interrupt number */
230  Interrupt = *(PUCHAR)Eip;
231 
232  /* Read the EIP from its IVT entry */
233  Interrupt = *(PULONG)(Interrupt * 4);
234  TrapFrame->Eip = (USHORT)Interrupt;
235 
236  /* Now get the CS segment */
237  Interrupt = (USHORT)(Interrupt >> 16);
238 
239  /* Check if the trap was not V8086 trap */
240  if (!(TrapFrame->EFlags & EFLAGS_V86_MASK))
241  {
242  /* Was it a kernel CS? */
243  Interrupt |= RPL_MASK;
244  if (TrapFrame->SegCs == KGDT_R0_CODE)
245  {
246  /* Add the RPL mask */
247  TrapFrame->SegCs = Interrupt;
248  }
249  else
250  {
251  /* Set user CS */
252  TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
253  }
254  }
255  else
256  {
257  /* Set IVT CS */
258  TrapFrame->SegCs = Interrupt;
259  }
260 
261  /* We're done */
262  return TRUE;
263 }
264 
265 BOOLEAN
266 FASTCALL
268  IN ULONG Flags)
269 {
270  ULONG Esp, V86EFlags, EFlags, TrapEFlags, Eip;
271 
272  /* Build flat ESP */
273  Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp;
274 
275  /* Check for OPER32 */
277  {
278  /* Build segmented EIP */
279  TrapFrame->Eip = *(PULONG)Esp;
280  TrapFrame->SegCs = *(PUSHORT)(Esp + 4);
281 
282  /* Set new ESP */
283  TrapFrame->HardwareEsp += 12;
284 
285  /* Get EFLAGS */
286  EFlags = *(PULONG)(Esp + 8);
287  }
288  else
289  {
290  /* Build segmented EIP */
291  TrapFrame->Eip = *(PUSHORT)Esp;
292  TrapFrame->SegCs = *(PUSHORT)(Esp + 2);
293 
294  /* Set new ESP */
295  TrapFrame->HardwareEsp += 6;
296 
297  /* Get EFLAGS */
298  EFlags = *(PUSHORT)(Esp + 4);
299  }
300 
301  /* Mask out EFlags */
303  V86EFlags = EFlags;
304 
305  /* Check for VME support */
307 
308  /* Add V86 and Interrupt flag */
310 
311  /* Update EFlags in trap frame */
312  TrapEFlags = TrapFrame->EFlags;
313  TrapFrame->EFlags = (TrapFrame->EFlags & EFLAGS_VIP) | EFlags;
314 
315  /* Check if ESP0 needs to be fixed up */
316  if (!(TrapEFlags & EFLAGS_V86_MASK)) Ki386AdjustEsp0(TrapFrame);
317 
318  /* Update the V8086 EFlags state */
320  KiVdmSetVdmEFlags(V86EFlags);
321 
322  /* Build flat EIP and check if this is the BOP instruction */
323  Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
324  if (*(PUSHORT)Eip == 0xC4C4)
325  {
326  /* Dispatch the BOP */
327  VdmDispatchBop(TrapFrame);
328  }
329  else
330  {
331  /* FIXME: Check for VDM interrupts */
332  DPRINT("FIXME: Check for VDM interrupts\n");
333  }
334 
335  /* We're done */
336  return TRUE;
337 }
338 
339 BOOLEAN
340 FASTCALL
342  IN ULONG Flags)
343 {
344  /* Check for VME support */
346 
347  /* Disable interrupts */
349 
350  /* Skip instruction */
351  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
352 
353  /* Done */
354  return TRUE;
355 }
356 
357 BOOLEAN
358 FASTCALL
360  IN ULONG Flags)
361 {
362  /* Check for VME support */
364 
365  /* Enable interrupts */
367 
368  /* Skip instruction */
369  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
370 
371  /* Done */
372  return TRUE;
373 }
374 
375 /* MASTER OPCODE HANDLER ******************************************************/
376 
377 BOOLEAN
378 FASTCALL
380  IN ULONG Flags)
381 {
382  ULONG Eip;
383 
384  /* Get flat EIP of the *current* instruction (not the original EIP) */
385  Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
386  Eip += KiVdmGetInstructionSize(Flags) - 1;
387 
388  /* Read the opcode entry */
389  switch (*(PUCHAR)Eip)
390  {
391  case 0xF: return KiCallVdmHandler(F);
392  case 0x26: return KiCallVdmPrefixHandler(PFX_FLAG_ES);
393  case 0x2E: return KiCallVdmPrefixHandler(PFX_FLAG_CS);
394  case 0x36: return KiCallVdmPrefixHandler(PFX_FLAG_SS);
395  case 0x3E: return KiCallVdmPrefixHandler(PFX_FLAG_DS);
396  case 0x64: return KiCallVdmPrefixHandler(PFX_FLAG_FS);
397  case 0x65: return KiCallVdmPrefixHandler(PFX_FLAG_GS);
398  case 0x66: return KiCallVdmPrefixHandler(PFX_FLAG_OPER32);
399  case 0x67: return KiCallVdmPrefixHandler(PFX_FLAG_ADDR32);
400  case 0xF0: return KiCallVdmPrefixHandler(PFX_FLAG_LOCK);
401  case 0xF2: return KiCallVdmPrefixHandler(PFX_FLAG_REPNE);
402  case 0xF3: return KiCallVdmPrefixHandler(PFX_FLAG_REP);
403  case 0x6C: return KiCallVdmHandler(INSB);
404  case 0x6D: return KiCallVdmHandler(INSW);
405  case 0x6E: return KiCallVdmHandler(OUTSB);
406  case 0x6F: return KiCallVdmHandler(OUTSW);
407  case 0x98: return KiCallVdmHandler(NPX);
408  case 0xD8: return KiCallVdmHandler(NPX);
409  case 0xD9: return KiCallVdmHandler(NPX);
410  case 0xDA: return KiCallVdmHandler(NPX);
411  case 0xDB: return KiCallVdmHandler(NPX);
412  case 0xDC: return KiCallVdmHandler(NPX);
413  case 0xDD: return KiCallVdmHandler(NPX);
414  case 0xDE: return KiCallVdmHandler(NPX);
415  case 0xDF: return KiCallVdmHandler(NPX);
416  case 0x9C: return KiCallVdmHandler(PUSHF);
417  case 0x9D: return KiCallVdmHandler(POPF);
418  case 0xCD: return KiCallVdmHandler(INTnn);
419  case 0xCE: return KiCallVdmHandler(INTO);
420  case 0xCF: return KiCallVdmHandler(IRET);
421  case 0xE4: return KiCallVdmHandler(INBimm);
422  case 0xE5: return KiCallVdmHandler(INWimm);
423  case 0xE6: return KiCallVdmHandler(OUTBimm);
424  case 0xE7: return KiCallVdmHandler(OUTWimm);
425  case 0xEC: return KiCallVdmHandler(INB);
426  case 0xED: return KiCallVdmHandler(INW);
427  case 0xEE: return KiCallVdmHandler(OUTB);
428  case 0xEF: return KiCallVdmHandler(OUTW);
429  case 0xF4: return KiCallVdmHandler(HLT);
430  case 0xFA: return KiCallVdmHandler(CLI);
431  case 0xFB: return KiCallVdmHandler(STI);
432  default: return KiCallVdmHandler(INV);
433  }
434 }
435 
436 /* PREFIX HANDLER *************************************************************/
437 
438 BOOLEAN
439 FASTCALL
441  IN ULONG Flags)
442 {
443  /* Increase instruction size */
444  Flags++;
445 
446  /* Handle the next opcode */
447  return KiVdmHandleOpcode(TrapFrame, Flags);
448 }
449 
450 /* TRAP HANDLER ***************************************************************/
451 
452 BOOLEAN
453 FASTCALL
455 {
456  /* Clean up */
457  TrapFrame->Eip &= 0xFFFF;
458  TrapFrame->HardwareEsp &= 0xFFFF;
459 
460  /* We start with only 1 byte per instruction */
461  return KiVdmHandleOpcode(TrapFrame, 1);
462 }
463 
464 ULONG_PTR
465 FASTCALL
467 {
468  ULONG_PTR StackFrameUnaligned;
469  PKV8086_STACK_FRAME StackFrame;
471  PKTRAP_FRAME PmTrapFrame;
472  PKV86_FRAME V86Frame;
473  PFX_SAVE_AREA NpxFrame;
474 
475  /* Get the stack frame back */
476  StackFrameUnaligned = TrapFrame->Esi;
477  StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4);
478  PmTrapFrame = &StackFrame->TrapFrame;
479  V86Frame = &StackFrame->V86Frame;
480  NpxFrame = &StackFrame->NpxArea;
481  ASSERT((ULONG_PTR)NpxFrame % 16 == 0);
482 
483  /* Copy the FPU frame back */
484  Thread = KeGetCurrentThread();
485  RtlCopyMemory(KiGetThreadNpxArea(Thread), NpxFrame, sizeof(FX_SAVE_AREA));
486 
487  /* Set initial stack back */
488  Thread->InitialStack = (PVOID)((ULONG_PTR)V86Frame->ThreadStack + sizeof(FX_SAVE_AREA));
489 
490  /* Set ESP0 back in the KTSS */
491  KeGetPcr()->TSS->Esp0 = (ULONG_PTR)&PmTrapFrame->V86Es;
492 
493  /* Restore TEB addresses */
494  Thread->Teb = V86Frame->ThreadTeb;
495  KiSetTebBase(KeGetPcr(), V86Frame->ThreadTeb);
496 
497  /* Enable interrupts and return a pointer to the trap frame */
498  _enable();
499  return StackFrameUnaligned;
500 }
501 
502 VOID
503 FASTCALL
504 KiEnterV86Mode(IN ULONG_PTR StackFrameUnaligned)
505 {
507  PKV8086_STACK_FRAME StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4);
508  PKTRAP_FRAME TrapFrame = &StackFrame->TrapFrame;
509  PKV86_FRAME V86Frame = &StackFrame->V86Frame;
510  PFX_SAVE_AREA NpxFrame = &StackFrame->NpxArea;
511 
512  ASSERT((ULONG_PTR)NpxFrame % 16 == 0);
513 
514  /* Build fake user-mode trap frame */
515  TrapFrame->SegCs = KGDT_R0_CODE | RPL_MASK;
516  TrapFrame->SegEs = TrapFrame->SegDs = TrapFrame->SegFs = TrapFrame->SegGs = 0;
517  TrapFrame->ErrCode = 0;
518 
519  /* Get the current thread's initial stack */
520  Thread = KeGetCurrentThread();
521  V86Frame->ThreadStack = KiGetThreadNpxArea(Thread);
522 
523  /* Save TEB addresses */
524  V86Frame->ThreadTeb = Thread->Teb;
525  V86Frame->PcrTeb = KeGetPcr()->NtTib.Self;
526 
527  /* Save return EIP */
529 
530  /* Save our stack (after the frames) */
531  TrapFrame->Esi = StackFrameUnaligned;
532  TrapFrame->Edi = (ULONG_PTR)_AddressOfReturnAddress() + 4;
533 
534  /* Sanitize EFlags and enable interrupts */
535  TrapFrame->EFlags = __readeflags() & 0x60DD7;
536  TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
537 
538  /* Fill out the rest of the frame */
539  TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
540  TrapFrame->HardwareEsp = 0x11FFE;
541  TrapFrame->ExceptionList = EXCEPTION_CHAIN_END;
542  TrapFrame->Dr7 = 0;
543 
544  /* Set some debug fields if trap debugging is enabled */
545  KiFillTrapFrameDebug(TrapFrame);
546 
547  /* Disable interrupts */
548  _disable();
549 
550  /* Copy the thread's NPX frame */
551  RtlCopyMemory(NpxFrame, V86Frame->ThreadStack, sizeof(FX_SAVE_AREA));
552 
553  /* Clear exception list */
554  KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
555 
556  /* Set new ESP0 */
557  KeGetPcr()->TSS->Esp0 = (ULONG_PTR)&TrapFrame->V86Es;
558 
559  /* Set new initial stack */
560  Thread->InitialStack = V86Frame;
561 
562  /* Set VDM TEB */
563  Thread->Teb = (PTEB)TRAMPOLINE_TEB;
565 
566  /* Enable interrupts */
567  _enable();
568 
569  /* Start VDM execution */
571 
572  /* Exit to V86 mode */
573  KiEoiHelper(TrapFrame);
574 }
575 
576 VOID
577 NTAPI
579 {
580 
582  PKPROCESS Process = Thread->ApcState.Process;
583  PKTRAP_FRAME TrapFrame;
585 
586  /* IOPL was enabled for this process/thread */
587  Process->Iopl = TRUE;
588  Thread->Iopl = TRUE;
589 
590  /* Get the trap frame on exit */
591  TrapFrame = KeGetTrapFrame(Thread);
592 
593  /* Convert to a context */
594  Context.ContextFlags = CONTEXT_CONTROL;
595  KeTrapFrameToContext(TrapFrame, NULL, &Context);
596 
597  /* Set the IOPL flag */
598  Context.EFlags |= EFLAGS_IOPL;
599 
600  /* Convert back to a trap frame */
601  KeContextToTrapFrame(&Context, NULL, TrapFrame, CONTEXT_CONTROL, UserMode);
602 }
603 
604 /* PUBLIC FUNCTIONS ***********************************************************/
605 
606 /*
607  * @implemented
608  */
609 NTSTATUS
610 NTAPI
613 {
614  PUCHAR Trampoline = (PUCHAR)TRAMPOLINE_BASE;
615  PTEB VdmTeb = (PTEB)TRAMPOLINE_TEB;
616  PVDM_TIB VdmTib = (PVDM_TIB)TRAMPOLINE_TIB;
617  ULONG ContextSize = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
619  PKTSS Tss = KeGetPcr()->TSS;
620  PKPROCESS Process = Thread->ApcState.Process;
621  PVDM_PROCESS_OBJECTS VdmProcessObjects;
622  USHORT OldOffset, OldBase;
623 
624  /* Start with a clean TEB */
625  RtlZeroMemory(VdmTeb, sizeof(TEB));
626 
627  /* Write the interrupt and bop */
628  *Trampoline++ = 0xCD;
629  *Trampoline++ = (UCHAR)Int;
630  *(PULONG)Trampoline = TRAMPOLINE_BOP;
631 
632  /* Setup the VDM TEB and TIB */
633  VdmTeb->Vdm = (PVOID)TRAMPOLINE_TIB;
634  RtlZeroMemory(VdmTib, sizeof(VDM_TIB));
635  VdmTib->Size = sizeof(VDM_TIB);
636 
637  /* Set a blank VDM state */
638  *VdmState = 0;
639 
640  /* Copy the context */
641  RtlCopyMemory(&VdmTib->VdmContext, Context, ContextSize);
642  VdmTib->VdmContext.SegCs = (ULONG_PTR)Trampoline >> 4;
643  VdmTib->VdmContext.SegSs = (ULONG_PTR)Trampoline >> 4;
644  VdmTib->VdmContext.Eip = 0;
645  VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG_PTR);
648 
649  /* This can't be a real VDM process */
650  ASSERT(PsGetCurrentProcess()->VdmObjects == NULL);
651 
652  /* Allocate VDM structure */
653  VdmProcessObjects = ExAllocatePoolWithTag(NonPagedPool,
654  sizeof(VDM_PROCESS_OBJECTS),
655  ' eK');
656  if (!VdmProcessObjects) return STATUS_NO_MEMORY;
657 
658  /* Set it up */
659  RtlZeroMemory(VdmProcessObjects, sizeof(VDM_PROCESS_OBJECTS));
660  VdmProcessObjects->VdmTib = VdmTib;
661  PsGetCurrentProcess()->VdmObjects = VdmProcessObjects;
662 
663  /* Set the system affinity for the current thread */
665 
666  /* Make sure there's space for two IOPMs, then copy & clear the current */
667  ASSERT(((PKIPCR)KeGetPcr())->GDT[KGDT_TSS / 8].LimitLow >=
668  (0x2000 + IOPM_OFFSET - 1));
670  RtlZeroMemory(&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2);
671 
672  /* Save the old offset and base, and set the new ones */
673  OldOffset = Process->IopmOffset;
674  OldBase = Tss->IoMapBase;
675  Process->IopmOffset = (USHORT)IOPM_OFFSET;
676  Tss->IoMapBase = (USHORT)IOPM_OFFSET;
677 
678  /* Switch stacks and work the magic */
680 
681  /* Restore IOPM */
683  Process->IopmOffset = OldOffset;
684  Tss->IoMapBase = OldBase;
685 
686  /* Restore affinity */
688 
689  /* Restore context */
690  RtlCopyMemory(Context, &VdmTib->VdmContext, ContextSize);
691  Context->ContextFlags = CONTEXT_FULL;
692 
693  /* Free VDM objects */
694  ExFreePoolWithTag(PsGetCurrentProcess()->VdmObjects, ' eK');
695  PsGetCurrentProcess()->VdmObjects = NULL;
696 
697  /* Return status */
698  return STATUS_SUCCESS;
699 }
700 
701 /*
702  * @implemented
703  */
704 BOOLEAN
705 NTAPI
707  IN ULONG MapNumber)
708 {
709  USHORT MapOffset;
710  PKPRCB Prcb;
711  KAFFINITY TargetProcessors;
712 
713  if(MapNumber > IOPM_COUNT)
714  return FALSE;
715 
716  MapOffset = KiComputeIopmOffset(MapNumber);
717 
718  Process->IopmOffset = MapOffset;
719 
720  TargetProcessors = Process->ActiveProcessors;
721  Prcb = KeGetCurrentPrcb();
722  if (TargetProcessors & Prcb->SetMember)
723  KeGetPcr()->TSS->IoMapBase = MapOffset;
724 
725  return TRUE;
726 }
727 
728 /*
729  * @implemented
730  */
731 BOOLEAN
732 NTAPI
734  IN PKIO_ACCESS_MAP IopmBuffer)
735 {
737  PKPRCB Prcb;
738  PVOID pt;
739 
740  if ((MapNumber > IOPM_COUNT) || (MapNumber == IO_ACCESS_MAP_NONE))
741  return FALSE;
742 
743  Prcb = KeGetCurrentPrcb();
744 
745  // Copy the IOP map and load the map for the current process.
746  pt = &(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
747  RtlMoveMemory(pt, (PVOID)IopmBuffer, IOPM_SIZE);
748  CurrentProcess = Prcb->CurrentThread->ApcState.Process;
749  KeGetPcr()->TSS->IoMapBase = CurrentProcess->IopmOffset;
750 
751  return TRUE;
752 }
753 
754 /*
755  * @implemented
756  */
757 BOOLEAN
758 NTAPI
760  IN PKIO_ACCESS_MAP IopmBuffer)
761 {
762  ULONG i;
763  PVOID Map;
764  PUCHAR p;
765 
766  if (MapNumber > IOPM_COUNT)
767  return FALSE;
768 
769  if (MapNumber == IO_ACCESS_MAP_NONE)
770  {
771  // no access, simply return a map of all 1s
772  p = (PUCHAR)IopmBuffer;
773  for (i = 0; i < IOPM_SIZE; i++) {
774  p[i] = (UCHAR)-1;
775  }
776  }
777  else
778  {
779  // copy the bits
780  Map = (PVOID)&(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
781  RtlMoveMemory((PVOID)IopmBuffer, Map, IOPM_SIZE);
782  }
783 
784  return TRUE;
785 }
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
DWORD *typedef PVOID
Definition: winlogon.h:52
NTSTATUS NTAPI NtVdmControl(IN ULONG ControlCode, IN PVOID ControlData)
Definition: stubs.c:432
#define KiCallVdmPrefixHandler(x)
Definition: ke.h:132
KV86_FRAME V86Frame
Definition: ke.h:163
#define IN
Definition: typedefs.h:39
#define EFLAGS_ALIGN_CHECK
Definition: ketypes.h:130
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: vdm.h:134
ULONG Esp
Definition: nt_native.h:1479
#define FIXED_NTVDMSTATE_LINEAR_PC_AT
Definition: asm.h:632
ULONG V86Es
Definition: ketypes.h:270
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define IOPM_SIZE
Definition: ketypes.h:177
#define KiCallVdmHandler(x)
Definition: ke.h:131
ULONG Eip
Definition: nt_native.h:1476
#define VdmState
Definition: vdm.h:48
FX_SAVE_AREA NpxArea
Definition: ke.h:162
#define PFX_FLAG_ADDR32
Definition: ke.h:102
#define TRAMPOLINE_TIB
Definition: vdm.h:37
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define pt(x, y)
Definition: drawing.c:79
struct _KV8086_STACK_FRAME * PKV8086_STACK_FRAME
return STATUS_SUCCESS
Definition: btrfs.c:2664
VOID NTAPI KeRevertToUserAffinityThread(VOID)
Definition: thrdobj.c:1030
unsigned char * PUCHAR
Definition: retypes.h:3
ULONG OldOffset
Definition: shell.c:90
CONTEXT VdmContext
Definition: vdm.h:140
USHORT IopmOffset
Definition: ketypes.h:1392
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID NTAPI Ke386SetIOPL(VOID)
Definition: v86vdm.c:578
BOOLEAN FASTCALL KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:104
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
USHORT SegFs
Definition: ketypes.h:366
VOID NTAPI Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame)
Definition: exp.c:280
void * _AddressOfReturnAddress(void)
#define KGDT_R0_CODE
Definition: ketypes.h:74
PVOID PcrTeb
Definition: ke.h:153
#define TRAMPOLINE_BASE
Definition: vdm.h:36
#define PFX_FLAG_DS
Definition: ke.h:98
#define KiVdmGetInstructionSize(x)
Definition: v86vdm.c:16
#define PFX_FLAG_REP
Definition: ke.h:105
ULONG HardwareSegSs
Definition: ketypes.h:269
VOID FASTCALL KiEnterV86Mode(IN ULONG_PTR StackFrameUnaligned)
Definition: v86vdm.c:504
#define PFX_FLAG_LOCK
Definition: ke.h:103
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T ContextSize
Definition: fltkernel.h:1444
#define CONTEXT_FULL
Definition: compat.h:270
ULONG Esi
Definition: ketypes.h:261
#define FASTCALL
Definition: nt_native.h:50
struct _TEB * Teb
Definition: ketypes.h:1057
#define CLI
Definition: assyntax.h:414
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
ULONG Size
Definition: vdm.h:136
#define KeGetPcr()
Definition: ke.h:25
ULONG Edi
Definition: ketypes.h:260
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
VOID NTAPI KeSetSystemAffinityThread(IN KAFFINITY Affinity)
Definition: thrdobj.c:1116
#define EFLAGS_V86_MASK
Definition: ketypes.h:129
PVDM_TIB VdmTib
Definition: vdm.h:165
#define INTO
Definition: assyntax.h:465
uint32_t ULONG_PTR
Definition: typedefs.h:64
BOOLEAN FASTCALL KiVdmOpcodeCLI(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:341
#define HLT
Definition: assyntax.h:434
#define EFLAGS_VIP
Definition: ketypes.h:132
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLenum GLclampf GLint i
Definition: glfuncs.h:14
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1456
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PVOID ThreadStack
Definition: ke.h:151
USHORT SegGs
Definition: ketypes.h:367
#define FALSE
Definition: types.h:117
#define PFX_FLAG_OPER32
Definition: ke.h:101
#define EFLAGS_NESTED_TASK
Definition: ketypes.h:128
KAPC_STATE ApcState
Definition: ketypes.h:969
#define EFLAGS_USER_SANITIZE
Definition: ketypes.h:133
USHORT SegEs
Definition: ketypes.h:365
#define PsGetCurrentProcess
Definition: psfuncs.h:17
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
#define RPL_MASK
Definition: ketypes.h:69
#define F(i)
Definition: internal.h:87
ULONG SegCs
Definition: nt_native.h:1477
#define PFX_FLAG_ES
Definition: ke.h:95
BOOLEAN NTAPI Ke386SetIoAccessMap(IN ULONG MapNumber, IN PKIO_ACCESS_MAP IopmBuffer)
Definition: v86vdm.c:733
smooth NULL
Definition: ftsmooth.c:513
BOOLEAN FASTCALL KiVdmOpcodeSTI(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:359
#define IRET
Definition: assyntax.h:466
#define KiVdmGetPrefixFlags(x)
Definition: v86vdm.c:17
USHORT SegCs
Definition: ketypes.h:380
BOOLEAN FASTCALL KiVdmOpcodePrefix(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:440
#define KiVdmClearVdmEFlags(x)
Definition: ke.h:130
Definition: ketypes.h:787
void DPRINT(...)
Definition: polytest.cpp:61
#define KGDT_R3_DATA
Definition: ketypes.h:77
ULONG EFlags
Definition: nt_native.h:1478
VOID NTAPI KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT Context)
Definition: context.c:146
KIO_ACCESS_MAP * PKIO_ACCESS_MAP
Definition: ketypes.h:189
#define PFX_FLAG_GS
Definition: ke.h:100
Definition: utils.h:160
ULONG ContextFlags
Definition: compat.h:331
FORCEINLINE PFX_SAVE_AREA KiGetThreadNpxArea(IN PKTHREAD Thread)
Definition: ke.h:582
#define STI
Definition: assyntax.h:663
struct _Vdm_Tib * PVDM_TIB
#define IO_ACCESS_MAP_NONE
Definition: ketypes.h:263
ULONG KeI386EFlagsOrMaskV86
Definition: v86vdm.c:22
ULONG KeI386EFlagsAndMaskV86
Definition: v86vdm.c:21
unsigned char BOOLEAN
#define CONTEXT_CONTROL
Definition: compat.h:265
ULONG CurrentProcess
Definition: shell.c:125
PVOID Ki386IopmSaveArea
Definition: v86vdm.c:23
const PULONG KiNtVdmState
Definition: v86vdm.c:25
struct _FX_SAVE_AREA FX_SAVE_AREA
#define KGDT_TSS
Definition: ketypes.h:78
if(!(yy_init))
Definition: macro.lex.yy.c:704
ULONG HardwareEsp
Definition: ketypes.h:268
unsigned short * PUSHORT
Definition: retypes.h:2
BOOLEAN FASTCALL KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:178
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define TRAMPOLINE_BOP
Definition: vdm.h:43
struct _EXCEPTION_REGISTRATION_RECORD FAR * ExceptionList
Definition: ketypes.h:258
#define PFX_FLAG_CS
Definition: ke.h:96
#define KiFillTrapFrameDebug(x)
Definition: trap_x.h:189
USHORT IoMapBase
Definition: ketypes.h:821
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define EFLAGS_VIF
Definition: ketypes.h:131
BOOLEAN KeI386VirtualIntExtensions
Definition: v86vdm.c:24
PVOID ThreadTeb
Definition: ke.h:152
unsigned char UCHAR
Definition: xmlstorage.h:181
#define EFLAGS_IOPL
Definition: cpu.c:17
VOID NTAPI Ki386SetupAndExitToV86Mode(OUT PTEB VdmTeb)
BOOLEAN FASTCALL KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:51
VOID FASTCALL Ki386BiosCallReturnAddress(IN PKTRAP_FRAME TrapFrame)
#define PFX_FLAG_REPNE
Definition: ke.h:104
#define PFX_FLAG_SS
Definition: ke.h:97
#define PAGE_SIZE
Definition: env_spec_w32.h:49
USHORT SegDs
Definition: ketypes.h:364
#define EFLAGS_TF
Definition: ketypes.h:125
#define IOPM_COUNT
Definition: ketypes.h:176
ULONG Eip
Definition: ketypes.h:265
UINT64 SetMember
Definition: ketypes.h:578
Definition: compat.h:484
#define TRAMPOLINE_TEB
Definition: vdm.h:38
BOOLEAN NTAPI Ke386QueryIoAccessMap(IN ULONG MapNumber, IN PKIO_ACCESS_MAP IopmBuffer)
Definition: v86vdm.c:759
BOOLEAN NTAPI Ke386IoSetAccessProcess(IN PKPROCESS Process, IN ULONG MapNumber)
Definition: v86vdm.c:706
#define IOPM_OFFSET
Definition: ketypes.h:264
NTSTATUS NTAPI Ke386CallBios(IN ULONG Int, OUT PCONTEXT Context)
Definition: v86vdm.c:611
LONG NTSTATUS
Definition: DriverTester.h:11
#define EXCEPTION_CHAIN_END
Definition: rtltypes.h:63
ULONG SegSs
Definition: nt_native.h:1480
unsigned short USHORT
Definition: pedump.c:61
#define PFX_FLAG_FS
Definition: ke.h:99
ULONG_PTR KAFFINITY
Definition: compat.h:75
#define KiComputeIopmOffset(MapNumber)
Definition: ketypes.h:265
BOOLEAN FASTCALL KiVdmHandleOpcode(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:379
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
struct _TEB * PTEB
BOOLEAN NTAPI VdmDispatchBop(IN PKTRAP_FRAME TrapFrame)
Definition: vdmexec.c:313
UCHAR IoMap[8196]
Definition: ketypes.h:903
BOOLEAN FASTCALL Ki386HandleOpcodeV86(IN PKTRAP_FRAME TrapFrame)
Definition: v86vdm.c:454
BOOLEAN FASTCALL KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:267
#define KiVdmSetVdmEFlags(x)
Definition: ke.h:129
#define KGDT_R3_CODE
Definition: ketypes.h:76
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define OUT
Definition: typedefs.h:40
void __cdecl _disable(void)
Definition: intrin_arm.h:365
struct tagContext Context
Definition: acpixf.h:1014
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE VOID KiSetTebBase(PKPCR Pcr, PVOID TebAddress)
Definition: ke.h:318
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
UINT64 Dr7
Definition: ketypes.h:347
GLfloat GLfloat p
Definition: glext.h:8902
#define KeGetCurrentThread
Definition: hal.h:44
PVOID InitialStack
Definition: ketypes.h:937
#define KeGetTrapFrame(Thread)
Definition: ke.h:121
ULONG ErrCode
Definition: ketypes.h:264
ULONG EFlags
Definition: ketypes.h:384
PVOID Vdm
Definition: compat.h:530
KIIO_ACCESS_MAP IoMaps[IOPM_COUNT]
Definition: ketypes.h:822
struct _Vdm_Tib VDM_TIB
KiVdmUnhandledOpcode(F)
int Int
Definition: definitions.h:37
KTRAP_FRAME TrapFrame
Definition: ke.h:161
#define EFLAGS_INTERRUPT_MASK
Definition: ketypes.h:126
ULONG_PTR FASTCALL KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
Definition: v86vdm.c:466