1 /* $NetBSD: arm32_machdep.c,v 1.105 2014/05/19 22:47:53 rmind 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.105 2014/05/19 22:47:53 rmind Exp $"); 46 47 #include "opt_modular.h" 48 #include "opt_md.h" 49 #include "opt_pmap_debug.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/reboot.h> 54 #include <sys/proc.h> 55 #include <sys/kauth.h> 56 #include <sys/kernel.h> 57 #include <sys/mbuf.h> 58 #include <sys/mount.h> 59 #include <sys/buf.h> 60 #include <sys/msgbuf.h> 61 #include <sys/device.h> 62 #include <sys/sysctl.h> 63 #include <sys/cpu.h> 64 #include <sys/intr.h> 65 #include <sys/module.h> 66 #include <sys/atomic.h> 67 #include <sys/xcall.h> 68 #include <sys/ipi.h> 69 70 #include <uvm/uvm_extern.h> 71 72 #include <dev/cons.h> 73 #include <dev/mm.h> 74 75 #include <arm/locore.h> 76 77 #include <arm/arm32/katelib.h> 78 #include <arm/arm32/machdep.h> 79 80 #include <machine/bootconfig.h> 81 #include <machine/pcb.h> 82 83 void (*cpu_reset_address)(void); /* Used by locore */ 84 paddr_t cpu_reset_address_paddr; /* Used by locore */ 85 86 struct vm_map *phys_map = NULL; 87 88 #if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE) 89 extern size_t md_root_size; /* Memory disc size */ 90 #endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */ 91 92 pv_addr_t kernelstack; 93 pv_addr_t abtstack; 94 pv_addr_t fiqstack; 95 pv_addr_t irqstack; 96 pv_addr_t undstack; 97 pv_addr_t idlestack; 98 99 void * msgbufaddr; 100 extern paddr_t msgbufphys; 101 102 int kernel_debug = 0; 103 int cpu_printfataltraps = 0; 104 int cpu_fpu_present; 105 int cpu_hwdiv_present; 106 int cpu_neon_present; 107 int cpu_simd_present; 108 int cpu_simdex_present; 109 int cpu_umull_present; 110 int cpu_synchprim_present; 111 const char *cpu_arch = ""; 112 113 int cpu_instruction_set_attributes[6]; 114 int cpu_memory_model_features[4]; 115 int cpu_processor_features[2]; 116 int cpu_media_and_vfp_features[2]; 117 118 /* exported variable to be filled in by the bootloaders */ 119 char *booted_kernel; 120 121 /* Prototypes */ 122 123 void data_abort_handler(trapframe_t *frame); 124 void prefetch_abort_handler(trapframe_t *frame); 125 extern void configure(void); 126 127 /* 128 * arm32_vector_init: 129 * 130 * Initialize the vector page, and select whether or not to 131 * relocate the vectors. 132 * 133 * NOTE: We expect the vector page to be mapped at its expected 134 * destination. 135 */ 136 void 137 arm32_vector_init(vaddr_t va, int which) 138 { 139 #if defined(CPU_ARMV7) || defined(CPU_ARM11) || defined(ARM_HAS_VBAR) 140 /* 141 * If this processor has the security extension, don't bother 142 * to move/map the vector page. Simply point VBAR to the copy 143 * that exists in the .text segment. 144 */ 145 #ifndef ARM_HAS_VBAR 146 if (va == ARM_VECTORS_LOW 147 && (armreg_pfr1_read() & ARM_PFR1_SEC_MASK) != 0) { 148 #endif 149 extern const uint32_t page0rel[]; 150 vector_page = (vaddr_t)page0rel; 151 KASSERT((vector_page & 0x1f) == 0); 152 armreg_vbar_write(vector_page); 153 #ifdef VERBOSE_INIT_ARM 154 printf(" vbar=%p", page0rel); 155 #endif 156 cpu_control(CPU_CONTROL_VECRELOC, 0); 157 return; 158 #ifndef ARM_HAS_VBAR 159 } 160 #endif 161 #endif 162 #ifndef ARM_HAS_VBAR 163 if (CPU_IS_PRIMARY(curcpu())) { 164 extern unsigned int page0[], page0_data[]; 165 unsigned int *vectors = (int *) va; 166 unsigned int *vectors_data = vectors + (page0_data - page0); 167 int vec; 168 169 /* 170 * Loop through the vectors we're taking over, and copy the 171 * vector's insn and data word. 172 */ 173 for (vec = 0; vec < ARM_NVEC; vec++) { 174 if ((which & (1 << vec)) == 0) { 175 /* Don't want to take over this vector. */ 176 continue; 177 } 178 vectors[vec] = page0[vec]; 179 vectors_data[vec] = page0_data[vec]; 180 } 181 182 /* Now sync the vectors. */ 183 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 184 185 vector_page = va; 186 } 187 188 if (va == ARM_VECTORS_HIGH) { 189 /* 190 * Assume the MD caller knows what it's doing here, and 191 * really does want the vector page relocated. 192 * 193 * Note: This has to be done here (and not just in 194 * cpu_setup()) because the vector page needs to be 195 * accessible *before* cpu_startup() is called. 196 * Think ddb(9) ... 197 * 198 * NOTE: If the CPU control register is not readable, 199 * this will totally fail! We'll just assume that 200 * any system that has high vector support has a 201 * readable CPU control register, for now. If we 202 * ever encounter one that does not, we'll have to 203 * rethink this. 204 */ 205 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 206 } 207 #endif 208 } 209 210 /* 211 * Debug function just to park the CPU 212 */ 213 214 void 215 halt(void) 216 { 217 while (1) 218 cpu_sleep(0); 219 } 220 221 222 /* Sync the discs, unmount the filesystems, and adjust the todr */ 223 224 void 225 bootsync(void) 226 { 227 static bool bootsyncdone = false; 228 229 if (bootsyncdone) return; 230 231 bootsyncdone = true; 232 233 /* Make sure we can still manage to do things */ 234 if (GetCPSR() & I32_bit) { 235 /* 236 * If we get here then boot has been called without RB_NOSYNC 237 * and interrupts were disabled. This means the boot() call 238 * did not come from a user process e.g. shutdown, but must 239 * have come from somewhere in the kernel. 240 */ 241 IRQenable; 242 printf("Warning IRQ's disabled during boot()\n"); 243 } 244 245 vfs_shutdown(); 246 247 resettodr(); 248 } 249 250 /* 251 * void cpu_startup(void) 252 * 253 * Machine dependent startup code. 254 * 255 */ 256 void 257 cpu_startup(void) 258 { 259 vaddr_t minaddr; 260 vaddr_t maxaddr; 261 char pbuf[9]; 262 263 /* 264 * Until we better locking, we have to live under the kernel lock. 265 */ 266 //KERNEL_LOCK(1, NULL); 267 268 /* Set the CPU control register */ 269 cpu_setup(boot_args); 270 271 #ifndef ARM_HAS_VBAR 272 /* Lock down zero page */ 273 vector_page_setprot(VM_PROT_READ); 274 #endif 275 276 /* 277 * Give pmap a chance to set up a few more things now the vm 278 * is initialised 279 */ 280 pmap_postinit(); 281 282 /* 283 * Initialize error message buffer (at end of core). 284 */ 285 286 /* msgbufphys was setup during the secondary boot strap */ 287 if (!pmap_extract(pmap_kernel(), (vaddr_t)msgbufaddr, NULL)) { 288 for (u_int loop = 0; loop < btoc(MSGBUFSIZE); ++loop) { 289 pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE, 290 msgbufphys + loop * PAGE_SIZE, 291 VM_PROT_READ|VM_PROT_WRITE, 0); 292 } 293 } 294 pmap_update(pmap_kernel()); 295 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); 296 297 /* 298 * Identify ourselves for the msgbuf (everything printed earlier will 299 * not be buffered). 300 */ 301 printf("%s%s", copyright, version); 302 303 format_bytes(pbuf, sizeof(pbuf), arm_ptob(physmem)); 304 printf("total memory = %s\n", pbuf); 305 306 minaddr = 0; 307 308 /* 309 * Allocate a submap for physio 310 */ 311 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 312 VM_PHYS_SIZE, 0, false, NULL); 313 314 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 315 printf("avail memory = %s\n", pbuf); 316 317 struct lwp * const l = &lwp0; 318 struct pcb * const pcb = lwp_getpcb(l); 319 pcb->pcb_ksp = uvm_lwp_getuarea(l) + USPACE_SVC_STACK_TOP; 320 lwp_settrapframe(l, (struct trapframe *)pcb->pcb_ksp - 1); 321 } 322 323 /* 324 * machine dependent system variables. 325 */ 326 static int 327 sysctl_machdep_booted_device(SYSCTLFN_ARGS) 328 { 329 struct sysctlnode node; 330 331 if (booted_device == NULL) 332 return (EOPNOTSUPP); 333 334 node = *rnode; 335 node.sysctl_data = __UNCONST(device_xname(booted_device)); 336 node.sysctl_size = strlen(device_xname(booted_device)) + 1; 337 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 338 } 339 340 static int 341 sysctl_machdep_booted_kernel(SYSCTLFN_ARGS) 342 { 343 struct sysctlnode node; 344 345 if (booted_kernel == NULL || booted_kernel[0] == '\0') 346 return (EOPNOTSUPP); 347 348 node = *rnode; 349 node.sysctl_data = booted_kernel; 350 node.sysctl_size = strlen(booted_kernel) + 1; 351 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 352 } 353 354 static int 355 sysctl_machdep_cpu_arch(SYSCTLFN_ARGS) 356 { 357 struct sysctlnode node = *rnode; 358 node.sysctl_data = __UNCONST(cpu_arch); 359 node.sysctl_size = strlen(cpu_arch) + 1; 360 return sysctl_lookup(SYSCTLFN_CALL(&node)); 361 } 362 363 static int 364 sysctl_machdep_powersave(SYSCTLFN_ARGS) 365 { 366 struct sysctlnode node = *rnode; 367 int error, newval; 368 369 newval = cpu_do_powersave; 370 node.sysctl_data = &newval; 371 if (cpufuncs.cf_sleep == (void *) cpufunc_nullop) 372 node.sysctl_flags &= ~CTLFLAG_READWRITE; 373 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 374 if (error || newp == NULL || newval == cpu_do_powersave) 375 return (error); 376 377 if (newval < 0 || newval > 1) 378 return (EINVAL); 379 cpu_do_powersave = newval; 380 381 return (0); 382 } 383 384 static int 385 sysctl_hw_machine_arch(SYSCTLFN_ARGS) 386 { 387 struct sysctlnode node = *rnode; 388 node.sysctl_data = l->l_proc->p_md.md_march; 389 node.sysctl_size = strlen(l->l_proc->p_md.md_march) + 1; 390 return sysctl_lookup(SYSCTLFN_CALL(&node)); 391 } 392 393 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 394 { 395 396 sysctl_createv(clog, 0, NULL, NULL, 397 CTLFLAG_PERMANENT, 398 CTLTYPE_NODE, "machdep", NULL, 399 NULL, 0, NULL, 0, 400 CTL_MACHDEP, CTL_EOL); 401 402 sysctl_createv(clog, 0, NULL, NULL, 403 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 404 CTLTYPE_INT, "debug", NULL, 405 NULL, 0, &kernel_debug, 0, 406 CTL_MACHDEP, CPU_DEBUG, CTL_EOL); 407 sysctl_createv(clog, 0, NULL, NULL, 408 CTLFLAG_PERMANENT, 409 CTLTYPE_STRING, "booted_device", NULL, 410 sysctl_machdep_booted_device, 0, NULL, 0, 411 CTL_MACHDEP, CPU_BOOTED_DEVICE, CTL_EOL); 412 sysctl_createv(clog, 0, NULL, NULL, 413 CTLFLAG_PERMANENT, 414 CTLTYPE_STRING, "booted_kernel", NULL, 415 sysctl_machdep_booted_kernel, 0, NULL, 0, 416 CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); 417 sysctl_createv(clog, 0, NULL, NULL, 418 CTLFLAG_PERMANENT, 419 CTLTYPE_STRUCT, "console_device", NULL, 420 sysctl_consdev, 0, NULL, sizeof(dev_t), 421 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 422 sysctl_createv(clog, 0, NULL, NULL, 423 CTLFLAG_PERMANENT, 424 CTLTYPE_STRING, "cpu_arch", NULL, 425 sysctl_machdep_cpu_arch, 0, NULL, 0, 426 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 427 sysctl_createv(clog, 0, NULL, NULL, 428 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 429 CTLTYPE_INT, "powersave", NULL, 430 sysctl_machdep_powersave, 0, &cpu_do_powersave, 0, 431 CTL_MACHDEP, CPU_POWERSAVE, CTL_EOL); 432 sysctl_createv(clog, 0, NULL, NULL, 433 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE, 434 CTLTYPE_INT, "cpu_id", NULL, 435 NULL, curcpu()->ci_arm_cpuid, NULL, 0, 436 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 437 #ifdef FPU_VFP 438 sysctl_createv(clog, 0, NULL, NULL, 439 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 440 CTLTYPE_INT, "fpu_id", NULL, 441 NULL, 0, &cpu_info_store.ci_vfp_id, 0, 442 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 443 #endif 444 sysctl_createv(clog, 0, NULL, NULL, 445 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 446 CTLTYPE_INT, "fpu_present", NULL, 447 NULL, 0, &cpu_fpu_present, 0, 448 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 449 sysctl_createv(clog, 0, NULL, NULL, 450 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 451 CTLTYPE_INT, "hwdiv_present", NULL, 452 NULL, 0, &cpu_hwdiv_present, 0, 453 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 454 sysctl_createv(clog, 0, NULL, NULL, 455 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 456 CTLTYPE_INT, "neon_present", NULL, 457 NULL, 0, &cpu_neon_present, 0, 458 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 459 sysctl_createv(clog, 0, NULL, NULL, 460 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 461 CTLTYPE_STRUCT, "id_isar", NULL, 462 NULL, 0, 463 cpu_instruction_set_attributes, 464 sizeof(cpu_instruction_set_attributes), 465 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 466 sysctl_createv(clog, 0, NULL, NULL, 467 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 468 CTLTYPE_STRUCT, "id_mmfr", NULL, 469 NULL, 0, 470 cpu_memory_model_features, 471 sizeof(cpu_memory_model_features), 472 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 473 sysctl_createv(clog, 0, NULL, NULL, 474 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 475 CTLTYPE_STRUCT, "id_pfr", NULL, 476 NULL, 0, 477 cpu_processor_features, 478 sizeof(cpu_processor_features), 479 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 480 sysctl_createv(clog, 0, NULL, NULL, 481 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 482 CTLTYPE_STRUCT, "id_mvfr", NULL, 483 NULL, 0, 484 cpu_media_and_vfp_features, 485 sizeof(cpu_media_and_vfp_features), 486 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 487 sysctl_createv(clog, 0, NULL, NULL, 488 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 489 CTLTYPE_INT, "simd_present", NULL, 490 NULL, 0, &cpu_simd_present, 0, 491 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 492 sysctl_createv(clog, 0, NULL, NULL, 493 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 494 CTLTYPE_INT, "simdex_present", NULL, 495 NULL, 0, &cpu_simdex_present, 0, 496 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 497 sysctl_createv(clog, 0, NULL, NULL, 498 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 499 CTLTYPE_INT, "synchprim_present", NULL, 500 NULL, 0, &cpu_synchprim_present, 0, 501 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 502 sysctl_createv(clog, 0, NULL, NULL, 503 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 504 CTLTYPE_INT, "printfataltraps", NULL, 505 NULL, 0, &cpu_printfataltraps, 0, 506 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 507 508 509 /* 510 * We need override the usual CTL_HW HW_MACHINE_ARCH so we 511 * return the right machine_arch based on the running executable. 512 */ 513 sysctl_createv(clog, 0, NULL, NULL, 514 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 515 CTLTYPE_STRING, "machine_arch", 516 SYSCTL_DESCR("Machine CPU class"), 517 sysctl_hw_machine_arch, 0, NULL, 0, 518 CTL_HW, HW_MACHINE_ARCH, CTL_EOL); 519 } 520 521 void 522 parse_mi_bootargs(char *args) 523 { 524 int integer; 525 526 if (get_bootconf_option(args, "single", BOOTOPT_TYPE_BOOLEAN, &integer) 527 || get_bootconf_option(args, "-s", BOOTOPT_TYPE_BOOLEAN, &integer)) 528 if (integer) 529 boothowto |= RB_SINGLE; 530 if (get_bootconf_option(args, "kdb", BOOTOPT_TYPE_BOOLEAN, &integer) 531 || get_bootconf_option(args, "-k", BOOTOPT_TYPE_BOOLEAN, &integer) 532 || get_bootconf_option(args, "-d", BOOTOPT_TYPE_BOOLEAN, &integer)) 533 if (integer) 534 boothowto |= RB_KDB; 535 if (get_bootconf_option(args, "ask", BOOTOPT_TYPE_BOOLEAN, &integer) 536 || get_bootconf_option(args, "-a", BOOTOPT_TYPE_BOOLEAN, &integer)) 537 if (integer) 538 boothowto |= RB_ASKNAME; 539 540 #ifdef PMAP_DEBUG 541 if (get_bootconf_option(args, "pmapdebug", BOOTOPT_TYPE_INT, &integer)) { 542 pmap_debug_level = integer; 543 pmap_debug(pmap_debug_level); 544 } 545 #endif /* PMAP_DEBUG */ 546 547 /* if (get_bootconf_option(args, "nbuf", BOOTOPT_TYPE_INT, &integer)) 548 bufpages = integer;*/ 549 550 #if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE) 551 if (get_bootconf_option(args, "memorydisc", BOOTOPT_TYPE_INT, &integer) 552 || get_bootconf_option(args, "memorydisk", BOOTOPT_TYPE_INT, &integer)) { 553 md_root_size = integer; 554 md_root_size *= 1024; 555 if (md_root_size < 32*1024) 556 md_root_size = 32*1024; 557 if (md_root_size > 2048*1024) 558 md_root_size = 2048*1024; 559 } 560 #endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */ 561 562 if (get_bootconf_option(args, "quiet", BOOTOPT_TYPE_BOOLEAN, &integer) 563 || get_bootconf_option(args, "-q", BOOTOPT_TYPE_BOOLEAN, &integer)) 564 if (integer) 565 boothowto |= AB_QUIET; 566 if (get_bootconf_option(args, "verbose", BOOTOPT_TYPE_BOOLEAN, &integer) 567 || get_bootconf_option(args, "-v", BOOTOPT_TYPE_BOOLEAN, &integer)) 568 if (integer) 569 boothowto |= AB_VERBOSE; 570 } 571 572 #ifdef __HAVE_FAST_SOFTINTS 573 #if IPL_SOFTSERIAL != IPL_SOFTNET + 1 574 #error IPLs are screwed up 575 #elif IPL_SOFTNET != IPL_SOFTBIO + 1 576 #error IPLs are screwed up 577 #elif IPL_SOFTBIO != IPL_SOFTCLOCK + 1 578 #error IPLs are screwed up 579 #elif !(IPL_SOFTCLOCK > IPL_NONE) 580 #error IPLs are screwed up 581 #elif (IPL_NONE != 0) 582 #error IPLs are screwed up 583 #endif 584 585 #ifndef __HAVE_PIC_FAST_SOFTINTS 586 #define SOFTINT2IPLMAP \ 587 (((IPL_SOFTSERIAL - IPL_SOFTCLOCK) << (SOFTINT_SERIAL * 4)) | \ 588 ((IPL_SOFTNET - IPL_SOFTCLOCK) << (SOFTINT_NET * 4)) | \ 589 ((IPL_SOFTBIO - IPL_SOFTCLOCK) << (SOFTINT_BIO * 4)) | \ 590 ((IPL_SOFTCLOCK - IPL_SOFTCLOCK) << (SOFTINT_CLOCK * 4))) 591 #define SOFTINT2IPL(l) ((SOFTINT2IPLMAP >> ((l) * 4)) & 0x0f) 592 593 /* 594 * This returns a mask of softint IPLs that be dispatch at <ipl> 595 * SOFTIPLMASK(IPL_NONE) = 0x0000000f 596 * SOFTIPLMASK(IPL_SOFTCLOCK) = 0x0000000e 597 * SOFTIPLMASK(IPL_SOFTBIO) = 0x0000000c 598 * SOFTIPLMASK(IPL_SOFTNET) = 0x00000008 599 * SOFTIPLMASK(IPL_SOFTSERIAL) = 0x00000000 600 */ 601 #define SOFTIPLMASK(ipl) ((0x0f << (ipl)) & 0x0f) 602 603 void softint_switch(lwp_t *, int); 604 605 void 606 softint_trigger(uintptr_t mask) 607 { 608 curcpu()->ci_softints |= mask; 609 } 610 611 void 612 softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep) 613 { 614 lwp_t ** lp = &l->l_cpu->ci_softlwps[level]; 615 KASSERT(*lp == NULL || *lp == l); 616 *lp = l; 617 *machdep = 1 << SOFTINT2IPL(level); 618 KASSERT(level != SOFTINT_CLOCK || *machdep == (1 << (IPL_SOFTCLOCK - IPL_SOFTCLOCK))); 619 KASSERT(level != SOFTINT_BIO || *machdep == (1 << (IPL_SOFTBIO - IPL_SOFTCLOCK))); 620 KASSERT(level != SOFTINT_NET || *machdep == (1 << (IPL_SOFTNET - IPL_SOFTCLOCK))); 621 KASSERT(level != SOFTINT_SERIAL || *machdep == (1 << (IPL_SOFTSERIAL - IPL_SOFTCLOCK))); 622 } 623 624 void 625 dosoftints(void) 626 { 627 struct cpu_info * const ci = curcpu(); 628 const int opl = ci->ci_cpl; 629 const uint32_t softiplmask = SOFTIPLMASK(opl); 630 631 splhigh(); 632 for (;;) { 633 u_int softints = ci->ci_softints & softiplmask; 634 KASSERT((softints != 0) == ((ci->ci_softints >> opl) != 0)); 635 KASSERT(opl == IPL_NONE || (softints & (1 << (opl - IPL_SOFTCLOCK))) == 0); 636 if (softints == 0) { 637 splx(opl); 638 return; 639 } 640 #define DOSOFTINT(n) \ 641 if (ci->ci_softints & (1 << (IPL_SOFT ## n - IPL_SOFTCLOCK))) { \ 642 ci->ci_softints &= \ 643 ~(1 << (IPL_SOFT ## n - IPL_SOFTCLOCK)); \ 644 softint_switch(ci->ci_softlwps[SOFTINT_ ## n], \ 645 IPL_SOFT ## n); \ 646 continue; \ 647 } 648 DOSOFTINT(SERIAL); 649 DOSOFTINT(NET); 650 DOSOFTINT(BIO); 651 DOSOFTINT(CLOCK); 652 panic("dosoftints wtf (softints=%u?, ipl=%d)", softints, opl); 653 } 654 } 655 #endif /* !__HAVE_PIC_FAST_SOFTINTS */ 656 #endif /* __HAVE_FAST_SOFTINTS */ 657 658 #ifdef MODULAR 659 /* 660 * Push any modules loaded by the boot loader. 661 */ 662 void 663 module_init_md(void) 664 { 665 } 666 #endif /* MODULAR */ 667 668 int 669 mm_md_physacc(paddr_t pa, vm_prot_t prot) 670 { 671 672 return (pa < ctob(physmem)) ? 0 : EFAULT; 673 } 674 675 #ifdef __HAVE_CPU_UAREA_ALLOC_IDLELWP 676 vaddr_t 677 cpu_uarea_alloc_idlelwp(struct cpu_info *ci) 678 { 679 const vaddr_t va = idlestack.pv_va + ci->ci_cpuid * USPACE; 680 // printf("%s: %s: va=%lx\n", __func__, ci->ci_data.cpu_name, va); 681 return va; 682 } 683 #endif 684 685 #ifdef MULTIPROCESSOR 686 void 687 cpu_boot_secondary_processors(void) 688 { 689 #ifdef VERBOSE_INIT_ARM 690 printf("%s: writing mbox with %#x\n", __func__, arm_cpu_hatched); 691 #endif 692 arm_cpu_mbox = arm_cpu_hatched; 693 membar_producer(); 694 #ifdef _ARM_ARCH_7 695 __asm __volatile("sev; sev; sev"); 696 #endif 697 while (arm_cpu_mbox) { 698 __asm("wfe"); 699 } 700 } 701 702 void 703 xc_send_ipi(struct cpu_info *ci) 704 { 705 KASSERT(kpreempt_disabled()); 706 KASSERT(curcpu() != ci); 707 708 intr_ipi_send(ci != NULL ? ci->ci_kcpuset : NULL, IPI_XCALL); 709 } 710 711 void 712 cpu_ipi(struct cpu_info *ci) 713 { 714 KASSERT(kpreempt_disabled()); 715 KASSERT(curcpu() != ci); 716 717 intr_ipi_send(ci != NULL ? ci->ci_kcpuset : NULL, IPI_GENERIC); 718 } 719 720 #endif /* MULTIPROCESSOR */ 721 722 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS 723 bool 724 mm_md_direct_mapped_phys(paddr_t pa, vaddr_t *vap) 725 { 726 bool rv; 727 vaddr_t va = pmap_direct_mapped_phys(pa, &rv, 0); 728 if (rv) { 729 *vap = va; 730 } 731 return rv; 732 } 733 #endif 734