mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 14:53:09 +00:00
[FAST486][NTVDM]
Several fixes in fast486 and ntvdm: DosCopyEnvironmentBlock - prepend the program name tag (0x0001) to the program name. Fast486OpcodePushByteImm, Fast486OpcodePushImm - sign-extend instead of zero-extending. Fast486InterruptInternal - The parameter is supposed to be the type of the gate, not a boolean. GET_SEGMENT_RPL will not work on real-mode selectors, use a special field for the RPL. Loading a data segment with the NULL selector should never generate an exception. Mask out the highest-order byte of the physical address when loading a descriptor table in 16-bit mode. Fast486InterruptInternal - The interrupt gate type determines the size. CORE-8257 #resolve #comment Fixed in revision r63482. svn path=/trunk/; revision=63482
This commit is contained in:
parent
58b39a1ecf
commit
af35d7f046
8 changed files with 61 additions and 25 deletions
|
@ -251,6 +251,7 @@ typedef struct _FAST486_SEG_REG
|
||||||
ULONG DirConf : 1;
|
ULONG DirConf : 1;
|
||||||
ULONG Executable : 1;
|
ULONG Executable : 1;
|
||||||
ULONG SystemType : 1;
|
ULONG SystemType : 1;
|
||||||
|
ULONG Rpl : 2;
|
||||||
ULONG Dpl : 2;
|
ULONG Dpl : 2;
|
||||||
ULONG Present : 1;
|
ULONG Present : 1;
|
||||||
ULONG Size : 1;
|
ULONG Size : 1;
|
||||||
|
|
|
@ -65,7 +65,7 @@ Fast486ReadMemory(PFAST486_STATE State,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl))
|
if ((!InstFetch && (CachedDescriptor->Rpl > CachedDescriptor->Dpl))
|
||||||
|| (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
|
|| (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
|
||||||
{
|
{
|
||||||
Fast486Exception(State, FAST486_EXCEPTION_GP);
|
Fast486Exception(State, FAST486_EXCEPTION_GP);
|
||||||
|
@ -132,7 +132,7 @@ Fast486WriteMemory(PFAST486_STATE State,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
|
if ((CachedDescriptor->Rpl > CachedDescriptor->Dpl)
|
||||||
|| (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
|
|| (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl))
|
||||||
{
|
{
|
||||||
Fast486Exception(State, FAST486_EXCEPTION_GP);
|
Fast486Exception(State, FAST486_EXCEPTION_GP);
|
||||||
|
@ -164,8 +164,11 @@ BOOLEAN
|
||||||
Fast486InterruptInternal(PFAST486_STATE State,
|
Fast486InterruptInternal(PFAST486_STATE State,
|
||||||
USHORT SegmentSelector,
|
USHORT SegmentSelector,
|
||||||
ULONG Offset,
|
ULONG Offset,
|
||||||
BOOLEAN InterruptGate)
|
ULONG GateType)
|
||||||
{
|
{
|
||||||
|
BOOLEAN GateSize = (GateType == FAST486_IDT_INT_GATE_32)
|
||||||
|
|| (GateType == FAST486_IDT_TRAP_GATE_32);
|
||||||
|
|
||||||
/* Check for protected mode */
|
/* Check for protected mode */
|
||||||
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
|
if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
|
||||||
{
|
{
|
||||||
|
@ -173,6 +176,15 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
||||||
USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
|
USHORT OldSs = State->SegmentRegs[FAST486_REG_SS].Selector;
|
||||||
ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
|
ULONG OldEsp = State->GeneralRegs[FAST486_REG_ESP].Long;
|
||||||
|
|
||||||
|
if (GateSize != (State->SegmentRegs[FAST486_REG_CS].Size))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The gate size doesn't match the current operand size, so toggle
|
||||||
|
* the OPSIZE flag.
|
||||||
|
*/
|
||||||
|
State->PrefixFlags ^= FAST486_PREFIX_OPSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the interrupt handler is more privileged */
|
/* Check if the interrupt handler is more privileged */
|
||||||
if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
|
if (Fast486GetCurrentPrivLevel(State) > GET_SEGMENT_RPL(SegmentSelector))
|
||||||
{
|
{
|
||||||
|
@ -257,7 +269,7 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
||||||
/* Push the instruction pointer */
|
/* Push the instruction pointer */
|
||||||
if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE;
|
if (!Fast486StackPush(State, State->InstPtr.Long)) return FALSE;
|
||||||
|
|
||||||
if (InterruptGate)
|
if ((GateType == FAST486_IDT_INT_GATE) || (GateType == FAST486_IDT_INT_GATE_32))
|
||||||
{
|
{
|
||||||
/* Disable interrupts after a jump to an interrupt gate handler */
|
/* Disable interrupts after a jump to an interrupt gate handler */
|
||||||
State->Flags.If = FALSE;
|
State->Flags.If = FALSE;
|
||||||
|
@ -270,7 +282,7 @@ Fast486InterruptInternal(PFAST486_STATE State,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (State->SegmentRegs[FAST486_REG_CS].Size)
|
if (GateSize)
|
||||||
{
|
{
|
||||||
/* 32-bit code segment, use EIP */
|
/* 32-bit code segment, use EIP */
|
||||||
State->InstPtr.Long = Offset;
|
State->InstPtr.Long = Offset;
|
||||||
|
|
|
@ -159,7 +159,7 @@ Fast486InterruptInternal
|
||||||
PFAST486_STATE State,
|
PFAST486_STATE State,
|
||||||
USHORT SegmentSelector,
|
USHORT SegmentSelector,
|
||||||
ULONG Offset,
|
ULONG Offset,
|
||||||
BOOLEAN InterruptGate
|
ULONG GateType
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -542,24 +542,32 @@ Fast486LoadSegment(PFAST486_STATE State,
|
||||||
{
|
{
|
||||||
/* Loading a data segment */
|
/* Loading a data segment */
|
||||||
|
|
||||||
if (!GdtEntry.SystemType)
|
if (GET_SEGMENT_INDEX(Selector) != 0)
|
||||||
{
|
{
|
||||||
/* This is a special descriptor */
|
if (!GdtEntry.SystemType)
|
||||||
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
|
{
|
||||||
return FALSE;
|
/* This is a special descriptor */
|
||||||
}
|
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
|
if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
|
||||||
|| (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
|
|| (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl))
|
||||||
{
|
{
|
||||||
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
|
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GdtEntry.Present)
|
if (!GdtEntry.Present)
|
||||||
|
{
|
||||||
|
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector);
|
/* This is a NULL selector */
|
||||||
return FALSE;
|
RtlZeroMemory(&GdtEntry, sizeof(GdtEntry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,6 +580,7 @@ Fast486LoadSegment(PFAST486_STATE State,
|
||||||
CachedDescriptor->DirConf = GdtEntry.DirConf;
|
CachedDescriptor->DirConf = GdtEntry.DirConf;
|
||||||
CachedDescriptor->Executable = GdtEntry.Executable;
|
CachedDescriptor->Executable = GdtEntry.Executable;
|
||||||
CachedDescriptor->SystemType = GdtEntry.SystemType;
|
CachedDescriptor->SystemType = GdtEntry.SystemType;
|
||||||
|
CachedDescriptor->Rpl = GET_SEGMENT_RPL(Selector);
|
||||||
CachedDescriptor->Dpl = GdtEntry.Dpl;
|
CachedDescriptor->Dpl = GdtEntry.Dpl;
|
||||||
CachedDescriptor->Present = GdtEntry.Present;
|
CachedDescriptor->Present = GdtEntry.Present;
|
||||||
CachedDescriptor->Size = GdtEntry.Size;
|
CachedDescriptor->Size = GdtEntry.Size;
|
||||||
|
|
|
@ -3702,9 +3702,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodePushImm)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
USHORT Data;
|
SHORT Data;
|
||||||
|
|
||||||
if (!Fast486FetchWord(State, &Data))
|
if (!Fast486FetchWord(State, (PUSHORT)&Data))
|
||||||
{
|
{
|
||||||
/* Exception occurred */
|
/* Exception occurred */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -3837,12 +3837,12 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
|
||||||
|
|
||||||
FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm)
|
FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm)
|
||||||
{
|
{
|
||||||
UCHAR Data;
|
CHAR Data;
|
||||||
|
|
||||||
/* Make sure this is the right instruction */
|
/* Make sure this is the right instruction */
|
||||||
ASSERT(Opcode == 0x6A);
|
ASSERT(Opcode == 0x6A);
|
||||||
|
|
||||||
if (!Fast486FetchByte(State, &Data))
|
if (!Fast486FetchByte(State, (PUCHAR)&Data))
|
||||||
{
|
{
|
||||||
/* Exception occurred */
|
/* Exception occurred */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -2018,10 +2018,13 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
|
||||||
{
|
{
|
||||||
UCHAR TableReg[6];
|
UCHAR TableReg[6];
|
||||||
FAST486_MOD_REG_RM ModRegRm;
|
FAST486_MOD_REG_RM ModRegRm;
|
||||||
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
|
BOOLEAN OperandSize, AddressSize;
|
||||||
FAST486_SEG_REGS Segment = FAST486_REG_DS;
|
FAST486_SEG_REGS Segment = FAST486_REG_DS;
|
||||||
|
|
||||||
|
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
|
||||||
|
|
||||||
NO_LOCK_PREFIX();
|
NO_LOCK_PREFIX();
|
||||||
|
TOGGLE_OPSIZE(OperandSize);
|
||||||
TOGGLE_ADSIZE(AddressSize);
|
TOGGLE_ADSIZE(AddressSize);
|
||||||
|
|
||||||
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
|
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
|
||||||
|
@ -2117,6 +2120,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
|
||||||
State->Gdtr.Size = *((PUSHORT)TableReg);
|
State->Gdtr.Size = *((PUSHORT)TableReg);
|
||||||
State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
|
State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
|
||||||
|
|
||||||
|
/* In 16-bit mode the highest byte is masked out */
|
||||||
|
if (!OperandSize) State->Gdtr.Address &= 0x00FFFFFF;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2153,6 +2159,9 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
|
||||||
State->Idtr.Size = *((PUSHORT)TableReg);
|
State->Idtr.Size = *((PUSHORT)TableReg);
|
||||||
State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
|
State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
|
||||||
|
|
||||||
|
/* In 16-bit mode the highest byte is masked out */
|
||||||
|
if (!OperandSize) State->Idtr.Address &= 0x00FFFFFF;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -442,6 +442,10 @@ static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
|
||||||
/* Set the final zero */
|
/* Set the final zero */
|
||||||
*(DestBuffer++) = 0;
|
*(DestBuffer++) = 0;
|
||||||
|
|
||||||
|
/* Store the special program name tag */
|
||||||
|
*(DestBuffer++) = LOWORD(DOS_PROGRAM_NAME_TAG);
|
||||||
|
*(DestBuffer++) = HIWORD(DOS_PROGRAM_NAME_TAG);
|
||||||
|
|
||||||
/* Copy the program name after the environment block */
|
/* Copy the program name after the environment block */
|
||||||
strcpy(DestBuffer, ProgramName);
|
strcpy(DestBuffer, ProgramName);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#define DOS_DIR_LENGTH 64
|
#define DOS_DIR_LENGTH 64
|
||||||
#define NUM_DRIVES ('Z' - 'A' + 1)
|
#define NUM_DRIVES ('Z' - 'A' + 1)
|
||||||
#define DOS_CHAR_ATTRIBUTE 0x07
|
#define DOS_CHAR_ATTRIBUTE 0x07
|
||||||
|
#define DOS_PROGRAM_NAME_TAG 0x0001
|
||||||
|
|
||||||
enum DOS_ALLOC_STRATEGY
|
enum DOS_ALLOC_STRATEGY
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue