kernel/eka/nkernsmp/x86/ncutils.cpp
changeset 0 a41df078684a
child 90 947f0dc9f7a8
child 256 c1f20ce4abcf
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2006-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\nkernsmp\x86\ncutils.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <x86.h>
       
    19 
       
    20 extern "C" {
       
    21 extern SVariantInterfaceBlock* VIB;
       
    22 }
       
    23 
       
    24 //#define __DBG_MON_FAULT__
       
    25 //#define __RAM_LOADED_CODE__
       
    26 //#define __EARLY_DEBUG__
       
    27 void InitFpu();
       
    28 
       
    29 
       
    30 TUint32 NKern::IdleGenerationCount()
       
    31 	{
       
    32 	return TheScheduler.iIdleGenerationCount;
       
    33 	}
       
    34 
       
    35 void NKern::Idle()
       
    36 	{
       
    37 	TScheduler& s = TheScheduler;
       
    38 	TSubScheduler& ss = SubScheduler();	// OK since idle thread is locked to CPU
       
    39 	TUint32 m = ss.iCpuMask;
       
    40 
       
    41 	s.iIdleSpinLock.LockIrq();	// don't allow any more idle DFCs for now
       
    42 	TUint32 orig_cpus_not_idle = __e32_atomic_and_ord32(&s.iCpusNotIdle, ~m);
       
    43 	if (orig_cpus_not_idle == m)
       
    44 		{
       
    45 		// all CPUs idle
       
    46 		if (!s.iIdleDfcs.IsEmpty())
       
    47 			{
       
    48 			__e32_atomic_ior_ord32(&s.iCpusNotIdle, m);		// we aren't idle after all
       
    49 			s.iIdleGeneration ^= 1;
       
    50 			++s.iIdleGenerationCount;
       
    51 			s.iIdleSpillCpu = (TUint8)ss.iCpuNum;
       
    52 			ss.iDfcs.MoveFrom(&s.iIdleDfcs);
       
    53 			ss.iDfcPendingFlag = 1;
       
    54 			s.iIdleSpinLock.UnlockIrq();
       
    55 			NKern::Lock();
       
    56 			NKern::Unlock();	// process idle DFCs here
       
    57 			return;
       
    58 			}
       
    59 		}
       
    60 	s.iIdleSpinLock.UnlockOnly();	// leave interrupts disabled
       
    61 	NKIdle(0);
       
    62 	}
       
    63 
       
    64 TUint32 ContextId()
       
    65 	{
       
    66 	switch(NKern::CurrentContext())
       
    67 		{
       
    68 	case NKern::EThread:
       
    69 		return (TUint32)NKern::CurrentThread();
       
    70 	case NKern::EIDFC:
       
    71 		return 3;
       
    72 	case NKern::EInterrupt:
       
    73 		return 2;
       
    74 	default:
       
    75 		return 0;
       
    76 		}
       
    77 	}
       
    78 
       
    79 EXPORT_C TBool BTrace::Out(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
       
    80 	{
       
    81 	SBTraceData& traceData = BTraceData;
       
    82 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
    83 		return FALSE;
       
    84 
       
    85 	TUint32 pc = (&a0)[-1]; // return address on X86
       
    86 	__ACQUIRE_BTRACE_LOCK();
       
    87 	TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc);
       
    88 	__RELEASE_BTRACE_LOCK();
       
    89 	return r;
       
    90 	}
       
    91 
       
    92 EXPORT_C TBool BTrace::OutX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
       
    93 	{
       
    94 	SBTraceData& traceData = BTraceData;
       
    95 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
    96 		return FALSE;
       
    97 
       
    98 	TUint32 context = ContextId();
       
    99 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   100 	__ACQUIRE_BTRACE_LOCK();
       
   101 	TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc);
       
   102 	__RELEASE_BTRACE_LOCK();
       
   103 	return r;
       
   104 	}
       
   105 
       
   106 EXPORT_C TBool BTrace::OutN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
       
   107 	{
       
   108 	SBTraceData& traceData = BTraceData;
       
   109 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   110 		return FALSE;
       
   111 
       
   112 	if(TUint(aDataSize)>KMaxBTraceDataArray)
       
   113 		{
       
   114 		aDataSize = KMaxBTraceDataArray;
       
   115 		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
       
   116 		}
       
   117 	a0 += aDataSize<<(BTrace::ESizeIndex*8);
       
   118 
       
   119 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   120 	TBool r;
       
   121 	__ACQUIRE_BTRACE_LOCK();
       
   122 	if (!aDataSize)
       
   123 		r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc);
       
   124 	else if (aDataSize<=4)
       
   125 		r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc);
       
   126 	else
       
   127 		r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc);
       
   128 	__RELEASE_BTRACE_LOCK();
       
   129 	return r;
       
   130 	}
       
   131 
       
   132 EXPORT_C TBool BTrace::OutNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
       
   133 	{
       
   134 	SBTraceData& traceData = BTraceData;
       
   135 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   136 		return FALSE;
       
   137 
       
   138 	if(TUint(aDataSize)>KMaxBTraceDataArray)
       
   139 		{
       
   140 		aDataSize = KMaxBTraceDataArray;
       
   141 		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
       
   142 		}
       
   143 	a0 += aDataSize<<(BTrace::ESizeIndex*8);
       
   144 
       
   145 	TUint32 context = ContextId();
       
   146 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   147 	TBool r;
       
   148 	__ACQUIRE_BTRACE_LOCK();
       
   149 	if(!aDataSize)
       
   150 		r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc);
       
   151 	else if(aDataSize<=4)
       
   152 		r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc);
       
   153 	else
       
   154 		r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc);
       
   155 	__RELEASE_BTRACE_LOCK();
       
   156 	return r;
       
   157 	}
       
   158 
       
   159 EXPORT_C TBool BTrace::OutBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize)
       
   160 	{
       
   161 	TUint32 context = ContextId();
       
   162 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   163 	SBTraceData& traceData = BTraceData;
       
   164 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   165 		return FALSE;
       
   166 	TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc);
       
   167 	return r;
       
   168 	}
       
   169 
       
   170 EXPORT_C TBool BTrace::OutFiltered(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
       
   171 	{
       
   172 	SBTraceData& traceData = BTraceData;
       
   173 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   174 		return FALSE;
       
   175 	if(!traceData.CheckFilter2(a1))
       
   176 		return FALSE;
       
   177 
       
   178 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   179 	__ACQUIRE_BTRACE_LOCK();
       
   180 	TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc);
       
   181 	__RELEASE_BTRACE_LOCK();
       
   182 	return r;
       
   183 	}
       
   184 
       
   185 EXPORT_C TBool BTrace::OutFilteredX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
       
   186 	{
       
   187 	SBTraceData& traceData = BTraceData;
       
   188 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   189 		return FALSE;
       
   190 	if(!traceData.CheckFilter2(a1))
       
   191 		return FALSE;
       
   192 
       
   193 	TUint32 context = ContextId();
       
   194 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   195 	__ACQUIRE_BTRACE_LOCK();
       
   196 	TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc);
       
   197 	__RELEASE_BTRACE_LOCK();
       
   198 	return r;
       
   199 	}
       
   200 
       
   201 EXPORT_C TBool BTrace::OutFilteredN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
       
   202 	{
       
   203 	SBTraceData& traceData = BTraceData;
       
   204 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   205 		return FALSE;
       
   206 	if(!traceData.CheckFilter2(a1))
       
   207 		return FALSE;
       
   208 
       
   209 	if(TUint(aDataSize)>KMaxBTraceDataArray)
       
   210 		{
       
   211 		aDataSize = KMaxBTraceDataArray;
       
   212 		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
       
   213 		}
       
   214 	a0 += aDataSize<<(BTrace::ESizeIndex*8);
       
   215 
       
   216 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   217 	TBool r;
       
   218 	__ACQUIRE_BTRACE_LOCK();
       
   219 	if(!aDataSize)
       
   220 		r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc);
       
   221 	else if(aDataSize<=4)
       
   222 		r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc);
       
   223 	else
       
   224 		r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc);
       
   225 	__RELEASE_BTRACE_LOCK();
       
   226 	return r;
       
   227 	}
       
   228 
       
   229 EXPORT_C TBool BTrace::OutFilteredNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
       
   230 	{
       
   231 	SBTraceData& traceData = BTraceData;
       
   232 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   233 		return FALSE;
       
   234 	if(!traceData.CheckFilter2(a1))
       
   235 		return FALSE;
       
   236 
       
   237 	if(TUint(aDataSize)>KMaxBTraceDataArray)
       
   238 		{
       
   239 		aDataSize = KMaxBTraceDataArray;
       
   240 		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
       
   241 		}
       
   242 	a0 += aDataSize<<(BTrace::ESizeIndex*8);
       
   243 
       
   244 	TUint32 context = ContextId();
       
   245 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   246 	TBool r;
       
   247 	__ACQUIRE_BTRACE_LOCK();
       
   248 	if(!aDataSize)
       
   249 		r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc);
       
   250 	else if(aDataSize<=4)
       
   251 		r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc);
       
   252 	else
       
   253 		r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc);
       
   254 	__RELEASE_BTRACE_LOCK();
       
   255 	return r;
       
   256 	}
       
   257 
       
   258 EXPORT_C TBool BTrace::OutFilteredBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize)
       
   259 	{
       
   260 	TUint32 context = ContextId();
       
   261 	TUint32 pc = (&a0)[-1]; // return address on X86
       
   262 	SBTraceData& traceData = BTraceData;
       
   263 	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
       
   264 		return FALSE;
       
   265 	if(!traceData.CheckFilter2(a1))
       
   266 		return FALSE;
       
   267 	TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc);
       
   268 	return r;
       
   269 	}
       
   270 
       
   271 EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 aHeader, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize)
       
   272 	{
       
   273 	return EFalse; //kernel side not implemented yet
       
   274 	}
       
   275 
       
   276 TInt BTraceDefaultControl(BTrace::TControl /*aFunction*/, TAny* /*aArg1*/, TAny* /*aArg2*/)
       
   277 	{
       
   278 	return KErrNotSupported;
       
   279 	}
       
   280 
       
   281 
       
   282 EXPORT_C void BTrace::SetHandlers(BTrace::THandler aNewHandler, BTrace::TControlFunction aNewControl, BTrace::THandler& aOldHandler, BTrace::TControlFunction& aOldControl)
       
   283 	{
       
   284 	BTrace::TControlFunction nc = aNewControl ? aNewControl : &BTraceDefaultControl;
       
   285 	__ACQUIRE_BTRACE_LOCK();
       
   286 	BTrace::THandler oldh = (BTrace::THandler)__e32_atomic_swp_ord_ptr(&BTraceData.iHandler, aNewHandler);
       
   287 	BTrace::TControlFunction oldc = (BTrace::TControlFunction)__e32_atomic_swp_ord_ptr(&BTraceData.iControl, nc);
       
   288 	__RELEASE_BTRACE_LOCK();
       
   289 	aOldHandler = oldh;
       
   290 	aOldControl = oldc;
       
   291 	}
       
   292 
       
   293 
       
   294 EXPORT_C TInt BTrace::SetFilter(TUint aCategory, TInt aValue)
       
   295 	{
       
   296 	if(!IsSupported(aCategory))
       
   297 		return KErrNotSupported;
       
   298 	TUint8* filter = BTraceData.iFilter+aCategory;
       
   299 	TUint oldValue = *filter;
       
   300 	if(TUint(aValue)<=1u)
       
   301 		{
       
   302 		oldValue = __e32_atomic_swp_ord8(filter, (TUint8)aValue);
       
   303 		BTraceContext4(BTrace::EMetaTrace, BTrace::EMetaTraceFilterChange, (TUint8)aCategory | (aValue<<8));
       
   304 		}
       
   305 	return oldValue;
       
   306 	}
       
   307 
       
   308 EXPORT_C SCpuIdleHandler* NKern::CpuIdleHandler()
       
   309 	{
       
   310 	return &::CpuIdleHandler;
       
   311 	}
       
   312 
       
   313 
       
   314 void NKern::Init0(TAny* a)
       
   315 	{
       
   316 	__KTRACE_OPT(KBOOT,DEBUGPRINT("VIB=%08x", a));
       
   317 	VIB = (SVariantInterfaceBlock*)a;
       
   318 	__NK_ASSERT_ALWAYS(VIB && VIB->iVer==0 && VIB->iSize==sizeof(SVariantInterfaceBlock));
       
   319 	__KTRACE_OPT(KBOOT,DEBUGPRINT("iVer=%d iSize=%d", VIB->iVer, VIB->iSize));
       
   320 	__KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxCpuClock=%08x %08x", I64HIGH(VIB->iMaxCpuClock), I64LOW(VIB->iMaxCpuClock)));
       
   321 	__KTRACE_OPT(KBOOT,DEBUGPRINT("iTimestampFreq=%u", VIB->iTimestampFreq));
       
   322 	__KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxTimerClock=%u", VIB->iMaxTimerClock));
       
   323 	TInt i;
       
   324 	for (i=0; i<KMaxCpus; ++i)
       
   325 		{
       
   326 		TSubScheduler& ss = TheSubSchedulers[i];
       
   327 		ss.i_TimerMultF = (TAny*)KMaxTUint32;
       
   328 		ss.i_TimerMultI = (TAny*)0x01000000u;
       
   329 		ss.i_CpuMult = (TAny*)KMaxTUint32;
       
   330 		VIB->iTimerMult[i] = (volatile STimerMult*)&ss.i_TimerMultF;
       
   331 		VIB->iCpuMult[i] = (volatile TUint32*)&ss.i_CpuMult;
       
   332 		}
       
   333 	TheScheduler.i_TimerMax = (TAny*)(VIB->iMaxTimerClock / 128);
       
   334 	InitFpu();
       
   335 	InterruptInit0();
       
   336 	}
       
   337 
       
   338 EXPORT_C TUint32 NKern::CpuTimeMeasFreq()
       
   339 	{
       
   340 	return NKern::TimestampFrequency();
       
   341 	}
       
   342 
       
   343 
       
   344 /**	Converts a time interval in microseconds to thread timeslice ticks
       
   345 
       
   346 	@param aMicroseconds time interval in microseconds.
       
   347 	@return Number of thread timeslice ticks.  Non-integral results are rounded up.
       
   348 
       
   349  	@pre aMicroseconds should be nonnegative
       
   350 	@pre any context
       
   351  */
       
   352 EXPORT_C TInt NKern::TimesliceTicks(TUint32 aMicroseconds)
       
   353 	{
       
   354 	TUint32 mf32 = (TUint32)TheScheduler.i_TimerMax;
       
   355 	TUint64 mf(mf32);
       
   356 	TUint64 ticks = mf*TUint64(aMicroseconds) + UI64LIT(999999);
       
   357 	ticks /= UI64LIT(1000000);
       
   358 	if (ticks > TUint64(TInt(KMaxTInt)))
       
   359 		return KMaxTInt;
       
   360 	else
       
   361 		return (TInt)ticks;
       
   362 	}
       
   363