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 +