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