|
1 // Copyright (c) 2006-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\x86\ncutils.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <x86.h> |
|
19 |
|
20 extern "C" { |
|
21 extern SVariantInterfaceBlock* VIB; |
|
22 } |
|
23 |
|
24 //#define __DBG_MON_FAULT__ |
|
25 //#define __RAM_LOADED_CODE__ |
|
26 //#define __EARLY_DEBUG__ |
|
27 void InitFpu(); |
|
28 |
|
29 |
|
30 TUint32 NKern::IdleGenerationCount() |
|
31 { |
|
32 return TheScheduler.iIdleGenerationCount; |
|
33 } |
|
34 |
|
35 void NKern::Idle() |
|
36 { |
|
37 TScheduler& s = TheScheduler; |
|
38 TSubScheduler& ss = SubScheduler(); // OK since idle thread is locked to CPU |
|
39 TUint32 m = ss.iCpuMask; |
|
40 |
|
41 s.iIdleSpinLock.LockIrq(); // don't allow any more idle DFCs for now |
|
42 TUint32 orig_cpus_not_idle = __e32_atomic_and_ord32(&s.iCpusNotIdle, ~m); |
|
43 if (orig_cpus_not_idle == m) |
|
44 { |
|
45 // all CPUs idle |
|
46 if (!s.iIdleDfcs.IsEmpty()) |
|
47 { |
|
48 __e32_atomic_ior_ord32(&s.iCpusNotIdle, m); // we aren't idle after all |
|
49 s.iIdleGeneration ^= 1; |
|
50 ++s.iIdleGenerationCount; |
|
51 s.iIdleSpillCpu = (TUint8)ss.iCpuNum; |
|
52 ss.iDfcs.MoveFrom(&s.iIdleDfcs); |
|
53 ss.iDfcPendingFlag = 1; |
|
54 s.iIdleSpinLock.UnlockIrq(); |
|
55 NKern::Lock(); |
|
56 NKern::Unlock(); // process idle DFCs here |
|
57 return; |
|
58 } |
|
59 } |
|
60 s.iIdleSpinLock.UnlockOnly(); // leave interrupts disabled |
|
61 NKIdle(0); |
|
62 } |
|
63 |
|
64 TUint32 ContextId() |
|
65 { |
|
66 switch(NKern::CurrentContext()) |
|
67 { |
|
68 case NKern::EThread: |
|
69 return (TUint32)NKern::CurrentThread(); |
|
70 case NKern::EIDFC: |
|
71 return 3; |
|
72 case NKern::EInterrupt: |
|
73 return 2; |
|
74 default: |
|
75 return 0; |
|
76 } |
|
77 } |
|
78 |
|
79 EXPORT_C TBool BTrace::Out(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
80 { |
|
81 SBTraceData& traceData = BTraceData; |
|
82 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
83 return FALSE; |
|
84 |
|
85 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
86 __ACQUIRE_BTRACE_LOCK(); |
|
87 TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc); |
|
88 __RELEASE_BTRACE_LOCK(); |
|
89 return r; |
|
90 } |
|
91 |
|
92 EXPORT_C TBool BTrace::OutX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
93 { |
|
94 SBTraceData& traceData = BTraceData; |
|
95 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
96 return FALSE; |
|
97 |
|
98 TUint32 context = ContextId(); |
|
99 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
100 __ACQUIRE_BTRACE_LOCK(); |
|
101 TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc); |
|
102 __RELEASE_BTRACE_LOCK(); |
|
103 return r; |
|
104 } |
|
105 |
|
106 EXPORT_C TBool BTrace::OutN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
107 { |
|
108 SBTraceData& traceData = BTraceData; |
|
109 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
110 return FALSE; |
|
111 |
|
112 if(TUint(aDataSize)>KMaxBTraceDataArray) |
|
113 { |
|
114 aDataSize = KMaxBTraceDataArray; |
|
115 a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); |
|
116 } |
|
117 a0 += aDataSize<<(BTrace::ESizeIndex*8); |
|
118 |
|
119 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
120 TBool r; |
|
121 __ACQUIRE_BTRACE_LOCK(); |
|
122 if (!aDataSize) |
|
123 r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc); |
|
124 else if (aDataSize<=4) |
|
125 r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc); |
|
126 else |
|
127 r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc); |
|
128 __RELEASE_BTRACE_LOCK(); |
|
129 return r; |
|
130 } |
|
131 |
|
132 EXPORT_C TBool BTrace::OutNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
133 { |
|
134 SBTraceData& traceData = BTraceData; |
|
135 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
136 return FALSE; |
|
137 |
|
138 if(TUint(aDataSize)>KMaxBTraceDataArray) |
|
139 { |
|
140 aDataSize = KMaxBTraceDataArray; |
|
141 a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); |
|
142 } |
|
143 a0 += aDataSize<<(BTrace::ESizeIndex*8); |
|
144 |
|
145 TUint32 context = ContextId(); |
|
146 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
147 TBool r; |
|
148 __ACQUIRE_BTRACE_LOCK(); |
|
149 if(!aDataSize) |
|
150 r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc); |
|
151 else if(aDataSize<=4) |
|
152 r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc); |
|
153 else |
|
154 r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc); |
|
155 __RELEASE_BTRACE_LOCK(); |
|
156 return r; |
|
157 } |
|
158 |
|
159 EXPORT_C TBool BTrace::OutBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize) |
|
160 { |
|
161 TUint32 context = ContextId(); |
|
162 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
163 SBTraceData& traceData = BTraceData; |
|
164 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
165 return FALSE; |
|
166 TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc); |
|
167 return r; |
|
168 } |
|
169 |
|
170 EXPORT_C TBool BTrace::OutFiltered(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
171 { |
|
172 SBTraceData& traceData = BTraceData; |
|
173 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
174 return FALSE; |
|
175 if(!traceData.CheckFilter2(a1)) |
|
176 return FALSE; |
|
177 |
|
178 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
179 __ACQUIRE_BTRACE_LOCK(); |
|
180 TBool r = traceData.iHandler(a0,0,0,a1,a2,a3,0,pc); |
|
181 __RELEASE_BTRACE_LOCK(); |
|
182 return r; |
|
183 } |
|
184 |
|
185 EXPORT_C TBool BTrace::OutFilteredX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
186 { |
|
187 SBTraceData& traceData = BTraceData; |
|
188 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
189 return FALSE; |
|
190 if(!traceData.CheckFilter2(a1)) |
|
191 return FALSE; |
|
192 |
|
193 TUint32 context = ContextId(); |
|
194 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
195 __ACQUIRE_BTRACE_LOCK(); |
|
196 TBool r = traceData.iHandler(a0,0,context,a1,a2,a3,0,pc); |
|
197 __RELEASE_BTRACE_LOCK(); |
|
198 return r; |
|
199 } |
|
200 |
|
201 EXPORT_C TBool BTrace::OutFilteredN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
202 { |
|
203 SBTraceData& traceData = BTraceData; |
|
204 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
205 return FALSE; |
|
206 if(!traceData.CheckFilter2(a1)) |
|
207 return FALSE; |
|
208 |
|
209 if(TUint(aDataSize)>KMaxBTraceDataArray) |
|
210 { |
|
211 aDataSize = KMaxBTraceDataArray; |
|
212 a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); |
|
213 } |
|
214 a0 += aDataSize<<(BTrace::ESizeIndex*8); |
|
215 |
|
216 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
217 TBool r; |
|
218 __ACQUIRE_BTRACE_LOCK(); |
|
219 if(!aDataSize) |
|
220 r = traceData.iHandler(a0,0,0,a1,a2,0,0,pc); |
|
221 else if(aDataSize<=4) |
|
222 r = traceData.iHandler(a0,0,0,a1,a2,*(TUint32*)aData,0,pc); |
|
223 else |
|
224 r = traceData.iHandler(a0,0,0,a1,a2,(TUint32)aData,0,pc); |
|
225 __RELEASE_BTRACE_LOCK(); |
|
226 return r; |
|
227 } |
|
228 |
|
229 EXPORT_C TBool BTrace::OutFilteredNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
230 { |
|
231 SBTraceData& traceData = BTraceData; |
|
232 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
233 return FALSE; |
|
234 if(!traceData.CheckFilter2(a1)) |
|
235 return FALSE; |
|
236 |
|
237 if(TUint(aDataSize)>KMaxBTraceDataArray) |
|
238 { |
|
239 aDataSize = KMaxBTraceDataArray; |
|
240 a0 |= BTrace::ERecordTruncated<<(BTrace::EFlagsIndex*8); |
|
241 } |
|
242 a0 += aDataSize<<(BTrace::ESizeIndex*8); |
|
243 |
|
244 TUint32 context = ContextId(); |
|
245 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
246 TBool r; |
|
247 __ACQUIRE_BTRACE_LOCK(); |
|
248 if(!aDataSize) |
|
249 r = traceData.iHandler(a0,0,context,a1,a2,0,0,pc); |
|
250 else if(aDataSize<=4) |
|
251 r = traceData.iHandler(a0,0,context,a1,a2,*(TUint32*)aData,0,pc); |
|
252 else |
|
253 r = traceData.iHandler(a0,0,context,a1,a2,(TUint32)aData,0,pc); |
|
254 __RELEASE_BTRACE_LOCK(); |
|
255 return r; |
|
256 } |
|
257 |
|
258 EXPORT_C TBool BTrace::OutFilteredBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize) |
|
259 { |
|
260 TUint32 context = ContextId(); |
|
261 TUint32 pc = (&a0)[-1]; // return address on X86 |
|
262 SBTraceData& traceData = BTraceData; |
|
263 if(!traceData.iFilter[(a0>>BTrace::ECategoryIndex*8)&0xff]) |
|
264 return FALSE; |
|
265 if(!traceData.CheckFilter2(a1)) |
|
266 return FALSE; |
|
267 TBool r = DoOutBig(a0,a1,aData,aDataSize,context,pc); |
|
268 return r; |
|
269 } |
|
270 |
|
271 EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 aHeader, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize) |
|
272 { |
|
273 return EFalse; //kernel side not implemented yet |
|
274 } |
|
275 |
|
276 TInt BTraceDefaultControl(BTrace::TControl /*aFunction*/, TAny* /*aArg1*/, TAny* /*aArg2*/) |
|
277 { |
|
278 return KErrNotSupported; |
|
279 } |
|
280 |
|
281 |
|
282 EXPORT_C void BTrace::SetHandlers(BTrace::THandler aNewHandler, BTrace::TControlFunction aNewControl, BTrace::THandler& aOldHandler, BTrace::TControlFunction& aOldControl) |
|
283 { |
|
284 BTrace::TControlFunction nc = aNewControl ? aNewControl : &BTraceDefaultControl; |
|
285 __ACQUIRE_BTRACE_LOCK(); |
|
286 BTrace::THandler oldh = (BTrace::THandler)__e32_atomic_swp_ord_ptr(&BTraceData.iHandler, aNewHandler); |
|
287 BTrace::TControlFunction oldc = (BTrace::TControlFunction)__e32_atomic_swp_ord_ptr(&BTraceData.iControl, nc); |
|
288 __RELEASE_BTRACE_LOCK(); |
|
289 aOldHandler = oldh; |
|
290 aOldControl = oldc; |
|
291 } |
|
292 |
|
293 |
|
294 EXPORT_C TInt BTrace::SetFilter(TUint aCategory, TInt aValue) |
|
295 { |
|
296 if(!IsSupported(aCategory)) |
|
297 return KErrNotSupported; |
|
298 TUint8* filter = BTraceData.iFilter+aCategory; |
|
299 TUint oldValue = *filter; |
|
300 if(TUint(aValue)<=1u) |
|
301 { |
|
302 oldValue = __e32_atomic_swp_ord8(filter, (TUint8)aValue); |
|
303 BTraceContext4(BTrace::EMetaTrace, BTrace::EMetaTraceFilterChange, (TUint8)aCategory | (aValue<<8)); |
|
304 } |
|
305 return oldValue; |
|
306 } |
|
307 |
|
308 EXPORT_C SCpuIdleHandler* NKern::CpuIdleHandler() |
|
309 { |
|
310 return &::CpuIdleHandler; |
|
311 } |
|
312 |
|
313 |
|
314 void NKern::Init0(TAny* a) |
|
315 { |
|
316 __KTRACE_OPT(KBOOT,DEBUGPRINT("VIB=%08x", a)); |
|
317 VIB = (SVariantInterfaceBlock*)a; |
|
318 __NK_ASSERT_ALWAYS(VIB && VIB->iVer==0 && VIB->iSize==sizeof(SVariantInterfaceBlock)); |
|
319 __KTRACE_OPT(KBOOT,DEBUGPRINT("iVer=%d iSize=%d", VIB->iVer, VIB->iSize)); |
|
320 __KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxCpuClock=%08x %08x", I64HIGH(VIB->iMaxCpuClock), I64LOW(VIB->iMaxCpuClock))); |
|
321 __KTRACE_OPT(KBOOT,DEBUGPRINT("iTimestampFreq=%u", VIB->iTimestampFreq)); |
|
322 __KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxTimerClock=%u", VIB->iMaxTimerClock)); |
|
323 TInt i; |
|
324 for (i=0; i<KMaxCpus; ++i) |
|
325 { |
|
326 TSubScheduler& ss = TheSubSchedulers[i]; |
|
327 ss.i_TimerMultF = (TAny*)KMaxTUint32; |
|
328 ss.i_TimerMultI = (TAny*)0x01000000u; |
|
329 ss.i_CpuMult = (TAny*)KMaxTUint32; |
|
330 VIB->iTimerMult[i] = (volatile STimerMult*)&ss.i_TimerMultF; |
|
331 VIB->iCpuMult[i] = (volatile TUint32*)&ss.i_CpuMult; |
|
332 } |
|
333 TheScheduler.i_TimerMax = (TAny*)(VIB->iMaxTimerClock / 128); |
|
334 InitFpu(); |
|
335 InterruptInit0(); |
|
336 } |
|
337 |
|
338 EXPORT_C TUint32 NKern::CpuTimeMeasFreq() |
|
339 { |
|
340 return NKern::TimestampFrequency(); |
|
341 } |
|
342 |
|
343 |
|
344 /** Converts a time interval in microseconds to thread timeslice ticks |
|
345 |
|
346 @param aMicroseconds time interval in microseconds. |
|
347 @return Number of thread timeslice ticks. Non-integral results are rounded up. |
|
348 |
|
349 @pre aMicroseconds should be nonnegative |
|
350 @pre any context |
|
351 */ |
|
352 EXPORT_C TInt NKern::TimesliceTicks(TUint32 aMicroseconds) |
|
353 { |
|
354 TUint32 mf32 = (TUint32)TheScheduler.i_TimerMax; |
|
355 TUint64 mf(mf32); |
|
356 TUint64 ticks = mf*TUint64(aMicroseconds) + UI64LIT(999999); |
|
357 ticks /= UI64LIT(1000000); |
|
358 if (ticks > TUint64(TInt(KMaxTInt))) |
|
359 return KMaxTInt; |
|
360 else |
|
361 return (TInt)ticks; |
|
362 } |
|
363 |