os/kernelhwsrv/kernel/eka/nkernsmp/x86/ncutils.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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