Author: aandrejevic Date: Thu May 7 03:22:18 2015 New Revision: 67591
URL: http://svn.reactos.org/svn/reactos?rev=67591&view=rev Log: [FAST486] Add support for legacy (286) Task State Segments.
Modified: trunk/reactos/lib/fast486/common.c trunk/reactos/lib/fast486/common.inl
Modified: trunk/reactos/lib/fast486/common.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.c?rev=67... ============================================================================== --- trunk/reactos/lib/fast486/common.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/common.c [iso-8859-1] Thu May 7 03:22:18 2015 @@ -554,22 +554,39 @@ { ULONG NewTssAddress; ULONG NewTssLimit; + FAST486_SYSTEM_DESCRIPTOR NewTssDescriptor; FAST486_TSS OldTss; + PFAST486_LEGACY_TSS OldLegacyTss = (PFAST486_LEGACY_TSS)&OldTss; FAST486_TSS NewTss; - FAST486_SYSTEM_DESCRIPTOR NewTssDescriptor; + PFAST486_LEGACY_TSS NewLegacyTss = (PFAST486_LEGACY_TSS)&NewTss; + USHORT NewLdtr, NewEs, NewCs, NewSs, NewDs; + + if (State->TaskReg.Limit < sizeof(FAST486_TSS) + && State->TaskReg.Limit != sizeof(FAST486_LEGACY_TSS)) + { + /* Invalid task register limit */ + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, State->TaskReg.Selector); + return FALSE; + }
/* Read the old TSS */ if (!Fast486ReadLinearMemory(State, State->TaskReg.Base, &OldTss, - sizeof(OldTss))) + State->TaskReg.Limit >= sizeof(FAST486_TSS) + ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS))) { /* Exception occurred */ return FALSE; }
+ /* If this is a task return, use the linked previous selector */ - if (Type == FAST486_TASK_RETURN) Selector = LOWORD(OldTss.Link); + if (Type == FAST486_TASK_RETURN) + { + if (State->TaskReg.Limit >= sizeof(FAST486_TSS)) Selector = LOWORD(OldTss.Link); + else Selector = OldLegacyTss->Link; + }
/* Make sure the entry exists in the GDT (not LDT!) */ if ((GET_SEGMENT_INDEX(Selector) == 0) @@ -611,9 +628,9 @@ NewTssLimit |= 0x00000FFF; }
- if (NewTssLimit < sizeof(FAST486_TSS)) - { - /* TSS limit too small */ + if (NewTssLimit < sizeof(FAST486_TSS) && NewTssLimit != sizeof(FAST486_LEGACY_TSS)) + { + /* TSS limit invalid */ Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, Selector); return FALSE; } @@ -622,9 +639,11 @@ * The incoming task shouldn't be busy if we're executing it as a * new task, and it should be busy if we're returning to it. */ - if (((NewTssDescriptor.Signature != FAST486_TSS_SIGNATURE) + if ((((NewTssDescriptor.Signature != FAST486_TSS_SIGNATURE) + && (NewTssDescriptor.Signature != FAST486_TSS_16_SIGNATURE)) || (Type == FAST486_TASK_RETURN)) - && ((NewTssDescriptor.Signature != FAST486_BUSY_TSS_SIGNATURE) + && (((NewTssDescriptor.Signature != FAST486_BUSY_TSS_SIGNATURE) + && (NewTssDescriptor.Signature != FAST486_BUSY_TSS_16_SIGNATURE)) || (Type != FAST486_TASK_RETURN))) { Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); @@ -635,7 +654,8 @@ if (!Fast486ReadLinearMemory(State, NewTssAddress, &NewTss, - sizeof(NewTss))) + NewTssLimit >= sizeof(FAST486_TSS) + ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS))) { /* Exception occurred */ return FALSE; @@ -671,34 +691,57 @@ else { /* Store the link */ - NewTss.Link = State->TaskReg.Selector; + if (NewTssLimit >= sizeof(FAST486_TSS)) NewTss.Link = State->TaskReg.Selector; + else NewLegacyTss->Link = State->TaskReg.Selector; }
/* Save the current task into the TSS */ - OldTss.Cr3 = State->ControlRegisters[FAST486_REG_CR3]; - OldTss.Eip = State->InstPtr.Long; - OldTss.Eflags = State->Flags.Long; - OldTss.Eax = State->GeneralRegs[FAST486_REG_EAX].Long; - OldTss.Ecx = State->GeneralRegs[FAST486_REG_ECX].Long; - OldTss.Edx = State->GeneralRegs[FAST486_REG_EDX].Long; - OldTss.Ebx = State->GeneralRegs[FAST486_REG_EBX].Long; - OldTss.Esp = State->GeneralRegs[FAST486_REG_ESP].Long; - OldTss.Ebp = State->GeneralRegs[FAST486_REG_EBP].Long; - OldTss.Esi = State->GeneralRegs[FAST486_REG_ESI].Long; - OldTss.Edi = State->GeneralRegs[FAST486_REG_EDI].Long; - OldTss.Es = State->SegmentRegs[FAST486_REG_ES].Selector; - OldTss.Cs = State->SegmentRegs[FAST486_REG_CS].Selector; - OldTss.Ss = State->SegmentRegs[FAST486_REG_SS].Selector; - OldTss.Ds = State->SegmentRegs[FAST486_REG_DS].Selector; - OldTss.Fs = State->SegmentRegs[FAST486_REG_FS].Selector; - OldTss.Gs = State->SegmentRegs[FAST486_REG_GS].Selector; - OldTss.Ldtr = State->Ldtr.Selector; + if (State->TaskReg.Limit >= sizeof(FAST486_TSS)) + { + OldTss.Cr3 = State->ControlRegisters[FAST486_REG_CR3]; + OldTss.Eip = State->InstPtr.Long; + OldTss.Eflags = State->Flags.Long; + OldTss.Eax = State->GeneralRegs[FAST486_REG_EAX].Long; + OldTss.Ecx = State->GeneralRegs[FAST486_REG_ECX].Long; + OldTss.Edx = State->GeneralRegs[FAST486_REG_EDX].Long; + OldTss.Ebx = State->GeneralRegs[FAST486_REG_EBX].Long; + OldTss.Esp = State->GeneralRegs[FAST486_REG_ESP].Long; + OldTss.Ebp = State->GeneralRegs[FAST486_REG_EBP].Long; + OldTss.Esi = State->GeneralRegs[FAST486_REG_ESI].Long; + OldTss.Edi = State->GeneralRegs[FAST486_REG_EDI].Long; + OldTss.Es = State->SegmentRegs[FAST486_REG_ES].Selector; + OldTss.Cs = State->SegmentRegs[FAST486_REG_CS].Selector; + OldTss.Ss = State->SegmentRegs[FAST486_REG_SS].Selector; + OldTss.Ds = State->SegmentRegs[FAST486_REG_DS].Selector; + OldTss.Fs = State->SegmentRegs[FAST486_REG_FS].Selector; + OldTss.Gs = State->SegmentRegs[FAST486_REG_GS].Selector; + OldTss.Ldtr = State->Ldtr.Selector; + } + else + { + OldLegacyTss->Ip = State->InstPtr.LowWord; + OldLegacyTss->Flags = State->Flags.LowWord; + OldLegacyTss->Ax = State->GeneralRegs[FAST486_REG_EAX].LowWord; + OldLegacyTss->Cx = State->GeneralRegs[FAST486_REG_ECX].LowWord; + OldLegacyTss->Dx = State->GeneralRegs[FAST486_REG_EDX].LowWord; + OldLegacyTss->Bx = State->GeneralRegs[FAST486_REG_EBX].LowWord; + OldLegacyTss->Sp = State->GeneralRegs[FAST486_REG_ESP].LowWord; + OldLegacyTss->Bp = State->GeneralRegs[FAST486_REG_EBP].LowWord; + OldLegacyTss->Si = State->GeneralRegs[FAST486_REG_ESI].LowWord; + OldLegacyTss->Di = State->GeneralRegs[FAST486_REG_EDI].LowWord; + OldLegacyTss->Es = State->SegmentRegs[FAST486_REG_ES].Selector; + OldLegacyTss->Cs = State->SegmentRegs[FAST486_REG_CS].Selector; + OldLegacyTss->Ss = State->SegmentRegs[FAST486_REG_SS].Selector; + OldLegacyTss->Ds = State->SegmentRegs[FAST486_REG_DS].Selector; + OldLegacyTss->Ldtr = State->Ldtr.Selector; + }
/* Write back the old TSS */ if (!Fast486WriteLinearMemory(State, State->TaskReg.Base, &OldTss, - sizeof(OldTss))) + State->TaskReg.Limit >= sizeof(FAST486_TSS) + ? sizeof(FAST486_TSS) : sizeof(FAST486_LEGACY_TSS))) { /* Exception occurred */ return FALSE; @@ -725,54 +768,78 @@ State->TaskReg.Base = NewTssAddress; State->TaskReg.Limit = NewTssLimit;
- /* Change the page directory */ - State->ControlRegisters[FAST486_REG_CR3] = NewTss.Cr3; + if (NewTssLimit >= sizeof(FAST486_TSS)) + { + /* Change the page directory */ + State->ControlRegisters[FAST486_REG_CR3] = NewTss.Cr3; + }
/* Flush the TLB */ if (State->Tlb) RtlZeroMemory(State->Tlb, NUM_TLB_ENTRIES * sizeof(ULONG));
/* Update the CPL */ - State->Cpl = GET_SEGMENT_RPL(NewTss.Cs); + if (NewTssLimit >= sizeof(FAST486_TSS)) State->Cpl = GET_SEGMENT_RPL(NewTss.Cs); + else State->Cpl = GET_SEGMENT_RPL(NewLegacyTss->Cs);
#ifndef FAST486_NO_PREFETCH /* Context switching invalidates the prefetch */ State->PrefetchValid = FALSE; #endif
- /* Update the CPL */ - State->Cpl = GET_SEGMENT_RPL(NewTss.Cs); - /* Load the registers */ - State->InstPtr.Long = State->SavedInstPtr.Long = NewTss.Eip; - State->Flags.Long = NewTss.Eflags; - State->GeneralRegs[FAST486_REG_EAX].Long = NewTss.Eax; - State->GeneralRegs[FAST486_REG_ECX].Long = NewTss.Ecx; - State->GeneralRegs[FAST486_REG_EDX].Long = NewTss.Edx; - State->GeneralRegs[FAST486_REG_EBX].Long = NewTss.Ebx; - State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp; - State->GeneralRegs[FAST486_REG_EBP].Long = NewTss.Ebp; - State->GeneralRegs[FAST486_REG_ESI].Long = NewTss.Esi; - State->GeneralRegs[FAST486_REG_EDI].Long = NewTss.Edi; + if (NewTssLimit >= sizeof(FAST486_TSS)) + { + State->InstPtr.Long = State->SavedInstPtr.Long = NewTss.Eip; + State->Flags.Long = NewTss.Eflags; + State->GeneralRegs[FAST486_REG_EAX].Long = NewTss.Eax; + State->GeneralRegs[FAST486_REG_ECX].Long = NewTss.Ecx; + State->GeneralRegs[FAST486_REG_EDX].Long = NewTss.Edx; + State->GeneralRegs[FAST486_REG_EBX].Long = NewTss.Ebx; + State->GeneralRegs[FAST486_REG_ESP].Long = NewTss.Esp; + State->GeneralRegs[FAST486_REG_EBP].Long = NewTss.Ebp; + State->GeneralRegs[FAST486_REG_ESI].Long = NewTss.Esi; + State->GeneralRegs[FAST486_REG_EDI].Long = NewTss.Edi; + NewEs = NewTss.Es; + NewCs = NewTss.Cs; + NewSs = NewTss.Ss; + NewDs = NewTss.Ds; + NewLdtr = NewTss.Ldtr; + } + else + { + State->InstPtr.LowWord = State->SavedInstPtr.LowWord = NewLegacyTss->Ip; + State->Flags.LowWord = NewLegacyTss->Flags; + State->GeneralRegs[FAST486_REG_EAX].LowWord = NewLegacyTss->Ax; + State->GeneralRegs[FAST486_REG_ECX].LowWord = NewLegacyTss->Cx; + State->GeneralRegs[FAST486_REG_EDX].LowWord = NewLegacyTss->Dx; + State->GeneralRegs[FAST486_REG_EBX].LowWord = NewLegacyTss->Bx; + State->GeneralRegs[FAST486_REG_ESP].LowWord = NewLegacyTss->Sp; + State->GeneralRegs[FAST486_REG_EBP].LowWord = NewLegacyTss->Bp; + State->GeneralRegs[FAST486_REG_ESI].LowWord = NewLegacyTss->Si; + State->GeneralRegs[FAST486_REG_EDI].LowWord = NewLegacyTss->Di; + NewEs = NewLegacyTss->Es; + NewCs = NewLegacyTss->Cs; + NewSs = NewLegacyTss->Ss; + NewDs = NewLegacyTss->Ds; + NewLdtr = NewLegacyTss->Ldtr; + }
/* Set the NT flag if nesting */ if (Type == FAST486_TASK_CALL) State->Flags.Nt = TRUE;
- if (GET_SEGMENT_INDEX(NewTss.Ldtr) != 0) + if (GET_SEGMENT_INDEX(NewLdtr) != 0) { BOOLEAN Valid; FAST486_SYSTEM_DESCRIPTOR GdtEntry;
- if (NewTss.Ldtr & SEGMENT_TABLE_INDICATOR) + if (NewLdtr & SEGMENT_TABLE_INDICATOR) { /* This selector doesn't point to the GDT */ - Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewTss.Ldtr); - return FALSE; - } - - if (!Fast486ReadDescriptorEntry(State, - NewTss.Ldtr, - &Valid, - (PFAST486_GDT_ENTRY)&GdtEntry)) + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr); + return FALSE; + } + + if (!Fast486ReadDescriptorEntry(State, NewLdtr, &Valid, (PFAST486_GDT_ENTRY)&GdtEntry)) { /* Exception occurred */ return FALSE; @@ -781,25 +848,25 @@ if (!Valid) { /* Invalid selector */ - Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewTss.Ldtr); + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr); return FALSE; }
if (GdtEntry.Signature != FAST486_LDT_SIGNATURE) { /* This is not an LDT descriptor */ - Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewTss.Ldtr); + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr); return FALSE; }
if (!GdtEntry.Present) { - Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewTss.Ldtr); + Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_TS, NewLdtr); return FALSE; }
/* Update the LDTR */ - State->Ldtr.Selector = NewTss.Ldtr; + State->Ldtr.Selector = NewLdtr; State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
@@ -816,52 +883,43 @@ }
/* Load the new segments */ - if (!Fast486LoadSegmentInternal(State, - FAST486_REG_CS, - NewTss.Cs, - FAST486_EXCEPTION_TS)) - { - return FALSE; - } - - if (!Fast486LoadSegmentInternal(State, - FAST486_REG_SS, - NewTss.Ss, - FAST486_EXCEPTION_TS)) - { - return FALSE; - } - - if (!Fast486LoadSegmentInternal(State, - FAST486_REG_ES, - NewTss.Es, - FAST486_EXCEPTION_TS)) - { - return FALSE; - } - - if (!Fast486LoadSegmentInternal(State, - FAST486_REG_DS, - NewTss.Ds, - FAST486_EXCEPTION_TS)) - { - return FALSE; - } - - if (!Fast486LoadSegmentInternal(State, - FAST486_REG_FS, - NewTss.Fs, - FAST486_EXCEPTION_TS)) - { - return FALSE; - } - - if (!Fast486LoadSegmentInternal(State, - FAST486_REG_GS, - NewTss.Gs, - FAST486_EXCEPTION_TS)) - { - return FALSE; + if (!Fast486LoadSegmentInternal(State, FAST486_REG_CS, NewCs, FAST486_EXCEPTION_TS)) + { + return FALSE; + } + + if (!Fast486LoadSegmentInternal(State, FAST486_REG_SS, NewSs, FAST486_EXCEPTION_TS)) + { + return FALSE; + } + + if (!Fast486LoadSegmentInternal(State, FAST486_REG_ES, NewEs, FAST486_EXCEPTION_TS)) + { + return FALSE; + } + + if (!Fast486LoadSegmentInternal(State, FAST486_REG_DS, NewDs, FAST486_EXCEPTION_TS)) + { + return FALSE; + } + + if (NewTssLimit >= sizeof(FAST486_TSS)) + { + if (!Fast486LoadSegmentInternal(State, + FAST486_REG_FS, + NewTss.Fs, + FAST486_EXCEPTION_TS)) + { + return FALSE; + } + + if (!Fast486LoadSegmentInternal(State, + FAST486_REG_GS, + NewTss.Gs, + FAST486_EXCEPTION_TS)) + { + return FALSE; + } }
return TRUE;
Modified: trunk/reactos/lib/fast486/common.inl URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.inl?rev=... ============================================================================== --- trunk/reactos/lib/fast486/common.inl [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/common.inl [iso-8859-1] Thu May 7 03:22:18 2015 @@ -773,7 +773,10 @@ return FALSE; }
+ case FAST486_TSS_16_SIGNATURE: + case FAST486_BUSY_TSS_16_SIGNATURE: case FAST486_TSS_SIGNATURE: + case FAST486_BUSY_TSS_SIGNATURE: { Fast486TaskSwitch(State, Call ? FAST486_TASK_CALL : FAST486_TASK_JUMP,