1 /* $NetBSD: arm32_machdep.c,v 1.148 2025/09/06 21:02:40 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1994-1998 Mark Brinicombe. 5 * Copyright (c) 1994 Brini. 6 * All rights reserved. 7 * 8 * This code is derived from software written for Brini by Mark Brinicombe 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Mark Brinicombe 21 * for the NetBSD Project. 22 * 4. The name of the company nor the name of the author may be used to 23 * endorse or promote products derived from this software without specific 24 * prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * Machine dependent functions for kernel setup 39 * 40 * Created : 17/09/94 41 * Updated : 18/04/01 updated for new wscons 42 */ 43 44 #include <sys/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: arm32_machdep.c,v 1.148 2025/09/06 21:02:40 thorpej Exp $"); 46 47 #include "opt_arm_debug.h" 48 #include "opt_arm_start.h" 49 #include "opt_fdt.h" 50 #include "opt_modular.h" 51 #include "opt_md.h" 52 #include "opt_multiprocessor.h" 53 54 #include <sys/param.h> 55 56 #include <sys/atomic.h> 57 #include <sys/buf.h> 58 #include <sys/cpu.h> 59 #include <sys/device.h> 60 #include <sys/intr.h> 61 #include <sys/ipi.h> 62 #include <sys/kauth.h> 63 #include <sys/kernel.h> 64 #include <sys/mbuf.h> 65 #include <sys/module.h> 66 #include <sys/mount.h> 67 #include <sys/msgbuf.h> 68 #include <sys/proc.h> 69 #include <sys/reboot.h> 70 #include <sys/sysctl.h> 71 #include <sys/systm.h> 72 #include <sys/xcall.h> 73 74 #include <uvm/uvm_extern.h> 75 76 #include <dev/cons.h> 77 #include <dev/mm.h> 78 79 #include <arm/locore.h> 80 81 #include <arm/cpu_topology.h> 82 #include <arm/arm32/machdep.h> 83 84 #include <machine/bootconfig.h> 85 #include <machine/pcb.h> 86 87 #if defined(FDT) 88 #include <dev/fdt/fdtvar.h> 89 #include <dev/fdt/fdt_platform.h> 90 91 #include <arm/fdt/arm_fdtvar.h> 92 #include <arch/evbarm/fdt/platform.h> 93 #endif 94 95 #ifdef VERBOSE_INIT_ARM 96 #define VPRINTF(...) printf(__VA_ARGS__) 97 #ifdef __HAVE_GENERIC_START 98 void generic_prints(const char *); 99 void generic_printx(int); 100 #define VPRINTS(s) generic_prints(s) 101 #define VPRINTX(x) generic_printx(x) 102 #else 103 #define VPRINTS(s) __nothing 104 #define VPRINTX(x) __nothing 105 #endif 106 #else 107 #define VPRINTF(...) __nothing 108 #define VPRINTS(s) __nothing 109 #define VPRINTX(x) __nothing 110 #endif 111 112 void (*cpu_reset_address)(void); /* Used by locore */ 113 paddr_t cpu_reset_address_paddr; /* Used by locore */ 114 115 struct vm_map *phys_map = NULL; 116 117 #if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE) 118 extern size_t md_root_size; /* Memory disc size */ 119 #endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */ 120 121 pv_addr_t kernelstack; 122 pv_addr_t abtstack; 123 pv_addr_t fiqstack; 124 pv_addr_t irqstack; 125 pv_addr_t undstack; 126 pv_addr_t idlestack; 127 128 void * msgbufaddr; 129 extern paddr_t msgbufphys; 130 131 int kernel_debug = 0; 132 int cpu_printfataltraps = 0; 133 int cpu_fpu_present; 134 int cpu_hwdiv_present; 135 int cpu_neon_present; 136 int cpu_simd_present; 137 int cpu_simdex_present; 138 int cpu_umull_present; 139 int cpu_synchprim_present; 140 int cpu_unaligned_sigbus; 141 const char *cpu_arch = ""; 142 143 int cpu_instruction_set_attributes[6]; 144 int cpu_memory_model_features[4]; 145 int cpu_processor_features[2]; 146 int cpu_media_and_vfp_features[2]; 147 148 /* exported variable to be filled in by the bootloaders */ 149 char *booted_kernel; 150 151 /* Prototypes */ 152 153 void data_abort_handler(trapframe_t *frame); 154 void prefetch_abort_handler(trapframe_t *frame); 155 extern void configure(void); 156 157 /* 158 * arm32_vector_init: 159 * 160 * Initialize the vector page, and select whether or not to 161 * relocate the vectors. 162 * 163 * NOTE: We expect the vector page to be mapped at its expected 164 * destination. 165 */ 166 void 167 arm32_vector_init(vaddr_t va, int which) 168 { 169 #if defined(CPU_ARMV7) || defined(CPU_ARM11) || defined(ARM_HAS_VBAR) 170 /* 171 * If this processor has the security extension, don't bother 172 * to move/map the vector page. Simply point VBAR to the copy 173 * that exists in the .text segment. 174 */ 175 #ifndef ARM_HAS_VBAR 176 if (va == ARM_VECTORS_LOW 177 && (armreg_pfr1_read() & ARM_PFR1_SEC_MASK) != 0) { 178 #endif 179 extern const uint32_t page0rel[]; 180 vector_page = (vaddr_t)page0rel; 181 KASSERT((vector_page & 0x1f) == 0); 182 armreg_vbar_write(vector_page); 183 VPRINTF(" vbar=%p", page0rel); 184 cpu_control(CPU_CONTROL_VECRELOC, 0); 185 return; 186 #ifndef ARM_HAS_VBAR 187 } 188 #endif 189 #endif 190 #ifndef ARM_HAS_VBAR 191 if (CPU_IS_PRIMARY(curcpu())) { 192 extern unsigned int page0[], page0_data[]; 193 unsigned int *vectors = (int *) va; 194 unsigned int *vectors_data = vectors + (page0_data - page0); 195 int vec; 196 197 /* 198 * Loop through the vectors we're taking over, and copy the 199 * vector's insn and data word. 200 */ 201 for (vec = 0; vec < ARM_NVEC; vec++) { 202 if ((which & (1 << vec)) == 0) { 203 /* Don't want to take over this vector. */ 204 continue; 205 } 206 vectors[vec] = page0[vec]; 207 vectors_data[vec] = page0_data[vec]; 208 } 209 210 /* Now sync the vectors. */ 211 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 212 213 vector_page = va; 214 } 215 216 if (va == ARM_VECTORS_HIGH) { 217 /* 218 * Assume the MD caller knows what it's doing here, and 219 * really does want the vector page relocated. 220 * 221 * Note: This has to be done here (and not just in 222 * cpu_setup()) because the vector page needs to be 223 * accessible *before* cpu_startup() is called. 224 * Think ddb(9) ... 225 * 226 * NOTE: If the CPU control register is not readable, 227 * this will totally fail! We'll just assume that 228 * any system that has high vector support has a 229 * readable CPU control register, for now. If we 230 * ever encounter one that does not, we'll have to 231 * rethink this. 232 */ 233 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 234 } 235 #endif 236 } 237 238 /* 239 * Debug function just to park the CPU 240 */ 241 242 void 243 halt(void) 244 { 245 while (1) 246 cpu_sleep(0); 247 } 248 249 250 /* Sync the discs, unmount the filesystems, and adjust the todr */ 251 252 void 253 bootsync(void) 254 { 255 static bool bootsyncdone = false; 256 257 if (bootsyncdone) return; 258 259 bootsyncdone = true; 260 261 /* Make sure we can still manage to do things */ 262 if (GetCPSR() & I32_bit) { 263 /* 264 * If we get here then boot has been called without RB_NOSYNC 265 * and interrupts were disabled. This means the boot() call 266 * did not come from a user process e.g. shutdown, but must 267 * have come from somewhere in the kernel. 268 */ 269 IRQenable; 270 printf("Warning IRQ's disabled during boot()\n"); 271 } 272 273 vfs_shutdown(); 274 } 275 276 /* 277 * void cpu_startup(void) 278 * 279 * Machine dependent startup code. 280 * 281 */ 282 void 283 cpu_startup(void) 284 { 285 vaddr_t minaddr; 286 vaddr_t maxaddr; 287 288 #ifndef __HAVE_GENERIC_START 289 /* Set the CPU control register */ 290 cpu_setup(boot_args); 291 #endif 292 293 #ifndef ARM_HAS_VBAR 294 /* Lock down zero page */ 295 vector_page_setprot(VM_PROT_READ); 296 #endif 297 298 /* 299 * Give pmap a chance to set up a few more things now the vm 300 * is initialised 301 */ 302 pmap_postinit(); 303 304 #ifdef FDT 305 const struct fdt_platform * const plat = fdt_platform_find(); 306 if (plat->fp_startup != NULL) 307 plat->fp_startup(); 308 #endif 309 310 /* 311 * Initialize error message buffer (at end of core). 312 */ 313 314 /* msgbufphys was setup during the secondary boot strap */ 315 if (!pmap_extract(pmap_kernel(), (vaddr_t)msgbufaddr, NULL)) { 316 for (u_int loop = 0; loop < btoc(MSGBUFSIZE); ++loop) { 317 pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE, 318 msgbufphys + loop * PAGE_SIZE, 319 VM_PROT_READ|VM_PROT_WRITE, 0); 320 } 321 } 322 pmap_update(pmap_kernel()); 323 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); 324 325 /* 326 * Allocate a submap for physio 327 */ 328 minaddr = 0; 329 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 330 VM_PHYS_SIZE, 0, false, NULL); 331 332 banner(); 333 334 /* 335 * This is actually done by initarm_common, but not all ports use it 336 * yet so do it here to catch them as well 337 */ 338 struct lwp * const l = &lwp0; 339 struct pcb * const pcb = lwp_getpcb(l); 340 341 /* Zero out the PCB. */ 342 memset(pcb, 0, sizeof(*pcb)); 343 344 pcb->pcb_ksp = uvm_lwp_getuarea(l) + USPACE_SVC_STACK_TOP; 345 pcb->pcb_ksp -= sizeof(struct trapframe); 346 347 struct trapframe * tf = (struct trapframe *)pcb->pcb_ksp; 348 349 /* Zero out the trapframe. */ 350 memset(tf, 0, sizeof(*tf)); 351 lwp_settrapframe(l, tf); 352 353 tf->tf_spsr = PSR_USR32_MODE; 354 #ifdef _ARM_ARCH_BE8 355 tf->tf_spsr |= PSR_E_BIT; 356 #endif 357 358 cpu_startup_hook(); 359 } 360 361 __weak_alias(cpu_startup_hook,cpu_startup_default) 362 void 363 cpu_startup_default(void) 364 { 365 } 366 367 /* 368 * machine dependent system variables. 369 */ 370 static int 371 sysctl_machdep_booted_device(SYSCTLFN_ARGS) 372 { 373 struct sysctlnode node; 374 375 if (booted_device == NULL) 376 return EOPNOTSUPP; 377 378 node = *rnode; 379 node.sysctl_data = __UNCONST(device_xname(booted_device)); 380 node.sysctl_size = strlen(device_xname(booted_device)) + 1; 381 return sysctl_lookup(SYSCTLFN_CALL(&node)); 382 } 383 384 static int 385 sysctl_machdep_booted_kernel(SYSCTLFN_ARGS) 386 { 387 struct sysctlnode node; 388 389 if (booted_kernel == NULL || booted_kernel[0] == '\0') 390 return EOPNOTSUPP; 391 392 node = *rnode; 393 node.sysctl_data = booted_kernel; 394 node.sysctl_size = strlen(booted_kernel) + 1; 395 return sysctl_lookup(SYSCTLFN_CALL(&node)); 396 } 397 398 static int 399 sysctl_machdep_cpu_arch(SYSCTLFN_ARGS) 400 { 401 struct sysctlnode node = *rnode; 402 node.sysctl_data = __UNCONST(cpu_arch); 403 node.sysctl_size = strlen(cpu_arch) + 1; 404 return sysctl_lookup(SYSCTLFN_CALL(&node)); 405 } 406 407 static int 408 sysctl_machdep_powersave(SYSCTLFN_ARGS) 409 { 410 struct sysctlnode node = *rnode; 411 int error, newval; 412 413 newval = cpu_do_powersave; 414 node.sysctl_data = &newval; 415 if (cpufuncs.cf_sleep == (void *) cpufunc_nullop) 416 node.sysctl_flags &= ~CTLFLAG_READWRITE; 417 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 418 if (error || newp == NULL || newval == cpu_do_powersave) 419 return error; 420 421 if (newval < 0 || newval > 1) 422 return EINVAL; 423 cpu_do_powersave = newval; 424 425 return 0; 426 } 427 428 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 429 { 430 431 sysctl_createv(clog, 0, NULL, NULL, 432 CTLFLAG_PERMANENT, 433 CTLTYPE_NODE, "machdep", NULL, 434 NULL, 0, NULL, 0, 435 CTL_MACHDEP, CTL_EOL); 436 437 sysctl_createv(clog, 0, NULL, NULL, 438 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 439 CTLTYPE_INT, "debug", NULL, 440 NULL, 0, &kernel_debug, 0, 441 CTL_MACHDEP, CPU_DEBUG, CTL_EOL); 442 sysctl_createv(clog, 0, NULL, NULL, 443 CTLFLAG_PERMANENT, 444 CTLTYPE_STRING, "booted_device", NULL, 445 sysctl_machdep_booted_device, 0, NULL, 0, 446 CTL_MACHDEP, CPU_BOOTED_DEVICE, CTL_EOL); 447 sysctl_createv(clog, 0, NULL, NULL, 448 CTLFLAG_PERMANENT, 449 CTLTYPE_STRING, "booted_kernel", NULL, 450 sysctl_machdep_booted_kernel, 0, NULL, 0, 451 CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); 452 sysctl_createv(clog, 0, NULL, NULL, 453 CTLFLAG_PERMANENT, 454 CTLTYPE_STRUCT, "console_device", NULL, 455 sysctl_consdev, 0, NULL, sizeof(dev_t), 456 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 457 sysctl_createv(clog, 0, NULL, NULL, 458 CTLFLAG_PERMANENT, 459 CTLTYPE_STRING, "cpu_arch", NULL, 460 sysctl_machdep_cpu_arch, 0, NULL, 0, 461 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 462 sysctl_createv(clog, 0, NULL, NULL, 463 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 464 CTLTYPE_INT, "powersave", NULL, 465 sysctl_machdep_powersave, 0, &cpu_do_powersave, 0, 466 CTL_MACHDEP, CPU_POWERSAVE, CTL_EOL); 467 sysctl_createv(clog, 0, NULL, NULL, 468 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 469 CTLTYPE_INT, "cpu_id", NULL, 470 NULL, curcpu()->ci_arm_cpuid, NULL, 0, 471 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 472 #ifdef FPU_VFP 473 sysctl_createv(clog, 0, NULL, NULL, 474 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 475 CTLTYPE_INT, "fpu_id", NULL, 476 NULL, 0, &cpu_info_store[0].ci_vfp_id, 0, 477 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 478 #endif 479 sysctl_createv(clog, 0, NULL, NULL, 480 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 481 CTLTYPE_INT, "fpu_present", NULL, 482 NULL, 0, &cpu_fpu_present, 0, 483 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 484 sysctl_createv(clog, 0, NULL, NULL, 485 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 486 CTLTYPE_INT, "hwdiv_present", NULL, 487 NULL, 0, &cpu_hwdiv_present, 0, 488 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 489 sysctl_createv(clog, 0, NULL, NULL, 490 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 491 CTLTYPE_INT, "neon_present", NULL, 492 NULL, 0, &cpu_neon_present, 0, 493 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 494 sysctl_createv(clog, 0, NULL, NULL, 495 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 496 CTLTYPE_STRUCT, "id_isar", NULL, 497 NULL, 0, 498 cpu_instruction_set_attributes, 499 sizeof(cpu_instruction_set_attributes), 500 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 501 sysctl_createv(clog, 0, NULL, NULL, 502 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 503 CTLTYPE_STRUCT, "id_mmfr", NULL, 504 NULL, 0, 505 cpu_memory_model_features, 506 sizeof(cpu_memory_model_features), 507 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 508 sysctl_createv(clog, 0, NULL, NULL, 509 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 510 CTLTYPE_STRUCT, "id_pfr", NULL, 511 NULL, 0, 512 cpu_processor_features, 513 sizeof(cpu_processor_features), 514 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 515 sysctl_createv(clog, 0, NULL, NULL, 516 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 517 CTLTYPE_STRUCT, "id_mvfr", NULL, 518 NULL, 0, 519 cpu_media_and_vfp_features, 520 sizeof(cpu_media_and_vfp_features), 521 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 522 sysctl_createv(clog, 0, NULL, NULL, 523 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 524 CTLTYPE_INT, "simd_present", NULL, 525 NULL, 0, &cpu_simd_present, 0, 526 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 527 sysctl_createv(clog, 0, NULL, NULL, 528 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 529 CTLTYPE_INT, "simdex_present", NULL, 530 NULL, 0, &cpu_simdex_present, 0, 531 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 532 sysctl_createv(clog, 0, NULL, NULL, 533 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 534 CTLTYPE_INT, "synchprim_present", NULL, 535 NULL, 0, &cpu_synchprim_present, 0, 536 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 537 sysctl_createv(clog, 0, NULL, NULL, 538 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 539 CTLTYPE_INT, "printfataltraps", NULL, 540 NULL, 0, &cpu_printfataltraps, 0, 541 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 542 cpu_unaligned_sigbus = 543 #if defined(__ARMEL__) 544 !CPU_IS_ARMV6_P() && !CPU_IS_ARMV7_P(); 545 #elif defined(_ARM_ARCH_BE8) 546 0; 547 #else 548 1; 549 #endif 550 sysctl_createv(clog, 0, NULL, NULL, 551 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 552 CTLTYPE_INT, "unaligned_sigbus", 553 SYSCTL_DESCR("Do SIGBUS for fixed unaligned accesses"), 554 NULL, 0, &cpu_unaligned_sigbus, 0, 555 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 556 } 557 558 void 559 parse_mi_bootargs(char *args) 560 { 561 int integer; 562 563 if (get_bootconf_option(args, "-1", BOOTOPT_TYPE_BOOLEAN, &integer)) 564 if (integer) 565 boothowto |= RB_MD1; 566 if (get_bootconf_option(args, "single", BOOTOPT_TYPE_BOOLEAN, &integer) 567 || get_bootconf_option(args, "-s", BOOTOPT_TYPE_BOOLEAN, &integer)) 568 if (integer) 569 boothowto |= RB_SINGLE; 570 if (get_bootconf_option(args, "kdb", BOOTOPT_TYPE_BOOLEAN, &integer) 571 || get_bootconf_option(args, "-k", BOOTOPT_TYPE_BOOLEAN, &integer) 572 || get_bootconf_option(args, "-d", BOOTOPT_TYPE_BOOLEAN, &integer)) 573 if (integer) 574 boothowto |= RB_KDB; 575 if (get_bootconf_option(args, "ask", BOOTOPT_TYPE_BOOLEAN, &integer) 576 || get_bootconf_option(args, "-a", BOOTOPT_TYPE_BOOLEAN, &integer)) 577 if (integer) 578 boothowto |= RB_ASKNAME; 579 if (get_bootconf_option(args, "userconf", BOOTOPT_TYPE_BOOLEAN, &integer) 580 || get_bootconf_option(args, "-c", BOOTOPT_TYPE_BOOLEAN, &integer)) 581 if (integer) 582 boothowto |= RB_USERCONF; 583 if (get_bootconf_option(args, "halt", BOOTOPT_TYPE_BOOLEAN, &integer) 584 || get_bootconf_option(args, "-b", BOOTOPT_TYPE_BOOLEAN, &integer)) 585 if (integer) 586 boothowto |= RB_HALT; 587 if (get_bootconf_option(args, "-1", BOOTOPT_TYPE_BOOLEAN, &integer)) 588 if (integer) 589 boothowto |= RB_MD1; 590 if (get_bootconf_option(args, "-2", BOOTOPT_TYPE_BOOLEAN, &integer)) 591 if (integer) 592 boothowto |= RB_MD2; 593 if (get_bootconf_option(args, "-3", BOOTOPT_TYPE_BOOLEAN, &integer)) 594 if (integer) 595 boothowto |= RB_MD3; 596 if (get_bootconf_option(args, "-4", BOOTOPT_TYPE_BOOLEAN, &integer)) 597 if (integer) 598 boothowto |= RB_MD4; 599 600 /* if (get_bootconf_option(args, "nbuf", BOOTOPT_TYPE_INT, &integer)) 601 bufpages = integer;*/ 602 603 #if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE) 604 if (get_bootconf_option(args, "memorydisc", BOOTOPT_TYPE_INT, &integer) 605 || get_bootconf_option(args, "memorydisk", BOOTOPT_TYPE_INT, &integer)) { 606 md_root_size = integer; 607 md_root_size *= 1024; 608 if (md_root_size < 32*1024) 609 md_root_size = 32*1024; 610 if (md_root_size > 2048*1024) 611 md_root_size = 2048*1024; 612 } 613 #endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */ 614 615 if (get_bootconf_option(args, "quiet", BOOTOPT_TYPE_BOOLEAN, &integer) 616 || get_bootconf_option(args, "-q", BOOTOPT_TYPE_BOOLEAN, &integer)) 617 if (integer) 618 boothowto |= AB_QUIET; 619 if (get_bootconf_option(args, "verbose", BOOTOPT_TYPE_BOOLEAN, &integer) 620 || get_bootconf_option(args, "-v", BOOTOPT_TYPE_BOOLEAN, &integer)) 621 if (integer) 622 boothowto |= AB_VERBOSE; 623 if (get_bootconf_option(args, "debug", BOOTOPT_TYPE_BOOLEAN, &integer) 624 || get_bootconf_option(args, "-x", BOOTOPT_TYPE_BOOLEAN, &integer)) 625 if (integer) 626 boothowto |= AB_DEBUG; 627 if (get_bootconf_option(args, "silent", BOOTOPT_TYPE_BOOLEAN, &integer) 628 || get_bootconf_option(args, "-z", BOOTOPT_TYPE_BOOLEAN, &integer)) 629 if (integer) 630 boothowto |= AB_SILENT; 631 } 632 633 #ifdef __HAVE_FAST_SOFTINTS 634 #if IPL_SOFTSERIAL != IPL_SOFTNET + 1 635 #error IPLs are screwed up 636 #elif IPL_SOFTNET != IPL_SOFTBIO + 1 637 #error IPLs are screwed up 638 #elif IPL_SOFTBIO != IPL_SOFTCLOCK + 1 639 #error IPLs are screwed up 640 #elif !(IPL_SOFTCLOCK > IPL_NONE) 641 #error IPLs are screwed up 642 #elif (IPL_NONE != 0) 643 #error IPLs are screwed up 644 #endif 645 646 #ifndef __HAVE_PIC_FAST_SOFTINTS 647 #define SOFTINT2IPLMAP \ 648 (((IPL_SOFTSERIAL - IPL_SOFTCLOCK) << (SOFTINT_SERIAL * 4)) | \ 649 ((IPL_SOFTNET - IPL_SOFTCLOCK) << (SOFTINT_NET * 4)) | \ 650 ((IPL_SOFTBIO - IPL_SOFTCLOCK) << (SOFTINT_BIO * 4)) | \ 651 ((IPL_SOFTCLOCK - IPL_SOFTCLOCK) << (SOFTINT_CLOCK * 4))) 652 #define SOFTINT2IPL(l) ((SOFTINT2IPLMAP >> ((l) * 4)) & 0x0f) 653 654 /* 655 * This returns a mask of softint IPLs that be dispatch at <ipl> 656 * SOFTIPLMASK(IPL_NONE) = 0x0000000f 657 * SOFTIPLMASK(IPL_SOFTCLOCK) = 0x0000000e 658 * SOFTIPLMASK(IPL_SOFTBIO) = 0x0000000c 659 * SOFTIPLMASK(IPL_SOFTNET) = 0x00000008 660 * SOFTIPLMASK(IPL_SOFTSERIAL) = 0x00000000 661 */ 662 #define SOFTIPLMASK(ipl) ((0x0f << (ipl)) & 0x0f) 663 664 void softint_switch(lwp_t *, int); 665 666 void 667 softint_trigger(uintptr_t mask) 668 { 669 curcpu()->ci_softints |= mask; 670 } 671 672 void 673 softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep) 674 { 675 lwp_t ** lp = &l->l_cpu->ci_softlwps[level]; 676 KASSERT(*lp == NULL || *lp == l); 677 *lp = l; 678 *machdep = 1 << SOFTINT2IPL(level); 679 KASSERT(level != SOFTINT_CLOCK || *machdep == (1 << (IPL_SOFTCLOCK - IPL_SOFTCLOCK))); 680 KASSERT(level != SOFTINT_BIO || *machdep == (1 << (IPL_SOFTBIO - IPL_SOFTCLOCK))); 681 KASSERT(level != SOFTINT_NET || *machdep == (1 << (IPL_SOFTNET - IPL_SOFTCLOCK))); 682 KASSERT(level != SOFTINT_SERIAL || *machdep == (1 << (IPL_SOFTSERIAL - IPL_SOFTCLOCK))); 683 } 684 685 void 686 dosoftints(void) 687 { 688 struct cpu_info * const ci = curcpu(); 689 const int opl = ci->ci_cpl; 690 const uint32_t softiplmask = SOFTIPLMASK(opl); 691 int s; 692 693 s = splhigh(); 694 KASSERT(s == opl); 695 for (;;) { 696 u_int softints = ci->ci_softints & softiplmask; 697 KASSERT((softints != 0) == ((ci->ci_softints >> opl) != 0)); 698 KASSERT(opl == IPL_NONE || (softints & (1 << (opl - IPL_SOFTCLOCK))) == 0); 699 if (softints == 0) { 700 break; 701 } 702 #define DOSOFTINT(n) \ 703 if (ci->ci_softints & (1 << (IPL_SOFT ## n - IPL_SOFTCLOCK))) { \ 704 ci->ci_softints &= \ 705 ~(1 << (IPL_SOFT ## n - IPL_SOFTCLOCK)); \ 706 softint_switch(ci->ci_softlwps[SOFTINT_ ## n], \ 707 IPL_SOFT ## n); \ 708 continue; \ 709 } 710 DOSOFTINT(SERIAL); 711 DOSOFTINT(NET); 712 DOSOFTINT(BIO); 713 DOSOFTINT(CLOCK); 714 panic("dosoftints wtf (softints=%u?, ipl=%d)", softints, opl); 715 } 716 splx(s); 717 } 718 #endif /* !__HAVE_PIC_FAST_SOFTINTS */ 719 #endif /* __HAVE_FAST_SOFTINTS */ 720 721 #ifdef MODULAR 722 /* 723 * Push any modules loaded by the boot loader. 724 */ 725 void 726 module_init_md(void) 727 { 728 #ifdef FDT 729 arm_fdt_module_init(); 730 #endif 731 } 732 #endif /* MODULAR */ 733 734 int 735 mm_md_physacc(paddr_t pa, vm_prot_t prot) 736 { 737 if (pa >= physical_start && pa < physical_end) 738 return 0; 739 740 return kauth_authorize_machdep(kauth_cred_get(), 741 KAUTH_MACHDEP_UNMANAGEDMEM, NULL, NULL, NULL, NULL); 742 } 743 744 #ifdef __HAVE_CPU_UAREA_ALLOC_IDLELWP 745 vaddr_t 746 cpu_uarea_alloc_idlelwp(struct cpu_info *ci) 747 { 748 const vaddr_t va = idlestack.pv_va + cpu_index(ci) * USPACE; 749 // printf("%s: %s: va=%lx\n", __func__, ci->ci_data.cpu_name, va); 750 return va; 751 } 752 #endif 753 754 #ifdef MULTIPROCESSOR 755 /* 756 * Initialise a secondary processor. 757 * 758 * printf isn't available to us for a number of reasons. 759 * 760 * - kprint_init has been called and printf will try to take locks which we 761 * can't do just yet because bootstrap translation tables do not allowing 762 * caching. 763 * 764 * - kmutex(9) relies on curcpu which isn't setup yet. 765 * 766 */ 767 void __noasan 768 cpu_init_secondary_processor(int cpuindex) 769 { 770 // pmap_kernel has been successfully built and we can switch to it 771 cpu_domains(DOMAIN_DEFAULT); 772 cpu_idcache_wbinv_all(); 773 774 VPRINTS("index: "); 775 VPRINTX(cpuindex); 776 VPRINTS(" ttb"); 777 778 cpu_setup(boot_args); 779 780 #ifdef ARM_MMU_EXTENDED 781 /* 782 * TTBCR should have been initialized by the MD start code. 783 */ 784 KASSERT((armreg_contextidr_read() & 0xff) == 0); 785 KASSERT(armreg_ttbcr_read() == __SHIFTIN(1, TTBCR_S_N)); 786 /* 787 * Disable lookups via TTBR0 until there is an activated pmap. 788 */ 789 790 armreg_ttbcr_write(armreg_ttbcr_read() | TTBCR_S_PD0); 791 cpu_setttb(pmap_kernel()->pm_l1_pa , KERNEL_PID); 792 isb(); 793 #else 794 cpu_setttb(pmap_kernel()->pm_l1->l1_physaddr, true); 795 #endif 796 797 cpu_tlb_flushID(); 798 799 VPRINTS(" (TTBR0="); 800 VPRINTX(armreg_ttbr_read()); 801 VPRINTS(")"); 802 803 #ifdef ARM_MMU_EXTENDED 804 VPRINTS(" (TTBR1="); 805 VPRINTX(armreg_ttbr1_read()); 806 VPRINTS(")"); 807 VPRINTS(" (TTBCR="); 808 VPRINTX(armreg_ttbcr_read()); 809 VPRINTS(")"); 810 #endif 811 812 struct cpu_info * ci = &cpu_info_store[cpuindex]; 813 814 VPRINTS(" ci = "); 815 VPRINTX((int)ci); 816 817 ci->ci_ctrl = armreg_sctlr_read(); 818 ci->ci_arm_cpuid = cpu_idnum(); 819 ci->ci_arm_cputype = ci->ci_arm_cpuid & CPU_ID_CPU_MASK; 820 ci->ci_arm_cpurev = ci->ci_arm_cpuid & CPU_ID_REVISION_MASK; 821 822 ci->ci_midr = armreg_midr_read(); 823 ci->ci_actlr = armreg_auxctl_read(); 824 ci->ci_revidr = armreg_revidr_read(); 825 ci->ci_mpidr = armreg_mpidr_read(); 826 827 arm_cpu_topology_set(ci, ci->ci_mpidr); 828 829 VPRINTS(" vfp"); 830 vfp_detect(ci); 831 832 VPRINTS(" hatched |="); 833 VPRINTX(__BIT(cpuindex)); 834 VPRINTS("\n\r"); 835 836 cpu_set_hatched(cpuindex); 837 838 /* 839 * return to assembly to wait for cpu_boot_secondary_processors 840 */ 841 } 842 843 void 844 xc_send_ipi(struct cpu_info *ci) 845 { 846 KASSERT(kpreempt_disabled()); 847 KASSERT(curcpu() != ci); 848 849 intr_ipi_send(ci != NULL ? ci->ci_kcpuset : NULL, IPI_XCALL); 850 } 851 852 void 853 cpu_ipi(struct cpu_info *ci) 854 { 855 KASSERT(kpreempt_disabled()); 856 KASSERT(curcpu() != ci); 857 858 intr_ipi_send(ci != NULL ? ci->ci_kcpuset : NULL, IPI_GENERIC); 859 } 860 861 #endif /* MULTIPROCESSOR */ 862 863 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS 864 bool 865 mm_md_direct_mapped_phys(paddr_t pa, vaddr_t *vap) 866 { 867 bool rv; 868 vaddr_t va = pmap_direct_mapped_phys(pa, &rv, 0); 869 if (rv) { 870 *vap = va; 871 } 872 return rv; 873 } 874 #endif 875 876 bool 877 mm_md_page_color(paddr_t pa, int *colorp) 878 { 879 #if (ARM_MMU_V6 + ARM_MMU_V7) != 0 880 *colorp = atop(pa & arm_cache_prefer_mask); 881 882 return arm_cache_prefer_mask ? false : true; 883 #else 884 *colorp = 0; 885 886 return true; 887 #endif 888 } 889 890 #if defined(FDT) 891 extern char KERNEL_BASE_phys[]; 892 #define KERNEL_BASE_PHYS ((paddr_t)KERNEL_BASE_phys) 893 894 void 895 cpu_kernel_vm_init(paddr_t memory_start, psize_t memory_size) 896 { 897 const struct fdt_platform *plat = fdt_platform_find(); 898 899 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS 900 const bool mapallmem_p = true; 901 #ifndef PMAP_NEED_ALLOC_POOLPAGE 902 if (memory_size > KERNEL_VM_BASE - KERNEL_BASE) { 903 VPRINTF("%s: dropping RAM size from %luMB to %uMB\n", 904 __func__, (unsigned long) (memory_size >> 20), 905 (KERNEL_VM_BASE - KERNEL_BASE) >> 20); 906 memory_size = KERNEL_VM_BASE - KERNEL_BASE; 907 } 908 #endif 909 #else 910 const bool mapallmem_p = false; 911 #endif 912 913 VPRINTF("%s: kernel phys start %" PRIxPADDR " end %" PRIxPADDR "\n", 914 __func__, memory_start, memory_start + memory_size); 915 916 arm32_bootmem_init(memory_start, memory_size, KERNEL_BASE_PHYS); 917 arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0, 918 plat->fp_devmap(), mapallmem_p); 919 } 920 #endif 921 922