[NTOS]: Fix some bugs and cleanup V8086 code in regards to flags usage.

[NTOS]: Add VDM debug spew to see why there's now an invalid opcode on Windows builds of VMWare and certain QEmu combinations. (Note: the double fault issue is fixed, this is a new issue).

svn path=/trunk/; revision=45057
This commit is contained in:
Sir Richard 2010-01-13 03:43:03 +00:00
parent 1697ed0f17
commit de10db923c

View file

@ -13,6 +13,9 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#define KiVdmGetInstructionSize(x) ((x) & 0xFF)
#define KiVdmGetPrefixFlags(x) ((x) & 0xFFFFFF00)
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
ULONG KeI386EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE; ULONG KeI386EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE;
@ -51,6 +54,7 @@ KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame,
ULONG Esp, V86EFlags, TrapEFlags; ULONG Esp, V86EFlags, TrapEFlags;
/* Get current V8086 flags and mask out interrupt flag */ /* Get current V8086 flags and mask out interrupt flag */
DbgPrint("VDM: Handling PUSHF (PREFIX [0x%lx])\n", KiVdmGetPrefixFlags(Flags));
V86EFlags = *KiNtVdmState; V86EFlags = *KiNtVdmState;
V86EFlags &= ~EFLAGS_INTERRUPT_MASK; V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
@ -67,7 +71,7 @@ KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame,
Esp -= 2; Esp -= 2;
/* Check for OPER32 */ /* Check for OPER32 */
if (Flags & PFX_FLAG_OPER32) if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32)
{ {
/* Save EFlags */ /* Save EFlags */
Esp -= 2; Esp -= 2;
@ -81,7 +85,7 @@ KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame,
/* Set new ESP and EIP */ /* Set new ESP and EIP */
TrapFrame->HardwareEsp = (USHORT)Esp; TrapFrame->HardwareEsp = (USHORT)Esp;
TrapFrame->Eip += (Flags & 0xFF); TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
/* We're done */ /* We're done */
return TRUE; return TRUE;
@ -95,6 +99,7 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
ULONG Esp, V86EFlags, EFlags, TrapEFlags; ULONG Esp, V86EFlags, EFlags, TrapEFlags;
/* Build flat ESP */ /* Build flat ESP */
DbgPrint("VDM: Handling POPF (PREFIX [0x%lx])\n", KiVdmGetPrefixFlags(Flags));
Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp; Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
/* Read EFlags */ /* Read EFlags */
@ -102,7 +107,7 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
Esp += 4; Esp += 4;
/* Check for OPER32 */ /* Check for OPER32 */
if (!(Flags & PFX_FLAG_OPER32)) if (!(KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32))
{ {
/* Read correct flags and use correct stack address */ /* Read correct flags and use correct stack address */
Esp -= 2; Esp -= 2;
@ -140,7 +145,7 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
/* FIXME: Check for VDM interrupts */ /* FIXME: Check for VDM interrupts */
/* Update EIP */ /* Update EIP */
TrapFrame->Eip += (Flags & 0xFF); TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
/* We're done */ /* We're done */
return TRUE; return TRUE;
@ -187,7 +192,7 @@ KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame,
/* Push IP */ /* Push IP */
Esp -= 2; Esp -= 2;
*(PUSHORT)(Esp) = (USHORT)TrapFrame->Eip + (Flags & 0xFF) + 1; *(PUSHORT)(Esp) = (USHORT)TrapFrame->Eip + KiVdmGetInstructionSize(Flags) + 1;
/* Update ESP */ /* Update ESP */
TrapFrame->HardwareEsp = (USHORT)Esp; TrapFrame->HardwareEsp = (USHORT)Esp;
@ -196,11 +201,12 @@ KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame,
Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip; Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
/* Now get the *next* EIP address (current is original + the count - 1) */ /* Now get the *next* EIP address (current is original + the count - 1) */
Eip += (Flags & 0xFF); Eip += KiVdmGetInstructionSize(Flags);
/* Now read the interrupt number */ /* Now read the interrupt number */
Interrupt = *(PUCHAR)Eip; Interrupt = *(PUCHAR)Eip;
DbgPrint("VDM: Handling INT [0x%lx]\n", Interrupt);
/* Read the EIP from its IVT entry */ /* Read the EIP from its IVT entry */
Interrupt = *(PULONG)(Interrupt * 4); Interrupt = *(PULONG)(Interrupt * 4);
TrapFrame->Eip = (USHORT)Interrupt; TrapFrame->Eip = (USHORT)Interrupt;
@ -240,12 +246,13 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
IN ULONG Flags) IN ULONG Flags)
{ {
ULONG Esp, V86EFlags, EFlags, TrapEFlags, Eip; ULONG Esp, V86EFlags, EFlags, TrapEFlags, Eip;
/* Build flat ESP */ /* Build flat ESP */
DbgPrint("VDM: Handling IRET (PREFIX [0x%lx])\n", KiVdmGetPrefixFlags(Flags));
Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp; Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp;
/* Check for OPER32 */ /* Check for OPER32 */
if (Flags & PFX_FLAG_OPER32) if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32)
{ {
/* Build segmented EIP */ /* Build segmented EIP */
TrapFrame->Eip = *(PULONG)Esp; TrapFrame->Eip = *(PULONG)Esp;
@ -292,6 +299,7 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
/* Build flat EIP and check if this is the BOP instruction */ /* Build flat EIP and check if this is the BOP instruction */
Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip; Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
DbgPrint("VDM: Handling IRET EIP @ 0x%p [OPCODE: %lx]\n", Eip, *(PUSHORT)Eip);
if (*(PUSHORT)Eip == 0xC4C4) if (*(PUSHORT)Eip == 0xC4C4)
{ {
/* Dispatch the BOP */ /* Dispatch the BOP */
@ -313,11 +321,12 @@ KiVdmOpcodeCLI(IN PKTRAP_FRAME TrapFrame,
{ {
/* FIXME: Support VME */ /* FIXME: Support VME */
/* disable interrupts */ /* Disable interrupts */
DbgPrint("VDM: Handling CLI\n");
KiVdmClearVdmEFlags(EFLAGS_INTERRUPT_MASK); KiVdmClearVdmEFlags(EFLAGS_INTERRUPT_MASK);
/* Skip instruction */ /* Skip instruction */
TrapFrame->Eip += (Flags & 0xFF); TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
/* Done */ /* Done */
return TRUE; return TRUE;
@ -331,10 +340,11 @@ KiVdmOpcodeSTI(IN PKTRAP_FRAME TrapFrame,
/* FIXME: Support VME */ /* FIXME: Support VME */
/* Enable interrupts */ /* Enable interrupts */
DbgPrint("VDM: Handling STI\n");
KiVdmSetVdmEFlags(EFLAGS_INTERRUPT_MASK); KiVdmSetVdmEFlags(EFLAGS_INTERRUPT_MASK);
/* Skip instruction */ /* Skip instruction */
TrapFrame->Eip += (Flags & 0xFF); TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
/* Done */ /* Done */
return TRUE; return TRUE;
@ -351,7 +361,8 @@ KiVdmHandleOpcode(IN PKTRAP_FRAME TrapFrame,
/* Get flat EIP of the *current* instruction (not the original EIP) */ /* Get flat EIP of the *current* instruction (not the original EIP) */
Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip; Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
Eip += (Flags & 0xFF) - 1; DbgPrint("VDM: Handling Opcode @ 0x%p\n", Eip);
Eip += KiVdmGetInstructionSize(Flags) - 1;
/* Read the opcode entry */ /* Read the opcode entry */
switch (*(PUCHAR)Eip) switch (*(PUCHAR)Eip)
@ -409,6 +420,7 @@ KiVdmOpcodePrefix(IN PKTRAP_FRAME TrapFrame,
IN ULONG Flags) IN ULONG Flags)
{ {
/* Increase instruction size */ /* Increase instruction size */
DbgPrint("VDM: Handling PREFIX [%lx] Opcode @ 0x%p\n", KiVdmGetPrefixFlags(Flags), TrapFrame->Eip);
Flags++; Flags++;
/* Handle the next opcode */ /* Handle the next opcode */
@ -623,7 +635,9 @@ Ke386CallBios(IN ULONG Int,
Tss->IoMapBase = (USHORT)IOPM_OFFSET; Tss->IoMapBase = (USHORT)IOPM_OFFSET;
/* Switch stacks and work the magic */ /* Switch stacks and work the magic */
DbgPrint("VDM: Entering V8086 Mode\n");
Ki386SetupAndExitToV86Mode(VdmTeb); Ki386SetupAndExitToV86Mode(VdmTeb);
DbgPrint("VDM: Exiting V8086 Mode\n");
/* Restore IOPM */ /* Restore IOPM */
RtlCopyMemory(&Tss->IoMaps[0].IoMap, Ki386IopmSaveArea, PAGE_SIZE * 2); RtlCopyMemory(&Tss->IoMaps[0].IoMap, Ki386IopmSaveArea, PAGE_SIZE * 2);