From bbc9efd2d9951a93c6c8a62b88fbbe8f6069a04d Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Fri, 15 Nov 2013 02:32:08 +0000 Subject: [PATCH] [FAST486] - Fix the privilege checks. - Store the CPL in a special field, so that it doesn't get mixed up with the lowest 2 bits of real mode selectors while switching into protected mode. - Reset the exception count after a successful ISR call. - In Fast486OpcodeGroup0F01, check for prefix overrides after parsing the Mod-Reg-R/M, which might add a SS: prefix override in some cases. svn path=/branches/ntvdm/; revision=60995 --- include/reactos/libs/fast486/fast486.h | 1 + lib/fast486/common.c | 18 +++++++++++++++--- lib/fast486/common.inl | 19 +++++++------------ lib/fast486/fast486.c | 3 +++ lib/fast486/opgroups.c | 12 ++++++------ 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/include/reactos/libs/fast486/fast486.h b/include/reactos/libs/fast486/fast486.h index 2a2a56301e5..d54570456e8 100644 --- a/include/reactos/libs/fast486/fast486.h +++ b/include/reactos/libs/fast486/fast486.h @@ -394,6 +394,7 @@ struct _FAST486_STATE FAST486_REG InstPtr, SavedInstPtr; FAST486_FLAGS_REG Flags; FAST486_TABLE_REG Gdtr, Idtr, Ldtr, Tss; + UCHAR Cpl; ULONG ControlRegisters[FAST486_NUM_CTRL_REGS]; ULONG DebugRegisters[FAST486_NUM_DBG_REGS]; ULONG ExceptionCount; diff --git a/lib/fast486/common.c b/lib/fast486/common.c index 871d77d2ba1..42b7b962204 100644 --- a/lib/fast486/common.c +++ b/lib/fast486/common.c @@ -65,7 +65,8 @@ Fast486ReadMemory(PFAST486_STATE State, return FALSE; } - if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) + if ((!InstFetch && (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)) + || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl)) { Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; @@ -132,7 +133,8 @@ Fast486WriteMemory(PFAST486_STATE State, return FALSE; } - if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) + if ((GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) + || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl)) { Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; @@ -330,8 +332,18 @@ Fast486ExceptionWithErrorCode(PFAST486_STATE State, && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)) { /* Push the error code */ - Fast486StackPush(State, ErrorCode); + if (!Fast486StackPush(State, ErrorCode)) + { + /* + * If this function failed, that means Fast486Exception + * was called again, so just return in this case. + */ + return; + } } + + /* Reset the exception count */ + State->ExceptionCount = 0; } /* EOF */ diff --git a/lib/fast486/common.inl b/lib/fast486/common.inl index acbdb2ae933..c2412c035dc 100644 --- a/lib/fast486/common.inl +++ b/lib/fast486/common.inl @@ -27,16 +27,8 @@ FORCEINLINE INT Fast486GetCurrentPrivLevel(PFAST486_STATE State) { - if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) - { - /* In protected mode, return the RPL of the CS */ - return GET_SEGMENT_RPL(State->SegmentRegs[FAST486_REG_CS].Selector); - } - else - { - /* Real mode is always in supervisor mode */ - return 0; - } + /* Return the CPL, or 3 if we're in virtual 8086 mode */ + return (!State->Flags.Vm) ? State->Cpl : 3; } FORCEINLINE @@ -464,7 +456,10 @@ Fast486LoadSegment(PFAST486_STATE State, else if (Segment == FAST486_REG_CS) { /* Loading the code segment */ - // TODO: NOT IMPLEMENTED + // TODO: Implement security checks, call gates, etc... + + /* Update CPL */ + State->Cpl = GET_SEGMENT_RPL(Selector); } else { @@ -478,7 +473,7 @@ Fast486LoadSegment(PFAST486_STATE State, } if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl) - && (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl)) + || (Fast486GetCurrentPrivLevel(State) > GdtEntry.Dpl)) { Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; diff --git a/lib/fast486/fast486.c b/lib/fast486/fast486.c index 1533662185e..7fef9865a67 100644 --- a/lib/fast486/fast486.c +++ b/lib/fast486/fast486.c @@ -239,6 +239,9 @@ Fast486Reset(PFAST486_STATE State) State->Flags.AlwaysSet = 1; State->InstPtr.LowWord = 0xFFF0; + /* Set the CPL to 0 */ + State->Cpl = 0; + /* Initialize segments */ for (i = 0; i < FAST486_NUM_SEG_REGS; i++) { diff --git a/lib/fast486/opgroups.c b/lib/fast486/opgroups.c index 754a9d8fc90..98833107bb5 100644 --- a/lib/fast486/opgroups.c +++ b/lib/fast486/opgroups.c @@ -1668,6 +1668,12 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01) NO_LOCK_PREFIX(); TOGGLE_ADSIZE(AddressSize); + if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) + { + /* Exception occurred */ + return FALSE; + } + /* Check for the segment override */ if (State->PrefixFlags & FAST486_PREFIX_SEG) { @@ -1675,12 +1681,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01) Segment = State->SegmentOverride; } - if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) - { - /* Exception occurred */ - return FALSE; - } - /* Check which operation this is */ switch (ModRegRm.Register) {