os/kernelhwsrv/kernel/eka/nkernsmp/x86/ncutils.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/nkernsmp/x86/ncutils.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,363 @@
     1.4 +// Copyright (c) 2006-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\nkernsmp\x86\ncutils.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <x86.h>
    1.22 +
    1.23 +extern "C" {
    1.24 +extern SVariantInterfaceBlock* VIB;
    1.25 +}
    1.26 +
    1.27 +//#define __DBG_MON_FAULT__
    1.28 +//#define __RAM_LOADED_CODE__
    1.29 +//#define __EARLY_DEBUG__
    1.30 +void InitFpu();
    1.31 +
    1.32 +
    1.33 +TUint32 NKern::IdleGenerationCount()
    1.34 +	{
    1.35 +	return TheScheduler.iIdleGenerationCount;
    1.36 +	}
    1.37 +
    1.38 +void NKern::Idle()
    1.39 +	{
    1.40 +	TScheduler& s = TheScheduler;
    1.41 +	TSubScheduler& ss = SubScheduler();	// OK since idle thread is locked to CPU
    1.42 +	TUint32 m = ss.iCpuMask;
    1.43 +
    1.44 +	s.iIdleSpinLock.LockIrq();	// don't allow any more idle DFCs for now
    1.45 +	TUint32 orig_cpus_not_idle = __e32_atomic_and_ord32(&s.iCpusNotIdle, ~m);
    1.46 +	if (orig_cpus_not_idle == m)
    1.47 +		{
    1.48 +		// all CPUs idle
    1.49 +		if (!s.iIdleDfcs.IsEmpty())
    1.50 +			{
    1.51 +			__e32_atomic_ior_ord32(&s.iCpusNotIdle, m);		// we aren't idle after all
    1.52 +			s.iIdleGeneration ^= 1;
    1.53 +			++s.iIdleGenerationCount;
    1.54 +			s.iIdleSpillCpu = (TUint8)ss.iCpuNum;
    1.55 +			ss.iDfcs.MoveFrom(&s.iIdleDfcs);
    1.56 +			ss.iDfcPendingFlag = 1;
    1.57 +			s.iIdleSpinLock.UnlockIrq();
    1.58 +			NKern::Lock();
    1.59 +			NKern::Unlock();	// process idle DFCs here
    1.60 +			return;
    1.61 +			}
    1.62 +		}
    1.63 +	s.iIdleSpinLock.UnlockOnly();	// leave interrupts disabled
    1.64 +	NKIdle(0);
    1.65 +	}
    1.66 +
    1.67 +TUint32 ContextId()
    1.68 +	{
    1.69 +	switch(NKern::CurrentContext())
    1.70 +		{
    1.71 +	case NKern::EThread:
    1.72 +		return (TUint32)NKern::CurrentThread();
    1.73 +	case NKern::EIDFC:
    1.74 +		return 3;
    1.75 +	case NKern::EInterrupt:
    1.76 +		return 2;
    1.77 +	default:
    1.78 +		return 0;
    1.79 +		}
    1.80 +	}
    1.81 +
    1.82 +EXPORT_C TBool BTrace::Out(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
    1.83 +	{
    1.84 +	SBTraceData& traceData = BTraceData;
    1.85 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
    1.86 +		return FALSE;
    1.87 +
    1.88 +	TUint32 pc = (&a0)[-1]; // return address on X86
    1.89 +	__ACQUIRE_BTRACE_LOCK();
    1.90 +	TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc);
    1.91 +	__RELEASE_BTRACE_LOCK();
    1.92 +	return r;
    1.93 +	}
    1.94 +
    1.95 +EXPORT_C TBool BTrace::OutX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
    1.96 +	{
    1.97 +	SBTraceData& traceData = BTraceData;
    1.98 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
    1.99 +		return FALSE;
   1.100 +
   1.101 +	TUint32 context = ContextId();
   1.102 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.103 +	__ACQUIRE_BTRACE_LOCK();
   1.104 +	TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc);
   1.105 +	__RELEASE_BTRACE_LOCK();
   1.106 +	return r;
   1.107 +	}
   1.108 +
   1.109 +EXPORT_C TBool BTrace::OutN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
   1.110 +	{
   1.111 +	SBTraceData& traceData = BTraceData;
   1.112 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.113 +		return FALSE;
   1.114 +
   1.115 +	if(TUint(aDataSize)>KMaxBTraceDataArray)
   1.116 +		{
   1.117 +		aDataSize = KMaxBTraceDataArray;
   1.118 +		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
   1.119 +		}
   1.120 +	a0 += aDataSize<<(BTrace::ESizeIndex*8);
   1.121 +
   1.122 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.123 +	TBool r;
   1.124 +	__ACQUIRE_BTRACE_LOCK();
   1.125 +	if (!aDataSize)
   1.126 +		r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc);
   1.127 +	else if (aDataSize<=4)
   1.128 +		r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc);
   1.129 +	else
   1.130 +		r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc);
   1.131 +	__RELEASE_BTRACE_LOCK();
   1.132 +	return r;
   1.133 +	}
   1.134 +
   1.135 +EXPORT_C TBool BTrace::OutNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
   1.136 +	{
   1.137 +	SBTraceData& traceData = BTraceData;
   1.138 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.139 +		return FALSE;
   1.140 +
   1.141 +	if(TUint(aDataSize)>KMaxBTraceDataArray)
   1.142 +		{
   1.143 +		aDataSize = KMaxBTraceDataArray;
   1.144 +		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
   1.145 +		}
   1.146 +	a0 += aDataSize<<(BTrace::ESizeIndex*8);
   1.147 +
   1.148 +	TUint32 context = ContextId();
   1.149 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.150 +	TBool r;
   1.151 +	__ACQUIRE_BTRACE_LOCK();
   1.152 +	if(!aDataSize)
   1.153 +		r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc);
   1.154 +	else if(aDataSize<=4)
   1.155 +		r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc);
   1.156 +	else
   1.157 +		r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc);
   1.158 +	__RELEASE_BTRACE_LOCK();
   1.159 +	return r;
   1.160 +	}
   1.161 +
   1.162 +EXPORT_C TBool BTrace::OutBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize)
   1.163 +	{
   1.164 +	TUint32 context = ContextId();
   1.165 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.166 +	SBTraceData& traceData = BTraceData;
   1.167 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.168 +		return FALSE;
   1.169 +	TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc);
   1.170 +	return r;
   1.171 +	}
   1.172 +
   1.173 +EXPORT_C TBool BTrace::OutFiltered(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
   1.174 +	{
   1.175 +	SBTraceData& traceData = BTraceData;
   1.176 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.177 +		return FALSE;
   1.178 +	if(!traceData.CheckFilter2(a1))
   1.179 +		return FALSE;
   1.180 +
   1.181 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.182 +	__ACQUIRE_BTRACE_LOCK();
   1.183 +	TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc);
   1.184 +	__RELEASE_BTRACE_LOCK();
   1.185 +	return r;
   1.186 +	}
   1.187 +
   1.188 +EXPORT_C TBool BTrace::OutFilteredX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3)
   1.189 +	{
   1.190 +	SBTraceData& traceData = BTraceData;
   1.191 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.192 +		return FALSE;
   1.193 +	if(!traceData.CheckFilter2(a1))
   1.194 +		return FALSE;
   1.195 +
   1.196 +	TUint32 context = ContextId();
   1.197 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.198 +	__ACQUIRE_BTRACE_LOCK();
   1.199 +	TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc);
   1.200 +	__RELEASE_BTRACE_LOCK();
   1.201 +	return r;
   1.202 +	}
   1.203 +
   1.204 +EXPORT_C TBool BTrace::OutFilteredN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
   1.205 +	{
   1.206 +	SBTraceData& traceData = BTraceData;
   1.207 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.208 +		return FALSE;
   1.209 +	if(!traceData.CheckFilter2(a1))
   1.210 +		return FALSE;
   1.211 +
   1.212 +	if(TUint(aDataSize)>KMaxBTraceDataArray)
   1.213 +		{
   1.214 +		aDataSize = KMaxBTraceDataArray;
   1.215 +		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
   1.216 +		}
   1.217 +	a0 += aDataSize<<(BTrace::ESizeIndex*8);
   1.218 +
   1.219 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.220 +	TBool r;
   1.221 +	__ACQUIRE_BTRACE_LOCK();
   1.222 +	if(!aDataSize)
   1.223 +		r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc);
   1.224 +	else if(aDataSize<=4)
   1.225 +		r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc);
   1.226 +	else
   1.227 +		r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc);
   1.228 +	__RELEASE_BTRACE_LOCK();
   1.229 +	return r;
   1.230 +	}
   1.231 +
   1.232 +EXPORT_C TBool BTrace::OutFilteredNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize)
   1.233 +	{
   1.234 +	SBTraceData& traceData = BTraceData;
   1.235 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.236 +		return FALSE;
   1.237 +	if(!traceData.CheckFilter2(a1))
   1.238 +		return FALSE;
   1.239 +
   1.240 +	if(TUint(aDataSize)>KMaxBTraceDataArray)
   1.241 +		{
   1.242 +		aDataSize = KMaxBTraceDataArray;
   1.243 +		a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8);
   1.244 +		}
   1.245 +	a0 += aDataSize<<(BTrace::ESizeIndex*8);
   1.246 +
   1.247 +	TUint32 context = ContextId();
   1.248 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.249 +	TBool r;
   1.250 +	__ACQUIRE_BTRACE_LOCK();
   1.251 +	if(!aDataSize)
   1.252 +		r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc);
   1.253 +	else if(aDataSize<=4)
   1.254 +		r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc);
   1.255 +	else
   1.256 +		r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc);
   1.257 +	__RELEASE_BTRACE_LOCK();
   1.258 +	return r;
   1.259 +	}
   1.260 +
   1.261 +EXPORT_C TBool BTrace::OutFilteredBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize)
   1.262 +	{
   1.263 +	TUint32 context = ContextId();
   1.264 +	TUint32 pc = (&a0)[-1]; // return address on X86
   1.265 +	SBTraceData& traceData = BTraceData;
   1.266 +	if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff])
   1.267 +		return FALSE;
   1.268 +	if(!traceData.CheckFilter2(a1))
   1.269 +		return FALSE;
   1.270 +	TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc);
   1.271 +	return r;
   1.272 +	}
   1.273 +
   1.274 +EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 aHeader, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize)
   1.275 +	{
   1.276 +	return EFalse; //kernel side not implemented yet
   1.277 +	}
   1.278 +
   1.279 +TInt BTraceDefaultControl(BTrace::TControl /*aFunction*/, TAny* /*aArg1*/, TAny* /*aArg2*/)
   1.280 +	{
   1.281 +	return KErrNotSupported;
   1.282 +	}
   1.283 +
   1.284 +
   1.285 +EXPORT_C void BTrace::SetHandlers(BTrace::THandler aNewHandler, BTrace::TControlFunction aNewControl, BTrace::THandler& aOldHandler, BTrace::TControlFunction& aOldControl)
   1.286 +	{
   1.287 +	BTrace::TControlFunction nc = aNewControl ? aNewControl : &BTraceDefaultControl;
   1.288 +	__ACQUIRE_BTRACE_LOCK();
   1.289 +	BTrace::THandler oldh = (BTrace::THandler)__e32_atomic_swp_ord_ptr(&BTraceData.iHandler, aNewHandler);
   1.290 +	BTrace::TControlFunction oldc = (BTrace::TControlFunction)__e32_atomic_swp_ord_ptr(&BTraceData.iControl, nc);
   1.291 +	__RELEASE_BTRACE_LOCK();
   1.292 +	aOldHandler = oldh;
   1.293 +	aOldControl = oldc;
   1.294 +	}
   1.295 +
   1.296 +
   1.297 +EXPORT_C TInt BTrace::SetFilter(TUint aCategory, TInt aValue)
   1.298 +	{
   1.299 +	if(!IsSupported(aCategory))
   1.300 +		return KErrNotSupported;
   1.301 +	TUint8* filter = BTraceData.iFilter+aCategory;
   1.302 +	TUint oldValue = *filter;
   1.303 +	if(TUint(aValue)<=1u)
   1.304 +		{
   1.305 +		oldValue = __e32_atomic_swp_ord8(filter, (TUint8)aValue);
   1.306 +		BTraceContext4(BTrace::EMetaTrace, BTrace::EMetaTraceFilterChange, (TUint8)aCategory | (aValue<<8));
   1.307 +		}
   1.308 +	return oldValue;
   1.309 +	}
   1.310 +
   1.311 +EXPORT_C SCpuIdleHandler* NKern::CpuIdleHandler()
   1.312 +	{
   1.313 +	return &::CpuIdleHandler;
   1.314 +	}
   1.315 +
   1.316 +
   1.317 +void NKern::Init0(TAny* a)
   1.318 +	{
   1.319 +	__KTRACE_OPT(KBOOT,DEBUGPRINT("VIB=%08x", a));
   1.320 +	VIB = (SVariantInterfaceBlock*)a;
   1.321 +	__NK_ASSERT_ALWAYS(VIB && VIB->iVer==0 && VIB->iSize==sizeof(SVariantInterfaceBlock));
   1.322 +	__KTRACE_OPT(KBOOT,DEBUGPRINT("iVer=%d iSize=%d", VIB->iVer, VIB->iSize));
   1.323 +	__KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxCpuClock=%08x %08x", I64HIGH(VIB->iMaxCpuClock), I64LOW(VIB->iMaxCpuClock)));
   1.324 +	__KTRACE_OPT(KBOOT,DEBUGPRINT("iTimestampFreq=%u", VIB->iTimestampFreq));
   1.325 +	__KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxTimerClock=%u", VIB->iMaxTimerClock));
   1.326 +	TInt i;
   1.327 +	for (i=0; i<KMaxCpus; ++i)
   1.328 +		{
   1.329 +		TSubScheduler& ss = TheSubSchedulers[i];
   1.330 +		ss.i_TimerMultF = (TAny*)KMaxTUint32;
   1.331 +		ss.i_TimerMultI = (TAny*)0x01000000u;
   1.332 +		ss.i_CpuMult = (TAny*)KMaxTUint32;
   1.333 +		VIB->iTimerMult[i] = (volatile STimerMult*)&ss.i_TimerMultF;
   1.334 +		VIB->iCpuMult[i] = (volatile TUint32*)&ss.i_CpuMult;
   1.335 +		}
   1.336 +	TheScheduler.i_TimerMax = (TAny*)(VIB->iMaxTimerClock / 128);
   1.337 +	InitFpu();
   1.338 +	InterruptInit0();
   1.339 +	}
   1.340 +
   1.341 +EXPORT_C TUint32 NKern::CpuTimeMeasFreq()
   1.342 +	{
   1.343 +	return NKern::TimestampFrequency();
   1.344 +	}
   1.345 +
   1.346 +
   1.347 +/**	Converts a time interval in microseconds to thread timeslice ticks
   1.348 +
   1.349 +	@param aMicroseconds time interval in microseconds.
   1.350 +	@return Number of thread timeslice ticks.  Non-integral results are rounded up.
   1.351 +
   1.352 + 	@pre aMicroseconds should be nonnegative
   1.353 +	@pre any context
   1.354 + */
   1.355 +EXPORT_C TInt NKern::TimesliceTicks(TUint32 aMicroseconds)
   1.356 +	{
   1.357 +	TUint32 mf32 = (TUint32)TheScheduler.i_TimerMax;
   1.358 +	TUint64 mf(mf32);
   1.359 +	TUint64 ticks = mf*TUint64(aMicroseconds) + UI64LIT(999999);
   1.360 +	ticks /= UI64LIT(1000000);
   1.361 +	if (ticks > TUint64(TInt(KMaxTInt)))
   1.362 +		return KMaxTInt;
   1.363 +	else
   1.364 +		return (TInt)ticks;
   1.365 +	}
   1.366 +