1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/nkern/x86/ncthrd.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,430 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\nkern\x86\ncthrd.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <x86.h>
1.22 +
1.23 +// Called by a thread when it first runs
1.24 +void __StartThread();
1.25 +void __DoForcedExit();
1.26 +
1.27 +void NThreadBase::OnKill()
1.28 + {
1.29 + }
1.30 +
1.31 +
1.32 +void NThreadBase::OnExit()
1.33 + {
1.34 + }
1.35 +
1.36 +
1.37 +void NThreadBase::SetEntry(NThreadFunction aFunc)
1.38 + {
1.39 + SThreadStack* stack=(SThreadStack*)iSavedSP;
1.40 + stack->iEdi=(TUint32)aFunc;
1.41 + }
1.42 +
1.43 +
1.44 +TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial)
1.45 + {
1.46 + if (!anInfo.iStackBase || anInfo.iStackSize<0x100)
1.47 + return KErrArgument;
1.48 + TInt r=NThreadBase::Create(anInfo,aInitial);
1.49 + if (r!=KErrNone)
1.50 + return r;
1.51 + if (!aInitial)
1.52 + {
1.53 + TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize);
1.54 + TUint32 esi=(TUint32)anInfo.iParameterBlock;
1.55 + if (anInfo.iParameterBlockSize)
1.56 + {
1.57 + wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize);
1.58 + esi=(TUint32)sp;
1.59 + }
1.60 + SThreadStack* stack=((SThreadStack*)sp)-1;
1.61 + stack->iCR0=X86::DefaultCR0 | KX86CR0_TS;
1.62 + stack->iEbx=0;
1.63 + stack->iEsi=esi; // parameter block pointer
1.64 + stack->iEdi=(TUint32)anInfo.iFunction;
1.65 + stack->iEbp=0;
1.66 + stack->iGs=KRing0DS;
1.67 + stack->iFs=0;
1.68 + stack->iReschedFlag=1;
1.69 + stack->iEip=(TUint32)__StartThread;
1.70 + iSavedSP=(TLinAddr)stack;
1.71 + wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState));
1.72 + }
1.73 + else
1.74 + {
1.75 +#ifdef MONITOR_THREAD_CPU_TIME
1.76 + iLastStartTime = NKern::FastCounter();
1.77 +#endif
1.78 + NKern::EnableAllInterrupts();
1.79 + }
1.80 +#ifdef BTRACE_THREAD_IDENTIFICATION
1.81 + BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
1.82 +#endif
1.83 + return KErrNone;
1.84 + }
1.85 +
1.86 +
1.87 +void NThreadBase::ForceExit()
1.88 + {
1.89 + SThreadStack* stack=(SThreadStack*)iSavedSP;
1.90 + stack->iEip=(TUint32)__DoForcedExit;
1.91 + }
1.92 +
1.93 +
1.94 +void DumpExcInfo(TX86ExcInfo& a)
1.95 + {
1.96 + DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode);
1.97 + DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx);
1.98 + DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi);
1.99 + DEBUGPRINT(" CS=%08x EIP=%08x DS=%08x SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs);
1.100 + DEBUGPRINT(" ES=%08x FS=%08x GS=%08x",a.iEs,a.iFs,a.iGs);
1.101 + if (a.iCs&3)
1.102 + {
1.103 + DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3);
1.104 + }
1.105 + DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount);
1.106 + }
1.107 +
1.108 +
1.109 +EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask)
1.110 + {
1.111 + CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext");
1.112 + TUint32* sp;
1.113 + TUint32* stackTop;
1.114 + TX86RegSet* regSet = (TX86RegSet*)aContext;
1.115 + TInt delta;
1.116 +
1.117 + NKern::Lock();
1.118 +
1.119 + NThread* currentThread = NCurrentThread();
1.120 + DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread);
1.121 +
1.122 + switch (NKern::CurrentContext())
1.123 + {
1.124 + case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break;
1.125 + case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break;
1.126 + case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break;
1.127 + default: DEBUGPRINT(" CurrentContext= Unknown"); break;
1.128 + }
1.129 +
1.130 + DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2);
1.131 + DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize);
1.132 +
1.133 + DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount);
1.134 +
1.135 + DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack);
1.136 +
1.137 + TBool isCurrentThread = (currentThread == aThread);
1.138 +
1.139 + sp = (TUint32*)aThread->iSavedSP;
1.140 + stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize);
1.141 + delta = stackTop - sp; // number of words on the supervisor stack
1.142 +
1.143 + DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta);
1.144 + DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3);
1.145 +
1.146 + DEBUGPRINT(" NThreadState:");
1.147 + switch(aThread->iSpare1)
1.148 + {
1.149 + case NThreadBase::EReady:
1.150 + DEBUGPRINT(" EReady");
1.151 + break;
1.152 + case NThreadBase::ESuspended:
1.153 + DEBUGPRINT(" ESuspended");
1.154 + break;
1.155 + case NThreadBase::EWaitFastSemaphore:
1.156 + DEBUGPRINT(" EWaitFastSemaphore");
1.157 + break;
1.158 + case NThreadBase::ESleep:
1.159 + DEBUGPRINT(" ESleep");
1.160 + break;
1.161 + case NThreadBase::EBlocked:
1.162 + DEBUGPRINT(" EBlocked");
1.163 + break;
1.164 + case NThreadBase::EDead:
1.165 + DEBUGPRINT(" EDead");
1.166 + break;
1.167 + case NThreadBase::EWaitDfc:
1.168 + DEBUGPRINT(" EWaitDfc");
1.169 + break;
1.170 + default:
1.171 + DEBUGPRINT(" *Unknown");
1.172 + }
1.173 +
1.174 + if (aAvailMask)
1.175 + {
1.176 + DEBUGPRINT(" Setting Stack-Saved Registers");
1.177 + // Hack while ThreadSetUserContext is not implemented
1.178 +
1.179 + if (0 == aThread->iSpare3)
1.180 + {
1.181 + // Context when interrupted by user
1.182 + if (aAvailMask & 1<<13)
1.183 + stackTop[-1] = regSet->iSs;
1.184 +
1.185 + if (aAvailMask & 1<<4)
1.186 + stackTop[-2] = regSet->iEsp;
1.187 +
1.188 + if (aAvailMask & 1<<14)
1.189 + {
1.190 + DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
1.191 + stackTop[-3] = regSet->iEflags;
1.192 + }
1.193 +
1.194 + if (aAvailMask & 1<<8)
1.195 + stackTop[-4] = regSet->iCs;
1.196 +
1.197 + if (aAvailMask & 1<<15)
1.198 + stackTop[-5] = regSet->iEip;
1.199 +
1.200 + if (aAvailMask & 1<<9)
1.201 + stackTop[-8] = regSet->iDs;
1.202 +
1.203 + if (aAvailMask & 1<<0)
1.204 + stackTop[-9] = regSet->iEax;
1.205 +
1.206 + if (aAvailMask & 1<<2)
1.207 + stackTop[-10] = regSet->iEcx;
1.208 +
1.209 + if (aAvailMask & 1<<5)
1.210 + stackTop[-16] = regSet->iEbp;
1.211 +
1.212 + if (aAvailMask & 1<<7)
1.213 + stackTop[-17] = regSet->iEdi;
1.214 +
1.215 + if (aAvailMask & 1<<6)
1.216 + stackTop[-18] = regSet->iEsi;
1.217 + }
1.218 + else
1.219 + {
1.220 + if (aAvailMask & 1<<13)
1.221 + stackTop[-1] = regSet->iSs;
1.222 +
1.223 + if (aAvailMask & 1<<4)
1.224 + stackTop[-2] = regSet->iEsp;
1.225 +
1.226 + if (aAvailMask & 1<<14)
1.227 + {
1.228 + stackTop[-3] = regSet->iEflags;
1.229 + DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
1.230 + }
1.231 +
1.232 + if (aAvailMask & 1<<8)
1.233 + stackTop[-4] = regSet->iCs;
1.234 +
1.235 + if (aAvailMask & 1<<15)
1.236 + stackTop[-5] = regSet->iEip;
1.237 +
1.238 + /* -6 and -7 are not used since they are the vector number and the error code,
1.239 + * which are 3 and 0 resp. for breakpoints.
1.240 + */
1.241 +
1.242 + /* The following are from the push instructions in __X86VectorExc */
1.243 + if (aAvailMask & 1<<9)
1.244 + stackTop[-8] = regSet->iDs;
1.245 +
1.246 + if (aAvailMask & 1<<10)
1.247 + stackTop[-9] = regSet->iEs;
1.248 +
1.249 + if (aAvailMask & 1<<11)
1.250 + stackTop[-10] = regSet->iFs;
1.251 +
1.252 + if (aAvailMask & 1<<12)
1.253 + stackTop[-11] = regSet->iGs;
1.254 +
1.255 + if (aAvailMask & 1<<5)
1.256 + stackTop[-12] = regSet->iEbp;
1.257 +
1.258 + if (aAvailMask & 1<<7)
1.259 + stackTop[-13] = regSet->iEdi;
1.260 +
1.261 + if (aAvailMask & 1<<6)
1.262 + stackTop[-14] = regSet->iEsi;
1.263 +
1.264 + if (aAvailMask & 1<<1)
1.265 + stackTop[-15] = regSet->iEbx;
1.266 +
1.267 + if (aAvailMask & 1<<2)
1.268 + stackTop[-16] = regSet->iEcx;
1.269 +
1.270 + if (aAvailMask & 1<<3)
1.271 + stackTop[-17] = regSet->iEdx;
1.272 +
1.273 + if (aAvailMask & 1<<0)
1.274 + stackTop[-18] = regSet->iEax;
1.275 + }
1.276 +
1.277 + DEBUGPRINT("stack from stack top, after changes " );
1.278 + if (delta < 128)
1.279 + {
1.280 + delta = -delta;
1.281 + }
1.282 + else
1.283 + {
1.284 + delta = -128;
1.285 + }
1.286 +
1.287 + for ( ; delta < 0; delta++)
1.288 + {
1.289 + DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
1.290 + }
1.291 + }
1.292 + else
1.293 + {
1.294 + memclr(aContext, sizeof(TX86RegSet));
1.295 +
1.296 + if (isCurrentThread)
1.297 + {
1.298 + // Not yet supported
1.299 + DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?");
1.300 + }
1.301 + else
1.302 + {
1.303 + DEBUGPRINT("stack from stack top " );
1.304 +
1.305 + if (delta < 128)
1.306 + {
1.307 + delta = -delta;
1.308 + }
1.309 + else
1.310 + {
1.311 + delta = -128;
1.312 + }
1.313 +
1.314 + for( ; delta < 0; delta++)
1.315 + {
1.316 + DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
1.317 + }
1.318 +
1.319 + if (0 == aThread->iSpare3)
1.320 + {
1.321 + // Context when interrupted by user
1.322 + regSet->iSs = stackTop[-1];
1.323 + aAvailMask |= 1<<13;
1.324 +
1.325 + regSet->iEsp = stackTop[-2];
1.326 + aAvailMask |= 1<<4;
1.327 +
1.328 + regSet->iEflags = stackTop[-3];
1.329 + aAvailMask |= 1<<14;
1.330 +
1.331 + regSet->iCs = stackTop[-4];
1.332 + aAvailMask |= 1<<8;
1.333 +
1.334 + regSet->iEip = stackTop[-5];
1.335 + aAvailMask |= 1<<15;
1.336 +
1.337 + regSet->iDs = stackTop[-8];
1.338 + aAvailMask |= 1<<9;
1.339 +
1.340 + regSet->iEax = stackTop[-9];
1.341 + aAvailMask |= 1<<0;
1.342 +
1.343 + regSet->iEcx = stackTop[-10];
1.344 + aAvailMask |= 1<<2;
1.345 +
1.346 + regSet->iEbp = stackTop[-16];
1.347 + aAvailMask |= 1<<5;
1.348 +
1.349 + regSet->iEdi = stackTop[-17];
1.350 + aAvailMask |= 1<<7;
1.351 +
1.352 + regSet->iEsi = stackTop[-18];
1.353 + aAvailMask |= 1<<6;
1.354 + }
1.355 + else
1.356 + {
1.357 + // Now populate the TX86RegSet with the contents of the stack
1.358 +
1.359 + /*
1.360 + * The first 5 are from the comments at the start of __X86VectorExc :
1.361 + * [ESP+0] = vector number
1.362 + * [ESP+4] = error code (filled with 0 for exceptions without error codes)
1.363 + * [ESP+8] = return EIP
1.364 + * [ESP+12] = return CS
1.365 + * [ESP+16] = return EFLAGS
1.366 + * [ESP+20] = return ESP if privilege change occurred
1.367 + * [ESP+24] = return SS if privilege change occurred
1.368 + */
1.369 + regSet->iSs = stackTop[-1];
1.370 + aAvailMask |= 1<<13;
1.371 +
1.372 + regSet->iEsp = stackTop[-2];
1.373 + aAvailMask |= 1<<4;
1.374 +
1.375 + regSet->iEflags = stackTop[-3];
1.376 + aAvailMask |= 1<<14;
1.377 +
1.378 + regSet->iCs = stackTop[-4];
1.379 + aAvailMask |= 1<<8;
1.380 +
1.381 + regSet->iEip = stackTop[-5];
1.382 + aAvailMask |= 1<<15;
1.383 +
1.384 + /* -6 and -7 are not used since they are the vector number and the error code,
1.385 + * which for a breakpoint are 3 and 0 resp.
1.386 + */
1.387 +
1.388 + /* The following are from the push instructions in __X86VectorExc */
1.389 + regSet->iDs = stackTop[-8];
1.390 + aAvailMask |= 1<<9;
1.391 +
1.392 + regSet->iEs = stackTop[-9];
1.393 + aAvailMask |= 1<<10;
1.394 +
1.395 + regSet->iFs = stackTop[-10];
1.396 + aAvailMask |= 1<<11;
1.397 +
1.398 + regSet->iGs = stackTop[-11];
1.399 + aAvailMask |= 1<<12;
1.400 +
1.401 + regSet->iEbp = stackTop[-12];
1.402 + aAvailMask |= 1<<5;
1.403 +
1.404 + regSet->iEdi = stackTop[-13];
1.405 + aAvailMask |= 1<<7;
1.406 +
1.407 + regSet->iEsi = stackTop[-14];
1.408 + aAvailMask |= 1<<6;
1.409 +
1.410 + regSet->iEbx = stackTop[-15];
1.411 + aAvailMask |= 1<<1;
1.412 +
1.413 + regSet->iEcx = stackTop[-16];
1.414 + aAvailMask |= 1<<2;
1.415 +
1.416 + regSet->iEdx = stackTop[-17];
1.417 + aAvailMask |= 1<<3;
1.418 +
1.419 + regSet->iEax = stackTop[-18];
1.420 + aAvailMask |= 1<<0;
1.421 + } // else if (0 == aThread->iSpare3)
1.422 +
1.423 + } // else if (isCurrentThread)
1.424 +
1.425 + } // else if (aAvailMask)
1.426 +
1.427 + NKern::Unlock();
1.428 + }
1.429 +
1.430 +
1.431 +void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp)
1.432 + {
1.433 + }