BOOLEAN FASTCALL KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags) { ULONG Esp, V86EFlags, EFlags, TrapEFlags; /* Build flat ESP */ Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp; /* Check for OPER32 */ if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32) { /* Read EFlags */ EFlags = *(PULONG)Esp; Esp += 4; } else { /* Read EFlags */ EFlags = *(PUSHORT)Esp; Esp += 2; } /* Set new ESP */ TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4); /* Mask out IOPL from the flags */ EFlags &= ~EFLAGS_IOPL; /* Save the V86 flags, but mask out the nested task flag */ V86EFlags = EFlags & ~EFLAGS_NESTED_TASK; /* Now leave only alignment, nested task and interrupt flag */ EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK); /* Get trap EFlags */ TrapEFlags = TrapFrame->EFlags; /* Check for VME support */ if(KeI386VirtualIntExtensions) { /* Copy the IF flag into the VIF one */ V86EFlags &= ~EFLAGS_VIF; if(V86EFlags & EFLAGS_INTERRUPT_MASK) { V86EFlags |= EFLAGS_VIF; /* Don't set the interrupt flag */ V86EFlags &= ~EFLAGS_INTERRUPT_MASK; } } /* Add V86 flag */ V86EFlags |= EFLAGS_V86_MASK; /* Update EFlags in trap frame */ TrapFrame->EFlags |= V86EFlags; /* Check if ESP0 needs to be fixed up */ if (TrapEFlags & EFLAGS_V86_MASK) Ki386AdjustEsp0(TrapFrame); /* Update the V8086 EFlags state */ KiVdmClearVdmEFlags(EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK); KiVdmSetVdmEFlags(EFlags); /* FIXME: Check for VDM interrupts */ /* Update EIP */ TrapFrame->Eip += KiVdmGetInstructionSize(Flags); /* We're done */ return TRUE; }
BOOLEAN FASTCALL KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags) { ULONG Esp, V86EFlags, EFlags, TrapEFlags, Eip; /* Build flat ESP */ Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp; /* Check for OPER32 */ if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32) { /* Build segmented EIP */ TrapFrame->Eip = *(PULONG)Esp; TrapFrame->SegCs = *(PUSHORT)(Esp + 4); /* Set new ESP */ TrapFrame->HardwareEsp += 12; /* Get EFLAGS */ EFlags = *(PULONG)(Esp + 8); } else { /* Build segmented EIP */ TrapFrame->Eip = *(PUSHORT)Esp; TrapFrame->SegCs = *(PUSHORT)(Esp + 2); /* Set new ESP */ TrapFrame->HardwareEsp += 6; /* Get EFLAGS */ EFlags = *(PUSHORT)(Esp + 4); } /* Mask out EFlags */ EFlags &= ~(EFLAGS_IOPL + EFLAGS_VIF + EFLAGS_NESTED_TASK + EFLAGS_VIP); V86EFlags = EFlags; /* Check for VME support */ ASSERT(KeI386VirtualIntExtensions == FALSE); /* Add V86 and Interrupt flag */ EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK; /* Update EFlags in trap frame */ TrapEFlags = TrapFrame->EFlags; TrapFrame->EFlags = (TrapFrame->EFlags & EFLAGS_VIP) | EFlags; /* Check if ESP0 needs to be fixed up */ if (!(TrapEFlags & EFLAGS_V86_MASK)) Ki386AdjustEsp0(TrapFrame); /* Update the V8086 EFlags state */ KiVdmClearVdmEFlags(EFLAGS_INTERRUPT_MASK); KiVdmSetVdmEFlags(V86EFlags); /* Build flat EIP and check if this is the BOP instruction */ Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip; if (*(PUSHORT)Eip == 0xC4C4) { /* Dispatch the BOP */ VdmDispatchBop(TrapFrame); } else { /* FIXME: Check for VDM interrupts */ DPRINT("FIXME: Check for VDM interrupts\n"); } /* We're done */ return TRUE; }
VOID NTAPI VdmSwapContext(IN PKTRAP_FRAME TrapFrame, IN PCONTEXT OutContext, IN PCONTEXT InContext) { ULONG EFlags, OldEFlags; /* Make sure that we're at APC_LEVEL and that this is a valid frame */ ASSERT(KeGetCurrentIrql() == APC_LEVEL); //ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00); /* Check if this is a V86 frame */ if (TrapFrame->EFlags & EFLAGS_V86_MASK) { /* Copy segment registers */ OutContext->SegGs = TrapFrame->V86Gs; OutContext->SegFs = TrapFrame->V86Fs; OutContext->SegEs = TrapFrame->V86Es; OutContext->SegDs = TrapFrame->V86Ds; } else if (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK)) { /* This was kernel mode, copy segment registers */ OutContext->SegGs = TrapFrame->SegGs; OutContext->SegFs = TrapFrame->SegFs; OutContext->SegEs = TrapFrame->SegEs; OutContext->SegDs = TrapFrame->SegDs; } /* Copy CS and SS */ OutContext->SegCs = TrapFrame->SegCs; OutContext->SegSs = TrapFrame->HardwareSegSs; /* Copy general purpose registers */ OutContext->Eax = TrapFrame->Eax; OutContext->Ebx = TrapFrame->Ebx; OutContext->Ecx = TrapFrame->Ecx; OutContext->Edx = TrapFrame->Edx; OutContext->Esi = TrapFrame->Esi; OutContext->Edi = TrapFrame->Edi; /* Copy stack and counter */ OutContext->Ebp = TrapFrame->Ebp; OutContext->Esp = TrapFrame->HardwareEsp; OutContext->Eip = TrapFrame->Eip; /* Finally the flags */ OutContext->EFlags = TrapFrame->EFlags; /* Now copy from the in frame to the trap frame */ TrapFrame->SegCs = InContext->SegCs; TrapFrame->HardwareSegSs = InContext->SegSs; /* Copy the general purpose registers */ TrapFrame->Eax = InContext->Eax; TrapFrame->Ebx = InContext->Ebx; TrapFrame->Ecx = InContext->Ecx; TrapFrame->Edx = InContext->Edx; TrapFrame->Esi = InContext->Esi; TrapFrame->Edi = InContext->Edi; /* Copy the stack and counter */ TrapFrame->Ebp = InContext->Ebp; TrapFrame->HardwareEsp = InContext->Esp; TrapFrame->Eip = InContext->Eip; /* Check if the context is from V86 */ EFlags = InContext->EFlags; if (EFlags & EFLAGS_V86_MASK) { /* Sanitize the flags for V86 */ EFlags &= KeI386EFlagsAndMaskV86; EFlags |= KeI386EFlagsOrMaskV86; } else { /* Add RPL_MASK to segments */ TrapFrame->SegCs |= RPL_MASK; TrapFrame->HardwareSegSs |= RPL_MASK; /* Check for bogus CS */ if (TrapFrame->SegCs < KGDT_R0_CODE) { /* Set user-mode */ TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; } /* Sanitize flags and add interrupt mask */ EFlags &= EFLAGS_USER_SANITIZE; EFlags |=EFLAGS_INTERRUPT_MASK; } /* Save the new eflags */ OldEFlags = TrapFrame->EFlags; TrapFrame->EFlags = EFlags; /* Check if we need to fixup ESP0 */ if ((OldEFlags ^ EFlags) & EFLAGS_V86_MASK) { /* Fix it up */ Ki386AdjustEsp0(TrapFrame); } /* Check if this is a V86 context */ if (InContext->EFlags & EFLAGS_V86_MASK) { /* Copy VDM segments */ TrapFrame->V86Gs = InContext->SegGs; TrapFrame->V86Fs = InContext->SegFs; TrapFrame->V86Es = InContext->SegEs; TrapFrame->V86Ds = InContext->SegDs; } else { /* Copy monitor segments */ TrapFrame->SegGs = InContext->SegGs; TrapFrame->SegFs = InContext->SegFs; TrapFrame->SegEs = InContext->SegEs; TrapFrame->SegDs = InContext->SegDs; } /* Clear the exception list and return */ TrapFrame->ExceptionList = EXCEPTION_CHAIN_END; }