📄 v86m_sup.s
字号:
/*
* FILE: ntoskrnl/ke/i386/v86m_sup.S
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: Virtual 8086 (V86) Mode Support
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
* NOTE: See asmmacro.S for the V86 trap code.
*/
/* INCLUDES ******************************************************************/
#include <asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
/* FIXME: Can we make a nice macro to generate V86 Opcode handlers? */
/* GLOBALS *******************************************************************/
//
// This table contains indexes into the OpcodeDispatchV86 Table for opcodes in
// Virtual-8086 Mode.
// There are 256 entries.
//
OpcodeIndex:
INVALID_V86_OPCODE 15 /* OP 00-14: UNHANDLED */
.byte 1 /* OP 0F: 0F */
INVALID_V86_OPCODE 22 /* OP 10-25: UNHANDLED */
.byte 2 /* OP 26: ES Prefix */
INVALID_V86_OPCODE 7 /* OP 27-2D: UNHANDLED */
.byte 3 /* OP 2E: CS Prefix */
INVALID_V86_OPCODE 7 /* OP 2F-35: UNHANDLED */
.byte 4 /* OP 36: SS Prefix */
INVALID_V86_OPCODE 7 /* OP 37-3D: UNHANDLED */
.byte 5 /* OP 3E: DS Prefix */
INVALID_V86_OPCODE 37 /* OP 3F-63: UNHANDLED */
.byte 6 /* OP 64: FS Prefix */
.byte 7 /* OP 65: GS Prefix */
.byte 8 /* OP 66: OPER32 Prefix */
.byte 9 /* OP 67: ADDR32 Prefix */
INVALID_V86_OPCODE 4 /* OP 68-6B: UNHANDLED */
.byte 10 /* OP 6C: INSB */
.byte 11 /* OP 6D: INSW */
.byte 12 /* OP 6E: OUTSB */
.byte 13 /* OP 6F: OUTSW */
INVALID_V86_OPCODE 43 /* OP 70-9A: UNHANDLED */
.byte 19 /* OP 9B: NPX */
.byte 14 /* OP 9C: PUSHF */
.byte 15 /* OP 9D: POPF */
INVALID_V86_OPCODE 47 /* OP 9E-CC: UNHANDLED */
.byte 16 /* OP CD: INTnn */
.byte 17 /* OP CE: INTO */
.byte 18 /* OP CF: IRETD */
INVALID_V86_OPCODE 8 /* OP D0-D7: UNHANDLED */
.byte 19 /* OP D8: NPX */
.byte 19 /* OP D9: NPX */
.byte 19 /* OP DA: NPX */
.byte 19 /* OP DB: NPX */
.byte 19 /* OP DC: NPX */
.byte 19 /* OP DD: NPX */
.byte 19 /* OP DE: NPX */
.byte 19 /* OP DF: NPX */
INVALID_V86_OPCODE 4 /* OP DE-E3: UNHANDLED */
.byte 20 /* OP E4: INBimm */
.byte 21 /* OP E5: INWimm */
.byte 22 /* OP E6: OUTBimm */
.byte 23 /* OP E7: OUTWimm */
INVALID_V86_OPCODE 4 /* OP E8-EB: UNHANDLED */
.byte 24 /* OP EC: INB */
.byte 25 /* OP EF: INW */
.byte 26 /* OP EE: OUTB */
.byte 27 /* OP EF: OUTW */
.byte 28 /* OP F0: LOCK Prefix */
.byte 0 /* OP F1: UNHANDLED */
.byte 29 /* OP F2: REPNE Prefix */
.byte 30 /* OP F3: REP Prefix */
.byte 33 /* OP F4: HLT */
INVALID_V86_OPCODE 5 /* OP F5-F9: UNHANDLED */
.byte 31 /* OP FA: CLI */
.byte 32 /* OP FB: STI */
INVALID_V86_OPCODE 4 /* OP FC-FF: UNHANDLED */
//
// This table contains the emulation routines for
// Virtual-8086 Mode. There are 34 entries.
//
OpcodeDispatchV86:
.long _OpcodeInvalidV86
.long _Opcode0FV86
.long _OpcodeESPrefixV86
.long _OpcodeCSPrefixV86
.long _OpcodeSSPrefixV86
.long _OpcodeDSPrefixV86
.long _OpcodeFSPrefixV86
.long _OpcodeGSPrefixV86
.long _OpcodeOPER32PrefixV86
.long _OpcodeADDR32PrefixV86
.long _OpcodeINSBV86
.long _OpcodeINSWV86
.long _OpcodeOUTSBV86
.long _OpcodeOUTSWV86
.long _OpcodePUSHFV86
.long _OpcodePOPFV86
.long _OpcodeINTnnV86
.long _OpcodeINTOV86
.long _OpcodeIRETV86
.long _OpcodeNPXV86
.long _OpcodeINBimmV86
.long _OpcodeINWimmV86
.long _OpcodeOUTBimmV86
.long _OpcodeOUTWimmV86
.long _OpcodeINBV86
.long _OpcodeINWV86
.long _OpcodeOUTBV86
.long _OpcodeOUTWV86
.long _OpcodeLOCKPrefixV86
.long _OpcodeREPNEPrefixV86
.long _OpcodeREPPrefixV86
.long _OpcodeCLIV86
.long _OpcodeSTIV86
.long _OpcodeHLTV86
_ExVdmOpcodeDispatchCounts:
.rept 34
.long 0
.endr
V86DebugMsg:
.asciz "Received V86 Emulation Opcode: %lx\n"
/* VIRTUAL-8086 MODE OPCODER HANDLERS ****************************************/
.func OpcodeInvalidV86
_OpcodeInvalidV86:
UNHANDLED_V86_OPCODE
.endfunc
.func Opcode0FV86
_Opcode0FV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeESPrefixV86
_OpcodeESPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeCSPrefixV86
_OpcodeCSPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeSSPrefixV86
_OpcodeSSPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeDSPrefixV86
_OpcodeDSPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeFSPrefixV86
_OpcodeFSPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeGSPrefixV86
_OpcodeGSPrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOPER32PrefixV86
_OpcodeOPER32PrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeADDR32PrefixV86
_OpcodeADDR32PrefixV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeINSBV86
_OpcodeINSBV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeINSWV86
_OpcodeINSWV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOUTSBV86
_OpcodeOUTSBV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeOUTSWV86
_OpcodeOUTSWV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodePUSHFV86
_OpcodePUSHFV86:
/* Get VDM state */
mov eax, 0x714
mov eax, [eax]
/* Get EFLAGS and mask out IF */
mov edx, [ebp+KTRAP_FRAME_EFLAGS]
and eax, ~EFLAGS_INTERRUPT_MASK
/* Mask align check and interrupt mask */
and eax, EFLAGS_ALIGN_CHECK + 0x4000 + EFLAGS_INTERRUPT_MASK
or eax, edx
/* Add IOPL Mask */
or eax, 0x3000
/* Get flat ESP */
movzx ecx, word ptr [ebp+KTRAP_FRAME_SS]
shl ecx, 4
movzx edx, word ptr [ebp+KTRAP_FRAME_ESP]
sub dx, 2
/* Check if there is an OPER32 prefix */
test ebx, 0x4000
jnz SkipPrefix
/* Push EFLAGS */
mov [ecx+edx], ax
UpdateFrame:
/* Update ESP and EIP */
mov [ebp+KTRAP_FRAME_ESP], dx
add [ebp+KTRAP_FRAME_EIP], edi
/* Return success */
mov eax, 1
ret
SkipPrefix:
/* Skip the prefix, push EFLAGS and jump back */
sub dx, 2
mov [edx+ecx], eax
jmp UpdateFrame
.endfunc
.func OpcodePOPFV86
_OpcodePOPFV86:
/* Get VDM state */
mov eax, 0x714
/* Get flat ESP */
mov ecx, [ebp+KTRAP_FRAME_SS]
shl ecx, 4
movzx edx, word ptr [ebp+KTRAP_FRAME_ESP]
/* Pop EFLAGS */
mov ecx, [ecx+edx]
add edx, 4
/* Check for OPER32 prefix */
test ebx, 0x4000
jnz NoPrefix
/* Skip 2 bytes */
and ecx, 0xFFFF
sub edx, 2
NoPrefix:
/* Set new ESP */
mov [ebp+KTRAP_FRAME_ESP], edx
/* Mask out EFLAGS */
and eax, ~0x3000
mov ebx, ebx
and ebx, ~0x4000
and ecx, EFLAGS_ALIGN_CHECK + 0x4000 + EFLAGS_INTERRUPT_MASK
/* FIXME: Support VME */
/* Save VDM State pointer */
push eax
/* Set new EFLAGS, make sure to add IF and V86 */
or ebx, EFLAGS_INTERRUPT_MASK + EFLAGS_V86_MASK
push [ebp+KTRAP_FRAME_EFLAGS]
mov [ebp+KTRAP_FRAME_EFLAGS], ebx
/* Make sure we were in V86 mode */
test ebx, EFLAGS_V86_MASK
jnz CheckEspAdjust
int 3
CheckEspAdjust:
/* Check if we have to update ESP0 and fixup the stack from our push */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
lea esp, [esp+4]
jnz NoAdjustEsp0
/* Adjust it */
push ebp
call _Ki386AdjustEsp0@4
NoAdjustEsp0:
/* Restore VDM state */
pop eax
/* Update the flags in the VDM State */
LOCK and dword ptr [eax], ~(EFLAGS_ALIGN_CHECK + 0x4000 + EFLAGS_INTERRUPT_MASK)
LOCK or [eax], ecx
/* Update EIP */
add [ebp+KTRAP_FRAME_EIP], edi
/* FIXME: Check for VDM Pending interrupts */
/* Return success */
mov eax, 1
ret
.endfunc
.func OpcodeINTnnV86
_OpcodeINTnnV86:
/* Get EFlags */
mov edx, [ebp+KTRAP_FRAME_EFLAGS]
/* Remove the flag in the VDM State */
mov eax, 0x714
mov ecx, [eax]
LOCK and dword ptr [eax], ~EFLAGS_INTERRUPT_MASK
/* Mask it out from EFLAGS too */
mov eax, edx
and eax, ~EFLAGS_INTERRUPT_MASK
/* Mask out the alignment check and IF flag from the VDM state */
and ecx, EFLAGS_ALIGN_CHECK + EFLAGS_INTERRUPT_MASK
/* FIXME: Support VME */
/* Now mask out VIF and TF */
or eax, ecx
and edx, ~(EFLAGS_VIF + 0x4000 + EFLAGS_TF)
mov [ebp+KTRAP_FRAME_EFLAGS], edx
/* Set the IOPL Mask */
or eax, 0x3000
/* Get stack flat address */
movzx ecx, word ptr [ebp+KTRAP_FRAME_SS]
shl ecx, 4
movzx edx, word ptr [ebp+KTRAP_FRAME_ESP]
/* Push EFLAGS */
sub dx, 2
mov word ptr [ecx+edx], ax
/* Push CS */
mov ax, word ptr [ebp+KTRAP_FRAME_CS]
sub dx, 2
mov word ptr [ecx+edx], ax
/* Push IP */
movzx eax, word ptr [ebp+KTRAP_FRAME_EIP]
add eax, edi
inc eax
sub dx, 2
mov word ptr [ecx+edx], ax
/* Update ESP */
mov [ebp+KTRAP_FRAME_ESP], dx
/* Get the interrupt */
inc esi
movzx ecx, byte ptr [esi]
/* FIXME: Analyze and see if this is a hooked VDM (PM) Interrupt */
/* Get the entry in the IVT */
mov ebx, [ecx*4]
mov eax, ebx
shr eax, 16
/* Update EIP */
mov word ptr [ebp+KTRAP_FRAME_EIP], bx
/* Check if this was V86 mode */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz SetCs
/* Check if it was a kernel CS */
or ax, RPL_MASK
cmp ax, KGDT_R0_CODE
jnb SetCs
/* Set user-mode CS */
mov ax, KGDT_R3_CODE + RPL_MASK
SetCs:
/* Set new CS */
mov [ebp+KTRAP_FRAME_CS], ax
/* Return success */
mov eax, 1
ret
.endfunc
.func OpcodeINTOV86
_OpcodeINTOV86:
UNHANDLED_V86_OPCODE
.endfunc
.func OpcodeIRETV86
_OpcodeIRETV86:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -