[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:
Aleksandar Andrejevic 2014-05-27 21:10:45 +00:00
parent 58b39a1ecf
commit af35d7f046
8 changed files with 61 additions and 25 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;
} }

View file

@ -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);

View file

@ -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
{ {