sl@0: // Copyright (c) 2008-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\arm\nccpu.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: extern "C" { sl@0: extern SVariantInterfaceBlock* VIB; sl@0: } sl@0: sl@0: struct SAPBootPage : public SFullArmRegSet sl@0: { sl@0: volatile T_UintPtr iAPBootPtr[KMaxCpus]; sl@0: volatile T_UintPtr iBootFlags; sl@0: volatile T_UintPtr iBootFlags2; sl@0: volatile T_UintPtr iBootFlags3; sl@0: volatile T_UintPtr iBootFlags4; sl@0: volatile TUint64 iBPTimestamp; sl@0: volatile TUint64 iAPTimestamp; sl@0: }; sl@0: sl@0: extern "C" void _ApEntry(); sl@0: extern "C" void KickCpu(volatile T_UintPtr* aPtr, T_UintPtr aRegsPhys); sl@0: extern void DumpFullRegSet(SFullArmRegSet& a); sl@0: sl@0: TInt NKern::BootAP(volatile SAPBootInfo* aInfo) sl@0: { sl@0: volatile SArmAPBootInfo& a = *(volatile SArmAPBootInfo*)aInfo; sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("NKern::BootAP %d %08x+%x", a.iCpu, a.iInitStackBase, a.iInitStackSize)); sl@0: sl@0: T_UintPtr bp_phys = a.iAPBootPhys; sl@0: T_UintPtr BootFlagsPhys = bp_phys + (T_UintPtr)_FOFF(SAPBootPage,iBootFlags); sl@0: volatile SAPBootPage& bootPage = *(volatile SAPBootPage*)a.iAPBootLin; sl@0: Arm::SaveState((SFullArmRegSet&)bootPage); sl@0: NKern::EnableAllInterrupts(); // Arm::SaveState() disables interrupts sl@0: sl@0: TLinAddr BootFlagsLin = (TLinAddr)&bootPage.iBootFlags; sl@0: TLinAddr init_sp = a.iInitStackBase + a.iInitStackSize; sl@0: sl@0: volatile T_UintPtr* pB = (volatile T_UintPtr*)BootFlagsLin; sl@0: *pB = 0; sl@0: pB[1] = 0; sl@0: pB[2] = 0; sl@0: pB[3] = 0; sl@0: sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("BootFlagsPhys=%08x BootFlagsLin=%08x RegsPhys=%08x RegsLin=%08x", sl@0: BootFlagsPhys, BootFlagsLin, bp_phys, &bootPage)); sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("SCU: iCtrl=%08x iConfig=%08x iCpuStat=%08x", SCU.iCtrl, SCU.iConfig, SCU.iCpuStatus)); sl@0: sl@0: bootPage.iN.iR13Abt = a.iInitR13Abt; sl@0: bootPage.iN.iR13Und = a.iInitR13Und; sl@0: bootPage.iN.iR13Irq = a.iInitR13Irq; sl@0: bootPage.iN.iR13Fiq = a.iInitR13Fiq; sl@0: bootPage.iN.iR13Svc = init_sp; sl@0: bootPage.iN.iFlags = 0x1D3; sl@0: bootPage.iN.iR1 = (TUint32)a.iAPBootPageDirPhys; sl@0: bootPage.iN.iR2 = TUint32(a.iAPBootCodeLin) - TUint32(a.iAPBootCodePhys); sl@0: bootPage.iN.iR3 = (TUint32)a.iAPBootLin; sl@0: bootPage.iN.iR4 = (TUint32)aInfo; sl@0: bootPage.iN.iR5 = BootFlagsPhys; sl@0: bootPage.iN.iR6 = BootFlagsLin; sl@0: bootPage.iN.iR7 = a.iInitStackSize; sl@0: bootPage.iN.iR15 = (TLinAddr)&_ApEntry; sl@0: bootPage.iB[0].iRWRWTID = 0; sl@0: bootPage.iB[0].iRWROTID = 0; sl@0: bootPage.iB[0].iRWNOTID = 0; sl@0: sl@0: __KTRACE_OPT(KBOOT,DumpFullRegSet((SFullArmRegSet&)bootPage)); sl@0: sl@0: arm_dsb(); // ensure writes to uncached memory visible sl@0: sl@0: KickCpu(&bootPage.iAPBootPtr[a.iCpu], bp_phys); sl@0: sl@0: TUint32 n = TUint32(VIB->iMaxCpuClock >> 3); sl@0: n = -n; sl@0: TUint32 b = 0; sl@0: do { sl@0: ++n; sl@0: b = *pB; sl@0: } while(b!=init_sp && n!=0); sl@0: arm_dsb(); sl@0: sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("BootFlag=%08x %08x %08x %08x n=%d", b, n, pB[1], pB[2], pB[3])); sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("SCU: iCtrl=%08x iConfig=%08x iCpuStat=%08x", SCU.iCtrl, SCU.iConfig, SCU.iCpuStatus)); sl@0: if (n==0) sl@0: return KErrTimedOut; sl@0: NKern::DisableAllInterrupts(); sl@0: arm_dsb(); sl@0: while (bootPage.iBootFlags2==0) sl@0: {} sl@0: arm_dsb(); sl@0: bootPage.iBootFlags2 = 2; sl@0: arm_dsb(); sl@0: bootPage.iBPTimestamp = NKern::Timestamp(); sl@0: arm_dsb(); sl@0: while (bootPage.iBootFlags2==2) sl@0: {} sl@0: arm_dsb(); sl@0: NKern::EnableAllInterrupts(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: void InitAPTimestamp(SNThreadCreateInfo& aInfo) sl@0: { sl@0: volatile SArmAPBootInfo& a = *(volatile SArmAPBootInfo*)aInfo.iParameterBlock; sl@0: volatile SAPBootPage& bootPage = *(volatile SAPBootPage*)a.iAPBootLin; sl@0: NKern::DisableAllInterrupts(); sl@0: bootPage.iBootFlags2 = 1; sl@0: arm_dsb(); sl@0: while (bootPage.iBootFlags2==1) sl@0: {} sl@0: arm_dsb(); sl@0: bootPage.iAPTimestamp = NKern::Timestamp(); sl@0: arm_dsb(); sl@0: TUint64 bpt = bootPage.iBPTimestamp; sl@0: TUint64 apt = bootPage.iAPTimestamp; sl@0: TUint64 delta = bpt - apt; sl@0: SubScheduler().iLastTimestamp64 += delta; sl@0: __KTRACE_OPT(KBOOT,DEBUGPRINT("APT=0x%lx BPT=0x%lx Delta=0x%lx", apt, bpt, delta)); sl@0: arm_dsb(); sl@0: bootPage.iBootFlags2 = 3; sl@0: NKern::EnableAllInterrupts(); sl@0: } sl@0: