1/* 2 * Copyright 2013, winocm. <winocm@icloud.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * Redistributions in binary form must reproduce the above copyright notice, this 12 * list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * If you are going to use this software in any form that does not involve 16 * releasing the source to this project or improving it, let me know beforehand. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/*- 30 * Copyright (c) 1995 Mark Brinicombe. 31 * Copyright (c) 1995 Brini. 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions 36 * are met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce the above copyright 40 * notice, this list of conditions and the following disclaimer in the 41 * documentation and/or other materials provided with the distribution. 42 * 3. All advertising materials mentioning features or use of this software 43 * must display the following acknowledgement: 44 * This product includes software developed by Brini. 45 * 4. The name of the company nor the name of the author may be used to 46 * endorse or promote products derived from this software without specific 47 * prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 51 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 52 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 53 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 54 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 55 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * RiscBSD kernel project 62 * 63 * cpu.c 64 * 65 * Probing and configuration for the master CPU 66 * 67 * Created : 10/10/95 68 */ 69/* 70 * CPU bootstrap, used to create core structures for the boot processor. 71 * 72 * SMP support coming soon. 73 */ 74 75#include <kern/kalloc.h> 76#include <kern/misc_protos.h> 77#include <kern/machine.h> 78#include <mach/processor_info.h> 79#include <arm/pmap.h> 80#include <arm/machine_routines.h> 81#include <vm/vm_kern.h> 82#include <kern/timer_call.h> 83#include <kern/etimer.h> 84#include <kern/processor.h> 85#include <arm/misc_protos.h> 86#include <mach/machine.h> 87#include <arm/arch.h> 88#include "proc_reg.h" 89 90/* 91 * Initial stack for first CPU. 92 */ 93extern uint32_t intstack_top[]; /* top */ 94extern uint32_t intstack[]; /* bottom */ 95 96struct processor BootProcessor; 97cpu_data_t cpu_data_master; 98 99enum cpu_class { 100 CPU_CLASS_NONE, 101 CPU_CLASS_ARM2, 102 CPU_CLASS_ARM2AS, 103 CPU_CLASS_ARM3, 104 CPU_CLASS_ARM6, 105 CPU_CLASS_ARM7, 106 CPU_CLASS_ARM7TDMI, 107 CPU_CLASS_ARM8, 108 CPU_CLASS_ARM9TDMI, 109 CPU_CLASS_ARM9ES, 110 CPU_CLASS_ARM9EJS, 111 CPU_CLASS_ARM10E, 112 CPU_CLASS_ARM10EJ, 113 CPU_CLASS_CORTEXA, 114 CPU_CLASS_SA1, 115 CPU_CLASS_XSCALE, 116 CPU_CLASS_ARM11J, 117 CPU_CLASS_MARVELL 118}; 119 120static const char *const generic_steppings[16] = { 121 "rev 0", "rev 1", "rev 2", "rev 3", 122 "rev 4", "rev 5", "rev 6", "rev 7", 123 "rev 8", "rev 9", "rev 10", "rev 11", 124 "rev 12", "rev 13", "rev 14", "rev 15", 125}; 126 127static const char *const sa110_steppings[16] = { 128 "rev 0", "step J", "step K", "step S", 129 "step T", "rev 5", "rev 6", "rev 7", 130 "rev 8", "rev 9", "rev 10", "rev 11", 131 "rev 12", "rev 13", "rev 14", "rev 15", 132}; 133 134static const char *const sa1100_steppings[16] = { 135 "rev 0", "step B", "step C", "rev 3", 136 "rev 4", "rev 5", "rev 6", "rev 7", 137 "step D", "step E", "rev 10" "step G", 138 "rev 12", "rev 13", "rev 14", "rev 15", 139}; 140 141static const char *const sa1110_steppings[16] = { 142 "step A-0", "rev 1", "rev 2", "rev 3", 143 "step B-0", "step B-1", "step B-2", "step B-3", 144 "step B-4", "step B-5", "rev 10", "rev 11", 145 "rev 12", "rev 13", "rev 14", "rev 15", 146}; 147 148static const char *const ixp12x0_steppings[16] = { 149 "(IXP1200 step A)", "(IXP1200 step B)", 150 "rev 2", "(IXP1200 step C)", 151 "(IXP1200 step D)", "(IXP1240/1250 step A)", 152 "(IXP1240 step B)", "(IXP1250 step B)", 153 "rev 8", "rev 9", "rev 10", "rev 11", 154 "rev 12", "rev 13", "rev 14", "rev 15", 155}; 156 157static const char *const xscale_steppings[16] = { 158 "step A-0", "step A-1", "step B-0", "step C-0", 159 "step D-0", "rev 5", "rev 6", "rev 7", 160 "rev 8", "rev 9", "rev 10", "rev 11", 161 "rev 12", "rev 13", "rev 14", "rev 15", 162}; 163 164static const char *const i80219_steppings[16] = { 165 "step A-0", "rev 1", "rev 2", "rev 3", 166 "rev 4", "rev 5", "rev 6", "rev 7", 167 "rev 8", "rev 9", "rev 10", "rev 11", 168 "rev 12", "rev 13", "rev 14", "rev 15", 169}; 170 171static const char *const i80321_steppings[16] = { 172 "step A-0", "step B-0", "rev 2", "rev 3", 173 "rev 4", "rev 5", "rev 6", "rev 7", 174 "rev 8", "rev 9", "rev 10", "rev 11", 175 "rev 12", "rev 13", "rev 14", "rev 15", 176}; 177 178static const char *const i81342_steppings[16] = { 179 "step A-0", "rev 1", "rev 2", "rev 3", 180 "rev 4", "rev 5", "rev 6", "rev 7", 181 "rev 8", "rev 9", "rev 10", "rev 11", 182 "rev 12", "rev 13", "rev 14", "rev 15", 183}; 184 185/* Steppings for PXA2[15]0 */ 186static const char *const pxa2x0_steppings[16] = { 187 "step A-0", "step A-1", "step B-0", "step B-1", 188 "step B-2", "step C-0", "rev 6", "rev 7", 189 "rev 8", "rev 9", "rev 10", "rev 11", 190 "rev 12", "rev 13", "rev 14", "rev 15", 191}; 192 193/* Steppings for PXA255/26x. 194 * rev 5: PXA26x B0, rev 6: PXA255 A0 195 */ 196static const char *const pxa255_steppings[16] = { 197 "rev 0", "rev 1", "rev 2", "step A-0", 198 "rev 4", "step B-0", "step A-0", "rev 7", 199 "rev 8", "rev 9", "rev 10", "rev 11", 200 "rev 12", "rev 13", "rev 14", "rev 15", 201}; 202 203/* Stepping for PXA27x */ 204static const char *const pxa27x_steppings[16] = { 205 "step A-0", "step A-1", "step B-0", "step B-1", 206 "step C-0", "rev 5", "rev 6", "rev 7", 207 "rev 8", "rev 9", "rev 10", "rev 11", 208 "rev 12", "rev 13", "rev 14", "rev 15", 209}; 210 211static const char *const ixp425_steppings[16] = { 212 "step 0 (A0)", "rev 1 (ARMv5TE)", "rev 2", "rev 3", 213 "rev 4", "rev 5", "rev 6", "rev 7", 214 "rev 8", "rev 9", "rev 10", "rev 11", 215 "rev 12", "rev 13", "rev 14", "rev 15", 216}; 217 218struct cpuidtab { 219 u_int32_t cpuid; 220 enum cpu_class cpu_class; 221 const char *cpu_name; 222 const char *const *cpu_steppings; 223}; 224 225const struct cpuidtab cpuids[] = { 226 {CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2", 227 generic_steppings}, 228 {CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250", 229 generic_steppings}, 230 231 {CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3", 232 generic_steppings}, 233 234 {CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600", 235 generic_steppings}, 236 {CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610", 237 generic_steppings}, 238 {CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620", 239 generic_steppings}, 240 241 {CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700", 242 generic_steppings}, 243 {CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710", 244 generic_steppings}, 245 {CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500", 246 generic_steppings}, 247 {CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a", 248 generic_steppings}, 249 {CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE", 250 generic_steppings}, 251 {CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T", 252 generic_steppings}, 253 {CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T", 254 generic_steppings}, 255 {CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)", 256 generic_steppings}, 257 {CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)", 258 generic_steppings}, 259 260 {CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810", 261 generic_steppings}, 262 263 {CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T", 264 generic_steppings}, 265 {CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T", 266 generic_steppings}, 267 {CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T", 268 generic_steppings}, 269 {CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S", 270 generic_steppings}, 271 {CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T", 272 generic_steppings}, 273 {CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S", 274 generic_steppings}, 275 {CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S", 276 generic_steppings}, 277 {CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S", 278 generic_steppings}, 279 {CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526", 280 generic_steppings}, 281 {CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE", 282 generic_steppings}, 283 284 {CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T", 285 generic_steppings}, 286 287 {CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E", 288 generic_steppings}, 289 {CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S", 290 generic_steppings}, 291 {CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S", 292 generic_steppings}, 293 294 {CPU_ID_CORTEXA5, CPU_CLASS_CORTEXA, "Cortex A5", 295 generic_steppings}, 296 {CPU_ID_CORTEXA7, CPU_CLASS_CORTEXA, "Cortex A7", 297 generic_steppings}, 298 {CPU_ID_CORTEXA8R0, CPU_CLASS_CORTEXA, "Cortex A8-r0", 299 generic_steppings}, 300 {CPU_ID_CORTEXA8R1, CPU_CLASS_CORTEXA, "Cortex A8-r1", 301 generic_steppings}, 302 {CPU_ID_CORTEXA8R2, CPU_CLASS_CORTEXA, "Cortex A8-r2", 303 generic_steppings}, 304 {CPU_ID_CORTEXA8R3, CPU_CLASS_CORTEXA, "Cortex A8-r3", 305 generic_steppings}, 306 {CPU_ID_CORTEXA9R1, CPU_CLASS_CORTEXA, "Cortex A9-r1", 307 generic_steppings}, 308 {CPU_ID_CORTEXA9R2, CPU_CLASS_CORTEXA, "Cortex A9-r2", 309 generic_steppings}, 310 {CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEXA, "Cortex A9-r3", 311 generic_steppings}, 312 {CPU_ID_CORTEXA15, CPU_CLASS_CORTEXA, "Cortex A15", 313 generic_steppings}, 314 315 {CPU_ID_SA110, CPU_CLASS_SA1, "SA-110", 316 sa110_steppings}, 317 {CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100", 318 sa1100_steppings}, 319 {CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110", 320 sa1110_steppings}, 321 322 {CPU_ID_IXP1200, CPU_CLASS_SA1, "IXP1200", 323 ixp12x0_steppings}, 324 325 {CPU_ID_80200, CPU_CLASS_XSCALE, "i80200", 326 xscale_steppings}, 327 328 {CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz", 329 i80321_steppings}, 330 {CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz", 331 i80321_steppings}, 332 {CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz", 333 i80321_steppings}, 334 {CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz", 335 i80321_steppings}, 336 337 {CPU_ID_81342, CPU_CLASS_XSCALE, "i81342", 338 i81342_steppings}, 339 340 {CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz", 341 i80219_steppings}, 342 {CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz", 343 i80219_steppings}, 344 345 {CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x", 346 pxa27x_steppings}, 347 {CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250", 348 pxa2x0_steppings}, 349 {CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210", 350 pxa2x0_steppings}, 351 {CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250", 352 pxa2x0_steppings}, 353 {CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210", 354 pxa2x0_steppings}, 355 {CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255", 356 pxa255_steppings}, 357 {CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210", 358 pxa2x0_steppings}, 359 360 {CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz", 361 ixp425_steppings}, 362 {CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz", 363 ixp425_steppings}, 364 {CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz", 365 ixp425_steppings}, 366 367 /* 368 * XXX ixp435 steppings? 369 */ 370 {CPU_ID_IXP435, CPU_CLASS_XSCALE, "IXP435", 371 ixp425_steppings}, 372 373 {CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S", 374 generic_steppings}, 375 {CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S R1", 376 generic_steppings}, 377 {CPU_ID_ARM1176JZS, CPU_CLASS_ARM11J, "ARM1176JZ-S", 378 generic_steppings}, 379 380 {CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131", 381 generic_steppings}, 382 383 {CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD", 384 generic_steppings}, 385 {CPU_ID_MV88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x", 386 generic_steppings}, 387 {CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x", 388 generic_steppings}, 389 {CPU_ID_MV88SV584X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV584x", 390 generic_steppings}, 391 392 {0, CPU_CLASS_NONE, NULL, NULL} 393}; 394 395struct cpu_classtab { 396 const char *class_name; 397 const char *class_option; 398}; 399 400const struct cpu_classtab cpu_classes[] = { 401 {"unknown", NULL}, /* CPU_CLASS_NONE */ 402 {"ARM2", "CPU_ARM2"}, /* CPU_CLASS_ARM2 */ 403 {"ARM2as", "CPU_ARM250"}, /* CPU_CLASS_ARM2AS */ 404 {"ARM3", "CPU_ARM3"}, /* CPU_CLASS_ARM3 */ 405 {"ARM6", "CPU_ARM6"}, /* CPU_CLASS_ARM6 */ 406 {"ARM7", "CPU_ARM7"}, /* CPU_CLASS_ARM7 */ 407 {"ARM7TDMI", "CPU_ARM7TDMI"}, /* CPU_CLASS_ARM7TDMI */ 408 {"ARM8", "CPU_ARM8"}, /* CPU_CLASS_ARM8 */ 409 {"ARM9TDMI", "CPU_ARM9TDMI"}, /* CPU_CLASS_ARM9TDMI */ 410 {"ARM9E-S", "CPU_ARM9E"}, /* CPU_CLASS_ARM9ES */ 411 {"ARM9EJ-S", "CPU_ARM9E"}, /* CPU_CLASS_ARM9EJS */ 412 {"ARM10E", "CPU_ARM10"}, /* CPU_CLASS_ARM10E */ 413 {"ARM10EJ", "CPU_ARM10"}, /* CPU_CLASS_ARM10EJ */ 414 {"Cortex-A", "CPU_CORTEXA"}, /* CPU_CLASS_CORTEXA */ 415 {"SA-1", "CPU_SA110"}, /* CPU_CLASS_SA1 */ 416 {"XScale", "CPU_XSCALE_..."}, /* CPU_CLASS_XSCALE */ 417 {"ARM11J", "CPU_ARM11"}, /* CPU_CLASS_ARM11J */ 418 {"Marvell", "CPU_MARVELL"}, /* CPU_CLASS_MARVELL */ 419}; 420 421/* 422 * Report the type of the specified arm processor. This uses the generic and 423 * arm specific information in the cpu structure to identify the processor. 424 * The remaining fields in the cpu structure are filled in appropriately. 425 */ 426 427static const char *const wtnames[] = { 428 "write-through", 429 "write-back", 430 "write-back", 431 "**unknown 3**", 432 "**unknown 4**", 433 "write-back-locking", /* XXX XScale-specific? */ 434 "write-back-locking-A", 435 "write-back-locking-B", 436 "**unknown 8**", 437 "**unknown 9**", 438 "**unknown 10**", 439 "**unknown 11**", 440 "**unknown 12**", 441 "**unknown 13**", 442 "write-back-locking-C", 443 "**unknown 15**", 444}; 445 446int arm_picache_size; 447int arm_picache_line_size; 448int arm_picache_ways; 449 450int arm_pdcache_size; /* and unified */ 451int arm_pdcache_line_size; 452int arm_pdcache_ways; 453 454int arm_pcache_type; 455int arm_pcache_unified; 456 457int arm_dcache_align; 458int arm_dcache_align_mask; 459 460u_int arm_cache_level; 461u_int arm_cache_type[14]; 462u_int arm_cache_loc; 463 464static int arm_dcache_l2_nsets; 465static int arm_dcache_l2_assoc; 466static int arm_dcache_l2_linesize; 467 468arm_processor_id_t arm_processor_id; 469 470void get_cachetype_cp15() 471{ 472 u_int ctype, isize, dsize, cpuid; 473 u_int clevel, csize, i, sel; 474 u_int multiplier; 475 u_char type; 476 477 __asm __volatile("mrc p15, 0, %0, c0, c0, 1":"=r"(ctype)); 478 479 cpuid = armreg_midr_read(); 480 arm_processor_id.processor_midr = cpuid; 481 482 /* 483 * ...and thus spake the ARM ARM: 484 * 485 * If an <opcode2> value corresponding to an unimplemented or 486 * reserved ID register is encountered, the System Control 487 * processor returns the value of the main ID register. 488 */ 489 if (ctype == cpuid) 490 goto out; 491 492 if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) { 493 __asm __volatile("mrc p15, 1, %0, c0, c0, 1":"=r"(clevel)); 494 arm_cache_level = clevel; 495 arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level); 496 i = 0; 497 while ((type = (clevel & 0x7)) && i < 7) { 498 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE || 499 type == CACHE_SEP_CACHE) { 500 sel = i << 1; 501 __asm __volatile("mcr p15, 2, %0, c0, c0, 0"::"r"(sel)); 502 __asm __volatile("mrc p15, 1, %0, c0, c0, 0":"=r"(csize)); 503 arm_cache_type[sel] = csize; 504 arm_dcache_align = 1 << (CPUV7_CT_xSIZE_LEN(csize) + 4); 505 arm_dcache_align_mask = arm_dcache_align - 1; 506 } 507 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) { 508 sel = (i << 1) | 1; 509 __asm __volatile("mcr p15, 2, %0, c0, c0, 0"::"r"(sel)); 510 __asm __volatile("mrc p15, 1, %0, c0, c0, 0":"=r"(csize)); 511 arm_cache_type[sel] = csize; 512 } 513 i++; 514 clevel >>= 3; 515 } 516 } else { 517 if ((ctype & CPU_CT_S) == 0) 518 arm_pcache_unified = 1; 519 520 /* 521 * If you want to know how this code works, go read the ARM ARM. 522 */ 523 524 arm_pcache_type = CPU_CT_CTYPE(ctype); 525 526 if (arm_pcache_unified == 0) { 527 isize = CPU_CT_ISIZE(ctype); 528 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; 529 arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); 530 if (CPU_CT_xSIZE_ASSOC(isize) == 0) { 531 if (isize & CPU_CT_xSIZE_M) 532 arm_picache_line_size = 0; /* not present */ 533 else 534 arm_picache_ways = 1; 535 } else { 536 arm_picache_ways = multiplier << (CPU_CT_xSIZE_ASSOC(isize) - 1); 537 } 538 arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); 539 } 540 541 dsize = CPU_CT_DSIZE(ctype); 542 multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; 543 arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); 544 if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { 545 if (dsize & CPU_CT_xSIZE_M) 546 arm_pdcache_line_size = 0; /* not present */ 547 else 548 arm_pdcache_ways = 1; 549 } else { 550 arm_pdcache_ways = multiplier << (CPU_CT_xSIZE_ASSOC(dsize) - 1); 551 } 552 arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); 553 554 arm_dcache_align = arm_pdcache_line_size; 555 556 arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; 557 arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; 558 arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - 559 CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); 560 561 out: 562 arm_dcache_align_mask = arm_dcache_align - 1; 563 } 564} 565 566static void print_enadis(int enadis, char *s) 567{ 568 569 kprintf(" %s %sabled", s, (enadis == 0) ? "dis" : "en"); 570} 571 572int ctrl; 573enum cpu_class cpu_class = CPU_CLASS_NONE; 574 575u_int cpu_pfr(int num) 576{ 577 u_int feat = 0; 578 579 switch (num) { 580 case 0: 581 __asm __volatile("mrc p15, 0, %0, c0, c1, 0":"=r"(feat)); 582 break; 583 case 1: 584 __asm __volatile("mrc p15, 0, %0, c0, c1, 1":"=r"(feat)); 585 break; 586 default: 587 panic("Processor Feature Register %d not implemented", num); 588 break; 589 } 590 591 return (feat); 592} 593 594static 595void identify_armv7(void) 596{ 597 u_int feature; 598 599 kprintf("Supported features:"); 600 /* 601 * Get Processor Feature Register 0 602 */ 603 feature = cpu_pfr(0); 604 605 if (feature & ARM_PFR0_ARM_ISA_MASK) { 606 kprintf(" ARM_ISA"); 607 arm_processor_id.processor_features |= kProcessorFeatureARM_ISA; 608 } 609 610 if (feature & ARM_PFR0_THUMB2) { 611 kprintf(" THUMB2"); 612 arm_processor_id.processor_features |= kProcessorFeatureThumb2 | kProcessorFeatureThumb; 613 } else if (feature & ARM_PFR0_THUMB) { 614 kprintf(" THUMB"); 615 arm_processor_id.processor_features |= kProcessorFeatureThumb; 616 } 617 618 if (feature & ARM_PFR0_JAZELLE_MASK) { 619 kprintf(" JAZELLE"); 620 arm_processor_id.processor_features |= kProcessorFeatureJazelle; 621 } 622 623 if (feature & ARM_PFR0_THUMBEE_MASK) { 624 kprintf(" THUMBEE"); 625 arm_processor_id.processor_features |= kProcessorFeatureThumbEE; 626 } 627 628 /* 629 * Get Processor Feature Register 1 630 */ 631 feature = cpu_pfr(1); 632 633 if (feature & ARM_PFR1_ARMV4_MASK) { 634 kprintf(" ARMv4"); 635 arm_processor_id.processor_features |= kProcessorFeatureARMv4; 636 } 637 638 if (feature & ARM_PFR1_SEC_EXT_MASK) { 639 kprintf(" Security_Ext"); 640 arm_processor_id.processor_features |= kProcessorFeatureSecurity; 641 } 642 643 if (feature & ARM_PFR1_MICROCTRL_MASK) { 644 kprintf(" M_profile"); 645 arm_processor_id.processor_features |= kProcessorFeatureMicrocontroller; 646 } 647 648 kprintf("\n"); 649} 650 651void identify_arm_cpu(void) 652{ 653 u_int cpuid, reg, size, sets, ways; 654 u_int8_t type, linesize; 655 int i; 656 657 cpuid = armreg_midr_read(); 658 ctrl = armreg_sctrl_read(); 659 660 if (cpuid == 0) { 661 kprintf("Processor failed probe - no CPU ID\n"); 662 return; 663 } 664 665 for (i = 0; cpuids[i].cpuid != 0; i++) 666 if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) { 667 cpu_class = cpuids[i].cpu_class; 668 arm_processor_id.processor_class = cpuids[i].cpu_name; 669 kprintf("CPU: %s %s (%s core)\n", 670 cpuids[i].cpu_name, 671 cpuids[i].cpu_steppings[cpuid & 672 CPU_ID_REVISION_MASK], 673 cpu_classes[cpu_class].class_name); 674 break; 675 } 676 if (cpuids[i].cpuid == 0) { 677 kprintf("unknown CPU (ID = 0x%x)\n", cpuid); 678 arm_processor_id.processor_class = "Unknown"; 679 } 680 681 kprintf(" "); 682 683 if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) { 684 identify_armv7(); 685 } else { 686 if (ctrl & CPU_CONTROL_BEND_ENABLE) 687 kprintf(" Big-endian"); 688 else 689 kprintf(" Little-endian"); 690 691 switch (cpu_class) { 692 case CPU_CLASS_ARM6: 693 case CPU_CLASS_ARM7: 694 case CPU_CLASS_ARM7TDMI: 695 case CPU_CLASS_ARM8: 696 print_enadis(ctrl & CPU_CONTROL_IDC_ENABLE, "IDC"); 697 break; 698 case CPU_CLASS_ARM9TDMI: 699 case CPU_CLASS_ARM9ES: 700 case CPU_CLASS_ARM9EJS: 701 case CPU_CLASS_ARM10E: 702 case CPU_CLASS_ARM10EJ: 703 case CPU_CLASS_SA1: 704 case CPU_CLASS_XSCALE: 705 case CPU_CLASS_ARM11J: 706 case CPU_CLASS_MARVELL: 707 print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC"); 708 print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC"); 709#ifdef CPU_XSCALE_81342 710 print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2"); 711#endif 712#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY) 713 i = sheeva_control_ext(0, 0); 714 print_enadis(i & MV_WA_ENABLE, "WA"); 715 print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming"); 716 kprintf("\n "); 717 print_enadis((i & MV_BTB_DISABLE) == 0, "BTB"); 718 print_enadis(i & MV_L2_ENABLE, "L2"); 719 print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0, "L2 prefetch"); 720 kprintf("\n "); 721#endif 722 break; 723 default: 724 break; 725 } 726 } 727 728 print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB"); 729 if (ctrl & CPU_CONTROL_LABT_ENABLE) 730 kprintf(" LABT"); 731 else 732 kprintf(" EABT"); 733 734 print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction"); 735 kprintf("\n"); 736 737 if (arm_cache_level) { 738 kprintf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1, 739 arm_cache_loc, CPU_CLIDR_LOUIS(arm_cache_level) + 1); 740 i = 0; 741 while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) { 742 kprintf("Cache level %d: \n", i + 1); 743 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE || 744 type == CACHE_SEP_CACHE) { 745 reg = arm_cache_type[2 * i]; 746 ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1; 747 sets = CPUV7_CT_xSIZE_SET(reg) + 1; 748 linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4); 749 size = (ways * sets * linesize) / 1024; 750 751 arm_processor_id.cache_levels[i].linesize = linesize; 752 arm_processor_id.cache_levels[i].ways = ways; 753 arm_processor_id.cache_levels[i].size = (ways * sets * linesize); 754 755 if (type == CACHE_UNI_CACHE) 756 kprintf(" %dKB/%dB %d-way unified cache", size, linesize, ways); 757 else 758 kprintf(" %dKB/%dB %d-way data cache", size, linesize, ways); 759 if (reg & CPUV7_CT_CTYPE_WT) 760 kprintf(" WT"); 761 if (reg & CPUV7_CT_CTYPE_WB) 762 kprintf(" WB"); 763 if (reg & CPUV7_CT_CTYPE_RA) 764 kprintf(" Read-Alloc"); 765 if (reg & CPUV7_CT_CTYPE_WA) 766 kprintf(" Write-Alloc"); 767 kprintf("\n"); 768 } 769 770 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) { 771 reg = arm_cache_type[(2 * i) + 1]; 772 773 ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1; 774 sets = CPUV7_CT_xSIZE_SET(reg) + 1; 775 linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4); 776 size = (ways * sets * linesize) / 1024; 777 778 kprintf(" %dKB/%dB %d-way instruction cache", size, linesize, ways); 779 if (reg & CPUV7_CT_CTYPE_WT) 780 kprintf(" WT"); 781 if (reg & CPUV7_CT_CTYPE_WB) 782 kprintf(" WB"); 783 if (reg & CPUV7_CT_CTYPE_RA) 784 kprintf(" Read-Alloc"); 785 if (reg & CPUV7_CT_CTYPE_WA) 786 kprintf(" Write-Alloc"); 787 kprintf("\n"); 788 } 789 i++; 790 } 791 } else { 792 /* 793 * Print cache info. 794 */ 795 if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0) 796 return; 797 798 if (arm_pcache_unified) { 799 kprintf(" %dKB/%dB %d-way %s unified cache\n", 800 arm_pdcache_size / 1024, 801 arm_pdcache_line_size, arm_pdcache_ways, wtnames[arm_pcache_type]); 802 } else { 803 kprintf(" %dKB/%dB %d-way instruction cache\n", 804 arm_picache_size / 1024, arm_picache_line_size, arm_picache_ways); 805 kprintf(" %dKB/%dB %d-way %s data cache\n", 806 arm_pdcache_size / 1024, 807 arm_pdcache_line_size, arm_pdcache_ways, wtnames[arm_pcache_type]); 808 } 809 } 810} 811 812/** 813 * cpu_bootstrap 814 * 815 * Initialize core processor data for CPU #0 during initialization. 816 */ 817void cpu_bootstrap(void) 818{ 819 cpu_data_ptr[0] = &cpu_data_master; 820 821 cpu_data_master.cpu_this = &cpu_data_master; 822 cpu_data_master.cpu_processor = &BootProcessor; 823 cpu_data_master.cpu_int_stack_top = (vm_offset_t)intstack_top; 824} 825 826/** 827 * cpu_init 828 * 829 * Initialize more core processor data for CPU #0 during initialization. 830 */ 831 832/* Stub definitions. */ 833extern void fleh_reset(void); 834extern void fleh_swi(void); 835extern void fleh_undef(void); 836extern void fleh_prefabt(void); 837extern void fleh_dataabt(void); 838extern void fleh_dataexc(void); 839extern void fleh_irq(void); 840 841void cpu_init(void) 842{ 843 cpu_data_t *cdp = current_cpu_datap(); 844 845 timer_call_initialize_queue(&cdp->rt_timer.queue); 846 cdp->rt_timer.deadline = EndOfAllTime; 847 848 cdp->cpu_type = CPU_TYPE_ARM; 849#if defined(_ARM_ARCH_7) 850 cdp->cpu_subtype = CPU_SUBTYPE_ARM_V7; 851#elif defined(_ARM_ARCH_V6) 852 cdp->cpu_subtype = CPU_SUBTYPE_ARM_V6; 853#else 854 cdp->cpu_subtype = CPU_SUBTYPE_ARM_ALL; 855#endif 856 857 cdp->fleh_reset = (uint32_t)&fleh_reset; 858 cdp->fleh_swi = (uint32_t)&fleh_swi; 859 cdp->fleh_undef = (uint32_t)&fleh_undef; 860 cdp->fleh_prefabt = (uint32_t)&fleh_prefabt; 861 cdp->fleh_dataabt = (uint32_t)&fleh_dataabt; 862 cdp->fleh_dataexc = (uint32_t)&fleh_dataexc; 863 cdp->fleh_irq = (uint32_t)&fleh_irq; 864} 865 866/** 867 * get_cpu_number 868 * 869 * Return the current processor number from the PCB. (Right now since we have 870 * no SMP support, we have only 1 processor. 871 * 872 * When SMP becomes of real importance, we can get the current MPCore number 873 * by reading some registers in the CP15 coprocessor. 874 */ 875int get_cpu_number(void) 876{ 877 return 0; 878} 879 880/** 881 * current_cpu_datap 882 * 883 * Return the current processor PCB. 884 */ 885cpu_data_t *current_cpu_datap(void) 886{ 887 int smp_number = get_cpu_number(); 888 cpu_data_t *current_cpu_data; 889 890 if (smp_number == 0) 891 return &cpu_data_master; 892 893 current_cpu_data = cpu_datap(smp_number); 894 if (!current_cpu_data) { 895 panic("cpu_data for slot %d is not available yet\n", smp_number); 896 } 897 898 return current_cpu_data; 899} 900 901/** 902 * cpu_processor_alloc 903 * 904 * Allocate a processor_t data structure for the specified processor. 905 * The boot processor will always use internal data, since vm won't be 906 * initialized to allocate data. 907 */ 908processor_t cpu_processor_alloc(boolean_t is_boot_cpu) 909{ 910 int ret; 911 processor_t proc; 912 913 if (is_boot_cpu) { 914 return &BootProcessor; 915 } 916 917 /* 918 * Allocate a new processor. 919 */ 920 ret = kmem_alloc(kernel_map, (vm_offset_t *) & proc, sizeof(*proc)); 921 if (ret != KERN_SUCCESS) 922 return NULL; 923 924 bzero((void *) proc, sizeof(*proc)); 925 return proc; 926} 927 928/** 929 * current_processor 930 * 931 * Return the processor_t to the for the current processor. 932 */ 933processor_t current_processor(void) 934{ 935 return current_cpu_datap()->cpu_processor; 936} 937 938/** 939 * cpu_to_processor 940 * 941 * Return the procesor_t for a specified processor. Please don't 942 * do bad things. 943 * 944 * This function needs validation to ensure that the cpu data accessed 945 * isn't null/exceeding buffer boundaries. 946 */ 947processor_t cpu_to_processor(int cpu) 948{ 949 assert(cpu_datap(cpu) != NULL); 950 return cpu_datap(cpu)->cpu_processor; 951} 952 953/* 954 * For sysctl(). 955 */ 956cpu_type_t cpu_type(void) 957{ 958 return current_cpu_datap()->cpu_type; 959} 960 961/** 962 * slot_type 963 * 964 * Return the current cpu type for a specified processor. 965 */ 966cpu_type_t slot_type(int slot_num) 967{ 968 return (cpu_datap(slot_num)->cpu_type); 969} 970 971/** 972 * slot_subtype 973 * 974 * Return the current cpu subtype for a specified processor. 975 */ 976cpu_subtype_t slot_subtype(int slot_num) 977{ 978 return (cpu_datap(slot_num)->cpu_subtype); 979} 980 981/** 982 * slot_threadtype 983 * 984 * Return the current SMT type for a specified processor. 985 */ 986cpu_threadtype_t slot_threadtype(int slot_num) 987{ 988 return CPU_THREADTYPE_NONE; 989} 990 991/** 992 * cpu_subtype 993 * 994 * Return the current cpu type for the current processor. 995 */ 996cpu_subtype_t cpu_subtype(void) 997{ 998 return current_cpu_datap()->cpu_subtype; 999} 1000 1001/** 1002 * cpu_threadtype 1003 * 1004 * Return the current SMT type for the current processor. 1005 */ 1006cpu_threadtype_t cpu_threadtype(void) 1007{ 1008 return CPU_THREADTYPE_NONE; 1009} 1010 1011/** 1012 * ast_pending 1013 * 1014 * Returns the current pending Asynchronous System Trap. 1015 */ 1016ast_t *ast_pending(void) 1017{ 1018 return (¤t_cpu_datap()->cpu_pending_ast); 1019} 1020 1021 /*ARGSUSED*/ 1022kern_return_t cpu_control(int slot_num, processor_info_t info, unsigned int count) 1023{ 1024 kprintf("cpu_control(%d,%p,%d) not implemented\n", slot_num, info, count); 1025 return (KERN_FAILURE); 1026} 1027 1028kern_return_t cpu_info(processor_flavor_t flavor, int slot_num, processor_info_t info, 1029 unsigned int *count) 1030{ 1031 kprintf("cpu_info(%d,%d,%p,%p) not implemented\n", flavor, slot_num, info, count); 1032 return (KERN_FAILURE); 1033} 1034 1035void cpu_machine_init(void) 1036{ 1037 cpu_data_t *cdp = current_cpu_datap(); 1038 1039 PE_cpu_machine_init(cdp->cpu_id, FALSE); 1040 cdp->cpu_running = TRUE; 1041 ml_init_interrupt(); 1042} 1043 1044kern_return_t cpu_start(int cpu) 1045{ 1046 kern_return_t ret; 1047 1048 if (cpu == cpu_number()) { 1049 cpu_machine_init(); 1050 return KERN_SUCCESS; 1051 } 1052 1053 return KERN_SUCCESS; 1054} 1055 1056kern_return_t cpu_info_count(processor_flavor_t flavor, unsigned int *count) 1057{ 1058 *count = 0; 1059 return KERN_FAILURE; 1060} 1061