|
1 // Copyright (c) 2008-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\arm\nccpu.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <arm.h> |
|
19 #include <arm_gic.h> |
|
20 #include <arm_scu.h> |
|
21 #include <arm_tmr.h> |
|
22 |
|
23 extern "C" { |
|
24 extern SVariantInterfaceBlock* VIB; |
|
25 } |
|
26 |
|
27 struct SAPBootPage : public SFullArmRegSet |
|
28 { |
|
29 volatile T_UintPtr iAPBootPtr[KMaxCpus]; |
|
30 volatile T_UintPtr iBootFlags; |
|
31 volatile T_UintPtr iBootFlags2; |
|
32 volatile T_UintPtr iBootFlags3; |
|
33 volatile T_UintPtr iBootFlags4; |
|
34 volatile TUint64 iBPTimestamp; |
|
35 volatile TUint64 iAPTimestamp; |
|
36 }; |
|
37 |
|
38 extern "C" void _ApEntry(); |
|
39 extern "C" void KickCpu(volatile T_UintPtr* aPtr, T_UintPtr aRegsPhys); |
|
40 extern void DumpFullRegSet(SFullArmRegSet& a); |
|
41 |
|
42 TInt NKern::BootAP(volatile SAPBootInfo* aInfo) |
|
43 { |
|
44 volatile SArmAPBootInfo& a = *(volatile SArmAPBootInfo*)aInfo; |
|
45 __KTRACE_OPT(KBOOT,DEBUGPRINT("NKern::BootAP %d %08x+%x", a.iCpu, a.iInitStackBase, a.iInitStackSize)); |
|
46 |
|
47 T_UintPtr bp_phys = a.iAPBootPhys; |
|
48 T_UintPtr BootFlagsPhys = bp_phys + (T_UintPtr)_FOFF(SAPBootPage,iBootFlags); |
|
49 volatile SAPBootPage& bootPage = *(volatile SAPBootPage*)a.iAPBootLin; |
|
50 Arm::SaveState((SFullArmRegSet&)bootPage); |
|
51 NKern::EnableAllInterrupts(); // Arm::SaveState() disables interrupts |
|
52 |
|
53 TLinAddr BootFlagsLin = (TLinAddr)&bootPage.iBootFlags; |
|
54 TLinAddr init_sp = a.iInitStackBase + a.iInitStackSize; |
|
55 |
|
56 volatile T_UintPtr* pB = (volatile T_UintPtr*)BootFlagsLin; |
|
57 *pB = 0; |
|
58 pB[1] = 0; |
|
59 pB[2] = 0; |
|
60 pB[3] = 0; |
|
61 |
|
62 __KTRACE_OPT(KBOOT,DEBUGPRINT("BootFlagsPhys=%08x BootFlagsLin=%08x RegsPhys=%08x RegsLin=%08x", |
|
63 BootFlagsPhys, BootFlagsLin, bp_phys, &bootPage)); |
|
64 __KTRACE_OPT(KBOOT,DEBUGPRINT("SCU: iCtrl=%08x iConfig=%08x iCpuStat=%08x", SCU.iCtrl, SCU.iConfig, SCU.iCpuStatus)); |
|
65 |
|
66 bootPage.iN.iR13Abt = a.iInitR13Abt; |
|
67 bootPage.iN.iR13Und = a.iInitR13Und; |
|
68 bootPage.iN.iR13Irq = a.iInitR13Irq; |
|
69 bootPage.iN.iR13Fiq = a.iInitR13Fiq; |
|
70 bootPage.iN.iR13Svc = init_sp; |
|
71 bootPage.iN.iFlags = 0x1D3; |
|
72 bootPage.iN.iR1 = (TUint32)a.iAPBootPageDirPhys; |
|
73 bootPage.iN.iR2 = TUint32(a.iAPBootCodeLin) - TUint32(a.iAPBootCodePhys); |
|
74 bootPage.iN.iR3 = (TUint32)a.iAPBootLin; |
|
75 bootPage.iN.iR4 = (TUint32)aInfo; |
|
76 bootPage.iN.iR5 = BootFlagsPhys; |
|
77 bootPage.iN.iR6 = BootFlagsLin; |
|
78 bootPage.iN.iR7 = a.iInitStackSize; |
|
79 bootPage.iN.iR15 = (TLinAddr)&_ApEntry; |
|
80 bootPage.iB[0].iRWRWTID = 0; |
|
81 bootPage.iB[0].iRWROTID = 0; |
|
82 bootPage.iB[0].iRWNOTID = 0; |
|
83 |
|
84 __KTRACE_OPT(KBOOT,DumpFullRegSet((SFullArmRegSet&)bootPage)); |
|
85 |
|
86 arm_dsb(); // ensure writes to uncached memory visible |
|
87 |
|
88 KickCpu(&bootPage.iAPBootPtr[a.iCpu], bp_phys); |
|
89 |
|
90 TUint32 n = TUint32(VIB->iMaxCpuClock >> 3); |
|
91 n = -n; |
|
92 TUint32 b = 0; |
|
93 do { |
|
94 ++n; |
|
95 b = *pB; |
|
96 } while(b!=init_sp && n!=0); |
|
97 arm_dsb(); |
|
98 |
|
99 __KTRACE_OPT(KBOOT,DEBUGPRINT("BootFlag=%08x %08x %08x %08x n=%d", b, n, pB[1], pB[2], pB[3])); |
|
100 __KTRACE_OPT(KBOOT,DEBUGPRINT("SCU: iCtrl=%08x iConfig=%08x iCpuStat=%08x", SCU.iCtrl, SCU.iConfig, SCU.iCpuStatus)); |
|
101 if (n==0) |
|
102 return KErrTimedOut; |
|
103 NKern::DisableAllInterrupts(); |
|
104 arm_dsb(); |
|
105 while (bootPage.iBootFlags2==0) |
|
106 {} |
|
107 arm_dsb(); |
|
108 bootPage.iBootFlags2 = 2; |
|
109 arm_dsb(); |
|
110 bootPage.iBPTimestamp = NKern::Timestamp(); |
|
111 arm_dsb(); |
|
112 while (bootPage.iBootFlags2==2) |
|
113 {} |
|
114 arm_dsb(); |
|
115 NKern::EnableAllInterrupts(); |
|
116 return KErrNone; |
|
117 } |
|
118 |
|
119 void InitAPTimestamp(SNThreadCreateInfo& aInfo) |
|
120 { |
|
121 volatile SArmAPBootInfo& a = *(volatile SArmAPBootInfo*)aInfo.iParameterBlock; |
|
122 volatile SAPBootPage& bootPage = *(volatile SAPBootPage*)a.iAPBootLin; |
|
123 NKern::DisableAllInterrupts(); |
|
124 bootPage.iBootFlags2 = 1; |
|
125 arm_dsb(); |
|
126 while (bootPage.iBootFlags2==1) |
|
127 {} |
|
128 arm_dsb(); |
|
129 bootPage.iAPTimestamp = NKern::Timestamp(); |
|
130 arm_dsb(); |
|
131 TUint64 bpt = bootPage.iBPTimestamp; |
|
132 TUint64 apt = bootPage.iAPTimestamp; |
|
133 TUint64 delta = bpt - apt; |
|
134 SubScheduler().iLastTimestamp64 += delta; |
|
135 __KTRACE_OPT(KBOOT,DEBUGPRINT("APT=0x%lx BPT=0x%lx Delta=0x%lx", apt, bpt, delta)); |
|
136 arm_dsb(); |
|
137 bootPage.iBootFlags2 = 3; |
|
138 NKern::EnableAllInterrupts(); |
|
139 } |
|
140 |