kernel/eka/nkern/x86/ncthrd.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\nkern\x86\ncthrd.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <x86.h>
       
    19 
       
    20 // Called by a thread when it first runs
       
    21 void __StartThread();
       
    22 void __DoForcedExit();
       
    23 
       
    24 void NThreadBase::OnKill()
       
    25 	{
       
    26 	}
       
    27 
       
    28 
       
    29 void NThreadBase::OnExit()
       
    30 	{
       
    31 	}
       
    32 
       
    33 
       
    34 void NThreadBase::SetEntry(NThreadFunction aFunc)
       
    35 	{
       
    36 	SThreadStack* stack=(SThreadStack*)iSavedSP;
       
    37 	stack->iEdi=(TUint32)aFunc;
       
    38 	}
       
    39 
       
    40 
       
    41 TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial)
       
    42 	{
       
    43 	if (!anInfo.iStackBase || anInfo.iStackSize<0x100)
       
    44 		return KErrArgument;
       
    45 	TInt r=NThreadBase::Create(anInfo,aInitial);
       
    46 	if (r!=KErrNone)
       
    47 		return r;
       
    48 	if (!aInitial)
       
    49 		{
       
    50 		TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize);
       
    51 		TUint32 esi=(TUint32)anInfo.iParameterBlock;
       
    52 		if (anInfo.iParameterBlockSize)
       
    53 			{
       
    54 			wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize);
       
    55 			esi=(TUint32)sp;
       
    56 			}
       
    57 		SThreadStack* stack=((SThreadStack*)sp)-1;
       
    58 		stack->iCR0=X86::DefaultCR0 | KX86CR0_TS;
       
    59 		stack->iEbx=0;
       
    60 		stack->iEsi=esi;					// parameter block pointer
       
    61 		stack->iEdi=(TUint32)anInfo.iFunction;
       
    62 		stack->iEbp=0;
       
    63 		stack->iGs=KRing0DS;
       
    64 		stack->iFs=0;
       
    65 		stack->iReschedFlag=1;
       
    66 		stack->iEip=(TUint32)__StartThread;
       
    67 		iSavedSP=(TLinAddr)stack;
       
    68 		wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState));
       
    69 		}
       
    70 	else
       
    71 		{
       
    72 #ifdef MONITOR_THREAD_CPU_TIME
       
    73 		iLastStartTime = NKern::FastCounter();
       
    74 #endif
       
    75 		NKern::EnableAllInterrupts();
       
    76 		}
       
    77 #ifdef BTRACE_THREAD_IDENTIFICATION
       
    78 	BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
       
    79 #endif
       
    80 	return KErrNone;
       
    81 	}
       
    82 
       
    83 
       
    84 void NThreadBase::ForceExit()
       
    85 	{
       
    86 	SThreadStack* stack=(SThreadStack*)iSavedSP;
       
    87 	stack->iEip=(TUint32)__DoForcedExit;
       
    88 	}
       
    89 
       
    90 
       
    91 void DumpExcInfo(TX86ExcInfo& a)
       
    92 	{
       
    93 	DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode);
       
    94 	DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx);
       
    95 	DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi);
       
    96 	DEBUGPRINT(" CS=%08x EIP=%08x  DS=%08x  SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs);
       
    97 	DEBUGPRINT(" ES=%08x  FS=%08x  GS=%08x",a.iEs,a.iFs,a.iGs);
       
    98 	if (a.iCs&3)
       
    99 		{
       
   100 		DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3);
       
   101 		}
       
   102 	DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount);
       
   103 	}
       
   104 
       
   105 
       
   106 EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask)
       
   107 	{
       
   108 	CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext");
       
   109 	TUint32* sp;
       
   110 	TUint32* stackTop;
       
   111 	TX86RegSet* regSet = (TX86RegSet*)aContext;
       
   112 	TInt delta;
       
   113 
       
   114 	NKern::Lock();
       
   115 
       
   116 	NThread* currentThread = NCurrentThread();
       
   117 	DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread);
       
   118 
       
   119 	switch (NKern::CurrentContext())
       
   120 		{
       
   121 		case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break;
       
   122 		case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break;
       
   123 		case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break;
       
   124 		default: DEBUGPRINT(" CurrentContext= Unknown"); break;
       
   125 		}
       
   126 
       
   127 	DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2);
       
   128 	DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize);
       
   129 
       
   130 	DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount);
       
   131 
       
   132 	DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack);
       
   133 
       
   134 	TBool isCurrentThread = (currentThread == aThread);
       
   135 
       
   136 	sp = (TUint32*)aThread->iSavedSP;
       
   137 	stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize);
       
   138 	delta = stackTop - sp;	// number of words on the supervisor stack
       
   139 
       
   140 	DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta);
       
   141 	DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3);
       
   142 
       
   143 	DEBUGPRINT(" NThreadState:");
       
   144 	switch(aThread->iSpare1)
       
   145 		{
       
   146 		case NThreadBase::EReady:
       
   147 			DEBUGPRINT(" EReady");
       
   148 			break;
       
   149 		case NThreadBase::ESuspended:
       
   150 			DEBUGPRINT(" ESuspended");
       
   151 			break;
       
   152 		case NThreadBase::EWaitFastSemaphore:
       
   153 			DEBUGPRINT(" EWaitFastSemaphore");
       
   154 			break;
       
   155 		case NThreadBase::ESleep:
       
   156 			DEBUGPRINT(" ESleep");
       
   157 			break;
       
   158 		case NThreadBase::EBlocked:
       
   159 			DEBUGPRINT(" EBlocked");
       
   160 			break;
       
   161 		case NThreadBase::EDead:
       
   162 			DEBUGPRINT(" EDead");
       
   163 			break;
       
   164 		case NThreadBase::EWaitDfc:
       
   165 			DEBUGPRINT(" EWaitDfc");
       
   166 			break;
       
   167 		default:
       
   168 			DEBUGPRINT(" *Unknown");
       
   169 		}
       
   170 
       
   171 	if (aAvailMask)
       
   172 		{
       
   173 		DEBUGPRINT(" Setting Stack-Saved Registers");
       
   174 		// Hack while ThreadSetUserContext is not implemented
       
   175 
       
   176 		if (0 == aThread->iSpare3)
       
   177 			{
       
   178 			// Context when interrupted by user
       
   179 			if (aAvailMask & 1<<13)
       
   180 				stackTop[-1] = regSet->iSs;
       
   181 
       
   182 			if (aAvailMask & 1<<4)
       
   183 				stackTop[-2] = regSet->iEsp;
       
   184 
       
   185 			if (aAvailMask & 1<<14)
       
   186 				{
       
   187 				DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
       
   188 				stackTop[-3] = regSet->iEflags;
       
   189 				}
       
   190 
       
   191 			if (aAvailMask & 1<<8)
       
   192 				stackTop[-4] = regSet->iCs;
       
   193 
       
   194 			if (aAvailMask & 1<<15)
       
   195 				stackTop[-5] = regSet->iEip;
       
   196 
       
   197 			if (aAvailMask & 1<<9)
       
   198 				stackTop[-8] = regSet->iDs;
       
   199 
       
   200 			if (aAvailMask & 1<<0)
       
   201 				stackTop[-9] = regSet->iEax;
       
   202 
       
   203 			if (aAvailMask & 1<<2)
       
   204 				stackTop[-10] = regSet->iEcx;
       
   205 
       
   206 			if (aAvailMask & 1<<5)
       
   207 				stackTop[-16] = regSet->iEbp;
       
   208 
       
   209 			if (aAvailMask & 1<<7)
       
   210 				stackTop[-17] = regSet->iEdi;
       
   211 
       
   212 			if (aAvailMask & 1<<6)
       
   213 				stackTop[-18] = regSet->iEsi;
       
   214 			}
       
   215 		else
       
   216 			{
       
   217 			if (aAvailMask & 1<<13)
       
   218 				stackTop[-1] = regSet->iSs;
       
   219 
       
   220 			if (aAvailMask & 1<<4)
       
   221 				stackTop[-2] = regSet->iEsp;
       
   222 
       
   223 			if (aAvailMask & 1<<14)
       
   224 				{
       
   225 				stackTop[-3] = regSet->iEflags;
       
   226 				DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
       
   227 				}
       
   228 
       
   229 			if (aAvailMask & 1<<8)
       
   230 				stackTop[-4] = regSet->iCs;
       
   231 
       
   232 			if (aAvailMask & 1<<15)
       
   233 				stackTop[-5] = regSet->iEip;
       
   234 
       
   235 			/* -6 and -7 are not used since they are the vector number and the error code,
       
   236 			 * which are 3 and 0 resp. for breakpoints.
       
   237 			 */
       
   238 
       
   239 			/* The following are from the push instructions in __X86VectorExc */
       
   240 			if (aAvailMask & 1<<9)
       
   241 				stackTop[-8] = regSet->iDs;
       
   242 
       
   243 			if (aAvailMask & 1<<10)
       
   244 				stackTop[-9] = regSet->iEs;
       
   245 
       
   246 			if (aAvailMask & 1<<11)
       
   247 				stackTop[-10] = regSet->iFs;
       
   248 
       
   249 			if (aAvailMask & 1<<12)
       
   250 				stackTop[-11] = regSet->iGs;
       
   251 
       
   252 			if (aAvailMask & 1<<5)
       
   253 				stackTop[-12] = regSet->iEbp;
       
   254 
       
   255 			if (aAvailMask & 1<<7)
       
   256 				stackTop[-13] = regSet->iEdi;
       
   257 
       
   258 			if (aAvailMask & 1<<6)
       
   259 				stackTop[-14] = regSet->iEsi;
       
   260 
       
   261 			if (aAvailMask & 1<<1)
       
   262 				stackTop[-15] = regSet->iEbx;
       
   263 
       
   264 			if (aAvailMask & 1<<2)
       
   265 				stackTop[-16] = regSet->iEcx;
       
   266 
       
   267 			if (aAvailMask & 1<<3)
       
   268 				stackTop[-17] = regSet->iEdx;
       
   269 
       
   270 			if (aAvailMask & 1<<0)
       
   271 				stackTop[-18] = regSet->iEax;
       
   272 			}
       
   273 
       
   274 		DEBUGPRINT("stack from stack top, after changes " );
       
   275 		if (delta < 128)
       
   276 			{
       
   277 			delta = -delta;
       
   278 			}
       
   279 		else
       
   280 			{
       
   281 			delta = -128;
       
   282 			}
       
   283 
       
   284 		for ( ; delta < 0; delta++)
       
   285 			{
       
   286 			DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
       
   287 			}
       
   288 		}
       
   289 	else
       
   290 		{
       
   291  		memclr(aContext, sizeof(TX86RegSet));
       
   292 
       
   293 		if (isCurrentThread)
       
   294 			{
       
   295 			// Not yet supported
       
   296 			DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?");
       
   297 			}
       
   298 		else
       
   299 			{
       
   300 			DEBUGPRINT("stack from stack top " );
       
   301 
       
   302 			if (delta < 128)
       
   303 				{
       
   304 				delta = -delta;
       
   305 				}
       
   306 			else
       
   307 				{
       
   308 				delta = -128;
       
   309 				}
       
   310 
       
   311 			for( ; delta < 0; delta++)
       
   312 				{
       
   313 				DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
       
   314 				}
       
   315 
       
   316 			if (0 == aThread->iSpare3)
       
   317 				{
       
   318 				// Context when interrupted by user
       
   319 				regSet->iSs		= stackTop[-1];
       
   320 				aAvailMask |= 1<<13;
       
   321 
       
   322 				regSet->iEsp	= stackTop[-2];
       
   323 				aAvailMask |= 1<<4;
       
   324 
       
   325 				regSet->iEflags = stackTop[-3];
       
   326 				aAvailMask |= 1<<14;
       
   327 
       
   328 				regSet->iCs		= stackTop[-4];
       
   329 				aAvailMask |= 1<<8;
       
   330 
       
   331 				regSet->iEip	= stackTop[-5];
       
   332 				aAvailMask |= 1<<15;
       
   333 
       
   334 				regSet->iDs		= stackTop[-8];
       
   335 				aAvailMask |= 1<<9;
       
   336 
       
   337 				regSet->iEax	= stackTop[-9];
       
   338 				aAvailMask |= 1<<0;
       
   339 
       
   340 				regSet->iEcx	= stackTop[-10];
       
   341 				aAvailMask |= 1<<2;
       
   342 
       
   343 				regSet->iEbp	= stackTop[-16];
       
   344 				aAvailMask |= 1<<5;
       
   345 
       
   346 				regSet->iEdi	= stackTop[-17];
       
   347 				aAvailMask |= 1<<7;
       
   348 
       
   349 				regSet->iEsi	= stackTop[-18];
       
   350 				aAvailMask |= 1<<6;
       
   351 				}
       
   352 			else
       
   353 				{
       
   354 				// Now populate the TX86RegSet with the contents of the stack
       
   355 
       
   356 				/*
       
   357 				 * The first 5 are from the comments at the start of __X86VectorExc :
       
   358 				 * [ESP+0] = vector number
       
   359 				 * [ESP+4] = error code (filled with 0 for exceptions without error codes)
       
   360 				 * [ESP+8] = return EIP
       
   361 				 * [ESP+12] = return CS
       
   362 				 * [ESP+16] = return EFLAGS
       
   363 				 * [ESP+20] = return ESP if privilege change occurred
       
   364 				 * [ESP+24] = return SS if privilege change occurred
       
   365 				 */
       
   366 				regSet->iSs		= stackTop[-1];
       
   367 				aAvailMask |= 1<<13;
       
   368 
       
   369 				regSet->iEsp	= stackTop[-2];
       
   370 				aAvailMask |= 1<<4;
       
   371 
       
   372 				regSet->iEflags = stackTop[-3];
       
   373 				aAvailMask |= 1<<14;
       
   374 
       
   375 				regSet->iCs		= stackTop[-4];
       
   376 				aAvailMask |= 1<<8;
       
   377 
       
   378 				regSet->iEip	= stackTop[-5];
       
   379 				aAvailMask |= 1<<15;
       
   380 
       
   381 				/* -6 and -7 are not used since they are the vector number and the error code,
       
   382 				 * which for a breakpoint are 3 and 0 resp.
       
   383 				 */
       
   384 
       
   385 				/* The following are from the push instructions in __X86VectorExc */
       
   386 				regSet->iDs		= stackTop[-8];
       
   387 				aAvailMask |= 1<<9;
       
   388 
       
   389 				regSet->iEs		= stackTop[-9];
       
   390 				aAvailMask |= 1<<10;
       
   391 
       
   392 				regSet->iFs		= stackTop[-10];
       
   393 				aAvailMask |= 1<<11;
       
   394 
       
   395 				regSet->iGs		= stackTop[-11];
       
   396 				aAvailMask |= 1<<12;
       
   397 
       
   398 				regSet->iEbp	= stackTop[-12];
       
   399 				aAvailMask |= 1<<5;
       
   400 
       
   401 				regSet->iEdi	= stackTop[-13];
       
   402 				aAvailMask |= 1<<7;
       
   403 
       
   404 				regSet->iEsi	= stackTop[-14];
       
   405 				aAvailMask |= 1<<6;
       
   406 
       
   407 				regSet->iEbx	= stackTop[-15];
       
   408 				aAvailMask |= 1<<1;
       
   409 
       
   410 				regSet->iEcx	= stackTop[-16];
       
   411 				aAvailMask |= 1<<2;
       
   412 
       
   413 				regSet->iEdx	= stackTop[-17];
       
   414 				aAvailMask |= 1<<3;
       
   415 
       
   416 				regSet->iEax = stackTop[-18];
       
   417 				aAvailMask |= 1<<0;
       
   418 				} // else if (0 == aThread->iSpare3)
       
   419 
       
   420 			} // else if (isCurrentThread)
       
   421 
       
   422 		} // else if (aAvailMask)
       
   423 
       
   424 	NKern::Unlock();
       
   425 	}
       
   426 
       
   427 
       
   428 void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp)
       
   429 	{
       
   430 	}