|
1 // Copyright (c) 1994-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\nkern\x86\ncthrd.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <x86.h> |
|
19 |
|
20 // Called by a thread when it first runs |
|
21 void __StartThread(); |
|
22 void __DoForcedExit(); |
|
23 |
|
24 void NThreadBase::OnKill() |
|
25 { |
|
26 } |
|
27 |
|
28 |
|
29 void NThreadBase::OnExit() |
|
30 { |
|
31 } |
|
32 |
|
33 |
|
34 void NThreadBase::SetEntry(NThreadFunction aFunc) |
|
35 { |
|
36 SThreadStack* stack=(SThreadStack*)iSavedSP; |
|
37 stack->iEdi=(TUint32)aFunc; |
|
38 } |
|
39 |
|
40 |
|
41 TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial) |
|
42 { |
|
43 if (!anInfo.iStackBase || anInfo.iStackSize<0x100) |
|
44 return KErrArgument; |
|
45 TInt r=NThreadBase::Create(anInfo,aInitial); |
|
46 if (r!=KErrNone) |
|
47 return r; |
|
48 if (!aInitial) |
|
49 { |
|
50 TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize); |
|
51 TUint32 esi=(TUint32)anInfo.iParameterBlock; |
|
52 if (anInfo.iParameterBlockSize) |
|
53 { |
|
54 wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize); |
|
55 esi=(TUint32)sp; |
|
56 } |
|
57 SThreadStack* stack=((SThreadStack*)sp)-1; |
|
58 stack->iCR0=X86::DefaultCR0 | KX86CR0_TS; |
|
59 stack->iEbx=0; |
|
60 stack->iEsi=esi; // parameter block pointer |
|
61 stack->iEdi=(TUint32)anInfo.iFunction; |
|
62 stack->iEbp=0; |
|
63 stack->iGs=KRing0DS; |
|
64 stack->iFs=0; |
|
65 stack->iReschedFlag=1; |
|
66 stack->iEip=(TUint32)__StartThread; |
|
67 iSavedSP=(TLinAddr)stack; |
|
68 wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState)); |
|
69 } |
|
70 else |
|
71 { |
|
72 #ifdef MONITOR_THREAD_CPU_TIME |
|
73 iLastStartTime = NKern::FastCounter(); |
|
74 #endif |
|
75 NKern::EnableAllInterrupts(); |
|
76 } |
|
77 #ifdef BTRACE_THREAD_IDENTIFICATION |
|
78 BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this); |
|
79 #endif |
|
80 return KErrNone; |
|
81 } |
|
82 |
|
83 |
|
84 void NThreadBase::ForceExit() |
|
85 { |
|
86 SThreadStack* stack=(SThreadStack*)iSavedSP; |
|
87 stack->iEip=(TUint32)__DoForcedExit; |
|
88 } |
|
89 |
|
90 |
|
91 void DumpExcInfo(TX86ExcInfo& a) |
|
92 { |
|
93 DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode); |
|
94 DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx); |
|
95 DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi); |
|
96 DEBUGPRINT(" CS=%08x EIP=%08x DS=%08x SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs); |
|
97 DEBUGPRINT(" ES=%08x FS=%08x GS=%08x",a.iEs,a.iFs,a.iGs); |
|
98 if (a.iCs&3) |
|
99 { |
|
100 DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3); |
|
101 } |
|
102 DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount); |
|
103 } |
|
104 |
|
105 |
|
106 EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask) |
|
107 { |
|
108 CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext"); |
|
109 TUint32* sp; |
|
110 TUint32* stackTop; |
|
111 TX86RegSet* regSet = (TX86RegSet*)aContext; |
|
112 TInt delta; |
|
113 |
|
114 NKern::Lock(); |
|
115 |
|
116 NThread* currentThread = NCurrentThread(); |
|
117 DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread); |
|
118 |
|
119 switch (NKern::CurrentContext()) |
|
120 { |
|
121 case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break; |
|
122 case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break; |
|
123 case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break; |
|
124 default: DEBUGPRINT(" CurrentContext= Unknown"); break; |
|
125 } |
|
126 |
|
127 DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2); |
|
128 DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize); |
|
129 |
|
130 DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount); |
|
131 |
|
132 DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack); |
|
133 |
|
134 TBool isCurrentThread = (currentThread == aThread); |
|
135 |
|
136 sp = (TUint32*)aThread->iSavedSP; |
|
137 stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize); |
|
138 delta = stackTop - sp; // number of words on the supervisor stack |
|
139 |
|
140 DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta); |
|
141 DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3); |
|
142 |
|
143 DEBUGPRINT(" NThreadState:"); |
|
144 switch(aThread->iSpare1) |
|
145 { |
|
146 case NThreadBase::EReady: |
|
147 DEBUGPRINT(" EReady"); |
|
148 break; |
|
149 case NThreadBase::ESuspended: |
|
150 DEBUGPRINT(" ESuspended"); |
|
151 break; |
|
152 case NThreadBase::EWaitFastSemaphore: |
|
153 DEBUGPRINT(" EWaitFastSemaphore"); |
|
154 break; |
|
155 case NThreadBase::ESleep: |
|
156 DEBUGPRINT(" ESleep"); |
|
157 break; |
|
158 case NThreadBase::EBlocked: |
|
159 DEBUGPRINT(" EBlocked"); |
|
160 break; |
|
161 case NThreadBase::EDead: |
|
162 DEBUGPRINT(" EDead"); |
|
163 break; |
|
164 case NThreadBase::EWaitDfc: |
|
165 DEBUGPRINT(" EWaitDfc"); |
|
166 break; |
|
167 default: |
|
168 DEBUGPRINT(" *Unknown"); |
|
169 } |
|
170 |
|
171 if (aAvailMask) |
|
172 { |
|
173 DEBUGPRINT(" Setting Stack-Saved Registers"); |
|
174 // Hack while ThreadSetUserContext is not implemented |
|
175 |
|
176 if (0 == aThread->iSpare3) |
|
177 { |
|
178 // Context when interrupted by user |
|
179 if (aAvailMask & 1<<13) |
|
180 stackTop[-1] = regSet->iSs; |
|
181 |
|
182 if (aAvailMask & 1<<4) |
|
183 stackTop[-2] = regSet->iEsp; |
|
184 |
|
185 if (aAvailMask & 1<<14) |
|
186 { |
|
187 DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags); |
|
188 stackTop[-3] = regSet->iEflags; |
|
189 } |
|
190 |
|
191 if (aAvailMask & 1<<8) |
|
192 stackTop[-4] = regSet->iCs; |
|
193 |
|
194 if (aAvailMask & 1<<15) |
|
195 stackTop[-5] = regSet->iEip; |
|
196 |
|
197 if (aAvailMask & 1<<9) |
|
198 stackTop[-8] = regSet->iDs; |
|
199 |
|
200 if (aAvailMask & 1<<0) |
|
201 stackTop[-9] = regSet->iEax; |
|
202 |
|
203 if (aAvailMask & 1<<2) |
|
204 stackTop[-10] = regSet->iEcx; |
|
205 |
|
206 if (aAvailMask & 1<<5) |
|
207 stackTop[-16] = regSet->iEbp; |
|
208 |
|
209 if (aAvailMask & 1<<7) |
|
210 stackTop[-17] = regSet->iEdi; |
|
211 |
|
212 if (aAvailMask & 1<<6) |
|
213 stackTop[-18] = regSet->iEsi; |
|
214 } |
|
215 else |
|
216 { |
|
217 if (aAvailMask & 1<<13) |
|
218 stackTop[-1] = regSet->iSs; |
|
219 |
|
220 if (aAvailMask & 1<<4) |
|
221 stackTop[-2] = regSet->iEsp; |
|
222 |
|
223 if (aAvailMask & 1<<14) |
|
224 { |
|
225 stackTop[-3] = regSet->iEflags; |
|
226 DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags); |
|
227 } |
|
228 |
|
229 if (aAvailMask & 1<<8) |
|
230 stackTop[-4] = regSet->iCs; |
|
231 |
|
232 if (aAvailMask & 1<<15) |
|
233 stackTop[-5] = regSet->iEip; |
|
234 |
|
235 /* -6 and -7 are not used since they are the vector number and the error code, |
|
236 * which are 3 and 0 resp. for breakpoints. |
|
237 */ |
|
238 |
|
239 /* The following are from the push instructions in __X86VectorExc */ |
|
240 if (aAvailMask & 1<<9) |
|
241 stackTop[-8] = regSet->iDs; |
|
242 |
|
243 if (aAvailMask & 1<<10) |
|
244 stackTop[-9] = regSet->iEs; |
|
245 |
|
246 if (aAvailMask & 1<<11) |
|
247 stackTop[-10] = regSet->iFs; |
|
248 |
|
249 if (aAvailMask & 1<<12) |
|
250 stackTop[-11] = regSet->iGs; |
|
251 |
|
252 if (aAvailMask & 1<<5) |
|
253 stackTop[-12] = regSet->iEbp; |
|
254 |
|
255 if (aAvailMask & 1<<7) |
|
256 stackTop[-13] = regSet->iEdi; |
|
257 |
|
258 if (aAvailMask & 1<<6) |
|
259 stackTop[-14] = regSet->iEsi; |
|
260 |
|
261 if (aAvailMask & 1<<1) |
|
262 stackTop[-15] = regSet->iEbx; |
|
263 |
|
264 if (aAvailMask & 1<<2) |
|
265 stackTop[-16] = regSet->iEcx; |
|
266 |
|
267 if (aAvailMask & 1<<3) |
|
268 stackTop[-17] = regSet->iEdx; |
|
269 |
|
270 if (aAvailMask & 1<<0) |
|
271 stackTop[-18] = regSet->iEax; |
|
272 } |
|
273 |
|
274 DEBUGPRINT("stack from stack top, after changes " ); |
|
275 if (delta < 128) |
|
276 { |
|
277 delta = -delta; |
|
278 } |
|
279 else |
|
280 { |
|
281 delta = -128; |
|
282 } |
|
283 |
|
284 for ( ; delta < 0; delta++) |
|
285 { |
|
286 DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]); |
|
287 } |
|
288 } |
|
289 else |
|
290 { |
|
291 memclr(aContext, sizeof(TX86RegSet)); |
|
292 |
|
293 if (isCurrentThread) |
|
294 { |
|
295 // Not yet supported |
|
296 DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?"); |
|
297 } |
|
298 else |
|
299 { |
|
300 DEBUGPRINT("stack from stack top " ); |
|
301 |
|
302 if (delta < 128) |
|
303 { |
|
304 delta = -delta; |
|
305 } |
|
306 else |
|
307 { |
|
308 delta = -128; |
|
309 } |
|
310 |
|
311 for( ; delta < 0; delta++) |
|
312 { |
|
313 DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]); |
|
314 } |
|
315 |
|
316 if (0 == aThread->iSpare3) |
|
317 { |
|
318 // Context when interrupted by user |
|
319 regSet->iSs = stackTop[-1]; |
|
320 aAvailMask |= 1<<13; |
|
321 |
|
322 regSet->iEsp = stackTop[-2]; |
|
323 aAvailMask |= 1<<4; |
|
324 |
|
325 regSet->iEflags = stackTop[-3]; |
|
326 aAvailMask |= 1<<14; |
|
327 |
|
328 regSet->iCs = stackTop[-4]; |
|
329 aAvailMask |= 1<<8; |
|
330 |
|
331 regSet->iEip = stackTop[-5]; |
|
332 aAvailMask |= 1<<15; |
|
333 |
|
334 regSet->iDs = stackTop[-8]; |
|
335 aAvailMask |= 1<<9; |
|
336 |
|
337 regSet->iEax = stackTop[-9]; |
|
338 aAvailMask |= 1<<0; |
|
339 |
|
340 regSet->iEcx = stackTop[-10]; |
|
341 aAvailMask |= 1<<2; |
|
342 |
|
343 regSet->iEbp = stackTop[-16]; |
|
344 aAvailMask |= 1<<5; |
|
345 |
|
346 regSet->iEdi = stackTop[-17]; |
|
347 aAvailMask |= 1<<7; |
|
348 |
|
349 regSet->iEsi = stackTop[-18]; |
|
350 aAvailMask |= 1<<6; |
|
351 } |
|
352 else |
|
353 { |
|
354 // Now populate the TX86RegSet with the contents of the stack |
|
355 |
|
356 /* |
|
357 * The first 5 are from the comments at the start of __X86VectorExc : |
|
358 * [ESP+0] = vector number |
|
359 * [ESP+4] = error code (filled with 0 for exceptions without error codes) |
|
360 * [ESP+8] = return EIP |
|
361 * [ESP+12] = return CS |
|
362 * [ESP+16] = return EFLAGS |
|
363 * [ESP+20] = return ESP if privilege change occurred |
|
364 * [ESP+24] = return SS if privilege change occurred |
|
365 */ |
|
366 regSet->iSs = stackTop[-1]; |
|
367 aAvailMask |= 1<<13; |
|
368 |
|
369 regSet->iEsp = stackTop[-2]; |
|
370 aAvailMask |= 1<<4; |
|
371 |
|
372 regSet->iEflags = stackTop[-3]; |
|
373 aAvailMask |= 1<<14; |
|
374 |
|
375 regSet->iCs = stackTop[-4]; |
|
376 aAvailMask |= 1<<8; |
|
377 |
|
378 regSet->iEip = stackTop[-5]; |
|
379 aAvailMask |= 1<<15; |
|
380 |
|
381 /* -6 and -7 are not used since they are the vector number and the error code, |
|
382 * which for a breakpoint are 3 and 0 resp. |
|
383 */ |
|
384 |
|
385 /* The following are from the push instructions in __X86VectorExc */ |
|
386 regSet->iDs = stackTop[-8]; |
|
387 aAvailMask |= 1<<9; |
|
388 |
|
389 regSet->iEs = stackTop[-9]; |
|
390 aAvailMask |= 1<<10; |
|
391 |
|
392 regSet->iFs = stackTop[-10]; |
|
393 aAvailMask |= 1<<11; |
|
394 |
|
395 regSet->iGs = stackTop[-11]; |
|
396 aAvailMask |= 1<<12; |
|
397 |
|
398 regSet->iEbp = stackTop[-12]; |
|
399 aAvailMask |= 1<<5; |
|
400 |
|
401 regSet->iEdi = stackTop[-13]; |
|
402 aAvailMask |= 1<<7; |
|
403 |
|
404 regSet->iEsi = stackTop[-14]; |
|
405 aAvailMask |= 1<<6; |
|
406 |
|
407 regSet->iEbx = stackTop[-15]; |
|
408 aAvailMask |= 1<<1; |
|
409 |
|
410 regSet->iEcx = stackTop[-16]; |
|
411 aAvailMask |= 1<<2; |
|
412 |
|
413 regSet->iEdx = stackTop[-17]; |
|
414 aAvailMask |= 1<<3; |
|
415 |
|
416 regSet->iEax = stackTop[-18]; |
|
417 aAvailMask |= 1<<0; |
|
418 } // else if (0 == aThread->iSpare3) |
|
419 |
|
420 } // else if (isCurrentThread) |
|
421 |
|
422 } // else if (aAvailMask) |
|
423 |
|
424 NKern::Unlock(); |
|
425 } |
|
426 |
|
427 |
|
428 void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp) |
|
429 { |
|
430 } |