This source file includes following definitions.
- two_on_nth
- two_on_nth_granule
- mmfr3_cache
- mmfr3_bp
- mmfr3_cms
- mmfr3_ss
- ctype_str
- ccsidr_linesize
- ccsidr_plusone
- cache_tcm_size_str
- cache_tcm_addr_str
- mpu_region_size_str
- bitfield8
- mpu_rattr
- dbg_version
- cpuinfo_get_info_pmsa
- tlb_unified
- tlb_entries
- ttbraddr0
- ttbraddr1
- ttbcr_n
- cpuinfo_get_info_vmsa
- cpu_is_vmsa
- get_mmuregs_vmsa
- interpret_l1_table_entry
- interpret_l2_table_entry
- memmapping_vmsa
1
2
3 static char linebuf[256];
4
5 static const char *two_nth_str[] = {
6 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1K", "2K", "4K", "8K", "16K", "32K"
7 };
8
9 static const char *two_on_nth(unsigned val) {
10 if (val < 16) {
11 return two_nth_str[val];
12 }
13 return "invalid";
14 }
15
16 static const char *two_on_nth_granule(unsigned val) {
17 if (val == 0) {
18 return "no info";
19 }
20 else if (val > 9) {
21 return "reserved";
22 }
23 else {
24 return two_nth_str[val];
25 }
26 return "invalid";
27 }
28
29 const struct cpuinfo_bitfield_desc_s cpuinf_feat0[] = {
30 {4,"ARM inst set",0},
31 {4,"Thumb inst set",0},
32 {4,"Jazelle inst set",0},
33 {4,"ThumbEE inst set",0},
34 {16,"-",0},
35 {0}
36 };
37
38 const struct cpuinfo_bitfield_desc_s cpuinf_feat1[] = {
39 {4,"Programmers' model",0},
40 {4,"Security extensions",0},
41 {4,"Microcontr. prog model",0},
42 {4,"Virt. extensions",0},
43 {4,"Generic timer ext.",0},
44 {12,"-",0},
45 {0}
46 };
47
48 const struct cpuinfo_bitfield_desc_s cpuinf_dbgfeat[] = {
49 {4,"Coproc. dbg model",0},
50 {4,"Coproc. secure dbg model",0},
51 {4,"Memory-mapped dbg model",0},
52 {4,"Coproc. trace model",0},
53 {4,"Memory-mapped trace model",0},
54 {4,"Debug model M",0},
55 {4,"Perf. monitors",0},
56 {4,"-",0},
57 {0}
58 };
59
60 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr0[] = {
61 {4,"VMSA support",0},
62 {4,"PMSA support",0},
63 {4,"Cache coherence",0},
64 {4,"Outer shareable",0},
65 {4,"TCM support",0},
66 {4,"Auxiliary registers",0},
67 {4,"FCSE support",0},
68 {4,"-",0},
69 {0}
70 };
71
72 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr1[] = {
73 {4,"L1 Harvard cache VA",0},
74 {4,"L1 unified cache VA",0},
75 {4,"L1 Harvard cache s/w",0},
76 {4,"L1 unified cache s/w",0},
77 {4,"L1 Harvard cache",0},
78 {4,"L1 unified cache",0},
79 {4,"L1 cache test & clean",0},
80 {4,"Branch predictor",0},
81 {0}
82 };
83
84 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr2[] = {
85 {4,"L1 Harvard fg prefetch",0},
86 {4,"L1 Harvard bg prefetch",0},
87 {4,"L1 Harvard range",0},
88 {4,"Harvard TLB",0},
89 {4,"Unified TLB",0},
90 {4,"Mem barrier",0},
91 {4,"WFI stall",0},
92 {4,"HW access flag",0},
93 {0}
94 };
95
96 static const char *mmfr3_cache(unsigned val) {
97 switch (val) {
98 case 0: return "Not supported";
99 case 1: return "Supported";
100 }
101 return "(invalid)";
102 }
103
104 static const char *mmfr3_bp(unsigned val) {
105 switch (val) {
106 case 0: return "Not supported";
107 case 1: return "Invalidate all";
108 case 2: return "Invalidate all, invalidate by MVA";
109 }
110 return "(invalid)";
111 }
112
113 static const char *mmfr3_cms(unsigned val) {
114 switch (val) {
115 case 0: return "4 GByte";
116 case 1: return "64 GByte";
117 case 2: return "1 TByte";
118 }
119 return "(invalid)";
120 }
121
122 static const char *mmfr3_ss(unsigned val) {
123 switch (val) {
124 case 0: return "Supported";
125 case 15: return "Not supported";
126 }
127 return "(invalid)";
128 }
129
130 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr3[] = {
131 {4,"Cache maintain MVA", mmfr3_cache},
132 {4,"Cache maintain set/way", mmfr3_cache},
133 {4,"Branch predictor maintenance", mmfr3_bp},
134 {4,"Maintenance broadcast",0},
135 {4,"-",0},
136 {4,"Transl. table coherent walk",0},
137 {4,"Cached memory size", mmfr3_cms},
138 {4,"Supersection support", mmfr3_ss},
139 {0}
140 };
141
142 const struct cpuinfo_bitfield_desc_s cpuinf_isar0[] = {
143 {4,"Swap instrs",0},
144 {4,"Bitcount instrs",0},
145 {4,"Bitfield instrs",0},
146 {4,"CmpBranch instrs",0},
147 {4,"Coproc instrs",0},
148 {4,"Debug instrs",0},
149 {4,"Divide instrs",0},
150 {4,"-",0},
151 {0}
152 };
153
154 const struct cpuinfo_bitfield_desc_s cpuinf_isar1[] = {
155 {4,"Endian instrs",0},
156 {4,"Exception instrs",0},
157 {4,"Exception AR instrs",0},
158 {4,"Extend instrs",0},
159 {4,"IfThen instrs",0},
160 {4,"Immediate instrs",0},
161 {4,"Interwork instrs",0},
162 {4,"Jazelle instrs",0},
163 {0}
164 };
165
166 const struct cpuinfo_bitfield_desc_s cpuinf_isar2[] = {
167 {4,"LoadStore instrs",0},
168 {4,"Memhint instrs",0},
169 {4,"MultiAccess Interruptible instructions",0},
170 {4,"Mult instrs",0},
171 {4,"MultS instrs",0},
172 {4,"MultU instrs",0},
173 {4,"PSR AR instrs",0},
174 {4,"Reversal instrs",0},
175 {0}
176 };
177
178 const struct cpuinfo_bitfield_desc_s cpuinf_isar3[] = {
179 {4,"Saturate instrs",0},
180 {4,"SIMD instrs",0},
181 {4,"SVC instrs",0},
182 {4,"SynchPrim instrs",0},
183 {4,"TabBranch instrs",0},
184 {4,"ThumbCopy instrs",0},
185 {4,"TrueNOP instrs",0},
186 {4,"T2 Exec Env instrs",0},
187 {0}
188 };
189
190 const struct cpuinfo_bitfield_desc_s cpuinf_isar4[] = {
191 {4,"Unprivileged instrs",0},
192 {4,"WithShifts instrs",0},
193 {4,"Writeback instrs",0},
194 {4,"SMC instrs",0},
195 {4,"Barrier instrs",0},
196 {4,"SynchPrim_instrs_frac",0},
197 {4,"PSR_M instrs",0},
198 {4,"-",0},
199 {0}
200 };
201
202 const struct cpuinfo_bitfield_desc_s cpuinf_isar5[] = {
203 {32,"-",0},
204 {0}
205 };
206
207 const struct cpuinfo_bitfield_desc_s cpuinf_ctr[] = {
208 {4,"Icache min words/line", two_on_nth},
209 {10,"(zero)",0},
210 {2,"L1 Icache policy",0},
211 {4,"Dcache min words/line", two_on_nth},
212 {4,"Exclusives Reservation Granule", two_on_nth_granule},
213 {4,"Cache Writeback Granule", two_on_nth_granule},
214 {1,"(zero)",0},
215 {3,"(register format)",0},
216 {0}
217 };
218
219 static const char *ctype_str(unsigned val) {
220 switch (val) {
221 case 0: return "no cache";
222 case 1: return "Icache only";
223 case 2: return "Dcache only";
224 case 3: return "Separate Icache, Dcache";
225 case 4: return "Unified cache";
226 }
227 return "-";
228 }
229
230 const struct cpuinfo_bitfield_desc_s cpuinf_clidr[] = {
231 {3,"Cache type, level1", ctype_str},
232 {3,"Cache type, level2", ctype_str},
233 {3,"Cache type, level3", ctype_str},
234 {3,"Cache type, level4", ctype_str},
235 {3,"Cache type, level5", ctype_str},
236 {3,"Cache type, level6", ctype_str},
237 {3,"Cache type, level7", ctype_str},
238 {3,"Cache type, level8", ctype_str},
239 {3,"Level of coherency",0},
240 {3,"Level of unification",0},
241 {2,"(zero)",0},
242 {0}
243 };
244
245 const struct cpuinfo_bitfield_desc_s cpuinf_csselr[] = {
246 {1,"Instruction, not data",0},
247 {3,"Level",0},
248 {28,"(unknown)",0},
249 {0}
250 };
251
252 static const char *ccsidr_linesize(unsigned val) {
253 return two_nth_str[val+2];
254 }
255
256 static const char *ccsidr_plusone(unsigned val) {
257 sprintf(linebuf,"%i",val+1);
258 return linebuf;
259 }
260
261 const struct cpuinfo_bitfield_desc_s cpuinf_ccsidr[] = {
262 {3,"Line size in words", ccsidr_linesize},
263 {10,"Associativity", ccsidr_plusone},
264 {15,"Number of sets", ccsidr_plusone},
265 {1,"Write allocation",0},
266 {1,"Read allocation",0},
267 {1,"Write back",0},
268 {1,"Write through",0},
269 {0}
270 };
271
272 static const char *cache_tcm_size_str(unsigned val) {
273 if (val == 0)
274 return "0";
275 if (val < 3 || val > 14)
276 return "invalid";
277 return reg_sizes[val-3];
278 }
279
280 static const char *cache_tcm_addr_str(unsigned val) {
281 sprintf(linebuf,"0x%08x",val<<12);
282 return linebuf;
283 }
284
285 const struct cpuinfo_bitfield_desc_s cpuinf_tcmreg[] = {
286 {1,"Enabled",0},
287 {1,"-",0},
288 {5,"Size", cache_tcm_size_str},
289 {5,"-",0},
290 {20,"Base address", cache_tcm_addr_str},
291 {0}
292 };
293
294 const struct cpuinfo_bitfield_desc_s cpuinf_mputype[] = {
295 {1,"S",0},
296 {7,"-",0},
297 {8,"Num of MPU regions",0},
298 {0}
299 };
300
301 const struct cpuinfo_bitfield_desc_s cpuinf_mpubase[] = {
302 {32,"Base address",0},
303 {0}
304 };
305
306 const struct cpuinfo_bitfield_desc_s cpuinf_sctlr[] = {
307 {1,"MPU Enable",0},
308 {1,"Strict Align",0},
309 {1,"L1 DCache Enable",0},
310 {4,"- (SBO)",0},
311 {4,"- (SBZ)",0},
312 {1,"Branch Pred Enable",0},
313 {1,"L1 ICache Enable",0},
314 {1,"High Vector",0},
315 {1,"Round Robin",0},
316 {1,"- (SBZ)",0},
317 {1,"- (SBO)",0},
318 {1,"MPU background reg",0},
319 {1,"- (SBO)",0},
320 {1,"Div0 exception",0},
321 {1,"- (SBZ)",0},
322 {1,"FIQ Enable",0},
323 {2,"- (SBO)",0},
324 {1,"VIC",0},
325 {1,"CPSR E bit",0},
326 {1,"- (SBZ)",0},
327 {1,"NMFI",0},
328 {1,"TRE",0},
329 {1,"AFE",0},
330 {1,"Thumb exceptions",0},
331 {1,"Endian",0},
332 {0}
333 };
334
335 static const char *mpu_region_size_str(unsigned val) {
336 if (val < 4 || val > 31)
337 return "invalid";
338 if (val < 11)
339 return two_nth_str[val+1];
340 return reg_sizes[val-11];
341 }
342
343 static const char *bitfield8(unsigned val) {
344 linebuf[8] = 0;
345 int n;
346 for (n=0; n<8; n++) {
347 linebuf[7-n] = (val & (1<<n))?'1':'0';
348 }
349 return linebuf;
350 }
351
352 const struct cpuinfo_bitfield_desc_s cpuinf_mpusizeen[] = {
353 {1,"Enabled",0},
354 {5,"Size", mpu_region_size_str},
355 {2,"-",0},
356 {8,"Sub-regions disabled", bitfield8},
357 {0}
358 };
359
360 static const char *mpu_rattr(unsigned val) {
361 char *s="";
362 char *s2="";
363 char *t;
364 t = (val&4)?"Shared":"Non-shared";
365 if (val&0x20) {
366 switch (val&3) {
367 case 0: s = "Inner Non-cacheable"; break;
368 case 1: s = "Inner Write-back, write-allocate"; break;
369 case 2: s = "Inner Write-through, no write-allocate"; break;
370 case 3: s = "Inner Write-back, no write-allocate"; break;
371 }
372 switch ((val&0x18)>>3) {
373 case 0: s2 = "Outer Non-cacheable"; break;
374 case 1: s2 = "Outer Write-back, write-allocate"; break;
375 case 2: s2 = "Outer Write-through, no write-allocate"; break;
376 case 3: s2 = "Outer Write-back, no write-allocate"; break;
377 }
378 sprintf(linebuf,"%s; %s; %s",s, s2, t);
379 }
380 else {
381 switch (val&0x1B) {
382 case 0: s = "Strongly ordered, shareable"; t=""; break;
383 case 1: s = "Shareable device"; t="Shareable"; break;
384 case 2: s = "Outer and Inner write-through, no write-allocate"; break;
385 case 3: s = "Outer and Inner write-back, no write-allocate"; break;
386 case 8: s = "Outer and Inner Non-cacheable"; break;
387 case 11: s = "Outer and Inner write-back, write-allocate"; break;
388 case 16: s = "Non-shareable Device"; t=""; break;
389 default: s = "(reserved)"; t="";
390 }
391 sprintf(linebuf,"%s; %s",s, t);
392 }
393 return linebuf;
394 }
395
396 const struct cpuinfo_bitfield_desc_s cpuinf_accesscontrol[] = {
397 {6,"Region attributes", mpu_rattr},
398 {2,"-",0},
399 {3,"Access permission", regperm_str},
400 {1,"-",0},
401 {1,"Execute never",0},
402 {0}
403 };
404
405 const struct cpuinfo_bitfield_desc_s cpuinf_generic[] = {
406 {32,"(raw value)",0},
407 {0}
408 };
409
410 static const char * dbg_version(unsigned val) {
411 switch(val) {
412 case 0b0001: return "v6";
413 case 0b0010: return "v6.1";
414 case 0b0011: return "v7 full";
415 case 0b0100: return "v7 basic";
416 case 0b0101: return "v7.1";
417 case 0b0110: return "v8";
418 case 0b0111: return "v8.1";
419 case 0b1000: return "v8.2";
420 }
421 return "???";
422 }
423
424 static const struct cpuinfo_bitfield_desc_s cpuinf_dbgdidr[] = {
425 {4,"Revision",0},
426 {4,"Variant",0},
427 {8,"- (RAZ)",0},
428 {4,"Version",dbg_version},
429 {4,"Context",ccsidr_plusone},
430 {4,"BRP",ccsidr_plusone},
431 {4,"WRP",ccsidr_plusone},
432 {0}
433 };
434
435 static const struct cpuinfo_bitfield_desc_s cpuinf_dbgd_address[] = {
436 {2,"Valid",0},
437 {10,"- (UNK)",0},
438 {20,"Address",cache_tcm_addr_str},
439 {0}
440 };
441
442 static const struct cpuinfo_bitfield_desc_s cpuinf_dbgdscr[] = {
443 {1,"HALTED",0},
444 {1,"RESTARTED",0},
445 {4,"MOE",0},
446 {1,"SDABORT_l",0},
447 {1,"ADABORT_l",0},
448 {1,"UND_l",0},
449 {1,"FS",0},
450 {1,"DBGack",0},
451 {1,"INTdis",0},
452 {1,"UDCCdis",0},
453 {1,"ITRen",0},
454 {1,"HDBGen",0},
455 {1,"MDBGen",0},
456 {1,"SPIDdis",0},
457 {1,"SPNIDdis",0},
458 {1,"NS",0},
459 {1,"ADAdiscard",0},
460 {2,"ExtDCCmode",0},
461 {2,"- (SBZ)",0},
462 {1,"InstrCompl_l",0},
463 {1,"PipeAdv",0},
464 {1,"TXfull_l",0},
465 {1,"RXfull_l",0},
466 {1,"- (SBZ)",0},
467 {1,"TXfull",0},
468 {1,"RXfull",0},
469 {1,"- (SBZ)",0},
470 {0}
471 };
472
473 const struct cpuinfo_word_desc_s cpuinfo_desc_pmsa[]={
474 {"ID", cpuinf_id },
475 {"Cache type", cpuinf_ctr },
476 {"TCM type", cpuinf_generic },
477 {"MPU type", cpuinf_mputype },
478 {"Multiprocessor ID", cpuinf_generic },
479 {"Processor feature 0", cpuinf_feat0 },
480 {"Processor feature 1", cpuinf_feat1 },
481 {"Debug feature", cpuinf_dbgfeat },
482 {"Aux feature", cpuinf_generic },
483 {"Mem model feature 0", cpuinf_mmfr0 },
484 {"Mem model feature 1", cpuinf_mmfr1 },
485 {"Mem model feature 2", cpuinf_mmfr2 },
486 {"Mem model feature 3", cpuinf_mmfr3 },
487 {"ISA feature 0", cpuinf_isar0 },
488 {"ISA feature 1", cpuinf_isar1 },
489 {"ISA feature 2", cpuinf_isar2 },
490 {"ISA feature 3", cpuinf_isar3 },
491 {"ISA feature 4", cpuinf_isar4 },
492 {"ISA feature 5", cpuinf_isar5 },
493 {"Cache level ID", cpuinf_clidr },
494 {"Cache size ID reg (data, level0)", cpuinf_ccsidr },
495 {"Cache size ID reg (inst, level0)", cpuinf_ccsidr },
496 {"SCTLR", cpuinf_sctlr },
497 {"ACTLR", cpuinf_generic },
498 {"ACTLR2", cpuinf_generic },
499 {"CPACR", cpuinf_generic },
500 {"Build options 1", cpuinf_generic },
501 {"Build options 2", cpuinf_generic },
502 {"ATCM region reg", cpuinf_tcmreg },
503 {"BTCM region reg", cpuinf_tcmreg },
504 {"MPU region 0 base", cpuinf_mpubase },
505 {"MPU region 0 size & enable", cpuinf_mpusizeen },
506 {"MPU region 0 access control", cpuinf_accesscontrol },
507 {"MPU region 1 base", cpuinf_mpubase },
508 {"MPU region 1 size & enable", cpuinf_mpusizeen },
509 {"MPU region 1 access control", cpuinf_accesscontrol },
510 {"MPU region 2 base", cpuinf_mpubase },
511 {"MPU region 2 size & enable", cpuinf_mpusizeen },
512 {"MPU region 2 access control", cpuinf_accesscontrol },
513 {"MPU region 3 base", cpuinf_mpubase },
514 {"MPU region 3 size & enable", cpuinf_mpusizeen },
515 {"MPU region 3 access control", cpuinf_accesscontrol },
516 {"MPU region 4 base", cpuinf_mpubase },
517 {"MPU region 4 size & enable", cpuinf_mpusizeen },
518 {"MPU region 4 access control", cpuinf_accesscontrol },
519 {"MPU region 5 base", cpuinf_mpubase },
520 {"MPU region 5 size & enable", cpuinf_mpusizeen },
521 {"MPU region 5 access control", cpuinf_accesscontrol },
522 {"MPU region 6 base", cpuinf_mpubase },
523 {"MPU region 6 size & enable", cpuinf_mpusizeen },
524 {"MPU region 6 access control", cpuinf_accesscontrol },
525 {"MPU region 7 base", cpuinf_mpubase },
526 {"MPU region 7 size & enable", cpuinf_mpusizeen },
527 {"MPU region 7 access control", cpuinf_accesscontrol },
528 {"DBGDIDR", cpuinf_dbgdidr },
529 {"DBGDRAR", cpuinf_dbgd_address },
530 {"DBGDSAR", cpuinf_dbgd_address },
531 {"DBGDSCR", cpuinf_dbgdscr },
532
533
534
535 {0}
536 };
537
538
539 void __attribute__((naked,noinline)) cpuinfo_get_info_pmsa(__attribute__ ((unused))unsigned *results) {
540 asm (
541 ".syntax unified\n"
542 ".code 16\n"
543 ".align 2\n"
544 "BX PC\n"
545 ".code 32\n"
546
547 "MRC p15, 0, R1,c0,c0\n"
548 "STR R1, [R0]\n"
549
550 "MRC p15, 0, R1,c0,c0,1\n"
551 "ADD R0, R0, #4\n"
552 "STR R1, [R0]\n"
553
554 "MRC p15, 0, R1,c0,c0,2\n"
555 "ADD R0, R0, #4\n"
556 "STR R1, [R0]\n"
557
558 "MRC p15, 0, R1,c0,c0,4\n"
559 "ADD R0, R0, #4\n"
560 "STR R1, [R0]\n"
561
562 "MRC p15, 0, R1,c0,c0,5\n"
563 "ADD R0, R0, #4\n"
564 "STR R1, [R0]\n"
565
566 "MRC p15, 0, R1,c0,c1,0\n"
567 "ADD R0, R0, #4\n"
568 "STR R1, [R0]\n"
569
570 "MRC p15, 0, R1,c0,c1,1\n"
571 "ADD R0, R0, #4\n"
572 "STR R1, [R0]\n"
573
574 "MRC p15, 0, R1,c0,c1,2\n"
575 "ADD R0, R0, #4\n"
576 "STR R1, [R0]\n"
577
578 "MRC p15, 0, R1,c0,c1,3\n"
579 "ADD R0, R0, #4\n"
580 "STR R1, [R0]\n"
581
582 "MRC p15, 0, R1,c0,c1,4\n"
583 "ADD R0, R0, #4\n"
584 "STR R1, [R0]\n"
585
586 "MRC p15, 0, R1,c0,c1,5\n"
587 "ADD R0, R0, #4\n"
588 "STR R1, [R0]\n"
589
590 "MRC p15, 0, R1,c0,c1,6\n"
591 "ADD R0, R0, #4\n"
592 "STR R1, [R0]\n"
593
594 "MRC p15, 0, R1,c0,c1,7\n"
595 "ADD R0, R0, #4\n"
596 "STR R1, [R0]\n"
597
598 "MRC p15, 0, R1,c0,c2,0\n"
599 "ADD R0, R0, #4\n"
600 "STR R1, [R0]\n"
601
602 "MRC p15, 0, R1,c0,c2,1\n"
603 "ADD R0, R0, #4\n"
604 "STR R1, [R0]\n"
605
606 "MRC p15, 0, R1,c0,c2,2\n"
607 "ADD R0, R0, #4\n"
608 "STR R1, [R0]\n"
609
610 "MRC p15, 0, R1,c0,c2,3\n"
611 "ADD R0, R0, #4\n"
612 "STR R1, [R0]\n"
613
614 "MRC p15, 0, R1,c0,c2,4\n"
615 "ADD R0, R0, #4\n"
616 "STR R1, [R0]\n"
617
618 "MRC p15, 0, R1,c0,c2,5\n"
619 "ADD R0, R0, #4\n"
620 "STR R1, [R0]\n"
621
622 "MRC p15, 1, R1,c0,c0,1\n"
623 "ADD R0, R0, #4\n"
624 "STR R1, [R0]\n"
625
626 "MOV R1, #0\n"
627 "MCR p15, 2, R1,c0,c0,0\n"
628
629 "MRC p15, 1, R1,c0,c0,0\n"
630 "ADD R0, R0, #4\n"
631 "STR R1, [R0]\n"
632
633 "MOV R1, #1\n"
634 "MCR p15, 2, R1,c0,c0,0\n"
635
636 "MRC p15, 1, R1,c0,c0,0\n"
637 "ADD R0, R0, #4\n"
638 "STR R1, [R0]\n"
639
640 "MRC p15, 0, R1,c1,c0,0\n"
641 "ADD R0, R0, #4\n"
642 "STR R1, [R0]\n"
643
644 "MRC p15, 0, R1,c1,c0,1\n"
645 "ADD R0, R0, #4\n"
646 "STR R1, [R0]\n"
647
648
649 "MRC p15, 0, R1,c15,c0,0\n"
650 "ADD R0, R0, #4\n"
651 "STR R1, [R0]\n"
652
653
654 "MRC p15, 0, R1,c1,c0,2\n"
655 "ADD R0, R0, #4\n"
656 "STR R1, [R0]\n"
657
658 "MRC p15, 0, R1,c15,c2,0\n"
659 "ADD R0, R0, #4\n"
660 "STR R1, [R0]\n"
661
662 "MRC p15, 0, R1,c15,c2,1\n"
663 "ADD R0, R0, #4\n"
664 "STR R1, [R0]\n"
665
666 "MRC p15, 0, R1,c9,c1,1\n"
667 "ADD R0, R0, #4\n"
668 "STR R1, [R0]\n"
669
670 "MRC p15, 0, R1,c9,c1,0\n"
671 "ADD R0, R0, #4\n"
672 "STR R1, [R0]\n"
673
674 "MOV R1, #0\n"
675 "MCR p15, 0, R1,c6,c2,0\n"
676
677 "MRC p15, 0, R1,c6,c1,0\n"
678 "ADD R0, R0, #4\n"
679 "STR R1, [R0]\n"
680 "MRC p15, 0, R1,c6,c1,2\n"
681 "ADD R0, R0, #4\n"
682 "STR R1, [R0]\n"
683 "MRC p15, 0, R1,c6,c1,4\n"
684 "ADD R0, R0, #4\n"
685 "STR R1, [R0]\n"
686
687 "MOV R1, #1\n"
688 "MCR p15, 0, R1,c6,c2,0\n"
689
690 "MRC p15, 0, R1,c6,c1,0\n"
691 "ADD R0, R0, #4\n"
692 "STR R1, [R0]\n"
693 "MRC p15, 0, R1,c6,c1,2\n"
694 "ADD R0, R0, #4\n"
695 "STR R1, [R0]\n"
696 "MRC p15, 0, R1,c6,c1,4\n"
697 "ADD R0, R0, #4\n"
698 "STR R1, [R0]\n"
699
700 "MOV R1, #2\n"
701 "MCR p15, 0, R1,c6,c2,0\n"
702
703 "MRC p15, 0, R1,c6,c1,0\n"
704 "ADD R0, R0, #4\n"
705 "STR R1, [R0]\n"
706 "MRC p15, 0, R1,c6,c1,2\n"
707 "ADD R0, R0, #4\n"
708 "STR R1, [R0]\n"
709 "MRC p15, 0, R1,c6,c1,4\n"
710 "ADD R0, R0, #4\n"
711 "STR R1, [R0]\n"
712
713 "MOV R1, #3\n"
714 "MCR p15, 0, R1,c6,c2,0\n"
715
716 "MRC p15, 0, R1,c6,c1,0\n"
717 "ADD R0, R0, #4\n"
718 "STR R1, [R0]\n"
719 "MRC p15, 0, R1,c6,c1,2\n"
720 "ADD R0, R0, #4\n"
721 "STR R1, [R0]\n"
722 "MRC p15, 0, R1,c6,c1,4\n"
723 "ADD R0, R0, #4\n"
724 "STR R1, [R0]\n"
725
726 "MOV R1, #4\n"
727 "MCR p15, 0, R1,c6,c2,0\n"
728
729 "MRC p15, 0, R1,c6,c1,0\n"
730 "ADD R0, R0, #4\n"
731 "STR R1, [R0]\n"
732 "MRC p15, 0, R1,c6,c1,2\n"
733 "ADD R0, R0, #4\n"
734 "STR R1, [R0]\n"
735 "MRC p15, 0, R1,c6,c1,4\n"
736 "ADD R0, R0, #4\n"
737 "STR R1, [R0]\n"
738
739 "MOV R1, #5\n"
740 "MCR p15, 0, R1,c6,c2,0\n"
741
742 "MRC p15, 0, R1,c6,c1,0\n"
743 "ADD R0, R0, #4\n"
744 "STR R1, [R0]\n"
745 "MRC p15, 0, R1,c6,c1,2\n"
746 "ADD R0, R0, #4\n"
747 "STR R1, [R0]\n"
748 "MRC p15, 0, R1,c6,c1,4\n"
749 "ADD R0, R0, #4\n"
750 "STR R1, [R0]\n"
751
752 "MOV R1, #6\n"
753 "MCR p15, 0, R1,c6,c2,0\n"
754
755 "MRC p15, 0, R1,c6,c1,0\n"
756 "ADD R0, R0, #4\n"
757 "STR R1, [R0]\n"
758 "MRC p15, 0, R1,c6,c1,2\n"
759 "ADD R0, R0, #4\n"
760 "STR R1, [R0]\n"
761 "MRC p15, 0, R1,c6,c1,4\n"
762 "ADD R0, R0, #4\n"
763 "STR R1, [R0]\n"
764
765 "MOV R1, #7\n"
766 "MCR p15, 0, R1,c6,c2,0\n"
767
768 "MRC p15, 0, R1,c6,c1,0\n"
769 "ADD R0, R0, #4\n"
770 "STR R1, [R0]\n"
771 "MRC p15, 0, R1,c6,c1,2\n"
772 "ADD R0, R0, #4\n"
773 "STR R1, [R0]\n"
774 "MRC p15, 0, R1,c6,c1,4\n"
775 "ADD R0, R0, #4\n"
776 "STR R1, [R0]\n"
777
778 "MRC p14, 0, R1,c0,c0,0\n"
779 "ADD R0, R0, #4\n"
780 "STR R1, [R0]\n"
781
782 "MRC p14, 0, R1,c1,c0,0\n"
783 "ADD R0, R0, #4\n"
784 "STR R1, [R0]\n"
785
786 "MRC p14, 0, R1,c2,c0,0\n"
787 "ADD R0, R0, #4\n"
788 "STR R1, [R0]\n"
789
790 "MRC p14, 0, R1,c0,c1,0\n"
791 "ADD R0, R0, #4\n"
792 "STR R1, [R0]\n"
793
794
795
796
797
798
799
800
801
802
803
804
805
806 "BX LR\n"
807
808 :::"r0","r1"
809 );
810 }
811
812 static const char * tlb_unified(unsigned val) {
813 switch(val) {
814 case 0: return "Unified TLB";
815 case 1: return "Separate data and instruction TLB";
816 }
817 return "???";
818 }
819
820 static const char * tlb_entries(unsigned val) {
821 switch(val) {
822 case 0: return "64";
823 case 1: return "128";
824 case 2: return "256";
825 case 3: return "512";
826 }
827 return "???";
828 }
829
830 const struct cpuinfo_bitfield_desc_s cpuinf_tlbtype[] = {
831 {1,"TLB", tlb_unified},
832 {2,"TLB entries", tlb_entries},
833 {5,"-",0},
834 {8,"Lockable unified or data entries",0},
835 {8,"Lockable instruction entries",0},
836 {8,"(zero)",0},
837 {0}
838 };
839
840 const struct cpuinfo_bitfield_desc_s cpuinf_sctlr_vmsa[] = {
841 {1,"MMU Enable",0},
842 {1,"Strict Align",0},
843 {1,"Data or Unified Cache Enable",0},
844 {1,"CP15 Barrier Enable",0},
845 {3,"- (SBO)",0},
846 {3,"- (SBZ)",0},
847 {1,"SWP/SWPB Enable",0},
848 {1,"Branch Pred Enable",0},
849 {1,"ICache Enable",0},
850 {1,"High Vector",0},
851 {1,"Round Robin",0},
852 {1,"- (SBZ)",0},
853 {1,"- (SBO)",0},
854 {1,"HA flag",0},
855 {1,"- (SBO)",0},
856 {1,"WXN (virt. ext. only)",0},
857 {1,"UWXN (virt. ext. only)",0},
858 {1,"FIQ Enable",0},
859 {2,"- (SBO)",0},
860 {1,"VE",0},
861 {1,"CPSR E",0},
862 {1,"- (SBZ)",0},
863 {1,"NMFI",0},
864 {1,"TRE",0},
865 {1,"AFE",0},
866 {1,"Thumb exceptions",0},
867 {1,"- (SBZ)",0},
868 {0}
869 };
870
871 const struct cpuinfo_bitfield_desc_s cpuinf_clidr_vmsa[] = {
872 {3,"Cache type, level1", ctype_str},
873 {3,"Cache type, level2", ctype_str},
874 {3,"Cache type, level3", ctype_str},
875 {3,"Cache type, level4", ctype_str},
876 {3,"Cache type, level5", ctype_str},
877 {3,"Cache type, level6", ctype_str},
878 {3,"Cache type, level7", ctype_str},
879 {3,"Level of unification Inner Shareable",0},
880 {3,"Level of coherency",0},
881 {3,"Level of unification",0},
882 {2,"(zero)",0},
883 {0}
884 };
885
886 static const char *ttbraddr0(unsigned val) {
887 val <<= 7;
888 sprintf(linebuf,"0x%08x",val);
889 return linebuf;
890 }
891
892 static const char *ttbraddr1(unsigned val) {
893 val <<= 7;
894 sprintf(linebuf,"0x%08x",val);
895 return linebuf;
896 }
897
898 static const char *ttbcr_n(unsigned val) {
899 val = 128 << (7-val);
900 sprintf(linebuf,"TTBR0 table size %u bytes",val);
901 return linebuf;
902 }
903
904 const struct cpuinfo_bitfield_desc_s cpuinf_ttbcr[] = {
905 {3,"N", ttbcr_n },
906 {1,"(zero)" ,0},
907 {1,"TTBR0 walks disabled" ,0},
908 {1,"TTBR1 walks disabled" ,0},
909 {25,"(zero)" ,0},
910 {1,"Long descriptors" ,0},
911 {0}
912 };
913
914 const struct cpuinfo_bitfield_desc_s cpuinf_ttbr0[] = {
915 {1,"IRGN[1]",0},
916 {1,"Shareable" ,0},
917 {1,"(impl. defined)" ,0},
918 {2,"RGN (Outer cacheability)" ,0},
919 {1,"NOS (Inner shareable)" ,0},
920 {1,"IRGN[0]" ,0},
921 {25,"Table address", ttbraddr0 },
922 {0}
923 };
924
925 const struct cpuinfo_bitfield_desc_s cpuinf_ttbr1[] = {
926 {1,"IRGN[1]",0},
927 {1,"Shareable" ,0},
928 {1,"(impl. defined)" ,0},
929 {2,"RGN (Outer cacheability)" ,0},
930 {1,"NOS (Inner shareable)" ,0},
931 {1,"IRGN[0]" ,0},
932 {25,"Table address", ttbraddr1 },
933 {0}
934 };
935
936 const struct cpuinfo_bitfield_desc_s cpuinf_actlr_vmsa[] = {
937 {1,"Cache & TLB maint. broadcast" ,0},
938 {1,"L2 prefetch enable" ,0},
939 {1,"L1 prefetch enable" ,0},
940 {1,"Write full line of zeroes" ,0},
941 {2,"(zero)",0},
942 {1,"SMP" ,0},
943 {1,"Exclusive cache" ,0},
944 {1,"Alloc in one way" ,0},
945 {1,"Parity on" ,0},
946 {22,"-",0},
947 {0}
948 };
949
950 const struct cpuinfo_bitfield_desc_s cpuinf_cpacr_vmsa[] = {
951 {20,"(zero)",0},
952 {2,"CP10 access permission",0},
953 {2,"CP11 access permission",0},
954 {6,"(zero)",0},
955 {1,"D32DIS",0},
956 {1,"ASEDIS",0},
957 {0}
958 };
959
960 const struct cpuinfo_word_desc_s cpuinfo_desc_vmsa[]={
961 {"ID", cpuinf_id },
962 {"Cache type", cpuinf_ctr },
963 {"TCM type", cpuinf_generic },
964 {"TLB type", cpuinf_tlbtype },
965 {"TTBCR", cpuinf_ttbcr },
966 {"TTBR0", cpuinf_ttbr0 },
967 {"TTBR1", cpuinf_ttbr1 },
968 {"Multiprocessor ID", cpuinf_generic },
969 {"Revision ID", cpuinf_generic },
970 {"Processor feature 0", cpuinf_feat0 },
971 {"Processor feature 1", cpuinf_feat1 },
972 {"Debug feature", cpuinf_dbgfeat },
973 {"Aux feature", cpuinf_generic },
974 {"Mem model feature 0", cpuinf_mmfr0 },
975 {"Mem model feature 1", cpuinf_mmfr1 },
976 {"Mem model feature 2", cpuinf_mmfr2 },
977 {"Mem model feature 3", cpuinf_mmfr3 },
978 {"ISA feature 0", cpuinf_isar0 },
979 {"ISA feature 1", cpuinf_isar1 },
980 {"ISA feature 2", cpuinf_isar2 },
981 {"ISA feature 3", cpuinf_isar3 },
982 {"ISA feature 4", cpuinf_isar4 },
983 {"ISA feature 5", cpuinf_isar5 },
984 {"Cache level ID", cpuinf_clidr_vmsa },
985 {"Cache size ID reg (data, level0)", cpuinf_ccsidr },
986 {"Cache size ID reg (inst, level0)", cpuinf_ccsidr },
987 {"SCTLR", cpuinf_sctlr_vmsa },
988 {"ACTLR", cpuinf_actlr_vmsa },
989 {"ACTLR2", cpuinf_generic },
990 {"CPACR", cpuinf_cpacr_vmsa },
991 {"DACR", cpuinf_generic },
992
993
994 {"NSACR (sec. ext. only)", cpuinf_generic },
995 {"DBGDIDR", cpuinf_dbgdidr },
996 {"DBGDRAR", cpuinf_dbgd_address },
997 {"DBGDSAR", cpuinf_dbgd_address },
998 {"DBGDSCR", cpuinf_dbgdscr },
999
1000
1001
1002 {"Config base addr reg", cpuinf_generic },
1003 {"PLEIDR", cpuinf_generic },
1004 {"TLB lockdown reg", cpuinf_generic },
1005 {"PRRR", cpuinf_generic },
1006 {"NMRR", cpuinf_generic },
1007 {0}
1008 };
1009
1010 void __attribute__((naked,noinline)) cpuinfo_get_info_vmsa(__attribute__ ((unused))unsigned *results) {
1011 asm (
1012 ".syntax unified\n"
1013 ".code 16\n"
1014 ".align 2\n"
1015 "BX PC\n"
1016 ".code 32\n"
1017
1018 "MRC p15, 0, R1,c0,c0\n"
1019 "STR R1, [R0]\n"
1020
1021 "MRC p15, 0, R1,c0,c0,1\n"
1022 "ADD R0, R0, #4\n"
1023 "STR R1, [R0]\n"
1024
1025 "MRC p15, 0, R1,c0,c0,2\n"
1026 "ADD R0, R0, #4\n"
1027 "STR R1, [R0]\n"
1028
1029 "MRC p15, 0, R1,c0,c0,3\n"
1030 "ADD R0, R0, #4\n"
1031 "STR R1, [R0]\n"
1032
1033 "MRC p15, 0, R1,c2,c0,2\n"
1034 "ADD R0, R0, #4\n"
1035 "STR R1, [R0]\n"
1036
1037 "MRC p15, 0, R1,c2,c0,0\n"
1038 "ADD R0, R0, #4\n"
1039 "STR R1, [R0]\n"
1040
1041 "MRC p15, 0, R1,c2,c0,1\n"
1042 "ADD R0, R0, #4\n"
1043 "STR R1, [R0]\n"
1044
1045 "MRC p15, 0, R1,c0,c0,5\n"
1046 "ADD R0, R0, #4\n"
1047 "STR R1, [R0]\n"
1048
1049 "MRC p15, 0, R1,c0,c0,6\n"
1050 "ADD R0, R0, #4\n"
1051 "STR R1, [R0]\n"
1052
1053 "MRC p15, 0, R1,c0,c1,0\n"
1054 "ADD R0, R0, #4\n"
1055 "STR R1, [R0]\n"
1056
1057 "MRC p15, 0, R1,c0,c1,1\n"
1058 "ADD R0, R0, #4\n"
1059 "STR R1, [R0]\n"
1060
1061 "MRC p15, 0, R1,c0,c1,2\n"
1062 "ADD R0, R0, #4\n"
1063 "STR R1, [R0]\n"
1064
1065 "MRC p15, 0, R1,c0,c1,3\n"
1066 "ADD R0, R0, #4\n"
1067 "STR R1, [R0]\n"
1068
1069 "MRC p15, 0, R1,c0,c1,4\n"
1070 "ADD R0, R0, #4\n"
1071 "STR R1, [R0]\n"
1072
1073 "MRC p15, 0, R1,c0,c1,5\n"
1074 "ADD R0, R0, #4\n"
1075 "STR R1, [R0]\n"
1076
1077 "MRC p15, 0, R1,c0,c1,6\n"
1078 "ADD R0, R0, #4\n"
1079 "STR R1, [R0]\n"
1080
1081 "MRC p15, 0, R1,c0,c1,7\n"
1082 "ADD R0, R0, #4\n"
1083 "STR R1, [R0]\n"
1084
1085 "MRC p15, 0, R1,c0,c2,0\n"
1086 "ADD R0, R0, #4\n"
1087 "STR R1, [R0]\n"
1088
1089 "MRC p15, 0, R1,c0,c2,1\n"
1090 "ADD R0, R0, #4\n"
1091 "STR R1, [R0]\n"
1092
1093 "MRC p15, 0, R1,c0,c2,2\n"
1094 "ADD R0, R0, #4\n"
1095 "STR R1, [R0]\n"
1096
1097 "MRC p15, 0, R1,c0,c2,3\n"
1098 "ADD R0, R0, #4\n"
1099 "STR R1, [R0]\n"
1100
1101 "MRC p15, 0, R1,c0,c2,4\n"
1102 "ADD R0, R0, #4\n"
1103 "STR R1, [R0]\n"
1104
1105 "MRC p15, 0, R1,c0,c2,5\n"
1106 "ADD R0, R0, #4\n"
1107 "STR R1, [R0]\n"
1108
1109 "MRC p15, 1, R1,c0,c0,1\n"
1110 "ADD R0, R0, #4\n"
1111 "STR R1, [R0]\n"
1112
1113 "MOV R1, #0\n"
1114 "MCR p15, 2, R1,c0,c0,0\n"
1115
1116 "MRC p15, 1, R1,c0,c0,0\n"
1117 "ADD R0, R0, #4\n"
1118 "STR R1, [R0]\n"
1119
1120 "MOV R1, #1\n"
1121 "MCR p15, 2, R1,c0,c0,0\n"
1122
1123 "MRC p15, 1, R1,c0,c0,0\n"
1124 "ADD R0, R0, #4\n"
1125 "STR R1, [R0]\n"
1126
1127 "MRC p15, 0, R1,c1,c0,0\n"
1128 "ADD R0, R0, #4\n"
1129 "STR R1, [R0]\n"
1130
1131 "MRC p15, 0, R1,c1,c0,1\n"
1132 "ADD R0, R0, #4\n"
1133 "STR R1, [R0]\n"
1134
1135
1136 "MRC p15, 0, R1,c15,c0,0\n"
1137 "ADD R0, R0, #4\n"
1138 "STR R1, [R0]\n"
1139
1140
1141 "MRC p15, 0, R1,c1,c0,2\n"
1142 "ADD R0, R0, #4\n"
1143 "STR R1, [R0]\n"
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 "MRC p15, 0, R1,c1,c1,2\n"
1154 "ADD R0, R0, #4\n"
1155 "STR R1, [R0]\n"
1156
1157 "MRC p15, 0, R1,c3,c0,0\n"
1158 "ADD R0, R0, #4\n"
1159 "STR R1, [R0]\n"
1160
1161 "MRC p14, 0, R1,c0,c0,0\n"
1162 "ADD R0, R0, #4\n"
1163 "STR R1, [R0]\n"
1164
1165 "MRC p14, 0, R1,c1,c0,0\n"
1166 "ADD R0, R0, #4\n"
1167 "STR R1, [R0]\n"
1168
1169 "MRC p14, 0, R1,c2,c0,0\n"
1170 "ADD R0, R0, #4\n"
1171 "STR R1, [R0]\n"
1172
1173 "MRC p14, 0, R1,c0,c1,0\n"
1174 "ADD R0, R0, #4\n"
1175 "STR R1, [R0]\n"
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189 "MRC p15, 4, R1,c15,c0,0\n"
1190 "ADD R0, R0, #4\n"
1191 "STR R1, [R0]\n"
1192
1193 "MRC p15, 0, R1,c11,c0,0\n"
1194 "ADD R0, R0, #4\n"
1195 "STR R1, [R0]\n"
1196
1197 "MRC p15, 0, R1,c10,c0,0\n"
1198 "ADD R0, R0, #4\n"
1199 "STR R1, [R0]\n"
1200
1201 "MRC p15, 0, R1,c10,c2,0\n"
1202 "ADD R0, R0, #4\n"
1203 "STR R1, [R0]\n"
1204
1205 "MRC p15, 0, R1,c10,c2,1\n"
1206 "ADD R0, R0, #4\n"
1207 "STR R1, [R0]\n"
1208
1209 "BX LR\n"
1210
1211 :::"r0","r1"
1212 );
1213 }
1214
1215 int __attribute__((naked,noinline)) cpu_is_vmsa() {
1216 asm (
1217 ".syntax unified\n"
1218 "MRC p15, 0, R0,c0,c1,4\n"
1219 "AND R0, #15\n"
1220 "BX LR\n"
1221 :::"r0"
1222 );
1223 return 0;
1224 }
1225
1226 void __attribute__((naked,noinline)) get_mmuregs_vmsa(__attribute__ ((unused))void *p) {
1227 asm (
1228 ".syntax unified\n"
1229 "MRC p15, 0, R1,c2,c0,0\n"
1230 "STR R1, [R0]\n"
1231 "MRC p15, 0, R1,c2,c0,1\n"
1232 "ADD R0, R0, #4\n"
1233 "STR R1, [R0]\n"
1234 "MRC p15, 0, R1,c2,c0,2\n"
1235 "ADD R0, R0, #4\n"
1236 "STR R1, [R0]\n"
1237 "BX LR\n"
1238 :::"r0","r1"
1239 );
1240 }
1241
1242 struct mmuregs_s {
1243 unsigned ttbr0;
1244 unsigned ttbr1;
1245 unsigned ttbcr;
1246 };
1247
1248 struct l1tblentry_s {
1249 char *typ;
1250 char *pbit;
1251 unsigned domain;
1252 char physaddr[12];
1253 char l2addr[12];
1254 char *ngbit;
1255 char *sbit;
1256 char *accperm;
1257 char *caching;
1258 char *memtype;
1259 char *xnbit;
1260 };
1261
1262 char *cpolicies[] = {
1263 "Cached OUTER 0 INNER 0",
1264 "Cached OUTER 0 INNER 1",
1265 "Cached OUTER 0 INNER 2",
1266 "Cached OUTER 0 INNER 3",
1267 "Cached OUTER 1 INNER 0",
1268 "Cached OUTER 1 INNER 1",
1269 "Cached OUTER 1 INNER 2",
1270 "Cached OUTER 1 INNER 3",
1271 "Cached OUTER 2 INNER 0",
1272 "Cached OUTER 2 INNER 1",
1273 "Cached OUTER 2 INNER 2",
1274 "Cached OUTER 2 INNER 3",
1275 "Cached OUTER 3 INNER 0",
1276 "Cached OUTER 3 INNER 1",
1277 "Cached OUTER 3 INNER 2",
1278 "Cached OUTER 3 INNER 3",
1279 };
1280
1281 unsigned interpret_l1_table_entry(unsigned e, char *buf) {
1282 unsigned ret = 0, l2a = 0;
1283 struct l1tblentry_s col;
1284 col.typ = "";
1285 col.pbit = "";
1286 col.ngbit = "";
1287 col.domain = 0;
1288 col.physaddr[0] = 0;
1289 col.l2addr[0] = 0;
1290 col.sbit = "";
1291 col.accperm = "";
1292 col.caching = "";
1293 col.memtype = "";
1294 col.xnbit = "";
1295 int typ = -1;
1296 switch (e & 3) {
1297 case 1: typ = 2;
1298 break;
1299 case 2: typ = (e & 0x40000)?1:0;
1300 break;
1301 }
1302 if (typ < 0) {
1303 sprintf(buf,"Fault,");
1304 return 2;
1305 }
1306 if (e & 0x200) {
1307 col.pbit = "P";
1308 }
1309 col.domain = (e >> 5) & 15;
1310 if (typ == 2) {
1311 col.typ = "L2 ref";
1312 l2a = e & 0xfffffc00;
1313 sprintf(col.l2addr,"0x%08x",l2a);
1314 }
1315 else {
1316 col.typ = typ==1?"Supersection":"Section";
1317 sprintf(col.physaddr,"0x%08x",e & 0xfff00000);
1318 col.ngbit = e&0x20000?"Nonglobal":"Global";
1319 col.sbit = e&0x10000?"Shareable":"";
1320 col.xnbit = e&0x10?"No exec":"";
1321 switch (e & 0x8C00) {
1322 case 0: col.accperm = "--/--"; break;
1323 case 0x400: col.accperm = "RW/--"; break;
1324 case 0x800: col.accperm = "RW/R-"; break;
1325 case 0xC00: col.accperm = "RW/RW"; break;
1326 case 0x8000: col.accperm = "rsrvd"; break;
1327 case 0x8400: col.accperm = "R-/--"; break;
1328 case 0x8800: col.accperm = "R-/R-"; break;
1329 case 0x8C00: col.accperm = "rsrvd"; break;
1330 }
1331 switch (e & 0x700c) {
1332 case 0: col.caching = "STR ORD"; col.memtype = "Strongly-ordered"; break;
1333 case 4: col.caching = "SHR DEV"; col.memtype = "Device"; break;
1334 case 8: col.caching = "WRTHR, NAW"; col.memtype = "Normal"; break;
1335 case 0xc: col.caching = "WRBCK, NAW"; col.memtype = "Normal"; break;
1336 case 0x1000: col.caching = "NON CACH"; col.memtype = "Normal"; break;
1337 case 0x2000: col.caching = "NONSHR DEV"; col.memtype = "Device"; break;
1338 default:
1339 if (e & 0x4000) {
1340 unsigned i = ((e&0x3000)>>10)|((e&0xc)>>2);
1341 col.caching = cpolicies[i];
1342 col.memtype = "Normal";
1343 }
1344 }
1345 }
1346 sprintf(buf,"%s,%s,%s,%u,%s,%s,%s,%s,%s,%s,%s,",col.typ,col.pbit,
1347 col.ngbit,col.domain,col.physaddr,col.l2addr,col.sbit,col.accperm,
1348 col.caching,col.memtype,col.xnbit);
1349 if (typ==1) {
1350 ret = 1;
1351 }
1352 if (l2a!=0) {
1353 ret = l2a;
1354 }
1355 return ret;
1356 }
1357
1358 unsigned interpret_l2_table_entry(unsigned e, char *buf) {
1359 unsigned ret = 0, f;
1360 struct l1tblentry_s col;
1361 col.typ = "";
1362 col.pbit = "";
1363 col.ngbit = "";
1364 col.domain = 0;
1365 col.physaddr[0] = 0;
1366 col.l2addr[0] = 0;
1367 col.sbit = "";
1368 col.accperm = "";
1369 col.caching = "";
1370 col.memtype = "";
1371 col.xnbit = "";
1372 int typ = -1;
1373 switch (e & 3) {
1374 case 1: typ = 1;
1375 col.typ = "Large page";
1376 sprintf(col.physaddr,"0x%08x",e & 0xffff0000);
1377 col.xnbit = e&0x8000?"No exec":"";
1378 f = e;
1379 break;
1380 case 2:
1381 case 3: typ = 0;
1382 col.typ = "Small page";
1383 sprintf(col.physaddr,"0x%08x",e & 0xfffff000);
1384 col.xnbit = e&1?"No exec":"";
1385 f = ((e<<6) & 0x7000) | (e & 0xc);
1386 break;
1387 }
1388 if (typ < 0) {
1389 sprintf(buf,"Fault,");
1390 return 2;
1391 }
1392 col.ngbit = e&0x800?"Nonglobal":"Global";
1393 col.sbit = e&0x400?"Shareable":"";
1394 switch ((e<<6) & 0x8C00) {
1395 case 0: col.accperm = "--/--"; break;
1396 case 0x400: col.accperm = "RW/--"; break;
1397 case 0x800: col.accperm = "RW/R-"; break;
1398 case 0xC00: col.accperm = "RW/RW"; break;
1399 case 0x8000: col.accperm = "rsrvd"; break;
1400 case 0x8400: col.accperm = "R-/--"; break;
1401 case 0x8800: col.accperm = "R-/R-"; break;
1402 case 0x8C00: col.accperm = "rsrvd"; break;
1403 }
1404 switch (f & 0x700c) {
1405 case 0: col.caching = "STR ORD"; col.memtype = "Strongly-ordered"; break;
1406 case 4: col.caching = "SHR DEV"; col.memtype = "Device"; break;
1407 case 8: col.caching = "WRTHR, NAW"; col.memtype = "Normal"; break;
1408 case 0xc: col.caching = "WRBCK, NAW"; col.memtype = "Normal"; break;
1409 case 0x1000: col.caching = "NON CACH"; col.memtype = "Normal"; break;
1410 case 0x2000: col.caching = "NONSHR DEV"; col.memtype = "Device"; break;
1411 default:
1412 if (f & 0x4000) {
1413 unsigned i = ((f&0x3000)>>10)|((f&0xc)>>2);
1414 col.caching = cpolicies[i];
1415 col.memtype = "Normal";
1416 }
1417 }
1418 sprintf(buf,"%s,%s,%s,,%s,%s,%s,%s,%s,%s,%s,",col.typ,col.pbit,
1419 col.ngbit,col.physaddr,col.l2addr,col.sbit,col.accperm,
1420 col.caching,col.memtype,col.xnbit);
1421 if (typ==1) {
1422 ret = 1;
1423 }
1424 return ret;
1425 }
1426
1427 const char *csvhead = "Virt.addr,Table,Type,P bit,NG bit,Domain,Phys.addr,L2 ref,S bit,Privileged/Nonpriv.,Caching,Memtype,XN bit\n";
1428
1429 void memmapping_vmsa(FILE *f) {
1430 struct mmuregs_s mmuregs;
1431 get_mmuregs_vmsa(&mmuregs);
1432 unsigned tt0len = 128 << (7 - (mmuregs.ttbcr & 7));
1433 unsigned tt0adr = mmuregs.ttbr0 & 0xffffff80;
1434 unsigned tt1adr = mmuregs.ttbr1 & 0xffffff80;
1435 unsigned n, *e, r, pr=42, cycl, l1a;
1436 char *conclude;
1437 e = (unsigned*)tt0adr;
1438 cycl = tt0len/4;
1439 l1a = 0;
1440 unsigned remain = 2;
1441 fwrite(csvhead,1,strlen(csvhead),f);
1442 while (remain) {
1443 for (n=0; n<cycl; n++) {
1444 sprintf(linebuf,"0x%08X,L1,",l1a);
1445 fwrite(linebuf,1,strlen(linebuf),f);
1446 conclude = "\n";
1447 r = interpret_l1_table_entry(*e, linebuf);
1448 fwrite(linebuf,1,strlen(linebuf),f);
1449 if (r==1 && pr!=1) {
1450 if ((unsigned)e & 0x3f) {
1451 conclude = "ERR: Unaligned supersection\n";
1452 }
1453 else {
1454 unsigned m, v;
1455 v = *e;
1456 for (m=1; m<16; m++) {
1457 if (v != *(e+m)) {
1458 conclude = "ERR: Inconsistent supersection\n";
1459 break;
1460 }
1461 }
1462 }
1463 }
1464 else if (r==2) {
1465 conclude = "\n";
1466 }
1467 fwrite(conclude,1,strlen(conclude),f);
1468 if (r>42) {
1469 unsigned nn, l2a, *ee, rr, prr=42;
1470 l2a = l1a;
1471 ee = (unsigned*) r;
1472 for (nn=0; nn<256; nn++) {
1473 sprintf(linebuf,"0x%08X,L2,",l2a);
1474 fwrite(linebuf,1,strlen(linebuf),f);
1475 conclude = "\n";
1476 rr = interpret_l2_table_entry(*ee, linebuf);
1477 fwrite(linebuf,1,strlen(linebuf),f);
1478
1479 if (rr==1 && prr!=1) {
1480 if ((unsigned)ee & 0x3f) {
1481 conclude = "ERR: Unaligned large page\n";
1482 }
1483 else {
1484 unsigned mm, vv;
1485 vv = *ee;
1486 for (mm=1; mm<16; mm++) {
1487 if (vv != *(ee+mm)) {
1488 conclude = "ERR: Inconsistent large page\n";
1489 break;
1490 }
1491 }
1492 }
1493 }
1494 else if (rr==2) {
1495 conclude = "\n";
1496 }
1497 fwrite(conclude,1,strlen(conclude),f);
1498
1499 ee++;
1500 prr = rr;
1501 l2a += 0x1000;
1502 }
1503 }
1504 e++;
1505 pr = r;
1506 l1a += 0x100000;
1507 }
1508 e = (unsigned*)(tt1adr+tt0len);
1509 cycl = (0x4000 - tt0len) / 4;
1510 remain--;
1511 }
1512 fclose(f);
1513 }
1514
1515