cpu.c revision 1.136
1/* $NetBSD: cpu.c,v 1.136 2019/12/20 21:05:33 ad Exp $ */ 2 3/* 4 * Copyright (c) 1995 Mark Brinicombe. 5 * Copyright (c) 1995 Brini. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Brini. 19 * 4. The name of the company nor the name of the author may be used to 20 * endorse or promote products derived from this software without specific 21 * prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * RiscBSD kernel project 36 * 37 * cpu.c 38 * 39 * Probing and configuration for the master CPU 40 * 41 * Created : 10/10/95 42 */ 43 44#include "opt_armfpe.h" 45#include "opt_cputypes.h" 46#include "opt_multiprocessor.h" 47 48#include <sys/cdefs.h> 49__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.136 2019/12/20 21:05:33 ad Exp $"); 50 51#include <sys/param.h> 52#include <sys/conf.h> 53#include <sys/cpu.h> 54#include <sys/device.h> 55#include <sys/kmem.h> 56#include <sys/proc.h> 57#include <sys/systm.h> 58 59#include <uvm/uvm_extern.h> 60 61#include <arm/locore.h> 62#include <arm/undefined.h> 63 64extern const char *cpu_arch; 65 66#ifdef MULTIPROCESSOR 67uint32_t cpu_mpidr[MAXCPUS] = { 68 [0 ... MAXCPUS - 1] = ~0, 69}; 70 71volatile u_int arm_cpu_hatched __cacheline_aligned = 0; 72volatile uint32_t arm_cpu_mbox __cacheline_aligned = 0; 73u_int arm_cpu_max = 1; 74 75#ifdef MPDEBUG 76uint32_t arm_cpu_marker[2] __cacheline_aligned = { 0, 0 }; 77#endif 78 79#endif 80 81/* Prototypes */ 82void identify_arm_cpu(device_t, struct cpu_info *); 83void identify_cortex_caches(device_t); 84void identify_features(device_t); 85 86/* 87 * Identify the master (boot) CPU 88 */ 89 90void 91cpu_attach(device_t dv, cpuid_t id) 92{ 93 const char * const xname = device_xname(dv); 94 const int unit = device_unit(dv); 95 struct cpu_info *ci; 96 97 if (unit == 0) { 98 ci = curcpu(); 99 100 /* Read SCTLR from cpu */ 101 ci->ci_ctrl = cpu_control(0, 0); 102 103 /* Get the CPU ID from coprocessor 15 */ 104 105 ci->ci_cpuid = id; 106 ci->ci_arm_cpuid = cpu_idnum(); 107 ci->ci_arm_cputype = ci->ci_arm_cpuid & CPU_ID_CPU_MASK; 108 ci->ci_arm_cpurev = ci->ci_arm_cpuid & CPU_ID_REVISION_MASK; 109#ifdef MULTIPROCESSOR 110 uint32_t mpidr = armreg_mpidr_read(); 111 ci->ci_mpidr = mpidr; 112 113 if (mpidr & MPIDR_MT) { 114 cpu_topology_set(ci, 115 __SHIFTOUT(mpidr, MPIDR_AFF2), 116 __SHIFTOUT(mpidr, MPIDR_AFF1), 117 __SHIFTOUT(mpidr, MPIDR_AFF0), 118 0); 119 } else { 120 cpu_topology_set(ci, 121 __SHIFTOUT(mpidr, MPIDR_AFF1), 122 __SHIFTOUT(mpidr, MPIDR_AFF0), 123 0, 124 0); 125 } 126#endif 127 } else { 128#ifdef MULTIPROCESSOR 129 KASSERT(cpu_info[unit] == NULL); 130 ci = kmem_zalloc(sizeof(*ci), KM_SLEEP); 131 ci->ci_cpl = IPL_HIGH; 132 ci->ci_cpuid = id; 133 ci->ci_data.cpu_cc_freq = cpu_info_store.ci_data.cpu_cc_freq; 134 135 ci->ci_undefsave[2] = cpu_info_store.ci_undefsave[2]; 136 137 cpu_info[unit] = ci; 138 if (cpu_hatched_p(unit) == false) { 139 ci->ci_dev = dv; 140 dv->dv_private = ci; 141 aprint_naive(": disabled\n"); 142 aprint_normal(": disabled (unresponsive)\n"); 143 return; 144 } 145#else 146 aprint_naive(": disabled\n"); 147 aprint_normal(": disabled (uniprocessor kernel)\n"); 148 return; 149#endif 150 } 151 152 ci->ci_dev = dv; 153 dv->dv_private = ci; 154 155 evcnt_attach_dynamic(&ci->ci_arm700bugcount, EVCNT_TYPE_MISC, 156 NULL, xname, "arm700swibug"); 157 158 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_WRTBUF_0], EVCNT_TYPE_TRAP, 159 NULL, xname, "vector abort"); 160 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_WRTBUF_1], EVCNT_TYPE_TRAP, 161 NULL, xname, "terminal abort"); 162 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_0], EVCNT_TYPE_TRAP, 163 NULL, xname, "external linefetch abort (S)"); 164 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_1], EVCNT_TYPE_TRAP, 165 NULL, xname, "external linefetch abort (P)"); 166 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_2], EVCNT_TYPE_TRAP, 167 NULL, xname, "external non-linefetch abort (S)"); 168 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_3], EVCNT_TYPE_TRAP, 169 NULL, xname, "external non-linefetch abort (P)"); 170 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSTRNL1], EVCNT_TYPE_TRAP, 171 NULL, xname, "external translation abort (L1)"); 172 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSTRNL2], EVCNT_TYPE_TRAP, 173 NULL, xname, "external translation abort (L2)"); 174 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_ALIGN_0], EVCNT_TYPE_TRAP, 175 NULL, xname, "alignment abort (0)"); 176 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_ALIGN_1], EVCNT_TYPE_TRAP, 177 NULL, xname, "alignment abort (1)"); 178 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_TRANS_S], EVCNT_TYPE_TRAP, 179 NULL, xname, "translation abort (S)"); 180 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_TRANS_P], EVCNT_TYPE_TRAP, 181 NULL, xname, "translation abort (P)"); 182 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_DOMAIN_S], EVCNT_TYPE_TRAP, 183 NULL, xname, "domain abort (S)"); 184 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_DOMAIN_P], EVCNT_TYPE_TRAP, 185 NULL, xname, "domain abort (P)"); 186 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_PERM_S], EVCNT_TYPE_TRAP, 187 NULL, xname, "permission abort (S)"); 188 evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_PERM_P], EVCNT_TYPE_TRAP, 189 NULL, xname, "permission abort (P)"); 190 evcnt_attach_dynamic_nozero(&ci->ci_und_ev, EVCNT_TYPE_TRAP, 191 NULL, xname, "undefined insn traps"); 192 evcnt_attach_dynamic_nozero(&ci->ci_und_cp15_ev, EVCNT_TYPE_TRAP, 193 NULL, xname, "undefined cp15 insn traps"); 194 195#ifdef MULTIPROCESSOR 196 /* 197 * and we are done if this is a secondary processor. 198 */ 199 if (unit != 0) { 200 aprint_naive("\n"); 201 aprint_normal("\n"); 202 mi_cpu_attach(ci); 203#ifdef ARM_MMU_EXTENDED 204 pmap_tlb_info_attach(&pmap_tlb0_info, ci); 205#endif 206 return; 207 } 208#endif 209 210 identify_arm_cpu(dv, ci); 211 212#ifdef CPU_STRONGARM 213 if (ci->ci_arm_cputype == CPU_ID_SA110 && 214 ci->ci_arm_cpurev < 3) { 215 aprint_normal_dev(dv, "SA-110 with bugged STM^ instruction\n"); 216 } 217#endif 218 219#ifdef CPU_ARM8 220 if ((ci->ci_arm_cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM810) { 221 int clock = arm8_clock_config(0, 0); 222 char *fclk; 223 aprint_normal_dev(dv, "ARM810 cp15=%02x", clock); 224 aprint_normal(" clock:%s", (clock & 1) ? " dynamic" : ""); 225 aprint_normal("%s", (clock & 2) ? " sync" : ""); 226 switch ((clock >> 2) & 3) { 227 case 0: 228 fclk = "bus clock"; 229 break; 230 case 1: 231 fclk = "ref clock"; 232 break; 233 case 3: 234 fclk = "pll"; 235 break; 236 default: 237 fclk = "illegal"; 238 break; 239 } 240 aprint_normal(" fclk source=%s\n", fclk); 241 } 242#endif 243 244 vfp_attach(ci); /* XXX SMP */ 245} 246 247#ifdef MULTIPROCESSOR 248bool 249cpu_hatched_p(u_int cpuindex) 250{ 251 membar_consumer(); 252 return (arm_cpu_hatched & __BIT(cpuindex)) != 0; 253} 254#endif 255 256enum cpu_class { 257 CPU_CLASS_NONE, 258 CPU_CLASS_ARM2, 259 CPU_CLASS_ARM2AS, 260 CPU_CLASS_ARM3, 261 CPU_CLASS_ARM6, 262 CPU_CLASS_ARM7, 263 CPU_CLASS_ARM7TDMI, 264 CPU_CLASS_ARM8, 265 CPU_CLASS_ARM9TDMI, 266 CPU_CLASS_ARM9ES, 267 CPU_CLASS_ARM9EJS, 268 CPU_CLASS_ARM10E, 269 CPU_CLASS_ARM10EJ, 270 CPU_CLASS_SA1, 271 CPU_CLASS_XSCALE, 272 CPU_CLASS_ARM11J, 273 CPU_CLASS_ARMV4, 274 CPU_CLASS_CORTEX, 275 CPU_CLASS_PJ4B, 276}; 277 278static const char * const generic_steppings[16] = { 279 "rev 0", "rev 1", "rev 2", "rev 3", 280 "rev 4", "rev 5", "rev 6", "rev 7", 281 "rev 8", "rev 9", "rev 10", "rev 11", 282 "rev 12", "rev 13", "rev 14", "rev 15", 283}; 284 285static const char * const pN_steppings[16] = { 286 "*p0", "*p1", "*p2", "*p3", "*p4", "*p5", "*p6", "*p7", 287 "*p8", "*p9", "*p10", "*p11", "*p12", "*p13", "*p14", "*p15", 288}; 289 290static const char * const sa110_steppings[16] = { 291 "rev 0", "step J", "step K", "step S", 292 "step T", "rev 5", "rev 6", "rev 7", 293 "rev 8", "rev 9", "rev 10", "rev 11", 294 "rev 12", "rev 13", "rev 14", "rev 15", 295}; 296 297static const char * const sa1100_steppings[16] = { 298 "rev 0", "step B", "step C", "rev 3", 299 "rev 4", "rev 5", "rev 6", "rev 7", 300 "step D", "step E", "rev 10" "step G", 301 "rev 12", "rev 13", "rev 14", "rev 15", 302}; 303 304static const char * const sa1110_steppings[16] = { 305 "step A-0", "rev 1", "rev 2", "rev 3", 306 "step B-0", "step B-1", "step B-2", "step B-3", 307 "step B-4", "step B-5", "rev 10", "rev 11", 308 "rev 12", "rev 13", "rev 14", "rev 15", 309}; 310 311static const char * const ixp12x0_steppings[16] = { 312 "(IXP1200 step A)", "(IXP1200 step B)", 313 "rev 2", "(IXP1200 step C)", 314 "(IXP1200 step D)", "(IXP1240/1250 step A)", 315 "(IXP1240 step B)", "(IXP1250 step B)", 316 "rev 8", "rev 9", "rev 10", "rev 11", 317 "rev 12", "rev 13", "rev 14", "rev 15", 318}; 319 320static const char * const xscale_steppings[16] = { 321 "step A-0", "step A-1", "step B-0", "step C-0", 322 "step D-0", "rev 5", "rev 6", "rev 7", 323 "rev 8", "rev 9", "rev 10", "rev 11", 324 "rev 12", "rev 13", "rev 14", "rev 15", 325}; 326 327static const char * const i80321_steppings[16] = { 328 "step A-0", "step B-0", "rev 2", "rev 3", 329 "rev 4", "rev 5", "rev 6", "rev 7", 330 "rev 8", "rev 9", "rev 10", "rev 11", 331 "rev 12", "rev 13", "rev 14", "rev 15", 332}; 333 334static const char * const i80219_steppings[16] = { 335 "step A-0", "rev 1", "rev 2", "rev 3", 336 "rev 4", "rev 5", "rev 6", "rev 7", 337 "rev 8", "rev 9", "rev 10", "rev 11", 338 "rev 12", "rev 13", "rev 14", "rev 15", 339}; 340 341/* Steppings for PXA2[15]0 */ 342static const char * const pxa2x0_steppings[16] = { 343 "step A-0", "step A-1", "step B-0", "step B-1", 344 "step B-2", "step C-0", "rev 6", "rev 7", 345 "rev 8", "rev 9", "rev 10", "rev 11", 346 "rev 12", "rev 13", "rev 14", "rev 15", 347}; 348 349/* Steppings for PXA255/26x. 350 * rev 5: PXA26x B0, rev 6: PXA255 A0 351 */ 352static const char * const pxa255_steppings[16] = { 353 "rev 0", "rev 1", "rev 2", "step A-0", 354 "rev 4", "step B-0", "step A-0", "rev 7", 355 "rev 8", "rev 9", "rev 10", "rev 11", 356 "rev 12", "rev 13", "rev 14", "rev 15", 357}; 358 359/* Stepping for PXA27x */ 360static const char * const pxa27x_steppings[16] = { 361 "step A-0", "step A-1", "step B-0", "step B-1", 362 "step C-0", "rev 5", "rev 6", "rev 7", 363 "rev 8", "rev 9", "rev 10", "rev 11", 364 "rev 12", "rev 13", "rev 14", "rev 15", 365}; 366 367static const char * const ixp425_steppings[16] = { 368 "step 0", "rev 1", "rev 2", "rev 3", 369 "rev 4", "rev 5", "rev 6", "rev 7", 370 "rev 8", "rev 9", "rev 10", "rev 11", 371 "rev 12", "rev 13", "rev 14", "rev 15", 372}; 373 374struct cpuidtab { 375 uint32_t cpuid; 376 enum cpu_class cpu_class; 377 const char *cpu_classname; 378 const char * const *cpu_steppings; 379 char cpu_arch[8]; 380}; 381 382const struct cpuidtab cpuids[] = { 383 { CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2", 384 generic_steppings, "2" }, 385 { CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250", 386 generic_steppings, "2" }, 387 388 { CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3", 389 generic_steppings, "2A" }, 390 391 { CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600", 392 generic_steppings, "3" }, 393 { CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610", 394 generic_steppings, "3" }, 395 { CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620", 396 generic_steppings, "3" }, 397 398 { CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700", 399 generic_steppings, "3" }, 400 { CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710", 401 generic_steppings, "3" }, 402 { CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500", 403 generic_steppings, "3" }, 404 { CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a", 405 generic_steppings, "3" }, 406 { CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE", 407 generic_steppings, "3" }, 408 409 { CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810", 410 generic_steppings, "4" }, 411 412 { CPU_ID_SA110, CPU_CLASS_SA1, "SA-110", 413 sa110_steppings, "4" }, 414 { CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100", 415 sa1100_steppings, "4" }, 416 { CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110", 417 sa1110_steppings, "4" }, 418 419 { CPU_ID_FA526, CPU_CLASS_ARMV4, "FA526", 420 generic_steppings, "4" }, 421 422 { CPU_ID_IXP1200, CPU_CLASS_SA1, "IXP1200", 423 ixp12x0_steppings, "4" }, 424 425 { CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T", 426 generic_steppings, "4T" }, 427 { CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T", 428 generic_steppings, "4T" }, 429 { CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)", 430 generic_steppings, "4T" }, 431 { CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)", 432 generic_steppings, "4T" }, 433 { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T", 434 generic_steppings, "4T" }, 435 { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T", 436 generic_steppings, "4T" }, 437 { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T", 438 generic_steppings, "4T" }, 439 { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T", 440 generic_steppings, "4T" }, 441 442 { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S", 443 generic_steppings, "5TE" }, 444 { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S", 445 generic_steppings, "5TE" }, 446 { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S", 447 generic_steppings, "5TE" }, 448 { CPU_ID_MV88SV131, CPU_CLASS_ARM9ES, "Sheeva 88SV131", 449 generic_steppings, "5TE" }, 450 { CPU_ID_MV88FR571_VD, CPU_CLASS_ARM9ES, "Sheeva 88FR571-vd", 451 generic_steppings, "5TE" }, 452 453 { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200", 454 xscale_steppings, "5TE" }, 455 456 { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz", 457 i80321_steppings, "5TE" }, 458 { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz", 459 i80321_steppings, "5TE" }, 460 { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz", 461 i80321_steppings, "5TE" }, 462 { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz", 463 i80321_steppings, "5TE" }, 464 465 { CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz", 466 i80219_steppings, "5TE" }, 467 { CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz", 468 i80219_steppings, "5TE" }, 469 470 { CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x", 471 pxa27x_steppings, "5TE" }, 472 { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250", 473 pxa2x0_steppings, "5TE" }, 474 { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210", 475 pxa2x0_steppings, "5TE" }, 476 { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250", 477 pxa2x0_steppings, "5TE" }, 478 { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210", 479 pxa2x0_steppings, "5TE" }, 480 { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255/26x", 481 pxa255_steppings, "5TE" }, 482 { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210", 483 pxa2x0_steppings, "5TE" }, 484 485 { CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz", 486 ixp425_steppings, "5TE" }, 487 { CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz", 488 ixp425_steppings, "5TE" }, 489 { CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz", 490 ixp425_steppings, "5TE" }, 491 492 { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E", 493 generic_steppings, "5TE" }, 494 { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S", 495 generic_steppings, "5TE" }, 496 497 { CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S", 498 generic_steppings, "5TEJ" }, 499 { CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S", 500 generic_steppings, "5TEJ" }, 501 502 { CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S r0", 503 pN_steppings, "6J" }, 504 { CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S r1", 505 pN_steppings, "6J" }, 506#if 0 507 /* The ARM1156T2-S only has a memory protection unit */ 508 { CPU_ID_ARM1156T2S, CPU_CLASS_ARM11J, "ARM1156T2-S r0", 509 pN_steppings, "6T2" }, 510#endif 511 { CPU_ID_ARM1176JZS, CPU_CLASS_ARM11J, "ARM1176JZ-S r0", 512 pN_steppings, "6ZK" }, 513 514 { CPU_ID_ARM11MPCORE, CPU_CLASS_ARM11J, "ARM11 MPCore", 515 generic_steppings, "6K" }, 516 517 { CPU_ID_CORTEXA5R0, CPU_CLASS_CORTEX, "Cortex-A5 r0", 518 pN_steppings, "7A" }, 519 { CPU_ID_CORTEXA7R0, CPU_CLASS_CORTEX, "Cortex-A7 r0", 520 pN_steppings, "7A" }, 521 { CPU_ID_CORTEXA8R1, CPU_CLASS_CORTEX, "Cortex-A8 r1", 522 pN_steppings, "7A" }, 523 { CPU_ID_CORTEXA8R2, CPU_CLASS_CORTEX, "Cortex-A8 r2", 524 pN_steppings, "7A" }, 525 { CPU_ID_CORTEXA8R3, CPU_CLASS_CORTEX, "Cortex-A8 r3", 526 pN_steppings, "7A" }, 527 { CPU_ID_CORTEXA9R1, CPU_CLASS_CORTEX, "Cortex-A9 r1", 528 pN_steppings, "7A" }, 529 { CPU_ID_CORTEXA9R2, CPU_CLASS_CORTEX, "Cortex-A9 r2", 530 pN_steppings, "7A" }, 531 { CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEX, "Cortex-A9 r3", 532 pN_steppings, "7A" }, 533 { CPU_ID_CORTEXA9R4, CPU_CLASS_CORTEX, "Cortex-A9 r4", 534 pN_steppings, "7A" }, 535 { CPU_ID_CORTEXA12R0, CPU_CLASS_CORTEX, "Cortex-A17(A12) r0", /* A12 was rebranded A17 */ 536 pN_steppings, "7A" }, 537 { CPU_ID_CORTEXA15R2, CPU_CLASS_CORTEX, "Cortex-A15 r2", 538 pN_steppings, "7A" }, 539 { CPU_ID_CORTEXA15R3, CPU_CLASS_CORTEX, "Cortex-A15 r3", 540 pN_steppings, "7A" }, 541 { CPU_ID_CORTEXA15R4, CPU_CLASS_CORTEX, "Cortex-A15 r4", 542 pN_steppings, "7A" }, 543 { CPU_ID_CORTEXA17R1, CPU_CLASS_CORTEX, "Cortex-A17 r1", 544 pN_steppings, "7A" }, 545 { CPU_ID_CORTEXA35R0, CPU_CLASS_CORTEX, "Cortex-A35 r0", 546 pN_steppings, "8A" }, 547 { CPU_ID_CORTEXA53R0, CPU_CLASS_CORTEX, "Cortex-A53 r0", 548 pN_steppings, "8A" }, 549 { CPU_ID_CORTEXA57R0, CPU_CLASS_CORTEX, "Cortex-A57 r0", 550 pN_steppings, "8A" }, 551 { CPU_ID_CORTEXA57R1, CPU_CLASS_CORTEX, "Cortex-A57 r1", 552 pN_steppings, "8A" }, 553 { CPU_ID_CORTEXA72R0, CPU_CLASS_CORTEX, "Cortex-A72 r0", 554 pN_steppings, "8A" }, 555 556 { CPU_ID_MV88SV581X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV581x", 557 generic_steppings }, 558 { CPU_ID_ARM_88SV581X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV581x", 559 generic_steppings }, 560 { CPU_ID_MV88SV581X_V7, CPU_CLASS_PJ4B, "Sheeva 88SV581x", 561 generic_steppings }, 562 { CPU_ID_ARM_88SV581X_V7, CPU_CLASS_PJ4B, "Sheeva 88SV581x", 563 generic_steppings }, 564 { CPU_ID_MV88SV584X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV584x", 565 generic_steppings }, 566 { CPU_ID_ARM_88SV584X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV584x", 567 generic_steppings }, 568 { CPU_ID_MV88SV584X_V7, CPU_CLASS_PJ4B, "Sheeva 88SV584x", 569 generic_steppings }, 570 571 572 { 0, CPU_CLASS_NONE, NULL, NULL, "" } 573}; 574 575struct cpu_classtab { 576 const char *class_name; 577 const char *class_option; 578}; 579 580const struct cpu_classtab cpu_classes[] = { 581 [CPU_CLASS_NONE] = { "unknown", NULL }, 582 [CPU_CLASS_ARM2] = { "ARM2", "CPU_ARM2" }, 583 [CPU_CLASS_ARM2AS] = { "ARM2as", "CPU_ARM250" }, 584 [CPU_CLASS_ARM3] = { "ARM3", "CPU_ARM3" }, 585 [CPU_CLASS_ARM6] = { "ARM6", "CPU_ARM6" }, 586 [CPU_CLASS_ARM7] = { "ARM7", "CPU_ARM7" }, 587 [CPU_CLASS_ARM7TDMI] = { "ARM7TDMI", "CPU_ARM7TDMI" }, 588 [CPU_CLASS_ARM8] = { "ARM8", "CPU_ARM8" }, 589 [CPU_CLASS_ARM9TDMI] = { "ARM9TDMI", NULL }, 590 [CPU_CLASS_ARM9ES] = { "ARM9E-S", "CPU_ARM9E" }, 591 [CPU_CLASS_ARM9EJS] = { "ARM9EJ-S", "CPU_ARM9E" }, 592 [CPU_CLASS_ARM10E] = { "ARM10E", "CPU_ARM10" }, 593 [CPU_CLASS_ARM10EJ] = { "ARM10EJ", "CPU_ARM10" }, 594 [CPU_CLASS_SA1] = { "SA-1", "CPU_SA110" }, 595 [CPU_CLASS_XSCALE] = { "XScale", "CPU_XSCALE_..." }, 596 [CPU_CLASS_ARM11J] = { "ARM11J", "CPU_ARM11" }, 597 [CPU_CLASS_ARMV4] = { "ARMv4", "CPU_ARMV4" }, 598 [CPU_CLASS_CORTEX] = { "Cortex", "CPU_CORTEX" }, 599 [CPU_CLASS_PJ4B] = { "Marvell", "CPU_PJ4B" }, 600}; 601 602/* 603 * Report the type of the specified arm processor. This uses the generic and 604 * arm specific information in the CPU structure to identify the processor. 605 * The remaining fields in the CPU structure are filled in appropriately. 606 */ 607 608static const char * const wtnames[] = { 609 "write-through", 610 "write-back", 611 "write-back", 612 "**unknown 3**", 613 "**unknown 4**", 614 "write-back-locking", /* XXX XScale-specific? */ 615 "write-back-locking-A", 616 "write-back-locking-B", 617 "**unknown 8**", 618 "**unknown 9**", 619 "**unknown 10**", 620 "**unknown 11**", 621 "write-back", 622 "write-back-locking-line", 623 "write-back-locking-C", 624 "write-back-locking-D", 625}; 626 627static void 628print_cache_info(device_t dv, struct arm_cache_info *info, u_int level) 629{ 630 if (info->cache_unified) { 631 aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Unified cache\n", 632 info->dcache_size / 1024, 633 info->dcache_line_size, info->dcache_ways, 634 wtnames[info->cache_type], level + 1, 635 info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V', 636 info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V'); 637 } else { 638 aprint_normal_dev(dv, "%dKB/%dB %d-way L%u %cI%cT Instruction cache\n", 639 info->icache_size / 1024, 640 info->icache_line_size, info->icache_ways, level + 1, 641 info->icache_type & CACHE_TYPE_PIxx ? 'P' : 'V', 642 info->icache_type & CACHE_TYPE_xxPT ? 'P' : 'V'); 643 aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Data cache\n", 644 info->dcache_size / 1024, 645 info->dcache_line_size, info->dcache_ways, 646 wtnames[info->cache_type], level + 1, 647 info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V', 648 info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V'); 649 } 650} 651 652static enum cpu_class 653identify_arm_model(uint32_t cpuid, char *buf, size_t len) 654{ 655 enum cpu_class cpu_class = CPU_CLASS_NONE; 656 for (const struct cpuidtab *id = cpuids; id->cpuid != 0; id++) { 657 if (id->cpuid == (cpuid & CPU_ID_CPU_MASK)) { 658 const char *steppingstr = 659 id->cpu_steppings[cpuid & CPU_ID_REVISION_MASK]; 660 cpu_arch = id->cpu_arch; 661 cpu_class = id->cpu_class; 662 snprintf(buf, len, "%s%s%s (%s V%s core)", 663 id->cpu_classname, 664 steppingstr[0] == '*' ? "" : " ", 665 &steppingstr[steppingstr[0] == '*'], 666 cpu_classes[cpu_class].class_name, 667 cpu_arch); 668 return cpu_class; 669 } 670 } 671 672 snprintf(buf, len, "unknown CPU (ID = 0x%x)", cpuid); 673 return cpu_class; 674} 675 676void 677identify_arm_cpu(device_t dv, struct cpu_info *ci) 678{ 679 const uint32_t arm_cpuid = ci->ci_arm_cpuid; 680 const char * const xname = device_xname(dv); 681 char model[128]; 682 683 if (arm_cpuid == 0) { 684 aprint_error("Processor failed probe - no CPU ID\n"); 685 return; 686 } 687 688 const enum cpu_class cpu_class = identify_arm_model(arm_cpuid, 689 model, sizeof(model)); 690 if (ci->ci_cpuid == 0) { 691 cpu_setmodel("%s", model); 692 } 693 694 if (ci->ci_data.cpu_cc_freq != 0) { 695 char freqbuf[10]; 696 humanize_number(freqbuf, sizeof(freqbuf), ci->ci_data.cpu_cc_freq, 697 "Hz", 1000); 698 699 aprint_naive(": %s %s\n", freqbuf, model); 700 aprint_normal(": %s %s\n", freqbuf, model); 701 } else { 702 aprint_naive(": %s\n", model); 703 aprint_normal(": %s\n", model); 704 } 705 706 aprint_debug_dev(dv, "midr: %#x\n", arm_cpuid); 707 708 aprint_normal("%s:", xname); 709 710 switch (cpu_class) { 711 case CPU_CLASS_ARM6: 712 case CPU_CLASS_ARM7: 713 case CPU_CLASS_ARM7TDMI: 714 case CPU_CLASS_ARM8: 715 if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0) 716 aprint_normal(" IDC disabled"); 717 else 718 aprint_normal(" IDC enabled"); 719 break; 720 case CPU_CLASS_ARM9TDMI: 721 case CPU_CLASS_ARM9ES: 722 case CPU_CLASS_ARM9EJS: 723 case CPU_CLASS_ARM10E: 724 case CPU_CLASS_ARM10EJ: 725 case CPU_CLASS_SA1: 726 case CPU_CLASS_XSCALE: 727 case CPU_CLASS_ARM11J: 728 case CPU_CLASS_ARMV4: 729 case CPU_CLASS_CORTEX: 730 case CPU_CLASS_PJ4B: 731 if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0) 732 aprint_normal(" DC disabled"); 733 else 734 aprint_normal(" DC enabled"); 735 if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0) 736 aprint_normal(" IC disabled"); 737 else 738 aprint_normal(" IC enabled"); 739 break; 740 default: 741 break; 742 } 743 if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0) 744 aprint_normal(" WB disabled"); 745 else 746 aprint_normal(" WB enabled"); 747 748 if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE) 749 aprint_normal(" LABT"); 750 else 751 aprint_normal(" EABT"); 752 753 if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE) 754 aprint_normal(" branch prediction enabled"); 755 756 aprint_normal("\n"); 757 758 if (CPU_ID_CORTEX_P(arm_cpuid) || CPU_ID_ARM11_P(arm_cpuid) || CPU_ID_MV88SV58XX_P(arm_cpuid)) { 759 identify_features(dv); 760 } 761 762 /* Print cache info. */ 763 if (arm_pcache.icache_line_size != 0 || arm_pcache.dcache_line_size != 0) { 764 print_cache_info(dv, &arm_pcache, 0); 765 } 766 if (arm_scache.icache_line_size != 0 || arm_scache.dcache_line_size != 0) { 767 print_cache_info(dv, &arm_scache, 1); 768 } 769 770 771 switch (cpu_class) { 772#ifdef CPU_ARM6 773 case CPU_CLASS_ARM6: 774#endif 775#ifdef CPU_ARM7 776 case CPU_CLASS_ARM7: 777#endif 778#ifdef CPU_ARM7TDMI 779 case CPU_CLASS_ARM7TDMI: 780#endif 781#ifdef CPU_ARM8 782 case CPU_CLASS_ARM8: 783#endif 784#ifdef CPU_ARM9 785 case CPU_CLASS_ARM9TDMI: 786#endif 787#if defined(CPU_ARM9E) || defined(CPU_SHEEVA) 788 case CPU_CLASS_ARM9ES: 789 case CPU_CLASS_ARM9EJS: 790#endif 791#ifdef CPU_ARM10 792 case CPU_CLASS_ARM10E: 793 case CPU_CLASS_ARM10EJ: 794#endif 795#if defined(CPU_SA110) || defined(CPU_SA1100) || \ 796 defined(CPU_SA1110) || defined(CPU_IXP12X0) 797 case CPU_CLASS_SA1: 798#endif 799#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 800 defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425) 801 case CPU_CLASS_XSCALE: 802#endif 803#if defined(CPU_ARM11) 804 case CPU_CLASS_ARM11J: 805#endif 806#if defined(CPU_CORTEX) 807 case CPU_CLASS_CORTEX: 808#endif 809#if defined(CPU_PJ4B) 810 case CPU_CLASS_PJ4B: 811#endif 812#if defined(CPU_FA526) 813 case CPU_CLASS_ARMV4: 814#endif 815 break; 816 default: 817 if (cpu_classes[cpu_class].class_option == NULL) { 818 aprint_error_dev(dv, "%s does not fully support this CPU.\n", 819 ostype); 820 } else { 821 aprint_error_dev(dv, "This kernel does not fully support " 822 "this CPU.\n"); 823 aprint_normal_dev(dv, "Recompile with \"options %s\" to " 824 "correct this.\n", cpu_classes[cpu_class].class_option); 825 } 826 break; 827 } 828} 829 830extern int cpu_instruction_set_attributes[6]; 831extern int cpu_memory_model_features[4]; 832extern int cpu_processor_features[2]; 833extern int cpu_simd_present; 834extern int cpu_simdex_present; 835 836void 837identify_features(device_t dv) 838{ 839 cpu_instruction_set_attributes[0] = armreg_isar0_read(); 840 cpu_instruction_set_attributes[1] = armreg_isar1_read(); 841 cpu_instruction_set_attributes[2] = armreg_isar2_read(); 842 cpu_instruction_set_attributes[3] = armreg_isar3_read(); 843 cpu_instruction_set_attributes[4] = armreg_isar4_read(); 844 cpu_instruction_set_attributes[5] = armreg_isar5_read(); 845 846 cpu_hwdiv_present = 847 ((cpu_instruction_set_attributes[0] >> 24) & 0x0f) >= 2; 848 cpu_simd_present = 849 ((cpu_instruction_set_attributes[3] >> 4) & 0x0f) >= 3; 850 cpu_simdex_present = cpu_simd_present 851 && ((cpu_instruction_set_attributes[1] >> 12) & 0x0f) >= 2; 852 cpu_synchprim_present = 853 ((cpu_instruction_set_attributes[3] >> 8) & 0xf0) 854 | ((cpu_instruction_set_attributes[4] >> 20) & 0x0f); 855 856 cpu_memory_model_features[0] = armreg_mmfr0_read(); 857 cpu_memory_model_features[1] = armreg_mmfr1_read(); 858 cpu_memory_model_features[2] = armreg_mmfr2_read(); 859 cpu_memory_model_features[3] = armreg_mmfr3_read(); 860 861#if 0 862 if (__SHIFTOUT(cpu_memory_model_features[3], __BITS(23,20))) { 863 /* 864 * Updates to the translation tables do not require a clean 865 * to the point of unification to ensure visibility by 866 * subsequent translation table walks. 867 */ 868 pmap_needs_pte_sync = 0; 869 } 870#endif 871 872 cpu_processor_features[0] = armreg_pfr0_read(); 873 cpu_processor_features[1] = armreg_pfr1_read(); 874 875 aprint_debug_dev(dv, "sctlr: %#x\n", armreg_sctlr_read()); 876 aprint_debug_dev(dv, "actlr: %#x\n", armreg_auxctl_read()); 877 aprint_debug_dev(dv, "revidr: %#x\n", armreg_revidr_read()); 878#ifdef MULTIPROCESSOR 879 aprint_debug_dev(dv, "mpidr: %#x\n", armreg_mpidr_read()); 880#endif 881 aprint_debug_dev(dv, 882 "isar: [0]=%#x [1]=%#x [2]=%#x [3]=%#x, [4]=%#x, [5]=%#x\n", 883 cpu_instruction_set_attributes[0], 884 cpu_instruction_set_attributes[1], 885 cpu_instruction_set_attributes[2], 886 cpu_instruction_set_attributes[3], 887 cpu_instruction_set_attributes[4], 888 cpu_instruction_set_attributes[5]); 889 aprint_debug_dev(dv, 890 "mmfr: [0]=%#x [1]=%#x [2]=%#x [3]=%#x\n", 891 cpu_memory_model_features[0], cpu_memory_model_features[1], 892 cpu_memory_model_features[2], cpu_memory_model_features[3]); 893 aprint_debug_dev(dv, 894 "pfr: [0]=%#x [1]=%#x\n", 895 cpu_processor_features[0], cpu_processor_features[1]); 896} 897