sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\nkernsmp\x86\ncutils.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: sl@0: extern "C" { sl@0: extern SVariantInterfaceBlock* VIB; sl@0: } sl@0: sl@0: //#define __DBG_MON_FAULT__ sl@0: //#define __RAM_LOADED_CODE__ sl@0: //#define __EARLY_DEBUG__ sl@0: void InitFpu(); sl@0: sl@0: sl@0: TUint32 NKern::IdleGenerationCount() sl@0: { sl@0: return TheScheduler.iIdleGenerationCount; sl@0: } sl@0: sl@0: void NKern::Idle() sl@0: { sl@0: TScheduler& s = TheScheduler; sl@0: TSubScheduler& ss = SubScheduler(); // OK since idle thread is locked to CPU sl@0: TUint32 m = ss.iCpuMask; sl@0: sl@0: s.iIdleSpinLock.LockIrq(); // don't allow any more idle DFCs for now sl@0: TUint32 orig_cpus_not_idle = __e32_atomic_and_ord32(&s.iCpusNotIdle, ~m); sl@0: if (orig_cpus_not_idle == m) sl@0: { sl@0: // all CPUs idle sl@0: if (!s.iIdleDfcs.IsEmpty()) sl@0: { sl@0: __e32_atomic_ior_ord32(&s.iCpusNotIdle, m); // we aren't idle after all sl@0: s.iIdleGeneration ^= 1; sl@0: ++s.iIdleGenerationCount; sl@0: s.iIdleSpillCpu = (TUint8)ss.iCpuNum; sl@0: ss.iDfcs.MoveFrom(&s.iIdleDfcs); sl@0: ss.iDfcPendingFlag = 1; sl@0: s.iIdleSpinLock.UnlockIrq(); sl@0: NKern::Lock(); sl@0: NKern::Unlock(); // process idle DFCs here sl@0: return; sl@0: } sl@0: } sl@0: s.iIdleSpinLock.UnlockOnly(); // leave interrupts disabled sl@0: NKIdle(0); sl@0: } sl@0: sl@0: TUint32 ContextId() sl@0: { sl@0: switch(NKern::CurrentContext()) sl@0: { sl@0: case NKern::EThread: sl@0: return (TUint32)NKern::CurrentThread(); sl@0: case NKern::EIDFC: sl@0: return 3; sl@0: case NKern::EInterrupt: sl@0: return 2; sl@0: default: sl@0: return 0; sl@0: } sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::Out(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: sl@0: TUint32 context = ContextId(); sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: sl@0: if(TUint(aDataSize)>KMaxBTraceDataArray) sl@0: { sl@0: aDataSize = KMaxBTraceDataArray; sl@0: a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); sl@0: } sl@0: a0 += aDataSize<<(BTrace::ESizeIndex*8); sl@0: sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: TBool r; sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: if (!aDataSize) sl@0: r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc); sl@0: else if (aDataSize<=4) sl@0: r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc); sl@0: else sl@0: r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: sl@0: if(TUint(aDataSize)>KMaxBTraceDataArray) sl@0: { sl@0: aDataSize = KMaxBTraceDataArray; sl@0: a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); sl@0: } sl@0: a0 += aDataSize<<(BTrace::ESizeIndex*8); sl@0: sl@0: TUint32 context = ContextId(); sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: TBool r; sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: if(!aDataSize) sl@0: r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc); sl@0: else if(aDataSize<=4) sl@0: r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc); sl@0: else sl@0: r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize) sl@0: { sl@0: TUint32 context = ContextId(); sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutFiltered(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: if(!traceData.CheckFilter2(a1)) sl@0: return FALSE; sl@0: sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutFilteredX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: if(!traceData.CheckFilter2(a1)) sl@0: return FALSE; sl@0: sl@0: TUint32 context = ContextId(); sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutFilteredN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: if(!traceData.CheckFilter2(a1)) sl@0: return FALSE; sl@0: sl@0: if(TUint(aDataSize)>KMaxBTraceDataArray) sl@0: { sl@0: aDataSize = KMaxBTraceDataArray; sl@0: a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); sl@0: } sl@0: a0 += aDataSize<<(BTrace::ESizeIndex*8); sl@0: sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: TBool r; sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: if(!aDataSize) sl@0: r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc); sl@0: else if(aDataSize<=4) sl@0: r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc); sl@0: else sl@0: r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutFilteredNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) sl@0: { sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: if(!traceData.CheckFilter2(a1)) sl@0: return FALSE; sl@0: sl@0: if(TUint(aDataSize)>KMaxBTraceDataArray) sl@0: { sl@0: aDataSize = KMaxBTraceDataArray; sl@0: a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); sl@0: } sl@0: a0 += aDataSize<<(BTrace::ESizeIndex*8); sl@0: sl@0: TUint32 context = ContextId(); sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: TBool r; sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: if(!aDataSize) sl@0: r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc); sl@0: else if(aDataSize<=4) sl@0: r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc); sl@0: else sl@0: r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutFilteredBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize) sl@0: { sl@0: TUint32 context = ContextId(); sl@0: TUint32 pc = (&a0)[-1]; // return address on X86 sl@0: SBTraceData& traceData = BTraceData; sl@0: if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) sl@0: return FALSE; sl@0: if(!traceData.CheckFilter2(a1)) sl@0: return FALSE; sl@0: TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc); sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 aHeader, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize) sl@0: { sl@0: return EFalse; //kernel side not implemented yet sl@0: } sl@0: sl@0: TInt BTraceDefaultControl(BTrace::TControl /*aFunction*/, TAny* /*aArg1*/, TAny* /*aArg2*/) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void BTrace::SetHandlers(BTrace::THandler aNewHandler, BTrace::TControlFunction aNewControl, BTrace::THandler& aOldHandler, BTrace::TControlFunction& aOldControl) sl@0: { sl@0: BTrace::TControlFunction nc = aNewControl ? aNewControl : &BTraceDefaultControl; sl@0: __ACQUIRE_BTRACE_LOCK(); sl@0: BTrace::THandler oldh = (BTrace::THandler)__e32_atomic_swp_ord_ptr(&BTraceData.iHandler, aNewHandler); sl@0: BTrace::TControlFunction oldc = (BTrace::TControlFunction)__e32_atomic_swp_ord_ptr(&BTraceData.iControl, nc); sl@0: __RELEASE_BTRACE_LOCK(); sl@0: aOldHandler = oldh; sl@0: aOldControl = oldc; sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt BTrace::SetFilter(TUint aCategory, TInt aValue) sl@0: { sl@0: if(!IsSupported(aCategory)) sl@0: return KErrNotSupported; sl@0: TUint8* filter = BTraceData.iFilter+aCategory; sl@0: TUint oldValue = *filter; sl@0: if(TUint(aValue)<=1u) sl@0: { sl@0: oldValue = __e32_atomic_swp_ord8(filter, (TUint8)aValue); sl@0: BTraceContext4(BTrace::EMetaTrace, BTrace::EMetaTraceFilterChange, (TUint8)aCategory | (aValue<<8)); sl@0: } sl@0: return oldValue; sl@0: } sl@0: sl@0: EXPORT_C SCpuIdleHandler* NKern::CpuIdleHandler() sl@0: { sl@0: return &::CpuIdleHandler; sl@0: } sl@0: sl@0: sl@0: void NKern::Init0(TAny* a) sl@0: { sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("VIB=%08x", a)); sl@0: VIB = (SVariantInterfaceBlock*)a; sl@0: __NK_ASSERT_ALWAYS(VIB && VIB->iVer==0 && VIB->iSize==sizeof(SVariantInterfaceBlock)); sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("iVer=%d iSize=%d", VIB->iVer, VIB->iSize)); sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxCpuClock=%08x %08x", I64HIGH(VIB->iMaxCpuClock), I64LOW(VIB->iMaxCpuClock))); sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("iTimestampFreq=%u", VIB->iTimestampFreq)); sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxTimerClock=%u", VIB->iMaxTimerClock)); sl@0: TInt i; sl@0: for (i=0; iiTimerMult[i] = (volatile STimerMult*)&ss.i_TimerMultF; sl@0: VIB->iCpuMult[i] = (volatile TUint32*)&ss.i_CpuMult; sl@0: } sl@0: TheScheduler.i_TimerMax = (TAny*)(VIB->iMaxTimerClock / 128); sl@0: InitFpu(); sl@0: InterruptInit0(); sl@0: } sl@0: sl@0: EXPORT_C TUint32 NKern::CpuTimeMeasFreq() sl@0: { sl@0: return NKern::TimestampFrequency(); sl@0: } sl@0: sl@0: sl@0: /** Converts a time interval in microseconds to thread timeslice ticks sl@0: sl@0: @param aMicroseconds time interval in microseconds. sl@0: @return Number of thread timeslice ticks. Non-integral results are rounded up. sl@0: sl@0: @pre aMicroseconds should be nonnegative sl@0: @pre any context sl@0: */ sl@0: EXPORT_C TInt NKern::TimesliceTicks(TUint32 aMicroseconds) sl@0: { sl@0: TUint32 mf32 = (TUint32)TheScheduler.i_TimerMax; sl@0: TUint64 mf(mf32); sl@0: TUint64 ticks = mf*TUint64(aMicroseconds) + UI64LIT(999999); sl@0: ticks /= UI64LIT(1000000); sl@0: if (ticks > TUint64(TInt(KMaxTInt))) sl@0: return KMaxTInt; sl@0: else sl@0: return (TInt)ticks; sl@0: } sl@0: