v86m.c
来自「一个类似windows」· C语言 代码 · 共 812 行 · 第 1/2 页
C
812 行
/* $Id: v86m.c 21252 2006-03-08 20:03:59Z audit $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/v86m.c
* PURPOSE: Support for v86 mode
*
* PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
#define IOPL_FLAG ((1 << 12) | (1 << 13))
#define INTERRUPT_FLAG (1 << 9)
#define TRAP_FLAG (1 << 8)
#define DIRECTION_FLAG (1 << 10)
#define VALID_FLAGS (0xDFF)
/* FUNCTIONS *****************************************************************/
ULONG
KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf)
{
PUCHAR ip;
PUSHORT sp;
PULONG dsp;
BOOL BigDataPrefix = FALSE;
BOOL BigAddressPrefix = FALSE;
BOOL RepPrefix = FALSE;
ULONG i = 0;
BOOL Exit = FALSE;
ip = (PUCHAR)((Tf->SegCs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF));
sp = (PUSHORT)((Tf->HardwareSegSs & 0xFFFF) * 16 + (Tf->HardwareEsp & 0xFFFF));
dsp = (PULONG)sp;
DPRINT("KeV86GPF handling %x at %x:%x ss:sp %x:%x Flags %x\n",
ip[0], Tf->SegCs, Tf->Eip, Tf->Ss, Tf->HardwareEsp, VTf->regs->Flags);
while (!Exit)
{
switch (ip[i])
{
/* 32-bit data prefix */
case 0x66:
BigDataPrefix = TRUE;
i++;
Tf->Eip++;
break;
/* 32-bit address prefix */
case 0x67:
BigAddressPrefix = TRUE;
i++;
Tf->Eip++;
break;
/* rep prefix */
case 0xFC:
RepPrefix = TRUE;
i++;
Tf->Eip++;
break;
/* sti */
case 0xFB:
if (BigDataPrefix || BigAddressPrefix || RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{
Tf->Eip++;
VTf->regs->Vif = 1;
return(0);
}
Exit = TRUE;
break;
/* cli */
case 0xFA:
if (BigDataPrefix || BigAddressPrefix || RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{
Tf->Eip++;
VTf->regs->Vif = 0;
return(0);
}
Exit = TRUE;
break;
/* pushf */
case 0x9C:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{
Tf->Eip++;
if (!BigAddressPrefix)
{
Tf->HardwareEsp = Tf->HardwareEsp - 2;
sp = sp - 1;
sp[0] = (USHORT)(Tf->EFlags & 0xFFFF);
if (VTf->regs->Vif == 1)
{
sp[0] = (USHORT)(sp[0] | INTERRUPT_FLAG);
}
else
{
sp[0] = (USHORT)(sp[0] & (~INTERRUPT_FLAG));
}
}
else
{
Tf->HardwareEsp = Tf->HardwareEsp - 4;
dsp = dsp - 1;
dsp[0] = Tf->EFlags;
dsp[0] = dsp[0] & VALID_FLAGS;
if (VTf->regs->Vif == 1)
{
dsp[0] = dsp[0] | INTERRUPT_FLAG;
}
else
{
dsp[0] = dsp[0] & (~INTERRUPT_FLAG);
}
}
return(0);
}
Exit = TRUE;
break;
/* popf */
case 0x9D:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{
Tf->Eip++;
if (!BigAddressPrefix)
{
Tf->EFlags = Tf->EFlags & (~0xFFFF);
Tf->EFlags = Tf->EFlags | (sp[0] & VALID_FLAGS);
if (Tf->EFlags & INTERRUPT_FLAG)
{
VTf->regs->Vif = 1;
}
else
{
VTf->regs->Vif = 0;
}
Tf->EFlags = Tf->EFlags | INTERRUPT_FLAG;
Tf->HardwareEsp = Tf->HardwareEsp + 2;
}
else
{
Tf->EFlags = Tf->EFlags | (dsp[0] & VALID_FLAGS);
if (dsp[0] & INTERRUPT_FLAG)
{
VTf->regs->Vif = 1;
}
else
{
VTf->regs->Vif = 0;
}
Tf->EFlags = Tf->EFlags | INTERRUPT_FLAG;
Tf->HardwareEsp = Tf->HardwareEsp + 2;
}
return(0);
}
Exit = TRUE;
break;
/* iret */
case 0xCF:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI)
{
Tf->Eip = sp[0];
Tf->SegCs = sp[1];
Tf->EFlags = Tf->EFlags & (~0xFFFF);
Tf->EFlags = Tf->EFlags | sp[2];
if (Tf->EFlags & INTERRUPT_FLAG)
{
VTf->regs->Vif = 1;
}
else
{
VTf->regs->Vif = 0;
}
Tf->EFlags = Tf->EFlags & (~INTERRUPT_FLAG);
Tf->HardwareEsp = Tf->HardwareEsp + 6;
return(0);
}
Exit = TRUE;
break;
/* out imm8, al */
case 0xE6:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
DPRINT("outb %d, %x\n", (ULONG)ip[i + 1], Tf->Eax & 0xFF);
WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[i + 1],
(UCHAR)(Tf->Eax & 0xFF));
Tf->Eip = Tf->Eip + 2;
return(0);
}
Exit = TRUE;
break;
/* out imm8, ax */
case 0xE7:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
if (!BigDataPrefix)
{
DPRINT("outw %d, %x\n", (ULONG)ip[i + 1], Tf->Eax & 0xFFFF);
WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], (USHORT)(Tf->Eax & 0xFFFF));
}
else
{
DPRINT("outl %d, %x\n", (ULONG)ip[i + 1], Tf->Eax);
WRITE_PORT_ULONG((PULONG)(ULONG)ip[1], Tf->Eax);
}
Tf->Eip = Tf->Eip + 2;
return(0);
}
Exit = TRUE;
break;
/* out dx, al */
case 0xEE:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
DPRINT("outb %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax & 0xFF);
WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), (UCHAR)(Tf->Eax & 0xFF));
Tf->Eip = Tf->Eip + 1;
return(0);
}
Exit = TRUE;
break;
/* out dx, ax */
case 0xEF:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
if (!BigDataPrefix)
{
DPRINT("outw %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax & 0xFFFF);
WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF),
(USHORT)(Tf->Eax & 0xFFFF));
}
else
{
DPRINT("outl %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax);
WRITE_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF),
Tf->Eax);
}
Tf->Eip = Tf->Eip + 1;
return(0);
}
Exit = TRUE;
break;
/* in al, imm8 */
case 0xE4:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
UCHAR v;
v = READ_PORT_UCHAR((PUCHAR)(ULONG)ip[1]);
DPRINT("inb %d\t%X\n", (ULONG)ip[1], v);
Tf->Eax = Tf->Eax & (~0xFF);
Tf->Eax = Tf->Eax | v;
Tf->Eip = Tf->Eip + 2;
return(0);
}
Exit = TRUE;
break;
/* in ax, imm8 */
case 0xE5:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
if (!BigDataPrefix)
{
USHORT v;
v = READ_PORT_USHORT((PUSHORT)(ULONG)ip[1]);
DPRINT("inw %d\t%X\n", (ULONG)ip[1], v);
Tf->Eax = Tf->Eax & (~0xFFFF);
Tf->Eax = Tf->Eax | v;
}
else
{
ULONG v;
v = READ_PORT_ULONG((PULONG)(ULONG)ip[1]);
DPRINT("inl %d\t%X\n", (ULONG)ip[1], v);
Tf->Eax = v;
}
Tf->Eip = Tf->Eip + 2;
return(0);
}
Exit = TRUE;
break;
/* in al, dx */
case 0xEC:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
UCHAR v;
v = READ_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF));
DPRINT("inb %d\t%X\n", Tf->Edx & 0xFFFF, v);
Tf->Eax = Tf->Eax & (~0xFF);
Tf->Eax = Tf->Eax | v;
Tf->Eip = Tf->Eip + 1;
return(0);
}
Exit = TRUE;
break;
/* in ax, dx */
case 0xED:
if (RepPrefix)
{
*VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
return(1);
}
if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS)
{
if (!BigDataPrefix)
{
USHORT v;
v = READ_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF));
DPRINT("inw %d\t%X\n", Tf->Edx & 0xFFFF, v);
Tf->Eax = Tf->Eax & (~0xFFFF);
Tf->Eax = Tf->Eax | v;
}
else
{
ULONG v;
v = READ_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF));
DPRINT("inl %d\t%X\n", Tf->Edx & 0xFFFF, v);
Tf->Eax = v;
}
Tf->Eip = Tf->Eip + 1;
return(0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?