|
1 // Copyright (c) 1998-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 // e32test\mmu\t_pages.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <e32std.h> |
|
19 #include <e32std_private.h> |
|
20 #include <e32svr.h> |
|
21 #include "d_shadow.h" |
|
22 |
|
23 RShadow Shadow; |
|
24 LOCAL_D TUint Read(TUint anAddr) |
|
25 { |
|
26 return Shadow.Read(anAddr); |
|
27 } |
|
28 TUint PageTables = 0; |
|
29 TCpu Cpu = ECpuUnknown; |
|
30 TInt CpuArc = 0; |
|
31 TInt CpuSpecial = 0; |
|
32 TUint ControlReg = 0; |
|
33 |
|
34 const TUint KXPbitM = 0x800000; |
|
35 |
|
36 LOCAL_C void ProcessCBTEX(TDes& aDes, TUint aCb, TUint aTex) |
|
37 { |
|
38 |
|
39 const TPtrC KTEXCB[9] = {_L("StOr"),_L("ShDv"),_L("WTRA"),_L("WBRA"),_L("NoCa"),_L("Resv"),_L("ImpD"),_L("WBWA"),_L("NSDv")}; |
|
40 const TPtrC KCacheP[4] = {_L("NoCa"),_L("WBWA"),_L("WTRA"),_L("WBRA")}; |
|
41 aCb = aCb >> 2; |
|
42 |
|
43 TUint texCB = aCb | ((aTex&7) << 2); |
|
44 |
|
45 if ((texCB<9) && (CpuArc>5)) |
|
46 aDes.Append(KTEXCB[texCB]); |
|
47 else if ((aTex&4) && (CpuArc>5)) |
|
48 { |
|
49 aDes.Append(KCacheP[aTex&3]); |
|
50 aDes.Append(TChar('/')); |
|
51 aDes.Append(KCacheP[aCb]); |
|
52 } |
|
53 else |
|
54 { |
|
55 if (CpuArc>5) |
|
56 { |
|
57 if (aTex&4) |
|
58 aDes.Append(TChar('1')); |
|
59 else |
|
60 aDes.Append(TChar('0')); |
|
61 |
|
62 if (aTex&2) |
|
63 aDes.Append(TChar('1')); |
|
64 else |
|
65 aDes.Append(TChar('0')); |
|
66 |
|
67 if (aTex&1) |
|
68 aDes.Append(TChar('1')); |
|
69 else |
|
70 aDes.Append(TChar('0')); |
|
71 } |
|
72 else if (CpuSpecial == 2) |
|
73 { |
|
74 if (aTex==1) |
|
75 aDes.Append(TChar('X')); |
|
76 else if (aTex==0) |
|
77 aDes.Append(TChar('_')); |
|
78 else |
|
79 aDes.Append(TChar('?')); |
|
80 |
|
81 } |
|
82 |
|
83 if (aCb & 2) |
|
84 aDes.Append(TChar('C')); |
|
85 else |
|
86 aDes.Append(TChar('_')); |
|
87 if (aCb & 1) |
|
88 aDes.Append(TChar('B')); |
|
89 else |
|
90 aDes.Append(TChar('_')); |
|
91 } |
|
92 } |
|
93 |
|
94 |
|
95 LOCAL_C void ProcessXNnGS(TDes& aDes, TUint anGS, TUint aXN) |
|
96 { |
|
97 if ((ControlReg & KXPbitM)) |
|
98 { |
|
99 aDes.Append(TChar(' ')); |
|
100 if (aXN ) |
|
101 aDes.Append(_L("XN ")); |
|
102 else |
|
103 aDes.Append(_L("__ ")); |
|
104 |
|
105 if (anGS&2 ) |
|
106 aDes.Append(_L("nG ")); |
|
107 else |
|
108 aDes.Append(_L("__ ")); |
|
109 |
|
110 if (anGS&1 ) |
|
111 aDes.Append(TChar('S')); |
|
112 else |
|
113 aDes.Append(TChar('_')); |
|
114 |
|
115 } |
|
116 } |
|
117 |
|
118 |
|
119 LOCAL_C void ProcessAP(TDes& aDes, TUint aAp) |
|
120 { |
|
121 const TPtrC KAccessP[7] = {_L(" RWNO"),_L(" RWRO"),_L(" RWRW"),_L(" Rsv0"),_L(" RONO"),_L(" RORO"),_L(" Rsv1")}; |
|
122 const TPtrC KAccZrP[4] = {_L(" NONO"), _L(" RONO"), _L(" RORO"), _L(" Rsv2")}; |
|
123 |
|
124 TUint access = aAp & 3; |
|
125 TUint apx = (aAp >> 3) & 4; |
|
126 |
|
127 if (((ControlReg & 0x300) !=0) && apx) |
|
128 { |
|
129 aDes.Append(_L(" Rsv3")); |
|
130 } |
|
131 else |
|
132 { |
|
133 if ((ControlReg & KXPbitM)) |
|
134 access |= apx; |
|
135 |
|
136 if (access==0) |
|
137 aDes.Append(KAccZrP[(ControlReg >> 8) & 3]); |
|
138 else |
|
139 aDes.Append(KAccessP[access-1]); |
|
140 } |
|
141 } |
|
142 |
|
143 LOCAL_C void ProcessPteSE(TUint aPte, TUint anAddr) |
|
144 { |
|
145 TUint type=aPte&3; |
|
146 TBuf<36> buf; |
|
147 switch(type) |
|
148 { |
|
149 case 0: |
|
150 // not present |
|
151 break; |
|
152 case 1: |
|
153 { |
|
154 // large page |
|
155 TUint phys=aPte & 0xffff0000; |
|
156 TUint ap0=(aPte>>4)&3; |
|
157 TUint ap1=(aPte>>6)&3; |
|
158 TUint ap2=(aPte>>8)&3; |
|
159 TUint ap3=(aPte>>10)&3; |
|
160 TUint tex=(aPte>>12)&0xf; |
|
161 ProcessCBTEX(buf,aPte&0xc,tex); |
|
162 ProcessAP(buf,ap0); |
|
163 ProcessAP(buf,ap1); |
|
164 ProcessAP(buf,ap2); |
|
165 ProcessAP(buf,ap3); |
|
166 RDebug::Print(_L("\t%08x Lpage: phys=%08x, %S"),anAddr,phys,&buf); |
|
167 break; |
|
168 } |
|
169 case 2: |
|
170 { |
|
171 // small page |
|
172 TUint phys=aPte & 0xfffff000; |
|
173 TUint ap0=(aPte>>4)&3; |
|
174 TUint ap1=(aPte>>6)&3; |
|
175 TUint ap2=(aPte>>8)&3; |
|
176 TUint ap3=(aPte>>10)&3; |
|
177 ProcessCBTEX(buf,aPte&0xc,0); |
|
178 ProcessAP(buf,ap0); |
|
179 ProcessAP(buf,ap1); |
|
180 ProcessAP(buf,ap2); |
|
181 ProcessAP(buf,ap3); |
|
182 RDebug::Print(_L("\t%08x Spage: phys=%08x, %S"),anAddr,phys,&buf); |
|
183 break; |
|
184 } |
|
185 case 3: |
|
186 { |
|
187 // extended small page |
|
188 TUint phys=aPte & 0xfffff000; |
|
189 TUint ap=(aPte>>4)&3; |
|
190 TUint tex=(aPte>>6)&0xf; |
|
191 ProcessCBTEX(buf,aPte&0xc,tex); |
|
192 ProcessAP(buf,ap); |
|
193 RDebug::Print(_L("\t%08x XSpage: phys=%08x, %S"),anAddr,phys,&buf); |
|
194 break; |
|
195 } |
|
196 } |
|
197 } |
|
198 |
|
199 |
|
200 LOCAL_C void ProcessPteSD(TUint aPte, TUint anAddr) |
|
201 { |
|
202 if ((aPte&3) != 0) |
|
203 { |
|
204 |
|
205 TBuf<36> buf; |
|
206 TUint ap=(aPte>>4)&23; |
|
207 |
|
208 if (aPte&2) // XS-Page |
|
209 { |
|
210 // extended small page |
|
211 TUint phys=aPte & 0xfffff000; |
|
212 TUint tex=(aPte>>6)&0x7; |
|
213 ProcessCBTEX(buf,aPte&0xc,tex); |
|
214 ProcessAP(buf,ap); |
|
215 ProcessXNnGS(buf, (aPte>>10)&3, aPte &1); |
|
216 RDebug::Print(_L("\t%08x XSpage: phys=%08x, %S"),anAddr,phys,&buf); |
|
217 } |
|
218 else // L-Page |
|
219 { |
|
220 |
|
221 // large page |
|
222 TUint phys=aPte & 0xffff0000; |
|
223 TUint tex=(aPte>>12)&0x7; |
|
224 ProcessCBTEX(buf,aPte&0xc,tex); |
|
225 ProcessAP(buf,ap); |
|
226 ProcessXNnGS(buf, (aPte>>10)&3, (aPte >> 15) &1); |
|
227 RDebug::Print(_L("\t%08x Lpage: phys=%08x, %S"),anAddr,phys,&buf); |
|
228 } |
|
229 |
|
230 }// Else "Fault" - Not Present |
|
231 |
|
232 } |
|
233 |
|
234 |
|
235 LOCAL_C void ProcessPde(TUint aPde, TUint anAddr) |
|
236 { |
|
237 TUint type=aPde&3; |
|
238 TBuf<24> buf; |
|
239 switch(type) |
|
240 { |
|
241 case 0: |
|
242 // not present |
|
243 if (aPde) |
|
244 RDebug::Print(_L(" Not Present\n")); |
|
245 break; |
|
246 case 1: |
|
247 { |
|
248 // page table |
|
249 TUint ptphys=aPde & 0xfffffc00; |
|
250 TUint domain=(aPde>>5)&15; |
|
251 TUint P=(aPde&0x200); |
|
252 TUint ptpgphys=ptphys & 0xfffff000; |
|
253 TUint ptlin=0; |
|
254 |
|
255 TInt i; |
|
256 for (i=0; i<256; i++) |
|
257 { |
|
258 if ((Read(PageTables+i*4)&0xfffff000)==ptpgphys) |
|
259 { |
|
260 if (ptlin==0) |
|
261 ptlin=PageTables+(i<<12)+(ptphys & 0xc00); |
|
262 else |
|
263 RDebug::Print(_L("WARNING Multiple page tables found! alt = %08x\n"), PageTables+(i<<12)+(ptphys & 0xc00)); |
|
264 } |
|
265 } |
|
266 if (ptlin) |
|
267 { |
|
268 RDebug::Print(_L("%08x page table: phys=%08x, domain %2d, %s, page table lin=%08x"),anAddr,ptphys,domain,P?L"ECC":L"No ECC",ptlin); |
|
269 for (i=0; i<256; i++) |
|
270 { |
|
271 TUint addr=anAddr+(i<<12); |
|
272 TUint pte=Read(ptlin+i*4); |
|
273 |
|
274 if (ControlReg & KXPbitM) |
|
275 ProcessPteSD(pte,addr); |
|
276 else |
|
277 ProcessPteSE(pte,addr); |
|
278 } |
|
279 } |
|
280 else |
|
281 RDebug::Print(_L("%08x page table: phys=%08x, domain %2d, %s, page table not found"),anAddr,ptphys,domain,P?L"ECC":L"No ECC"); |
|
282 |
|
283 break; |
|
284 } |
|
285 case 2: |
|
286 { |
|
287 // section |
|
288 TUint phys=aPde & 0xfff00000; |
|
289 TUint perm=(aPde>>10)&0x23; |
|
290 TUint P=(aPde&0x200); |
|
291 TUint domain=(aPde>>5)&15; |
|
292 ProcessCBTEX(buf,aPde&0xc,(aPde>>12)&0xf); // tex is bigger on xscale, but bit is masked off later. |
|
293 ProcessAP(buf,perm); |
|
294 ProcessXNnGS(buf, (aPde>>16)&3, (aPde>>4)&1); |
|
295 |
|
296 if ((ControlReg & KXPbitM) && (aPde & 0x40000)) |
|
297 { |
|
298 domain = (domain << 4) | ((aPde >> 20) &15); |
|
299 RDebug::Print(_L("%08x Supersectn: phys=%08x, base %4d, %s, %S"),anAddr,phys,domain,P?L"ECC":L"No ECC",&buf); |
|
300 } |
|
301 else |
|
302 { |
|
303 RDebug::Print(_L("%08x section : phys=%08x, domain %2d, %s, %S"),anAddr,phys,domain,P?L"ECC":L"No ECC",&buf); |
|
304 } |
|
305 break; |
|
306 } |
|
307 default: |
|
308 // invalid |
|
309 RDebug::Print(_L("PDE for %08x invalid, value %08x"),anAddr,aPde); |
|
310 break; |
|
311 } |
|
312 } |
|
313 |
|
314 const TInt KNotInInvalid = -2; |
|
315 TInt StartInvalid=KNotInInvalid; |
|
316 TInt StartInvalidBase=0; |
|
317 TInt EndInvalidBase=0; |
|
318 |
|
319 void DisplayNotPresent(TInt aCurrentPd) |
|
320 { |
|
321 aCurrentPd--; |
|
322 if (StartInvalid!=KNotInInvalid) // Display any Invalid ranges. |
|
323 { |
|
324 if (StartInvalid == aCurrentPd) |
|
325 RDebug::Print(_L("\nPage Directory 0x%x: Base=0x%x - Not Present.\n"), StartInvalid, StartInvalidBase); |
|
326 else |
|
327 RDebug::Print(_L("\nPage Directorys 0x%x-0x%x: Bases=0x%x-0x%x - Not Present.\n"), StartInvalid, aCurrentPd, StartInvalidBase, EndInvalidBase); |
|
328 |
|
329 StartInvalid=KNotInInvalid; |
|
330 } |
|
331 } |
|
332 |
|
333 void ProcessPd(TUint aPd) |
|
334 { |
|
335 TUint i; |
|
336 TUint pdSize; |
|
337 TUint pdBase; |
|
338 TUint offset; |
|
339 |
|
340 TInt err = Shadow.GetPdInfo(aPd, pdSize, pdBase, offset); |
|
341 |
|
342 if (err==KErrNone) |
|
343 { |
|
344 DisplayNotPresent(aPd); |
|
345 |
|
346 if (aPd==KGlobalPageDirectory) |
|
347 RDebug::Print(_L("Global Page Directory: Base=0x%x, Entries=0x%x, Start index=0x%x\n"), pdBase, pdSize, offset); |
|
348 else |
|
349 RDebug::Print(_L("\nPage Directory 0x%x: Base=0x%x, Entries=0x%x %x\n"), aPd, pdBase, pdSize, offset); |
|
350 |
|
351 if (Cpu == ECpuArm) |
|
352 { |
|
353 |
|
354 for (i=0; i<pdSize; i++) |
|
355 { |
|
356 TUint addr=(i+offset)<<20; |
|
357 TUint pde=Read(pdBase+i*4); |
|
358 ProcessPde(pde,addr); |
|
359 } |
|
360 } |
|
361 else |
|
362 RDebug::Print(_L("Cannot display pde for this CPU")); |
|
363 } |
|
364 else |
|
365 { // Dont list all invalid PDs - there are too many. |
|
366 if (StartInvalid==KNotInInvalid) |
|
367 { |
|
368 StartInvalidBase = pdBase; |
|
369 StartInvalid = aPd; |
|
370 } |
|
371 else |
|
372 { |
|
373 EndInvalidBase=pdBase; |
|
374 } |
|
375 |
|
376 } |
|
377 } |
|
378 |
|
379 GLDEF_C TInt E32Main() |
|
380 { |
|
381 TUint mmuId=0; |
|
382 TUint cacheType=0; |
|
383 |
|
384 |
|
385 |
|
386 TInt r=User::LoadLogicalDevice(_L("D_SHADOW")); |
|
387 if ((r!=KErrNone) && (r!=KErrAlreadyExists)) |
|
388 User::Panic(_L("T_PAGES0"),r); |
|
389 r=Shadow.Open(); |
|
390 if (r!=KErrNone) |
|
391 User::Panic(_L("T_PAGES1"),r); |
|
392 |
|
393 Shadow.GetMemoryArchitecture(Cpu, ControlReg); |
|
394 switch (Cpu) |
|
395 { |
|
396 case ECpuArm: |
|
397 { |
|
398 mmuId=Shadow.MmuId(); |
|
399 TUint implementor= (mmuId>>24); |
|
400 |
|
401 if (implementor==0x44) |
|
402 CpuSpecial = 1; |
|
403 |
|
404 switch ((mmuId>>12)&15) |
|
405 { |
|
406 case 0: // Pre-ARM7 |
|
407 if ((mmuId>>4)==0x4156030) |
|
408 CpuArc = 2; |
|
409 else if ((mmuId>>8)==0x415606) |
|
410 CpuArc = 3; |
|
411 break; |
|
412 case 7: // Mid-ARM7 |
|
413 CpuArc = 3; |
|
414 default:// Post-ARM7 |
|
415 TUint arc = (mmuId >>16) &15; |
|
416 if (arc<3) |
|
417 { |
|
418 CpuArc = 4; |
|
419 if ((implementor==0x69) && (arc==4)) |
|
420 CpuSpecial=1; |
|
421 } |
|
422 else if (arc<7) |
|
423 { |
|
424 CpuArc = 5; |
|
425 if ((implementor==0x69) && (arc==5)) |
|
426 CpuSpecial=2; |
|
427 } |
|
428 else if (arc==7) |
|
429 CpuArc = 6; |
|
430 else |
|
431 CpuArc = arc; |
|
432 } |
|
433 |
|
434 switch (CpuSpecial) |
|
435 { |
|
436 case 1:RDebug::Print(_L("\nCPU = ARMv%d (StrongArm), ControlRegister = 0x%x "),CpuArc, ControlReg); |
|
437 break; |
|
438 case 2:RDebug::Print(_L("\nCPU = ARMv%d (XScale), ControlRegister = 0x%x "),CpuArc, ControlReg); |
|
439 break; |
|
440 default: |
|
441 if (CpuArc<7) |
|
442 RDebug::Print(_L("\nCPU = ARMv%d, ControlRegister = 0x%x "),CpuArc, ControlReg); |
|
443 else |
|
444 RDebug::Print(_L("\nCPU = ARM (#%d), ControlRegister = 0x%x "),CpuArc, ControlReg); |
|
445 } |
|
446 |
|
447 RDebug::Print(_L("(MMU=%d, Alignment Checking=%d, Write Buffer=%d, System Protection=%d, "), |
|
448 ControlReg & 1,(ControlReg>>1)&1,(ControlReg>>3)&1, (ControlReg>>8)&1); |
|
449 |
|
450 if (ControlReg & KXPbitM) |
|
451 RDebug::Print(_L("ROM Protection=%d, Subpages Disabled, Exception Endian=%d)\n"), (ControlReg>>9)&1, (ControlReg>>25)&1); |
|
452 else |
|
453 RDebug::Print(_L("ROM Protection=%d, Subpages Enabled, Exception Endian=%d)\n"), (ControlReg>>9)&1, (ControlReg>>25)&1); |
|
454 |
|
455 RDebug::Print(_L("MMU ID=%08X"),mmuId); |
|
456 |
|
457 |
|
458 |
|
459 cacheType=Shadow.CacheType(); |
|
460 RDebug::Print(_L("CACHE TYPE=%08X"),cacheType); |
|
461 break; |
|
462 |
|
463 } |
|
464 |
|
465 case ECpuX86: |
|
466 RDebug::Print(_L("\nCPU = x86\n")); |
|
467 break; |
|
468 case ECpuUnknown: |
|
469 default: |
|
470 RDebug::Print(_L("\nCPU = Unknown, Flags = 0x%x\n"), ControlReg); |
|
471 |
|
472 } |
|
473 |
|
474 TUint numPages = 0; |
|
475 TMemModel memModel = Shadow.GetMemModelInfo(PageTables, numPages); |
|
476 |
|
477 switch (memModel) |
|
478 { |
|
479 case EMemModelMoving: RDebug::Print(_L("Moving Memory Model.\n")); |
|
480 break; |
|
481 case EMemModelMultiple : RDebug::Print(_L("Multiple Memory Model.\nMax number of PageDirectorys=0x%x.\n"), numPages); |
|
482 break; |
|
483 case EMemModelFlexible : RDebug::Print(_L("Flexible Memory Model.\nMax number of PageDirectorys=0x%x.\n"), numPages); |
|
484 break; |
|
485 default: |
|
486 RDebug::Print(_L("Unknown Memory Model.\n")); |
|
487 return KErrNone; |
|
488 } |
|
489 |
|
490 ProcessPd(KGlobalPageDirectory); |
|
491 |
|
492 if (memModel==2) |
|
493 { |
|
494 TUint i; |
|
495 for (i=0; i<numPages; i++) |
|
496 { |
|
497 ProcessPd(i); |
|
498 } |
|
499 DisplayNotPresent(numPages); |
|
500 } |
|
501 Shadow.Close(); |
|
502 User::FreeLogicalDevice(_L("Shadow")); |
|
503 return KErrNone; |
|
504 } |