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