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