1 /* $NetBSD: riscv_machdep.c,v 1.51 2026/07/25 15:49:49 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2014, 2019, 2022 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry, and by Nick Hudson. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_ddb.h" 33 #include "opt_modular.h" 34 #include "opt_multiprocessor.h" 35 #include "opt_riscv_debug.h" 36 37 #include <sys/cdefs.h> 38 __RCSID("$NetBSD: riscv_machdep.c,v 1.51 2026/07/25 15:49:49 skrll Exp $"); 39 40 #include <sys/param.h> 41 42 #include <sys/asan.h> 43 #include <sys/boot_flag.h> 44 #include <sys/cpu.h> 45 #include <sys/exec.h> 46 #include <sys/kmem.h> 47 #include <sys/ktrace.h> 48 #include <sys/lwp.h> 49 #include <sys/module.h> 50 #include <sys/mount.h> 51 #include <sys/msgbuf.h> 52 #include <sys/optstr.h> 53 #include <sys/proc.h> 54 #include <sys/reboot.h> 55 #include <sys/syscall.h> 56 #include <sys/sysctl.h> 57 #include <sys/systm.h> 58 59 #include <dev/cons.h> 60 #ifdef __HAVE_MM_MD_KERNACC 61 #include <dev/mm.h> 62 #endif 63 64 #include <uvm/uvm_extern.h> 65 66 #include <riscv/cpufunc.h> 67 #include <riscv/frame.h> 68 #include <riscv/locore.h> 69 #include <riscv/machdep.h> 70 #include <riscv/pte.h> 71 #include <riscv/sbi.h> 72 #include <riscv/userret.h> 73 74 #include <libfdt.h> 75 #include <dev/fdt/fdtvar.h> 76 #include <dev/fdt/fdt_boot.h> 77 #include <dev/fdt/fdt_console.h> 78 #include <dev/fdt/fdt_memory.h> 79 #include <dev/fdt/fdt_private.h> 80 #include <dev/fdt/fdt_platform.h> 81 82 int cpu_printfataltraps = 1; 83 char machine[] = MACHINE; 84 char machine_arch[] = MACHINE_ARCH; 85 86 #ifdef VERBOSE_INIT_RISCV 87 #define VPRINTF(...) printf(__VA_ARGS__) 88 #else 89 #define VPRINTF(...) __nothing 90 #endif 91 92 /* 64 should be enough, even for a ZFS UUID */ 93 #define MAX_BOOT_DEV_STR 64 94 95 char bootdevstr[MAX_BOOT_DEV_STR] = ""; 96 char *boot_args = NULL; 97 98 paddr_t physical_start; 99 paddr_t physical_end; 100 101 static void 102 earlyconsputc(dev_t dev, int c) 103 { 104 uartputc(c); 105 } 106 107 static int 108 earlyconsgetc(dev_t dev) 109 { 110 return uartgetc(); 111 } 112 113 static struct consdev earlycons = { 114 .cn_putc = earlyconsputc, 115 .cn_getc = earlyconsgetc, 116 .cn_pollc = nullcnpollc, 117 }; 118 119 struct vm_map *phys_map; 120 121 struct trapframe cpu_ddb_regs; 122 const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = { 123 #ifdef FPE 124 [PCU_FPU] = &pcu_fpu_ops, 125 #endif 126 }; 127 128 /* 129 * Used by PHYSTOV and VTOPHYS -- Will be set be BSS is zeroed so 130 * keep it in data 131 */ 132 unsigned long kern_vtopdiff __attribute__((__section__(".data"))); 133 134 135 /* 136 * machine dependent system variables. 137 */ 138 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 139 { 140 sysctl_createv(clog, 0, NULL, NULL, 141 CTLFLAG_PERMANENT, 142 CTLTYPE_NODE, "machdep", NULL, 143 NULL, 0, NULL, 0, 144 CTL_MACHDEP, CTL_EOL); 145 } 146 147 /* 148 * Set registers on exec. 149 * Clear all registers except sp, pc. 150 * sp is set to the stack pointer passed in. pc is set to the entry 151 * point given by the exec_package passed in. 152 */ 153 void 154 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 155 { 156 struct trapframe * const tf = l->l_md.md_utf; 157 struct proc * const p = l->l_proc; 158 159 memset(tf, 0, sizeof(*tf)); 160 tf->tf_sp = (intptr_t)stack_align(stack); 161 tf->tf_pc = (intptr_t)pack->ep_entry & ~1; 162 #ifdef _LP64 163 tf->tf_sr = (p->p_flag & PK_32) ? SR_USER32 : SR_USER64; 164 #else 165 tf->tf_sr = SR_USER; 166 #endif 167 168 // Set up arguments for ___start(cleanup, ps_strings) 169 tf->tf_a0 = 0; // cleanup 170 tf->tf_a1 = p->p_psstrp; // ps_strings 171 172 /* 173 * Must have interrupts disabled for exception return. 174 * Must be switching to user mode. 175 * Must enable interrupts after sret. 176 */ 177 KASSERT(__SHIFTOUT(tf->tf_sr, SR_SIE) == 0); 178 KASSERT(__SHIFTOUT(tf->tf_sr, SR_SPP) == 0); 179 KASSERT(__SHIFTOUT(tf->tf_sr, SR_SPIE) != 0); 180 } 181 182 void 183 md_child_return(struct lwp *l) 184 { 185 struct trapframe * const tf = lwp_trapframe(l); 186 187 tf->tf_a0 = 0; 188 tf->tf_a1 = 1; 189 #ifdef FPE 190 /* Disable FP as we can't be using it (yet). */ 191 tf->tf_sr &= ~SR_FS; 192 #endif 193 194 /* 195 * Must have interrupts disabled for exception return. 196 * Must be switching to user mode. 197 * Must enable interrupts after sret. 198 */ 199 200 KASSERT(__SHIFTOUT(tf->tf_sr, SR_SIE) == 0); 201 KASSERT(__SHIFTOUT(tf->tf_sr, SR_SPP) == 0); 202 KASSERT(__SHIFTOUT(tf->tf_sr, SR_SPIE) != 0); 203 204 userret(l); 205 } 206 207 /* 208 * Process the tail end of a posix_spawn() for the child. 209 */ 210 void 211 cpu_spawn_return(struct lwp *l) 212 { 213 userret(l); 214 } 215 216 /* 217 * Start a new LWP 218 */ 219 void 220 startlwp(void *arg) 221 { 222 ucontext_t * const uc = arg; 223 lwp_t * const l = curlwp; 224 int error __diagused; 225 226 error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 227 KASSERT(error == 0); 228 229 kmem_free(uc, sizeof(*uc)); 230 userret(l); 231 } 232 233 // We've worked hard to make sure struct reg and __gregset_t are the same. 234 // Ditto for struct fpreg and fregset_t. 235 236 #ifdef _LP64 237 CTASSERT(sizeof(struct reg) == sizeof(__gregset_t)); 238 #endif 239 CTASSERT(sizeof(struct fpreg) == sizeof(__fregset_t)); 240 241 void 242 cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) 243 { 244 const struct trapframe * const tf = l->l_md.md_utf; 245 246 /* Save register context. */ 247 *(struct reg *)mcp->__gregs = tf->tf_regs; 248 249 *flags |= _UC_CPU | _UC_TLSBASE; 250 251 /* Save floating point register context, if any. */ 252 KASSERT(l == curlwp); 253 if (fpu_valid_p(l)) { 254 /* 255 * If this process is the current FP owner, dump its 256 * context to the PCB first. 257 */ 258 fpu_save(l); 259 260 struct pcb * const pcb = lwp_getpcb(l); 261 *(struct fpreg *)mcp->__fregs = pcb->pcb_fpregs; 262 *flags |= _UC_FPU; 263 } 264 } 265 266 int 267 cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) 268 { 269 /* 270 * Verify that at least the PC and SP are user addresses. 271 */ 272 if ((intptr_t) mcp->__gregs[_REG_PC] < 0 273 || (intptr_t) mcp->__gregs[_REG_SP] < 0 274 || (mcp->__gregs[_REG_PC] & 1)) 275 return EINVAL; 276 277 return 0; 278 } 279 280 int 281 cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 282 { 283 struct trapframe * const tf = l->l_md.md_utf; 284 struct proc * const p = l->l_proc; 285 const __greg_t * const gr = mcp->__gregs; 286 int error; 287 288 /* Restore register context, if any. */ 289 if (flags & _UC_CPU) { 290 error = cpu_mcontext_validate(l, mcp); 291 if (error) 292 return error; 293 294 /* 295 * Avoid updating TLS register here. 296 */ 297 const __greg_t saved_tp = tf->tf_reg[_REG_TP]; 298 tf->tf_regs = *(const struct reg *)gr; 299 tf->tf_reg[_REG_TP] = saved_tp; 300 } 301 302 /* Restore the private thread context */ 303 if (flags & _UC_TLSBASE) { 304 lwp_setprivate(l, (void *)(intptr_t)mcp->__gregs[_X_TP]); 305 } 306 307 /* Restore floating point register context, if any. */ 308 if (flags & _UC_FPU) { 309 KASSERT(l == curlwp); 310 /* Tell PCU we are replacing the FPU contents. */ 311 fpu_replace(l); 312 313 /* 314 * The PCB FP regs struct includes the FP CSR, so use the 315 * proper size of fpreg when copying. 316 */ 317 struct pcb * const pcb = lwp_getpcb(l); 318 pcb->pcb_fpregs = *(const struct fpreg *)mcp->__fregs; 319 } 320 321 mutex_enter(p->p_lock); 322 if (flags & _UC_SETSTACK) 323 l->l_sigstk.ss_flags |= SS_ONSTACK; 324 if (flags & _UC_CLRSTACK) 325 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 326 mutex_exit(p->p_lock); 327 328 return 0; 329 } 330 331 void 332 cpu_need_resched(struct cpu_info *ci, struct lwp *l, int flags) 333 { 334 KASSERT(kpreempt_disabled()); 335 336 if ((flags & RESCHED_KPREEMPT) != 0) { 337 #ifdef __HAVE_PREEMPTION 338 if ((flags & RESCHED_REMOTE) != 0) { 339 cpu_send_ipi(ci, IPI_KPREEMPT); 340 } else { 341 softint_trigger(SOFTINT_KPREEMPT); 342 } 343 #endif 344 return; 345 } 346 if ((flags & RESCHED_REMOTE) != 0) { 347 #ifdef MULTIPROCESSOR 348 cpu_send_ipi(ci, IPI_AST); 349 #endif 350 } else { 351 l->l_md.md_astpending = 1; /* force call to ast() */ 352 } 353 } 354 355 void 356 cpu_signotify(struct lwp *l) 357 { 358 KASSERT(kpreempt_disabled()); 359 #ifdef __HAVE_FAST_SOFTINTS 360 KASSERT(lwp_locked(l, NULL)); 361 #endif 362 363 if (l->l_cpu != curcpu()) { 364 #ifdef MULTIPROCESSOR 365 cpu_send_ipi(l->l_cpu, IPI_AST); 366 #endif 367 } else { 368 l->l_md.md_astpending = 1; /* force call to ast() */ 369 } 370 } 371 372 void 373 cpu_need_proftick(struct lwp *l) 374 { 375 KASSERT(kpreempt_disabled()); 376 KASSERT(l->l_cpu == curcpu()); 377 378 l->l_pflag |= LP_OWEUPC; 379 l->l_md.md_astpending = 1; /* force call to ast() */ 380 } 381 382 383 /* Sync the discs, unmount the filesystems, and adjust the todr */ 384 static void 385 bootsync(void) 386 { 387 static bool bootsyncdone = false; 388 389 if (bootsyncdone) 390 return; 391 392 bootsyncdone = true; 393 394 /* Make sure we can still manage to do things */ 395 if ((csr_sstatus_read() & SR_SIE) == 0) { 396 /* 397 * If we get here then boot has been called without RB_NOSYNC 398 * and interrupts were disabled. This means the boot() call 399 * did not come from a user process e.g. shutdown, but must 400 * have come from somewhere in the kernel. 401 */ 402 ENABLE_INTERRUPTS(); 403 printf("Warning interrupts disabled during boot()\n"); 404 } 405 406 vfs_shutdown(); 407 } 408 409 410 void 411 cpu_reboot(int howto, char *bootstr) 412 { 413 414 /* 415 * If RB_NOSYNC was not specified sync the discs. 416 * Note: Unless cold is set to 1 here, syslogd will die during the 417 * unmount. It looks like syslogd is getting woken up only to find 418 * that it cannot page part of the binary in as the filesystem has 419 * been unmounted. 420 */ 421 if ((howto & RB_NOSYNC) == 0) 422 bootsync(); 423 424 #if 0 425 /* Disable interrupts. */ 426 const int s = splhigh(); 427 428 /* Do a dump if requested. */ 429 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 430 dumpsys(); 431 432 splx(s); 433 #endif 434 435 pmf_system_shutdown(boothowto); 436 437 /* Say NO to interrupts for good */ 438 splhigh(); 439 440 /* Run any shutdown hooks */ 441 doshutdownhooks(); 442 443 /* Make sure IRQ's are disabled */ 444 DISABLE_INTERRUPTS(); 445 446 if (howto & RB_HALT) { 447 if (howto & RB_POWERDOWN) { 448 printf("power off...\n"); 449 sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, 450 SBI_RESET_REASON_NONE); 451 } /* FALLTHRU */ 452 printf("\n"); 453 printf("The operating system has halted.\n"); 454 printf("Please press any key to reboot.\n\n"); 455 cnpollc(true); /* for proper keyboard command handling */ 456 if (cngetc() == 0) { 457 /* no console attached, so just hlt */ 458 printf("No keyboard - cannot reboot after all.\n"); 459 goto spin; 460 } 461 cnpollc(false); 462 } 463 464 printf("rebooting...\n"); 465 466 sbi_system_reset(SBI_RESET_TYPE_COLDREBOOT, SBI_RESET_REASON_NONE); 467 spin: 468 for (;;) { 469 asm volatile("wfi" ::: "memory"); 470 } 471 /* NOTREACHED */ 472 } 473 474 void 475 cpu_dumpconf(void) 476 { 477 // TBD!! 478 } 479 480 481 int 482 cpu_lwp_setprivate(lwp_t *l, void *addr) 483 { 484 struct trapframe * const tf = lwp_trapframe(l); 485 486 tf->tf_reg[_REG_TP] = (register_t)addr; 487 488 return 0; 489 } 490 491 492 void 493 cpu_startup(void) 494 { 495 vaddr_t minaddr, maxaddr; 496 char pbuf[10]; /* "999999 MB" -- But Sv39 is max 512GB */ 497 498 /* 499 * Good {morning,afternoon,evening,night}. 500 */ 501 printf("%s%s", copyright, version); 502 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 503 printf("total memory = %s\n", pbuf); 504 505 minaddr = 0; 506 /* 507 * Allocate a submap for physio. 508 */ 509 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 510 VM_PHYS_SIZE, 0, FALSE, NULL); 511 512 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false))); 513 printf("avail memory = %s\n", pbuf); 514 515 #ifdef MULTIPROCESSOR 516 kcpuset_create(&cpus_halted, true); 517 KASSERT(cpus_halted != NULL); 518 519 kcpuset_create(&cpus_hatched, true); 520 KASSERT(cpus_hatched != NULL); 521 522 kcpuset_create(&cpus_paused, true); 523 KASSERT(cpus_paused != NULL); 524 525 kcpuset_create(&cpus_resumed, true); 526 KASSERT(cpus_resumed != NULL); 527 528 kcpuset_create(&cpus_running, true); 529 KASSERT(cpus_running != NULL); 530 531 kcpuset_set(cpus_hatched, cpu_index(curcpu())); 532 kcpuset_set(cpus_running, cpu_index(curcpu())); 533 #endif 534 535 fdtbus_intr_init(); 536 537 fdt_setup_rndseed(); 538 fdt_setup_efirng(); 539 } 540 541 static void 542 riscv_add_memory(const struct fdt_memory *m, void *arg) 543 { 544 paddr_t first = atop(m->start); 545 paddr_t last = atop(m->end); 546 int freelist = VM_FREELIST_DEFAULT; 547 548 VPRINTF("adding %#16" PRIxPADDR " - %#16" PRIxPADDR" to freelist %d\n", 549 m->start, m->end, freelist); 550 551 uvm_page_physload(first, last, first, last, freelist); 552 physmem += last - first; 553 } 554 555 556 static void 557 cpu_kernel_vm_init(paddr_t memory_start, paddr_t memory_end) 558 { 559 extern char __kernel_text[]; 560 extern char _end[]; 561 562 vaddr_t kernstart = trunc_page((vaddr_t)__kernel_text); 563 vaddr_t kernend = round_page((vaddr_t)_end); 564 paddr_t kernstart_phys = KERN_VTOPHYS(kernstart); 565 paddr_t kernend_phys = KERN_VTOPHYS(kernend); 566 567 VPRINTF("%s: kernel phys start %#" PRIxPADDR " end %#" PRIxPADDR "\n", 568 __func__, kernstart_phys, kernend_phys); 569 fdt_memory_remove_range(kernstart_phys, 570 kernend_phys - kernstart_phys); 571 572 #if 0 573 /* 574 * Don't give these pages to UVM. 575 * 576 * cpu_kernel_vm_init need to create proper tables then the following 577 * will be true. 578 * 579 * Now we have APs started the pages used for stacks and L1PT can 580 * be given to uvm 581 */ 582 extern char const __start__init_memory[]; 583 extern char const __stop__init_memory[] __weak; 584 if (&__start__init_memory[0] != &__stop__init_memory[0]) { 585 const paddr_t spa = KERN_VTOPHYS((vaddr_t)__start__init_memory); 586 const paddr_t epa = KERN_VTOPHYS((vaddr_t)__stop__init_memory); 587 588 VPRINTF("%s: init phys start %#" PRIxPADDR 589 " end %#" PRIxPADDR "\n", __func__, spa, epa); 590 fdt_memory_remove_range(spa, epa - spa); 591 } 592 #endif 593 594 #ifdef _LP64 595 paddr_t pa = memory_start & ~XSEGOFSET; 596 pmap_direct_base = RISCV_DIRECTMAP_START; 597 extern pd_entry_t l2_pte[PAGE_SIZE / sizeof(pd_entry_t)]; 598 599 600 const vsize_t vshift = XSEGSHIFT; 601 const vaddr_t pdetab_mask = PMAP_PDETABSIZE - 1; 602 const vsize_t inc = 1UL << vshift; 603 604 const vaddr_t sva = RISCV_DIRECTMAP_START + pa; 605 const vaddr_t eva = RISCV_DIRECTMAP_END; 606 const size_t sidx = (sva >> vshift) & pdetab_mask; 607 const size_t eidx = (eva >> vshift) & pdetab_mask; 608 609 /* Allocate gigapages covering all physical memory in the direct map. */ 610 pt_entry_t pbmt_flag = pte_enter_flags_to_pbmt(0); 611 for (size_t i = sidx; i < eidx && pa < memory_end; i++, pa += inc) { 612 l2_pte[i] = PA_TO_PTE(pa) | PTE_KERN | PTE_HARDWIRED | PTE_RW | 613 pbmt_flag; 614 VPRINTF("dm: %p : %#" PRIxPADDR "\n", &l2_pte[i], l2_pte[i]); 615 } 616 #endif 617 // pt_dump(printf); 618 } 619 620 static void 621 riscv_init_lwp0_uarea(void) 622 { 623 extern char lwp0uspace[]; 624 625 uvm_lwp_setuarea(&lwp0, (vaddr_t)lwp0uspace); 626 memset(&lwp0.l_md, 0, sizeof(lwp0.l_md)); 627 memset(lwp_getpcb(&lwp0), 0, sizeof(struct pcb)); 628 629 struct trapframe *tf = (struct trapframe *)(lwp0uspace + USPACE) - 1; 630 memset(tf, 0, sizeof(*tf)); 631 632 lwp0.l_md.md_utf = lwp0.l_md.md_ktf = tf; 633 } 634 635 636 static void 637 riscv_print_memory(const struct fdt_memory *m, void *arg) 638 { 639 640 VPRINTF("FDT /memory @ 0x%" PRIx64 " size 0x%" PRIx64 "\n", 641 m->start, m->end - m->start); 642 } 643 644 645 static void 646 parse_mi_bootargs(char *args) 647 { 648 int howto; 649 bool found, start, skipping; 650 651 if (args == NULL) 652 return; 653 654 start = true; 655 skipping = false; 656 for (char *cp = args; *cp; cp++) { 657 /* check for "words" starting with a "-" only */ 658 if (start) { 659 if (*cp == '-') { 660 skipping = false; 661 } else { 662 skipping = true; 663 } 664 start = false; 665 continue; 666 } 667 668 if (*cp == ' ') { 669 start = true; 670 skipping = false; 671 continue; 672 } 673 674 if (skipping) { 675 continue; 676 } 677 678 /* Check valid boot flags */ 679 howto = 0; 680 BOOT_FLAG(*cp, howto); 681 if (!howto) 682 printf("bootflag '%c' not recognised\n", *cp); 683 else 684 boothowto |= howto; 685 } 686 687 found = optstr_get(args, "root", bootdevstr, sizeof(bootdevstr)); 688 if (found) { 689 bootspec = bootdevstr; 690 } 691 } 692 693 694 void 695 init_riscv(register_t hartid, paddr_t dtb) 696 { 697 698 /* set temporally to work printf()/panic() even before consinit() */ 699 cn_tab = &earlycons; 700 701 /* Load FDT */ 702 const vaddr_t dtbva = VM_KERNEL_DTB_BASE + (dtb & (NBSEG - 1)); 703 void *fdt_data = (void *)dtbva; 704 int error = fdt_check_header(fdt_data); 705 if (error != 0) 706 panic("fdt_check_header failed: %s", fdt_strerror(error)); 707 708 fdtbus_init(fdt_data); 709 710 /* Lookup platform specific backend */ 711 const struct fdt_platform * const plat = fdt_platform_find(); 712 if (plat == NULL) 713 panic("Kernel does not support this device"); 714 715 /* Early console may be available, announce ourselves. */ 716 VPRINTF("FDT<%p>\n", fdt_data); 717 718 boot_args = fdt_get_bootargs(); 719 720 /* Heads up ... Setup the CPU / MMU / TLB functions. */ 721 VPRINTF("cpufunc\n"); 722 if (set_cpufuncs()) 723 panic("cpu not recognized!"); 724 725 VPRINTF("devmap %p\n", plat->fp_devmap()); 726 pmap_devmap_bootstrap(0, plat->fp_devmap()); 727 728 VPRINTF("bootstrap\n"); 729 plat->fp_bootstrap(); 730 731 /* 732 * If stdout-path is specified on the command line, override the 733 * value in /chosen/stdout-path before initializing console. 734 */ 735 VPRINTF("stdout\n"); 736 fdt_update_stdout_path(fdt_data, boot_args); 737 738 /* 739 * Done making changes to the FDT. 740 */ 741 fdt_pack(fdt_data); 742 743 const uint32_t dtbsize = round_page(fdt_totalsize(fdt_data)); 744 745 VPRINTF("fdt size %x/%x\n", dtbsize, fdt_totalsize(fdt_data)); 746 747 VPRINTF("consinit "); 748 consinit(); 749 VPRINTF("ok\n"); 750 751 /* Talk to the user */ 752 printf("NetBSD/riscv (fdt) booting ...\n"); 753 754 #ifdef BOOT_ARGS 755 char mi_bootargs[] = BOOT_ARGS; 756 parse_mi_bootargs(mi_bootargs); 757 #endif 758 759 uint64_t memory_start, memory_end; 760 fdt_memory_get(&memory_start, &memory_end); 761 physical_start = memory_start; 762 physical_end = memory_end; 763 764 fdt_memory_foreach(riscv_print_memory, NULL); 765 766 /* Cannot map memory above largest page number */ 767 const uint64_t maxppn = __SHIFTOUT_MASK(PTE_PPN) - 1; 768 const uint64_t memory_limit = ptoa(maxppn); 769 770 if (memory_end > memory_limit) { 771 fdt_memory_remove_range(memory_limit, memory_end - memory_limit); 772 memory_end = memory_limit; 773 } 774 775 uint64_t memory_size __unused = memory_end - memory_start; 776 777 VPRINTF("%s: memory start %" PRIx64 " end %" PRIx64 " (len %" 778 PRIx64 ")\n", __func__, memory_start, memory_end, memory_size); 779 780 /* Parse ramdisk, rndseed, and firmware's RNG from EFI */ 781 fdt_probe_initrd(); 782 fdt_probe_rndseed(); 783 fdt_probe_efirng(); 784 785 fdt_memory_remove_reserved(memory_start, memory_end); 786 787 fdt_memory_remove_range(dtb, dtbsize); 788 fdt_reserve_initrd(); 789 fdt_reserve_rndseed(); 790 fdt_reserve_efirng(); 791 792 /* Perform PT build and VM init */ 793 cpu_kernel_vm_init(memory_start, memory_end); 794 795 VPRINTF("bootargs: %s\n", boot_args); 796 797 parse_mi_bootargs(boot_args); 798 799 #ifdef DDB 800 if (boothowto & RB_KDB) { 801 printf("Entering DDB...\n"); 802 cpu_Debugger(); 803 } 804 #endif 805 806 extern char __kernel_text[]; 807 extern char _end[]; 808 // extern char __data_start[]; 809 // extern char __rodata_start[]; 810 811 vaddr_t kernstart = trunc_page((vaddr_t)__kernel_text); 812 vaddr_t kernend = round_page((vaddr_t)_end); 813 paddr_t kernstart_phys __unused = KERN_VTOPHYS(kernstart); 814 paddr_t kernend_phys __unused = KERN_VTOPHYS(kernend); 815 816 vaddr_t kernelvmstart; 817 818 vaddr_t kernstart_mega __unused = MEGAPAGE_TRUNC(kernstart); 819 vaddr_t kernend_mega = MEGAPAGE_ROUND(kernend); 820 821 kernelvmstart = kernend_mega; 822 823 #if 0 824 #ifdef MODULAR 825 #define MODULE_RESERVED_MAX (1024 * 1024 * 128) 826 #define MODULE_RESERVED_SIZE (1024 * 1024 * 32) /* good enough? */ 827 module_start = kernelvmstart; 828 module_end = kernend_mega + MODULE_RESERVED_SIZE; 829 if (module_end >= kernstart_mega + MODULE_RESERVED_MAX) 830 module_end = kernstart_mega + MODULE_RESERVED_MAX; 831 KASSERT(module_end > kernend_mega); 832 kernelvmstart = module_end; 833 #endif /* MODULAR */ 834 #endif 835 KASSERT(kernelvmstart < VM_KERNEL_VM_BASE); 836 837 kernelvmstart = VM_KERNEL_VM_BASE; 838 839 /* 840 * msgbuf is allocated from the top of the last biggest memory block. 841 */ 842 paddr_t msgbufaddr = 0; 843 844 #ifdef _LP64 845 /* XXX check all ranges for last one with a big enough hole */ 846 msgbufaddr = memory_end - MSGBUFSIZE; 847 KASSERT(msgbufaddr != 0); /* no space for msgbuf */ 848 fdt_memory_remove_range(msgbufaddr, MSGBUFSIZE); 849 msgbufaddr = RISCV_PA_TO_KVA(msgbufaddr); 850 VPRINTF("msgbufaddr = %#lx\n", msgbufaddr); 851 initmsgbuf((void *)msgbufaddr, MSGBUFSIZE); 852 #endif 853 854 KASSERT(msgbufaddr != 0); /* no space for msgbuf */ 855 #ifdef _LP64 856 initmsgbuf((void *)RISCV_PA_TO_KVA(msgbufaddr), MSGBUFSIZE); 857 #endif 858 859 #define DPRINTF(v) VPRINTF("%24s = 0x%16lx\n", #v, (unsigned long)v); 860 861 VPRINTF("------------------------------------------\n"); 862 DPRINTF(kern_vtopdiff); 863 DPRINTF(memory_start); 864 DPRINTF(memory_end); 865 DPRINTF(memory_size); 866 DPRINTF(kernstart_phys); 867 DPRINTF(kernend_phys) 868 DPRINTF(msgbufaddr); 869 // DPRINTF(physical_end); 870 DPRINTF(VM_MIN_KERNEL_ADDRESS); 871 DPRINTF(kernstart_mega); 872 DPRINTF(kernstart); 873 DPRINTF(kernend); 874 DPRINTF(kernend_mega); 875 #if 0 876 #ifdef MODULAR 877 DPRINTF(module_start); 878 DPRINTF(module_end); 879 #endif 880 #endif 881 DPRINTF(VM_MAX_KERNEL_ADDRESS); 882 #ifdef _LP64 883 DPRINTF(pmap_direct_base); 884 #endif 885 VPRINTF("------------------------------------------\n"); 886 887 #undef DPRINTF 888 889 uvm_md_init(); 890 891 /* 892 * pass memory pages to uvm 893 */ 894 physmem = 0; 895 fdt_memory_foreach(riscv_add_memory, NULL); 896 897 pmap_bootstrap(kernelvmstart, VM_MAX_KERNEL_ADDRESS); 898 899 kasan_init(); 900 901 /* Finish setting up lwp0 on our end before we call main() */ 902 riscv_init_lwp0_uarea(); 903 904 error = 0; 905 if ((boothowto & RB_MD1) == 0) { 906 VPRINTF("mpstart\n"); 907 if (plat->fp_mpstart) 908 error = plat->fp_mpstart(); 909 } 910 if (error) 911 printf("AP startup problems\n"); 912 } 913 914 915 #ifdef __HAVE_MM_MD_KERNACC 916 917 #define IN_RANGE_P(addr, start, end) (start) <= (addr) && (addr) < (end) 918 #ifdef _LP64 919 #define IN_DIRECTMAP_P(va) \ 920 IN_RANGE_P(va, RISCV_DIRECTMAP_START, RISCV_DIRECTMAP_END) 921 #else 922 #define IN_DIRECTMAP_P(va) false 923 #endif 924 925 int 926 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled) 927 { 928 extern char __kernel_text[]; 929 extern char _end[]; 930 extern char __data_start[]; 931 932 const vaddr_t kernstart = trunc_page((vaddr_t)__kernel_text); 933 const vaddr_t kernend = round_page((vaddr_t)_end); 934 const vaddr_t data_start = (vaddr_t)__data_start; 935 936 const vaddr_t va = (vaddr_t)ptr; 937 938 *handled = false; 939 if (IN_RANGE_P(va, kernstart, kernend)) { 940 *handled = true; 941 if (va < data_start && (prot & VM_PROT_WRITE) != 0) { 942 return EFAULT; 943 } 944 } else if (IN_DIRECTMAP_P(va)) { 945 *handled = true; 946 } 947 948 return 0; 949 } 950 #endif 951 952 953 #ifdef _LP64 954 static void 955 pte_bits(void (*pr)(const char *, ...), pt_entry_t pte) 956 { 957 (*pr)("%c%c%c%c%c%c%c%c", 958 (pte & PTE_D) ? 'D' : '.', 959 (pte & PTE_A) ? 'A' : '.', 960 (pte & PTE_G) ? 'G' : '.', 961 (pte & PTE_U) ? 'U' : '.', 962 (pte & PTE_X) ? 'X' : '.', 963 (pte & PTE_W) ? 'W' : '.', 964 (pte & PTE_R) ? 'R' : '.', 965 (pte & PTE_V) ? 'V' : '.'); 966 } 967 968 static void 969 dump_ln_table(paddr_t pdp_pa, int topbit, int level, vaddr_t va, 970 void (*pr)(const char *, ...) __printflike(1, 2)) 971 { 972 pd_entry_t *pdp = (void *)PMAP_DIRECT_MAP(pdp_pa); 973 974 (*pr)("l%u @ pa %#16" PRIxREGISTER "\n", level, pdp_pa); 975 for (size_t i = 0; i < PAGE_SIZE / sizeof(pd_entry_t); i++) { 976 pd_entry_t entry = pdp[i]; 977 978 if (topbit) { 979 va = i << (PGSHIFT + level * SEGLENGTH); 980 if (va & __BIT(topbit)) { 981 va |= __BITS(63, topbit); 982 } 983 } 984 if (entry != 0) { 985 paddr_t pa = __SHIFTOUT(entry, PTE_PPN) << PGSHIFT; 986 // check level PPN bits. 987 if (PTE_ISLEAF_P(entry)) { 988 (*pr)("l%u %3zu va 0x%016lx pa 0x%012lx - ", 989 level, i, va, pa); 990 pte_bits(pr, entry); 991 (*pr)("\n"); 992 } else { 993 (*pr)("l%u %3zu va 0x%016lx -> 0x%012lx - ", 994 level, i, va, pa); 995 pte_bits(pr, entry); 996 (*pr)("\n"); 997 if (level == 0) { 998 (*pr)("wtf\n"); 999 continue; 1000 } 1001 if (pte_pde_valid_p(entry)) 1002 dump_ln_table(pa, 0, level - 1, va, pr); 1003 } 1004 } 1005 va += 1UL << (PGSHIFT + level * SEGLENGTH); 1006 } 1007 } 1008 1009 void 1010 pt_dump(void (*pr)(const char *, ...) __printflike(1, 2)) 1011 { 1012 const register_t satp = csr_satp_read(); 1013 size_t topbit = sizeof(long) * NBBY - 1; 1014 1015 #ifdef _LP64 1016 const paddr_t satp_pa = __SHIFTOUT(satp, SATP_PPN) << PGSHIFT; 1017 const uint8_t mode = __SHIFTOUT(satp, SATP_MODE); 1018 u_int level = 1; 1019 1020 switch (mode) { 1021 case SATP_MODE_SV39: 1022 case SATP_MODE_SV48: 1023 topbit = (39 - 1) + (mode - 8) * SEGLENGTH; 1024 level = mode - 6; 1025 break; 1026 } 1027 #endif 1028 (*pr)("topbit = %zu\n", topbit); 1029 1030 (*pr)("satp = 0x%" PRIxREGISTER "\n", satp); 1031 #ifdef _LP64 1032 dump_ln_table(satp_pa, topbit, level, 0, pr); 1033 #endif 1034 } 1035 #endif 1036 1037 void 1038 consinit(void) 1039 { 1040 static bool initialized = false; 1041 const struct fdt_console *cons = fdtbus_get_console(); 1042 const struct fdt_platform *plat = fdt_platform_find(); 1043 1044 if (initialized || cons == NULL) 1045 return; 1046 1047 u_int uart_freq = 0; 1048 extern struct bus_space riscv_generic_bs_tag; 1049 struct fdt_attach_args faa = { 1050 .faa_bst = &riscv_generic_bs_tag, 1051 }; 1052 1053 faa.faa_phandle = fdtbus_get_stdout_phandle(); 1054 if (plat->fp_uart_freq != NULL) 1055 uart_freq = plat->fp_uart_freq(); 1056 1057 cons->consinit(&faa, uart_freq); 1058 1059 initialized = true; 1060 } 1061