Пример #1
0
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);
    }
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}