diff -r 000000000000 -r a41df078684a kernel/eka/nkern/x86/ncthrd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/nkern/x86/ncthrd.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,430 @@ +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\nkern\x86\ncthrd.cpp +// +// + +#include + +// Called by a thread when it first runs +void __StartThread(); +void __DoForcedExit(); + +void NThreadBase::OnKill() + { + } + + +void NThreadBase::OnExit() + { + } + + +void NThreadBase::SetEntry(NThreadFunction aFunc) + { + SThreadStack* stack=(SThreadStack*)iSavedSP; + stack->iEdi=(TUint32)aFunc; + } + + +TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial) + { + if (!anInfo.iStackBase || anInfo.iStackSize<0x100) + return KErrArgument; + TInt r=NThreadBase::Create(anInfo,aInitial); + if (r!=KErrNone) + return r; + if (!aInitial) + { + TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize); + TUint32 esi=(TUint32)anInfo.iParameterBlock; + if (anInfo.iParameterBlockSize) + { + wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize); + esi=(TUint32)sp; + } + SThreadStack* stack=((SThreadStack*)sp)-1; + stack->iCR0=X86::DefaultCR0 | KX86CR0_TS; + stack->iEbx=0; + stack->iEsi=esi; // parameter block pointer + stack->iEdi=(TUint32)anInfo.iFunction; + stack->iEbp=0; + stack->iGs=KRing0DS; + stack->iFs=0; + stack->iReschedFlag=1; + stack->iEip=(TUint32)__StartThread; + iSavedSP=(TLinAddr)stack; + wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState)); + } + else + { +#ifdef MONITOR_THREAD_CPU_TIME + iLastStartTime = NKern::FastCounter(); +#endif + NKern::EnableAllInterrupts(); + } +#ifdef BTRACE_THREAD_IDENTIFICATION + BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this); +#endif + return KErrNone; + } + + +void NThreadBase::ForceExit() + { + SThreadStack* stack=(SThreadStack*)iSavedSP; + stack->iEip=(TUint32)__DoForcedExit; + } + + +void DumpExcInfo(TX86ExcInfo& a) + { + DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode); + DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx); + DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi); + DEBUGPRINT(" CS=%08x EIP=%08x DS=%08x SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs); + DEBUGPRINT(" ES=%08x FS=%08x GS=%08x",a.iEs,a.iFs,a.iGs); + if (a.iCs&3) + { + DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3); + } + DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount); + } + + +EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask) + { + CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext"); + TUint32* sp; + TUint32* stackTop; + TX86RegSet* regSet = (TX86RegSet*)aContext; + TInt delta; + + NKern::Lock(); + + NThread* currentThread = NCurrentThread(); + DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread); + + switch (NKern::CurrentContext()) + { + case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break; + case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break; + case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break; + default: DEBUGPRINT(" CurrentContext= Unknown"); break; + } + + DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2); + DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize); + + DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount); + + DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack); + + TBool isCurrentThread = (currentThread == aThread); + + sp = (TUint32*)aThread->iSavedSP; + stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize); + delta = stackTop - sp; // number of words on the supervisor stack + + DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta); + DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3); + + DEBUGPRINT(" NThreadState:"); + switch(aThread->iSpare1) + { + case NThreadBase::EReady: + DEBUGPRINT(" EReady"); + break; + case NThreadBase::ESuspended: + DEBUGPRINT(" ESuspended"); + break; + case NThreadBase::EWaitFastSemaphore: + DEBUGPRINT(" EWaitFastSemaphore"); + break; + case NThreadBase::ESleep: + DEBUGPRINT(" ESleep"); + break; + case NThreadBase::EBlocked: + DEBUGPRINT(" EBlocked"); + break; + case NThreadBase::EDead: + DEBUGPRINT(" EDead"); + break; + case NThreadBase::EWaitDfc: + DEBUGPRINT(" EWaitDfc"); + break; + default: + DEBUGPRINT(" *Unknown"); + } + + if (aAvailMask) + { + DEBUGPRINT(" Setting Stack-Saved Registers"); + // Hack while ThreadSetUserContext is not implemented + + if (0 == aThread->iSpare3) + { + // Context when interrupted by user + if (aAvailMask & 1<<13) + stackTop[-1] = regSet->iSs; + + if (aAvailMask & 1<<4) + stackTop[-2] = regSet->iEsp; + + if (aAvailMask & 1<<14) + { + DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags); + stackTop[-3] = regSet->iEflags; + } + + if (aAvailMask & 1<<8) + stackTop[-4] = regSet->iCs; + + if (aAvailMask & 1<<15) + stackTop[-5] = regSet->iEip; + + if (aAvailMask & 1<<9) + stackTop[-8] = regSet->iDs; + + if (aAvailMask & 1<<0) + stackTop[-9] = regSet->iEax; + + if (aAvailMask & 1<<2) + stackTop[-10] = regSet->iEcx; + + if (aAvailMask & 1<<5) + stackTop[-16] = regSet->iEbp; + + if (aAvailMask & 1<<7) + stackTop[-17] = regSet->iEdi; + + if (aAvailMask & 1<<6) + stackTop[-18] = regSet->iEsi; + } + else + { + if (aAvailMask & 1<<13) + stackTop[-1] = regSet->iSs; + + if (aAvailMask & 1<<4) + stackTop[-2] = regSet->iEsp; + + if (aAvailMask & 1<<14) + { + stackTop[-3] = regSet->iEflags; + DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags); + } + + if (aAvailMask & 1<<8) + stackTop[-4] = regSet->iCs; + + if (aAvailMask & 1<<15) + stackTop[-5] = regSet->iEip; + + /* -6 and -7 are not used since they are the vector number and the error code, + * which are 3 and 0 resp. for breakpoints. + */ + + /* The following are from the push instructions in __X86VectorExc */ + if (aAvailMask & 1<<9) + stackTop[-8] = regSet->iDs; + + if (aAvailMask & 1<<10) + stackTop[-9] = regSet->iEs; + + if (aAvailMask & 1<<11) + stackTop[-10] = regSet->iFs; + + if (aAvailMask & 1<<12) + stackTop[-11] = regSet->iGs; + + if (aAvailMask & 1<<5) + stackTop[-12] = regSet->iEbp; + + if (aAvailMask & 1<<7) + stackTop[-13] = regSet->iEdi; + + if (aAvailMask & 1<<6) + stackTop[-14] = regSet->iEsi; + + if (aAvailMask & 1<<1) + stackTop[-15] = regSet->iEbx; + + if (aAvailMask & 1<<2) + stackTop[-16] = regSet->iEcx; + + if (aAvailMask & 1<<3) + stackTop[-17] = regSet->iEdx; + + if (aAvailMask & 1<<0) + stackTop[-18] = regSet->iEax; + } + + DEBUGPRINT("stack from stack top, after changes " ); + if (delta < 128) + { + delta = -delta; + } + else + { + delta = -128; + } + + for ( ; delta < 0; delta++) + { + DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]); + } + } + else + { + memclr(aContext, sizeof(TX86RegSet)); + + if (isCurrentThread) + { + // Not yet supported + DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?"); + } + else + { + DEBUGPRINT("stack from stack top " ); + + if (delta < 128) + { + delta = -delta; + } + else + { + delta = -128; + } + + for( ; delta < 0; delta++) + { + DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]); + } + + if (0 == aThread->iSpare3) + { + // Context when interrupted by user + regSet->iSs = stackTop[-1]; + aAvailMask |= 1<<13; + + regSet->iEsp = stackTop[-2]; + aAvailMask |= 1<<4; + + regSet->iEflags = stackTop[-3]; + aAvailMask |= 1<<14; + + regSet->iCs = stackTop[-4]; + aAvailMask |= 1<<8; + + regSet->iEip = stackTop[-5]; + aAvailMask |= 1<<15; + + regSet->iDs = stackTop[-8]; + aAvailMask |= 1<<9; + + regSet->iEax = stackTop[-9]; + aAvailMask |= 1<<0; + + regSet->iEcx = stackTop[-10]; + aAvailMask |= 1<<2; + + regSet->iEbp = stackTop[-16]; + aAvailMask |= 1<<5; + + regSet->iEdi = stackTop[-17]; + aAvailMask |= 1<<7; + + regSet->iEsi = stackTop[-18]; + aAvailMask |= 1<<6; + } + else + { + // Now populate the TX86RegSet with the contents of the stack + + /* + * The first 5 are from the comments at the start of __X86VectorExc : + * [ESP+0] = vector number + * [ESP+4] = error code (filled with 0 for exceptions without error codes) + * [ESP+8] = return EIP + * [ESP+12] = return CS + * [ESP+16] = return EFLAGS + * [ESP+20] = return ESP if privilege change occurred + * [ESP+24] = return SS if privilege change occurred + */ + regSet->iSs = stackTop[-1]; + aAvailMask |= 1<<13; + + regSet->iEsp = stackTop[-2]; + aAvailMask |= 1<<4; + + regSet->iEflags = stackTop[-3]; + aAvailMask |= 1<<14; + + regSet->iCs = stackTop[-4]; + aAvailMask |= 1<<8; + + regSet->iEip = stackTop[-5]; + aAvailMask |= 1<<15; + + /* -6 and -7 are not used since they are the vector number and the error code, + * which for a breakpoint are 3 and 0 resp. + */ + + /* The following are from the push instructions in __X86VectorExc */ + regSet->iDs = stackTop[-8]; + aAvailMask |= 1<<9; + + regSet->iEs = stackTop[-9]; + aAvailMask |= 1<<10; + + regSet->iFs = stackTop[-10]; + aAvailMask |= 1<<11; + + regSet->iGs = stackTop[-11]; + aAvailMask |= 1<<12; + + regSet->iEbp = stackTop[-12]; + aAvailMask |= 1<<5; + + regSet->iEdi = stackTop[-13]; + aAvailMask |= 1<<7; + + regSet->iEsi = stackTop[-14]; + aAvailMask |= 1<<6; + + regSet->iEbx = stackTop[-15]; + aAvailMask |= 1<<1; + + regSet->iEcx = stackTop[-16]; + aAvailMask |= 1<<2; + + regSet->iEdx = stackTop[-17]; + aAvailMask |= 1<<3; + + regSet->iEax = stackTop[-18]; + aAvailMask |= 1<<0; + } // else if (0 == aThread->iSpare3) + + } // else if (isCurrentThread) + + } // else if (aAvailMask) + + NKern::Unlock(); + } + + +void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp) + { + }