root/modules/cpuinfo_v7.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. two_on_nth
  2. two_on_nth_granule
  3. mmfr3_cache
  4. mmfr3_bp
  5. mmfr3_cms
  6. mmfr3_ss
  7. ctype_str
  8. ccsidr_linesize
  9. ccsidr_plusone
  10. cache_tcm_size_str
  11. cache_tcm_addr_str
  12. mpu_region_size_str
  13. bitfield8
  14. mpu_rattr
  15. dbg_version
  16. cpuinfo_get_info_pmsa
  17. tlb_unified
  18. tlb_entries
  19. ttbraddr0
  20. ttbraddr1
  21. ttbcr_n
  22. cpuinfo_get_info_vmsa
  23. cpu_is_vmsa
  24. get_mmuregs_vmsa
  25. interpret_l1_table_entry
  26. interpret_l2_table_entry
  27. memmapping_vmsa

   1 // cpuinfo, ARMv7 specific parts
   2 
   3 static char linebuf[256]; // fixed buffer for outputting dynamic strings from interpreter functions
   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"},
  31     {4,"Thumb inst set"},
  32     {4,"Jazelle inst set"},
  33     {4,"ThumbEE inst set"},
  34     {16,"-"},
  35     {}
  36 };
  37 
  38 const struct cpuinfo_bitfield_desc_s cpuinf_feat1[] = {
  39     {4,"Programmers' model"},
  40     {4,"Security extensions"},
  41     {4,"Microcontr. prog model"},
  42     {4,"Virt. extensions"},
  43     {4,"Generic timer ext."},
  44     {12,"-"},
  45     {}
  46 };
  47 
  48 const struct cpuinfo_bitfield_desc_s cpuinf_dbgfeat[] = {
  49     {4,"Coproc. dbg model"},
  50     {4,"Coproc. secure dbg model"},
  51     {4,"Memory-mapped dbg model"},
  52     {4,"Coproc. trace model"},
  53     {4,"Memory-mapped trace model"},
  54     {4,"Debug model M"},
  55     {4,"Perf. monitors"},
  56     {4,"-"},
  57     {}
  58 };
  59 
  60 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr0[] = {
  61     {4,"VMSA support"},
  62     {4,"PMSA support"},
  63     {4,"Cache coherence"},
  64     {4,"Outer shareable"},
  65     {4,"TCM support"},
  66     {4,"Auxiliary registers"},
  67     {4,"FCSE support"},
  68     {4,"-"},
  69     {}
  70 };
  71 
  72 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr1[] = {
  73     {4,"L1 Harvard cache VA"},
  74     {4,"L1 unified cache VA"},
  75     {4,"L1 Harvard cache s/w"},
  76     {4,"L1 unified cache s/w"},
  77     {4,"L1 Harvard cache"},
  78     {4,"L1 unified cache"},
  79     {4,"L1 cache test & clean"},
  80     {4,"Branch predictor"},
  81     {}
  82 };
  83 
  84 const struct cpuinfo_bitfield_desc_s cpuinf_mmfr2[] = {
  85     {4,"L1 Harvard fg prefetch"},
  86     {4,"L1 Harvard bg prefetch"},
  87     {4,"L1 Harvard range"},
  88     {4,"Harvard TLB"},
  89     {4,"Unified TLB"},
  90     {4,"Mem barrier"},
  91     {4,"WFI stall"},
  92     {4,"HW access flag"},
  93     {}
  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"},
 135     {4,"-"},
 136     {4,"Transl. table coherent walk"},
 137     {4,"Cached memory size", mmfr3_cms},
 138     {4,"Supersection support", mmfr3_ss},
 139     {}
 140 };
 141 
 142 const struct cpuinfo_bitfield_desc_s cpuinf_isar0[] = {
 143     {4,"Swap instrs"},
 144     {4,"Bitcount instrs"},
 145     {4,"Bitfield instrs"},
 146     {4,"CmpBranch instrs"},
 147     {4,"Coproc instrs"},
 148     {4,"Debug instrs"},
 149     {4,"Divide instrs"},
 150     {4,"-"},
 151     {}
 152 };
 153 
 154 const struct cpuinfo_bitfield_desc_s cpuinf_isar1[] = {
 155     {4,"Endian instrs"},
 156     {4,"Exception instrs"},
 157     {4,"Exception AR instrs"},
 158     {4,"Extend instrs"},
 159     {4,"IfThen instrs"},
 160     {4,"Immediate instrs"},
 161     {4,"Interwork instrs"},
 162     {4,"Jazelle instrs"},
 163     {}
 164 };
 165 
 166 const struct cpuinfo_bitfield_desc_s cpuinf_isar2[] = {
 167     {4,"LoadStore instrs"},
 168     {4,"Memhint instrs"},
 169     {4,"MultiAccess Interruptible instructions"},
 170     {4,"Mult instrs"},
 171     {4,"MultS instrs"},
 172     {4,"MultU instrs"},
 173     {4,"PSR AR instrs"},
 174     {4,"Reversal instrs"},
 175     {}
 176 };
 177 
 178 const struct cpuinfo_bitfield_desc_s cpuinf_isar3[] = {
 179     {4,"Saturate instrs"},
 180     {4,"SIMD instrs"},
 181     {4,"SVC instrs"},
 182     {4,"SynchPrim instrs"},
 183     {4,"TabBranch instrs"},
 184     {4,"ThumbCopy instrs"},
 185     {4,"TrueNOP instrs"},
 186     {4,"T2 Exec Env instrs"},
 187     {}
 188 };
 189 
 190 const struct cpuinfo_bitfield_desc_s cpuinf_isar4[] = {
 191     {4,"Unprivileged instrs"},
 192     {4,"WithShifts instrs"},
 193     {4,"Writeback instrs"},
 194     {4,"SMC instrs"},
 195     {4,"Barrier instrs"},
 196     {4,"SynchPrim_instrs_frac"},
 197     {4,"PSR_M instrs"},
 198     {4,"-"},
 199     {}
 200 };
 201 
 202 const struct cpuinfo_bitfield_desc_s cpuinf_isar5[] = {
 203     {32,"-"},
 204     {}
 205 };
 206 
 207 const struct cpuinfo_bitfield_desc_s cpuinf_ctr[] = {
 208     {4,"Icache min words/line", two_on_nth},
 209     {10,"(zero)"},
 210     {2,"L1 Icache policy"},
 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)"},
 215     {3,"(register format)"},
 216     {}
 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}, // L8 mentioned only in Cortex R4 TRM
 239     {3,"Level of coherency"},
 240     {3,"Level of unification"},
 241     {2,"(zero)"},
 242     {}
 243 };
 244 
 245 const struct cpuinfo_bitfield_desc_s cpuinf_csselr[] = {
 246     {1,"Instruction, not data"},
 247     {3,"Level"},
 248     {28,"(unknown)"},
 249     {}
 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"},
 266     {1,"Read allocation"},
 267     {1,"Write back"},
 268     {1,"Write through"},
 269     {}
 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"},
 287     {1,"-"},
 288     {5,"Size", cache_tcm_size_str},
 289     {5,"-"},
 290     {20,"Base address", cache_tcm_addr_str},
 291     {}
 292 };
 293 
 294 const struct cpuinfo_bitfield_desc_s cpuinf_mputype[] = {
 295     {1,"S"},
 296     {7,"-"},
 297     {8,"Num of MPU regions"},
 298     {}
 299 };
 300 
 301 const struct cpuinfo_bitfield_desc_s cpuinf_mpubase[] = {
 302     {32,"Base address"},
 303     {}
 304 };
 305 
 306 const struct cpuinfo_bitfield_desc_s cpuinf_sctlr[] = {
 307     {1,"MPU Enable"},
 308     {1,"Strict Align"},
 309     {1,"L1 DCache Enable"},
 310     {4,"- (SBO)"},
 311     {4,"- (SBZ)"},
 312     {1,"Branch Pred Enable"},
 313     {1,"L1 ICache Enable"},
 314     {1,"High Vector"},
 315     {1,"Round Robin"},
 316     {1,"- (SBZ)"},
 317     {1,"- (SBO)"},
 318     {1,"MPU background reg"},
 319     {1,"- (SBO)"},
 320     {1,"Div0 exception"},
 321     {1,"- (SBZ)"},
 322     {1,"FIQ Enable"},
 323     {2,"- (SBO)"},
 324     {1,"VIC"},
 325     {1,"CPSR E bit"},
 326     {1,"- (SBZ)"},
 327     {1,"NMFI"},
 328     {1,"TRE"},
 329     {1,"AFE"},
 330     {1,"Thumb exceptions"},
 331     {1,"Endian"},
 332     {}
 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"},
 354     {5,"Size", mpu_region_size_str},
 355     {2,"-"},
 356     {8,"Sub-regions disabled", bitfield8},
 357     {}
 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,"-"},
 399     {3,"Access permission", regperm_str},
 400     {1,"-"},
 401     {1,"Execute never"},
 402     {}
 403 };
 404 
 405 const struct cpuinfo_bitfield_desc_s cpuinf_generic[] = {
 406     {32,"(raw value)"},
 407     {}
 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"},
 426     {4,"Variant"},
 427     {8,"- (RAZ)"},
 428     {4,"Version",dbg_version},
 429     {4,"Context",ccsidr_plusone},
 430     {4,"BRP",ccsidr_plusone},
 431     {4,"WRP",ccsidr_plusone},
 432     {}
 433 };
 434 
 435 static const struct cpuinfo_bitfield_desc_s cpuinf_dbgd_address[] = {
 436     {2,"Valid"},
 437     {10,"- (UNK)"},
 438     {20,"Address",cache_tcm_addr_str},
 439     {}
 440 };
 441 
 442 static const struct cpuinfo_bitfield_desc_s cpuinf_dbgdscr[] = {
 443     {1,"HALTED"},
 444     {1,"RESTARTED"},
 445     {4,"MOE"},
 446     {1,"SDABORT_l"},
 447     {1,"ADABORT_l"},
 448     {1,"UND_l"},
 449     {1,"FS"},
 450     {1,"DBGack"},
 451     {1,"INTdis"},
 452     {1,"UDCCdis"},
 453     {1,"ITRen"},
 454     {1,"HDBGen"},
 455     {1,"MDBGen"},
 456     {1,"SPIDdis"},
 457     {1,"SPNIDdis"},
 458     {1,"NS"},
 459     {1,"ADAdiscard"},
 460     {2,"ExtDCCmode"},
 461     {2,"- (SBZ)"},
 462     {1,"InstrCompl_l"},
 463     {1,"PipeAdv"},
 464     {1,"TXfull_l"},
 465     {1,"RXfull_l"},
 466     {1,"- (SBZ)"},
 467     {1,"TXfull"},
 468     {1,"RXfull"},
 469     {1,"- (SBZ)"},
 470     {}
 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     //{"Floating Point System ID register", cpuinf_generic },
 533     //{"Media and VFP Feature Register 0", cpuinf_generic },
 534     //{"Media and VFP Feature Register 1", cpuinf_generic },
 535     {}
 536 };
 537 
 538 
 539 void __attribute__((naked,noinline)) cpuinfo_get_info_pmsa(unsigned *results) {
 540     asm (
 541         ".syntax unified\n"
 542         ".code 16\n"
 543         ".align 2\n"
 544         "BX      PC\n"                  // switch to ARM mode
 545         ".code 32\n"
 546 
 547         "MRC    p15, 0, R1,c0,c0\n" // ident
 548         "STR    R1, [R0]\n"
 549 
 550         "MRC    p15, 0, R1,c0,c0,1\n" // cache
 551         "ADD    R0, R0, #4\n"
 552         "STR    R1, [R0]\n"
 553 
 554         "MRC    p15, 0, R1,c0,c0,2\n" // TCM
 555         "ADD    R0, R0, #4\n"
 556         "STR    R1, [R0]\n"
 557 
 558         "MRC    p15, 0, R1,c0,c0,4\n" // MPU
 559         "ADD    R0, R0, #4\n"
 560         "STR    R1, [R0]\n"
 561 
 562         "MRC    p15, 0, R1,c0,c0,5\n" // MPIDR
 563         "ADD    R0, R0, #4\n"
 564         "STR    R1, [R0]\n"
 565 
 566         "MRC    p15, 0, R1,c0,c1,0\n" // ID_PFR0
 567         "ADD    R0, R0, #4\n"
 568         "STR    R1, [R0]\n"
 569 
 570         "MRC    p15, 0, R1,c0,c1,1\n" // ID_PFR1
 571         "ADD    R0, R0, #4\n"
 572         "STR    R1, [R0]\n"
 573 
 574         "MRC    p15, 0, R1,c0,c1,2\n" // ID_DFR0
 575         "ADD    R0, R0, #4\n"
 576         "STR    R1, [R0]\n"
 577 
 578         "MRC    p15, 0, R1,c0,c1,3\n" // ID_AFR0
 579         "ADD    R0, R0, #4\n"
 580         "STR    R1, [R0]\n"
 581 
 582         "MRC    p15, 0, R1,c0,c1,4\n" // ID_MMFR0
 583         "ADD    R0, R0, #4\n"
 584         "STR    R1, [R0]\n"
 585 
 586         "MRC    p15, 0, R1,c0,c1,5\n" // ID_MMFR1
 587         "ADD    R0, R0, #4\n"
 588         "STR    R1, [R0]\n"
 589 
 590         "MRC    p15, 0, R1,c0,c1,6\n" // ID_MMFR2
 591         "ADD    R0, R0, #4\n"
 592         "STR    R1, [R0]\n"
 593 
 594         "MRC    p15, 0, R1,c0,c1,7\n" // ID_MMFR3
 595         "ADD    R0, R0, #4\n"
 596         "STR    R1, [R0]\n"
 597 
 598         "MRC    p15, 0, R1,c0,c2,0\n" // ID_ISAR0
 599         "ADD    R0, R0, #4\n"
 600         "STR    R1, [R0]\n"
 601 
 602         "MRC    p15, 0, R1,c0,c2,1\n" // ID_ISAR1
 603         "ADD    R0, R0, #4\n"
 604         "STR    R1, [R0]\n"
 605 
 606         "MRC    p15, 0, R1,c0,c2,2\n" // ID_ISAR2
 607         "ADD    R0, R0, #4\n"
 608         "STR    R1, [R0]\n"
 609 
 610         "MRC    p15, 0, R1,c0,c2,3\n" // ID_ISAR3
 611         "ADD    R0, R0, #4\n"
 612         "STR    R1, [R0]\n"
 613 
 614         "MRC    p15, 0, R1,c0,c2,4\n" // ID_ISAR4
 615         "ADD    R0, R0, #4\n"
 616         "STR    R1, [R0]\n"
 617 
 618         "MRC    p15, 0, R1,c0,c2,5\n" // ID_ISAR5
 619         "ADD    R0, R0, #4\n"
 620         "STR    R1, [R0]\n"
 621 
 622         "MRC    p15, 1, R1,c0,c0,1\n" // CLIDR
 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" // CSSELR (data cache, level0)
 628 
 629         "MRC    p15, 1, R1,c0,c0,0\n" // CCSIDR (the currently selected one)
 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" // CSSELR (inst cache, level0)
 635 
 636         "MRC    p15, 1, R1,c0,c0,0\n" // CCSIDR (the currently selected one)
 637         "ADD    R0, R0, #4\n"
 638         "STR    R1, [R0]\n"
 639 
 640         "MRC    p15, 0, R1,c1,c0,0\n" // SCTLR
 641         "ADD    R0, R0, #4\n"
 642         "STR    R1, [R0]\n"
 643 
 644         "MRC    p15, 0, R1,c1,c0,1\n" // ACTLR
 645         "ADD    R0, R0, #4\n"
 646         "STR    R1, [R0]\n"
 647 
 648 //#ifndef CONFIG_QEMU
 649         "MRC    p15, 0, R1,c15,c0,0\n" // ACTLR2
 650         "ADD    R0, R0, #4\n"
 651         "STR    R1, [R0]\n"
 652 //#endif
 653 
 654         "MRC    p15, 0, R1,c1,c0,2\n" // CPACR
 655         "ADD    R0, R0, #4\n"
 656         "STR    R1, [R0]\n"
 657 
 658         "MRC    p15, 0, R1,c15,c2,0\n" // Build options 1 reg (from Cortex R4 TRM)
 659         "ADD    R0, R0, #4\n"
 660         "STR    R1, [R0]\n"
 661 
 662         "MRC    p15, 0, R1,c15,c2,1\n" // Build options 2 reg (from Cortex R4 TRM)
 663         "ADD    R0, R0, #4\n"
 664         "STR    R1, [R0]\n"
 665 
 666         "MRC    p15, 0, R1,c9,c1,1\n" // ATCM region reg
 667         "ADD    R0, R0, #4\n"
 668         "STR    R1, [R0]\n"
 669 
 670         "MRC    p15, 0, R1,c9,c1,0\n" // BTCM region reg
 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" // MPU Memory Region Number Register, region 0
 676 
 677         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 678         "ADD    R0, R0, #4\n"
 679         "STR    R1, [R0]\n"
 680         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 681         "ADD    R0, R0, #4\n"
 682         "STR    R1, [R0]\n"
 683         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 1
 689 
 690         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 691         "ADD    R0, R0, #4\n"
 692         "STR    R1, [R0]\n"
 693         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 694         "ADD    R0, R0, #4\n"
 695         "STR    R1, [R0]\n"
 696         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 2
 702 
 703         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 704         "ADD    R0, R0, #4\n"
 705         "STR    R1, [R0]\n"
 706         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 707         "ADD    R0, R0, #4\n"
 708         "STR    R1, [R0]\n"
 709         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 3
 715 
 716         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 717         "ADD    R0, R0, #4\n"
 718         "STR    R1, [R0]\n"
 719         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 720         "ADD    R0, R0, #4\n"
 721         "STR    R1, [R0]\n"
 722         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 4
 728 
 729         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 730         "ADD    R0, R0, #4\n"
 731         "STR    R1, [R0]\n"
 732         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 733         "ADD    R0, R0, #4\n"
 734         "STR    R1, [R0]\n"
 735         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 5
 741 
 742         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 743         "ADD    R0, R0, #4\n"
 744         "STR    R1, [R0]\n"
 745         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 746         "ADD    R0, R0, #4\n"
 747         "STR    R1, [R0]\n"
 748         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 6
 754 
 755         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 756         "ADD    R0, R0, #4\n"
 757         "STR    R1, [R0]\n"
 758         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 759         "ADD    R0, R0, #4\n"
 760         "STR    R1, [R0]\n"
 761         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 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" // region 7
 767 
 768         "MRC    p15, 0, R1,c6,c1,0\n" // MPU region base register
 769         "ADD    R0, R0, #4\n"
 770         "STR    R1, [R0]\n"
 771         "MRC    p15, 0, R1,c6,c1,2\n" // MPU Region Size and Enable Register
 772         "ADD    R0, R0, #4\n"
 773         "STR    R1, [R0]\n"
 774         "MRC    p15, 0, R1,c6,c1,4\n" // MPU Region Access Control Register
 775         "ADD    R0, R0, #4\n"
 776         "STR    R1, [R0]\n"
 777 
 778         "MRC    p14, 0, R1,c0,c0,0\n" // DBGDIDR
 779         "ADD    R0, R0, #4\n"
 780         "STR    R1, [R0]\n"
 781 
 782         "MRC    p14, 0, R1,c1,c0,0\n" // DBGDRAR
 783         "ADD    R0, R0, #4\n"
 784         "STR    R1, [R0]\n"
 785 
 786         "MRC    p14, 0, R1,c2,c0,0\n" // DBGDSAR
 787         "ADD    R0, R0, #4\n"
 788         "STR    R1, [R0]\n"
 789 
 790         "MRC    p14, 0, R1,c0,c1,0\n" // DBGDSCR
 791         "ADD    R0, R0, #4\n"
 792         "STR    R1, [R0]\n"
 793 
 794         //".word  0xEEF01A10\n" //"VMRS   R1, FPSID\n" // Floating Point System ID register
 795         //"ADD    R0, R0, #4\n"
 796         //"STR    R1, [R0]\n"
 797 
 798         //".word  0xEEF71A10\n" //"VMRS   R1, MVFR0\n" // Media and VFP Feature Register 0
 799         //"ADD    R0, R0, #4\n"
 800         //"STR    R1, [R0]\n"
 801 
 802         //".word  0xEEF61A10\n" //"VMRS   R1, MVFR1\n" // Media and VFP Feature Register 1
 803         //"ADD    R0, R0, #4\n"
 804         //"STR    R1, [R0]\n"
 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,"-"},
 834     {8,"Lockable unified or data entries"},
 835     {8,"Lockable instruction entries"},
 836     {8,"(zero)"},
 837     {}
 838 };
 839 
 840 const struct cpuinfo_bitfield_desc_s cpuinf_sctlr_vmsa[] = {
 841     {1,"MMU Enable"},
 842     {1,"Strict Align"},
 843     {1,"Data or Unified Cache Enable"},
 844     {1,"CP15 Barrier Enable"},
 845     {3,"- (SBO)"},
 846     {3,"- (SBZ)"},
 847     {1,"SWP/SWPB Enable"},
 848     {1,"Branch Pred Enable"},
 849     {1,"ICache Enable"},
 850     {1,"High Vector"},
 851     {1,"Round Robin"},
 852     {1,"- (SBZ)"},
 853     {1,"- (SBO)"},
 854     {1,"HA flag"},
 855     {1,"- (SBO)"},
 856     {1,"WXN (virt. ext. only)"},
 857     {1,"UWXN (virt. ext. only)"},
 858     {1,"FIQ Enable"},
 859     {2,"- (SBO)"},
 860     {1,"VE"},
 861     {1,"CPSR E"},
 862     {1,"- (SBZ)"},
 863     {1,"NMFI"},
 864     {1,"TRE"},
 865     {1,"AFE"},
 866     {1,"Thumb exceptions"},
 867     {1,"- (SBZ)"},
 868     {}
 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"},
 880     {3,"Level of coherency"},
 881     {3,"Level of unification"},
 882     {2,"(zero)"},
 883     {}
 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)" },
 907     {1,"TTBR0 walks disabled" },
 908     {1,"TTBR1 walks disabled" },
 909     {25,"(zero)" },
 910     {1,"Long descriptors" },
 911     {}
 912 };
 913 
 914 const struct cpuinfo_bitfield_desc_s cpuinf_ttbr0[] = {
 915     {1,"IRGN[1]"},
 916     {1,"Shareable" },
 917     {1,"(impl. defined)" },
 918     {2,"RGN (Outer cacheability)" },
 919     {1,"NOS (Inner shareable)" },
 920     {1,"IRGN[0]" },
 921     {25,"Table address", ttbraddr0 },
 922     {}
 923 };
 924 
 925 const struct cpuinfo_bitfield_desc_s cpuinf_ttbr1[] = {
 926     {1,"IRGN[1]"},
 927     {1,"Shareable" },
 928     {1,"(impl. defined)" },
 929     {2,"RGN (Outer cacheability)" },
 930     {1,"NOS (Inner shareable)" },
 931     {1,"IRGN[0]" },
 932     {25,"Table address", ttbraddr1 },
 933     {}
 934 };
 935 
 936 const struct cpuinfo_bitfield_desc_s cpuinf_actlr_vmsa[] = {
 937     {1,"Cache & TLB maint. broadcast" },
 938     {1,"L2 prefetch enable" },
 939     {1,"L1 prefetch enable" },
 940     {1,"Write full line of zeroes" },
 941     {2,"(zero)"},
 942     {1,"SMP" },
 943     {1,"Exclusive cache" },
 944     {1,"Alloc in one way" },
 945     {1,"Parity on" },
 946     {22,"-"},
 947     {}
 948 };
 949 
 950 const struct cpuinfo_bitfield_desc_s cpuinf_cpacr_vmsa[] = {
 951     {20,"(zero)"},
 952     {2,"CP10 access permission" },
 953     {2,"CP11 access permission" },
 954     {6,"(zero)"},
 955     {1,"D32DIS" },
 956     {1,"ASEDIS" },
 957     {}
 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     //{"ATCM region reg", cpuinf_tcmreg }, // not specified in Cortex A literature
 993     //{"BTCM region reg", cpuinf_tcmreg }, // not specified in Cortex A literature
 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     //{"Floating Point System ID register", cpuinf_generic },
1000     //{"Media and VFP Feature Register 0", cpuinf_generic },
1001     //{"Media and VFP Feature Register 1", cpuinf_generic },
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     {}
1008 };
1009 
1010 void __attribute__((naked,noinline)) cpuinfo_get_info_vmsa(unsigned *results) {
1011     asm (
1012         ".syntax unified\n"
1013         ".code 16\n"
1014         ".align 2\n"
1015         "BX      PC\n"                  // switch to ARM mode
1016         ".code 32\n"
1017 
1018         "MRC    p15, 0, R1,c0,c0\n" // ident
1019         "STR    R1, [R0]\n"
1020 
1021         "MRC    p15, 0, R1,c0,c0,1\n" // CTR, cache
1022         "ADD    R0, R0, #4\n"
1023         "STR    R1, [R0]\n"
1024 
1025         "MRC    p15, 0, R1,c0,c0,2\n" // TCMTR, TCM
1026         "ADD    R0, R0, #4\n"
1027         "STR    R1, [R0]\n"
1028 
1029         "MRC    p15, 0, R1,c0,c0,3\n" // TLBTR
1030         "ADD    R0, R0, #4\n"
1031         "STR    R1, [R0]\n"
1032 
1033         "MRC    p15, 0, R1,c2,c0,2\n" // TTBCR
1034         "ADD    R0, R0, #4\n"
1035         "STR    R1, [R0]\n"
1036 
1037         "MRC    p15, 0, R1,c2,c0,0\n" // TTBR0
1038         "ADD    R0, R0, #4\n"
1039         "STR    R1, [R0]\n"
1040 
1041         "MRC    p15, 0, R1,c2,c0,1\n" // TTBR1
1042         "ADD    R0, R0, #4\n"
1043         "STR    R1, [R0]\n"
1044 
1045         "MRC    p15, 0, R1,c0,c0,5\n" // MPIDR
1046         "ADD    R0, R0, #4\n"
1047         "STR    R1, [R0]\n"
1048 
1049         "MRC    p15, 0, R1,c0,c0,6\n" // REVIDR
1050         "ADD    R0, R0, #4\n"
1051         "STR    R1, [R0]\n"
1052 
1053         "MRC    p15, 0, R1,c0,c1,0\n" // ID_PFR0
1054         "ADD    R0, R0, #4\n"
1055         "STR    R1, [R0]\n"
1056 
1057         "MRC    p15, 0, R1,c0,c1,1\n" // ID_PFR1
1058         "ADD    R0, R0, #4\n"
1059         "STR    R1, [R0]\n"
1060 
1061         "MRC    p15, 0, R1,c0,c1,2\n" // ID_DFR0
1062         "ADD    R0, R0, #4\n"
1063         "STR    R1, [R0]\n"
1064 
1065         "MRC    p15, 0, R1,c0,c1,3\n" // ID_AFR0
1066         "ADD    R0, R0, #4\n"
1067         "STR    R1, [R0]\n"
1068 
1069         "MRC    p15, 0, R1,c0,c1,4\n" // ID_MMFR0
1070         "ADD    R0, R0, #4\n"
1071         "STR    R1, [R0]\n"
1072 
1073         "MRC    p15, 0, R1,c0,c1,5\n" // ID_MMFR1
1074         "ADD    R0, R0, #4\n"
1075         "STR    R1, [R0]\n"
1076 
1077         "MRC    p15, 0, R1,c0,c1,6\n" // ID_MMFR2
1078         "ADD    R0, R0, #4\n"
1079         "STR    R1, [R0]\n"
1080 
1081         "MRC    p15, 0, R1,c0,c1,7\n" // ID_MMFR3
1082         "ADD    R0, R0, #4\n"
1083         "STR    R1, [R0]\n"
1084 
1085         "MRC    p15, 0, R1,c0,c2,0\n" // ID_ISAR0
1086         "ADD    R0, R0, #4\n"
1087         "STR    R1, [R0]\n"
1088 
1089         "MRC    p15, 0, R1,c0,c2,1\n" // ID_ISAR1
1090         "ADD    R0, R0, #4\n"
1091         "STR    R1, [R0]\n"
1092 
1093         "MRC    p15, 0, R1,c0,c2,2\n" // ID_ISAR2
1094         "ADD    R0, R0, #4\n"
1095         "STR    R1, [R0]\n"
1096 
1097         "MRC    p15, 0, R1,c0,c2,3\n" // ID_ISAR3
1098         "ADD    R0, R0, #4\n"
1099         "STR    R1, [R0]\n"
1100 
1101         "MRC    p15, 0, R1,c0,c2,4\n" // ID_ISAR4
1102         "ADD    R0, R0, #4\n"
1103         "STR    R1, [R0]\n"
1104 
1105         "MRC    p15, 0, R1,c0,c2,5\n" // ID_ISAR5
1106         "ADD    R0, R0, #4\n"
1107         "STR    R1, [R0]\n"
1108 
1109         "MRC    p15, 1, R1,c0,c0,1\n" // CLIDR
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" // CSSELR (data cache, level0)
1115 
1116         "MRC    p15, 1, R1,c0,c0,0\n" // CCSIDR (the currently selected one)
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" // CSSELR (inst cache, level0)
1122 
1123         "MRC    p15, 1, R1,c0,c0,0\n" // CCSIDR (the currently selected one)
1124         "ADD    R0, R0, #4\n"
1125         "STR    R1, [R0]\n"
1126 
1127         "MRC    p15, 0, R1,c1,c0,0\n" // SCTLR
1128         "ADD    R0, R0, #4\n"
1129         "STR    R1, [R0]\n"
1130 
1131         "MRC    p15, 0, R1,c1,c0,1\n" // ACTLR
1132         "ADD    R0, R0, #4\n"
1133         "STR    R1, [R0]\n"
1134 
1135 //#ifndef CONFIG_QEMU
1136         "MRC    p15, 0, R1,c15,c0,0\n" // ACTLR2
1137         "ADD    R0, R0, #4\n"
1138         "STR    R1, [R0]\n"
1139 //#endif
1140 
1141         "MRC    p15, 0, R1,c1,c0,2\n" // CPACR
1142         "ADD    R0, R0, #4\n"
1143         "STR    R1, [R0]\n"
1144 
1145         //"MRC    p15, 0, R1,c9,c1,1\n" // ATCM region reg, Cortex R4
1146         //"ADD    R0, R0, #4\n"
1147         //"STR    R1, [R0]\n"
1148 
1149         //"MRC    p15, 0, R1,c9,c1,0\n" // BTCM region reg, Cortex R4
1150         //"ADD    R0, R0, #4\n"
1151         //"STR    R1, [R0]\n"
1152 
1153         "MRC    p15, 0, R1,c1,c1,2\n" // NSACR
1154         "ADD    R0, R0, #4\n"
1155         "STR    R1, [R0]\n"
1156 
1157         "MRC    p15, 0, R1,c3,c0,0\n" // DACR
1158         "ADD    R0, R0, #4\n"
1159         "STR    R1, [R0]\n"
1160 
1161         "MRC    p14, 0, R1,c0,c0,0\n" // DBGDIDR
1162         "ADD    R0, R0, #4\n"
1163         "STR    R1, [R0]\n"
1164 
1165         "MRC    p14, 0, R1,c1,c0,0\n" // DBGDRAR
1166         "ADD    R0, R0, #4\n"
1167         "STR    R1, [R0]\n"
1168 
1169         "MRC    p14, 0, R1,c2,c0,0\n" // DBGDSAR
1170         "ADD    R0, R0, #4\n"
1171         "STR    R1, [R0]\n"
1172 
1173         "MRC    p14, 0, R1,c0,c1,0\n" // DBGDSCR
1174         "ADD    R0, R0, #4\n"
1175         "STR    R1, [R0]\n"
1176 
1177         //".word  0xEEF01A10\n" //"VMRS   R1, FPSID\n" // Floating Point System ID register
1178         //"ADD    R0, R0, #4\n"
1179         //"STR    R1, [R0]\n"
1180 
1181         //".word  0xEEF71A10\n" //"VMRS   R1, MVFR0\n" // Media and VFP Feature Register 0
1182         //"ADD    R0, R0, #4\n"
1183         //"STR    R1, [R0]\n"
1184 
1185         //".word  0xEEF61A10\n" //"VMRS   R1, MVFR1\n" // Media and VFP Feature Register 1
1186         //"ADD    R0, R0, #4\n"
1187         //"STR    R1, [R0]\n"
1188 
1189         "MRC    p15, 4, R1,c15,c0,0\n" // config base addr reg (Cortex A9)
1190         "ADD    R0, R0, #4\n"
1191         "STR    R1, [R0]\n"
1192 
1193         "MRC    p15, 0, R1,c11,c0,0\n" // PLEIDR (Cortex A9)
1194         "ADD    R0, R0, #4\n"
1195         "STR    R1, [R0]\n"
1196 
1197         "MRC    p15, 0, R1,c10,c0,0\n" // TLB lockdown reg (Cortex A9)
1198         "ADD    R0, R0, #4\n"
1199         "STR    R1, [R0]\n"
1200 
1201         "MRC    p15, 0, R1,c10,c2,0\n" // PRRR (Cortex A9)
1202         "ADD    R0, R0, #4\n"
1203         "STR    R1, [R0]\n"
1204 
1205         "MRC    p15, 0, R1,c10,c2,1\n" // NMRR (Cortex A9)
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" // ID_MMFR0
1219         "AND    R0, #15\n"
1220         "BX     LR\n"
1221         :::"r0"
1222         );
1223     return 0; // unreachable
1224 }
1225 
1226 void __attribute__((naked,noinline)) get_mmuregs_vmsa(void *p) {
1227     asm (
1228         ".syntax unified\n"
1229         "MRC    p15, 0, R1,c2,c0,0\n" // TTBR0
1230         "STR    R1, [R0]\n"
1231         "MRC    p15, 0, R1,c2,c0,1\n" // TTBR1
1232         "ADD    R0, R0, #4\n"
1233         "STR    R1, [R0]\n"
1234         "MRC    p15, 0, R1,c2,c0,2\n" // TTBCR
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); // rearrange bits for evaluation below
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); // virtual address to be described by L1 entry
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) { // supersection begins
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) { // interpret L2 table
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); // virtual address to be described by L2 entry
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) { // large page begins
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 

/* [<][>][^][v][top][bottom][index][help] */