BOOLEAN FASTCALL KiVdmHandleOpcode(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags) { ULONG Eip; /* Get flat EIP of the *current* instruction (not the original EIP) */ Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip; Eip += KiVdmGetInstructionSize(Flags) - 1; /* Read the opcode entry */ switch (*(PUCHAR)Eip) { case 0xF: return KiCallVdmHandler(F); case 0x26: return KiCallVdmPrefixHandler(PFX_FLAG_ES); case 0x2E: return KiCallVdmPrefixHandler(PFX_FLAG_CS); case 0x36: return KiCallVdmPrefixHandler(PFX_FLAG_SS); case 0x3E: return KiCallVdmPrefixHandler(PFX_FLAG_DS); case 0x64: return KiCallVdmPrefixHandler(PFX_FLAG_FS); case 0x65: return KiCallVdmPrefixHandler(PFX_FLAG_GS); case 0x66: return KiCallVdmPrefixHandler(PFX_FLAG_OPER32); case 0x67: return KiCallVdmPrefixHandler(PFX_FLAG_ADDR32); case 0xF0: return KiCallVdmPrefixHandler(PFX_FLAG_LOCK); case 0xF2: return KiCallVdmPrefixHandler(PFX_FLAG_REPNE); case 0xF3: return KiCallVdmPrefixHandler(PFX_FLAG_REP); case 0x6C: return KiCallVdmHandler(INSB); case 0x6D: return KiCallVdmHandler(INSW); case 0x6E: return KiCallVdmHandler(OUTSB); case 0x6F: return KiCallVdmHandler(OUTSW); case 0x98: return KiCallVdmHandler(NPX); case 0xD8: return KiCallVdmHandler(NPX); case 0xD9: return KiCallVdmHandler(NPX); case 0xDA: return KiCallVdmHandler(NPX); case 0xDB: return KiCallVdmHandler(NPX); case 0xDC: return KiCallVdmHandler(NPX); case 0xDD: return KiCallVdmHandler(NPX); case 0xDE: return KiCallVdmHandler(NPX); case 0xDF: return KiCallVdmHandler(NPX); case 0x9C: return KiCallVdmHandler(PUSHF); case 0x9D: return KiCallVdmHandler(POPF); case 0xCD: return KiCallVdmHandler(INTnn); case 0xCE: return KiCallVdmHandler(INTO); case 0xCF: return KiCallVdmHandler(IRET); case 0xE4: return KiCallVdmHandler(INBimm); case 0xE5: return KiCallVdmHandler(INWimm); case 0xE6: return KiCallVdmHandler(OUTBimm); case 0xE7: return KiCallVdmHandler(OUTWimm); case 0xEC: return KiCallVdmHandler(INB); case 0xED: return KiCallVdmHandler(INW); case 0xEE: return KiCallVdmHandler(OUTB); case 0xEF: return KiCallVdmHandler(OUTW); case 0xF4: return KiCallVdmHandler(HLT); case 0xFA: return KiCallVdmHandler(CLI); case 0xFB: return KiCallVdmHandler(STI); default: DPRINT1("Unhandled instruction: 0x%02x.\n", *(PUCHAR)Eip); return KiCallVdmHandler(INV); } }
BOOLEAN FASTCALL KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags) { ULONG Esp, V86EFlags, TrapEFlags; /* Get current V8086 flags and mask out interrupt flag */ V86EFlags = *KiNtVdmState; V86EFlags &= ~EFLAGS_INTERRUPT_MASK; /* Get trap frame EFLags */ TrapEFlags = TrapFrame->EFlags; /* Check for VME support */ if(KeI386VirtualIntExtensions) { /* Copy the virtual interrupt flag to the interrupt flag */ TrapEFlags &= ~EFLAGS_INTERRUPT_MASK; if(TrapEFlags & EFLAGS_VIF) TrapEFlags |= EFLAGS_INTERRUPT_MASK; } /* Leave only align, nested task and interrupt */ TrapEFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK); /* Add in those flags if they exist, and add in the IOPL flag */ V86EFlags |= TrapEFlags; V86EFlags |= EFLAGS_IOPL; /* Build flat ESP */ Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp; /* Check for OPER32 */ if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32) { /* Save EFlags */ Esp -= 4; *(PULONG)Esp = V86EFlags; } else { /* Save EFLags */ Esp -= 2; *(PUSHORT)Esp = (USHORT)V86EFlags; } /* Set new ESP and EIP */ TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4); TrapFrame->Eip += KiVdmGetInstructionSize(Flags); /* We're done */ return TRUE; }
BOOLEAN FASTCALL KiVdmOpcodeSTI(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags) { /* Check for VME support */ ASSERT(KeI386VirtualIntExtensions == FALSE); /* Enable interrupts */ KiVdmSetVdmEFlags(EFLAGS_INTERRUPT_MASK); /* Skip instruction */ TrapFrame->Eip += KiVdmGetInstructionSize(Flags); /* Done */ return TRUE; }
BOOLEAN FASTCALL KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags) { ULONG Esp, V86EFlags, TrapEFlags, Eip, Interrupt; /* Read trap frame EFlags */ TrapEFlags = TrapFrame->EFlags; /* Remove interrupt flag from V8086 EFlags */ V86EFlags = *KiNtVdmState; KiVdmClearVdmEFlags(EFLAGS_INTERRUPT_MASK); /* Keep only alignment and interrupt flag from the V8086 state */ V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_INTERRUPT_MASK); /* Check for VME support */ ASSERT(KeI386VirtualIntExtensions == FALSE); /* Mask in the relevant V86 EFlags into the trap flags */ V86EFlags |= (TrapEFlags & ~EFLAGS_INTERRUPT_MASK); /* And mask out the VIF, nested task and TF flag from the trap flags */ TrapFrame->EFlags = TrapEFlags &~ (EFLAGS_VIF | EFLAGS_NESTED_TASK | EFLAGS_TF); /* Add the IOPL flag to the local trap flags */ V86EFlags |= EFLAGS_IOPL; /* Build flat ESP */ Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp; /* Push EFlags */ Esp -= 2; *(PUSHORT)(Esp) = (USHORT)V86EFlags; /* Push CS */ Esp -= 2; *(PUSHORT)(Esp) = (USHORT)TrapFrame->SegCs; /* Push IP */ Esp -= 2; *(PUSHORT)(Esp) = (USHORT)TrapFrame->Eip + KiVdmGetInstructionSize(Flags) + 1; /* Update ESP */ TrapFrame->HardwareEsp = (USHORT)Esp; /* Get flat EIP */ Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip; /* Now get the *next* EIP address (current is original + the count - 1) */ Eip += KiVdmGetInstructionSize(Flags); /* Now read the interrupt number */ Interrupt = *(PUCHAR)Eip; /* Read the EIP from its IVT entry */ Interrupt = *(PULONG)(Interrupt * 4); TrapFrame->Eip = (USHORT)Interrupt; /* Now get the CS segment */ Interrupt = (USHORT)(Interrupt >> 16); /* Check if the trap was not V8086 trap */ if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Was it a kernel CS? */ Interrupt |= RPL_MASK; if (TrapFrame->SegCs == KGDT_R0_CODE) { /* Add the RPL mask */ TrapFrame->SegCs = Interrupt; } else { /* Set user CS */ TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; } } else { /* Set IVT CS */ TrapFrame->SegCs = Interrupt; } /* We're done */ return TRUE; }
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; }