1 /* $OpenBSD: machdep.c,v 1.40 2024/11/18 05:32:39 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se> 5 * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/sched.h> 23 #include <sys/proc.h> 24 #include <sys/sysctl.h> 25 #include <sys/reboot.h> 26 #include <sys/mount.h> 27 #include <sys/exec.h> 28 #include <sys/user.h> 29 #include <sys/conf.h> 30 #include <sys/kcore.h> 31 #include <sys/msgbuf.h> 32 #include <sys/buf.h> 33 #include <sys/sensors.h> 34 #include <sys/malloc.h> 35 #include <sys/syscallargs.h> 36 37 #include <net/if.h> 38 #include <uvm/uvm_extern.h> 39 #include <dev/cons.h> 40 #include <dev/ofw/fdt.h> 41 #include <dev/ofw/openfirm.h> 42 #include <machine/param.h> 43 #include <machine/bootconfig.h> 44 #include <machine/bus.h> 45 #include <machine/sbi.h> 46 #include <machine/sysarch.h> 47 48 #include <machine/db_machdep.h> 49 #include <ddb/db_extern.h> 50 51 #include <dev/efi/efi.h> 52 53 #include "softraid.h" 54 #if NSOFTRAID > 0 55 #include <dev/softraidvar.h> 56 #endif 57 58 extern vaddr_t virtual_avail; 59 extern uint64_t esym; 60 61 extern char _start[]; 62 63 char *boot_args = NULL; 64 uint8_t *bootmac = NULL; 65 66 int stdout_node; 67 int stdout_speed; 68 69 void (*cpuresetfn)(void); 70 void (*powerdownfn)(void); 71 72 int cold = 1; 73 74 struct vm_map *exec_map = NULL; 75 struct vm_map *phys_map = NULL; 76 77 int physmem; 78 79 caddr_t msgbufaddr; 80 paddr_t msgbufphys; 81 82 struct user *proc0paddr; 83 84 struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; 85 struct uvm_constraint_range *uvm_md_constraints[] = { 86 &dma_constraint, 87 NULL, 88 }; 89 90 /* the following is used externally (sysctl_hw) */ 91 char machine[] = MACHINE; /* from <machine/param.h> */ 92 93 int safepri = 0; 94 95 uint32_t boot_hart; /* The hart we booted on. */ 96 struct cpu_info cpu_info_primary; 97 struct cpu_info *cpu_info[MAXCPUS] = { &cpu_info_primary }; 98 99 uint64_t tb_freq = 1000000; 100 101 struct fdt_reg memreg[VM_PHYSSEG_MAX]; 102 int nmemreg; 103 104 void memreg_add(const struct fdt_reg *); 105 void memreg_remove(const struct fdt_reg *); 106 107 static int 108 atoi(const char *s) 109 { 110 int n, neg; 111 112 n = 0; 113 neg = 0; 114 115 while (*s == '-') { 116 s++; 117 neg = !neg; 118 } 119 120 while (*s != '\0') { 121 if (*s < '0' || *s > '9') 122 break; 123 124 n = (10 * n) + (*s - '0'); 125 s++; 126 } 127 128 return (neg ? -n : n); 129 } 130 131 void * 132 fdt_find_cons(const char *name) 133 { 134 char *alias = "serial0"; 135 char buf[128]; 136 char *stdout = NULL; 137 char *p; 138 void *node; 139 140 /* First check if "stdout-path" is set. */ 141 node = fdt_find_node("/chosen"); 142 if (node) { 143 if (fdt_node_property(node, "stdout-path", &stdout) > 0) { 144 if (strchr(stdout, ':') != NULL) { 145 strlcpy(buf, stdout, sizeof(buf)); 146 if ((p = strchr(buf, ':')) != NULL) { 147 *p++ = '\0'; 148 stdout_speed = atoi(p); 149 } 150 stdout = buf; 151 } 152 if (stdout[0] != '/') { 153 /* It's an alias. */ 154 alias = stdout; 155 stdout = NULL; 156 } 157 } 158 } 159 160 /* Perform alias lookup if necessary. */ 161 if (stdout == NULL) { 162 node = fdt_find_node("/aliases"); 163 if (node) 164 fdt_node_property(node, alias, &stdout); 165 } 166 167 /* Lookup the physical address of the interface. */ 168 if (stdout) { 169 node = fdt_find_node(stdout); 170 if (node && fdt_is_compatible(node, name)) { 171 stdout_node = OF_finddevice(stdout); 172 return (node); 173 } 174 } 175 176 return (NULL); 177 } 178 179 void com_fdt_init_cons(void); 180 void sfuart_init_cons(void); 181 182 void 183 consinit(void) 184 { 185 static int consinit_called = 0; 186 187 if (consinit_called != 0) 188 return; 189 190 consinit_called = 1; 191 192 com_fdt_init_cons(); 193 sfuart_init_cons(); 194 } 195 196 void 197 cpu_idle_cycle(void) 198 { 199 // Enable interrupts 200 intr_enable(); 201 // XXX Data Sync Barrier? (Maybe SFENCE???) 202 __asm volatile("wfi"); 203 } 204 205 /* Dummy trapframe for proc0. */ 206 struct trapframe proc0tf; 207 208 void 209 cpu_startup(void) 210 { 211 u_int loop; 212 paddr_t minaddr; 213 paddr_t maxaddr; 214 215 proc0.p_addr = proc0paddr; 216 217 /* 218 * Give pmap a chance to set up a few more things now the vm 219 * is initialised 220 */ 221 pmap_postinit(); 222 223 /* 224 * Initialize error message buffer (at end of core). 225 */ 226 227 /* msgbufphys was setup during the secondary boot strap */ 228 for (loop = 0; loop < atop(MSGBUFSIZE); ++loop) 229 pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE, 230 msgbufphys + loop * PAGE_SIZE, PROT_READ | PROT_WRITE); 231 pmap_update(pmap_kernel()); 232 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); 233 234 /* 235 * Identify ourselves for the msgbuf (everything printed earlier will 236 * not be buffered). 237 */ 238 printf("%s", version); 239 240 printf("real mem = %lu (%luMB)\n", ptoa(physmem), 241 ptoa(physmem) / 1024 / 1024); 242 243 /* 244 * Allocate a submap for exec arguments. This map effectively 245 * limits the number of processes exec'ing at any time. 246 */ 247 minaddr = vm_map_min(kernel_map); 248 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 249 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 250 251 /* 252 * Allocate a submap for physio 253 */ 254 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 255 VM_PHYS_SIZE, 0, FALSE, NULL); 256 257 /* 258 * Set up buffers, so they can be used to read disk labels. 259 */ 260 bufinit(); 261 262 printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), 263 ptoa(uvmexp.free) / 1024 / 1024); 264 265 sbi_print_version(); 266 267 curpcb = &proc0.p_addr->u_pcb; 268 curpcb->pcb_flags = 0; 269 curpcb->pcb_tf = &proc0tf; 270 271 if (boothowto & RB_CONFIG) { 272 #ifdef BOOT_CONFIG 273 user_config(); 274 #else 275 printf("kernel does not support -c; continuing..\n"); 276 #endif 277 } 278 } 279 280 /* 281 * Move parts of cpu_switchto into C, too difficult in asm 282 */ 283 284 void cpu_switchto_asm(struct proc *, struct proc *); 285 286 void 287 cpu_switchto(struct proc *old, struct proc *new) 288 { 289 if (old) { 290 struct pcb *pcb = &old->p_addr->u_pcb; 291 struct trapframe *tf = pcb->pcb_tf; 292 293 if (pcb->pcb_flags & PCB_FPU) 294 fpu_save(old, tf); 295 296 /* drop FPU state */ 297 tf->tf_sstatus &= ~SSTATUS_FS_MASK; 298 tf->tf_sstatus |= SSTATUS_FS_OFF; 299 } 300 301 cpu_switchto_asm(old, new); 302 } 303 304 /* 305 * machine dependent system variables. 306 */ 307 308 int 309 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 310 size_t newlen, struct proc *p) 311 { 312 char *compatible; 313 int node, len, error; 314 315 /* all sysctl names at this level are terminal */ 316 if (namelen != 1) 317 return (ENOTDIR); /* overloaded */ 318 319 switch (name[0]) { 320 case CPU_COMPATIBLE: 321 node = OF_finddevice("/"); 322 len = OF_getproplen(node, "compatible"); 323 if (len <= 0) 324 return (EOPNOTSUPP); 325 compatible = malloc(len, M_TEMP, M_WAITOK | M_ZERO); 326 OF_getprop(node, "compatible", compatible, len); 327 compatible[len - 1] = 0; 328 error = sysctl_rdstring(oldp, oldlenp, newp, compatible); 329 free(compatible, M_TEMP, len); 330 return error; 331 default: 332 return (EOPNOTSUPP); 333 } 334 /* NOTREACHED */ 335 } 336 337 int waittime = -1; 338 339 __dead void 340 boot(int howto) 341 { 342 if ((howto & RB_RESET) != 0) 343 goto doreset; 344 345 if (cold) { 346 if ((howto & RB_USERREQ) == 0) 347 howto |= RB_HALT; 348 goto haltsys; 349 } 350 351 boothowto = howto; 352 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 353 waittime = 0; 354 vfs_shutdown(curproc); 355 356 if ((howto & RB_TIMEBAD) == 0) { 357 resettodr(); 358 } else { 359 printf("WARNING: not updating battery clock\n"); 360 } 361 } 362 if_downall(); 363 364 uvm_shutdown(); 365 splhigh(); 366 cold = 1; 367 368 if ((howto & RB_DUMP) != 0) 369 printf("no dump so far\n"); 370 371 haltsys: 372 config_suspend_all(DVACT_POWERDOWN); 373 374 if ((howto & RB_HALT) != 0) { 375 if ((howto & RB_POWERDOWN) != 0) { 376 printf("\nAttempting to power down...\n"); 377 delay(500000); 378 if (powerdownfn) 379 (*powerdownfn)(); 380 } 381 382 printf("\n"); 383 printf("The operating system has halted.\n"); 384 printf("Please press any key to reboot.\n\n"); 385 cngetc(); 386 } 387 388 doreset: 389 printf("rebooting...\n"); 390 delay(500000); 391 if (cpuresetfn) 392 (*cpuresetfn)(); 393 printf("reboot failed; spinning\n"); 394 for (;;) 395 continue; 396 /* NOTREACHED */ 397 } 398 399 void 400 setregs(struct proc *p, struct exec_package *pack, u_long stack, 401 struct ps_strings *arginfo) 402 { 403 struct trapframe *tf = p->p_addr->u_pcb.pcb_tf; 404 struct pcb *pcb = &p->p_addr->u_pcb; 405 406 /* If we were using the FPU, forget about it. */ 407 pcb->pcb_flags &= ~PCB_FPU; 408 tf->tf_sstatus &= ~SSTATUS_FS_MASK; 409 tf->tf_sstatus |= SSTATUS_FS_OFF; 410 411 memset(tf, 0, sizeof *tf); 412 tf->tf_sp = STACKALIGN(stack); 413 tf->tf_ra = pack->ep_entry; 414 tf->tf_sepc = pack->ep_entry; 415 } 416 417 void 418 need_resched(struct cpu_info *ci) 419 { 420 ci->ci_want_resched = 1; 421 422 /* There's a risk we'll be called before the idle threads start */ 423 if (ci->ci_curproc) { 424 aston(ci->ci_curproc); 425 cpu_kick(ci); 426 } 427 } 428 429 430 /* 431 * Size of memory segments, before any memory is stolen. 432 */ 433 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 434 int mem_cluster_cnt; 435 436 /* 437 * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. 438 */ 439 int 440 cpu_dumpsize(void) 441 { 442 int size; 443 444 size = ALIGN(sizeof(kcore_seg_t)) + 445 ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t)); 446 if (roundup(size, dbtob(1)) != dbtob(1)) 447 return (-1); 448 449 return (1); 450 } 451 452 u_long 453 cpu_dump_mempagecnt(void) 454 { 455 return 0; 456 } 457 458 /* 459 * These variables are needed by /sbin/savecore 460 */ 461 u_long dumpmag = 0x8fca0101; /* magic number */ 462 int dumpsize = 0; /* pages */ 463 long dumplo = 0; /* blocks */ 464 465 /* 466 * This is called by main to set dumplo and dumpsize. 467 * Dumps always skip the first PAGE_SIZE of disk space 468 * in case there might be a disk label stored there. 469 * If there is extra space, put dump at the end to 470 * reduce the chance that swapping trashes it. 471 */ 472 void 473 dumpconf(void) 474 { 475 int nblks, dumpblks; /* size of dump area */ 476 477 if (dumpdev == NODEV || 478 (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0) 479 return; 480 if (nblks <= ctod(1)) 481 return; 482 483 dumpblks = cpu_dumpsize(); 484 if (dumpblks < 0) 485 return; 486 dumpblks += ctod(cpu_dump_mempagecnt()); 487 488 /* If dump won't fit (incl. room for possible label), punt. */ 489 if (dumpblks > (nblks - ctod(1))) 490 return; 491 492 /* Put dump at end of partition */ 493 dumplo = nblks - dumpblks; 494 495 /* dumpsize is in page units, and doesn't include headers. */ 496 dumpsize = cpu_dump_mempagecnt(); 497 } 498 499 int 500 sys_sysarch(struct proc *p, void *v, register_t *retval) 501 { 502 struct sys_sysarch_args /* { 503 syscallarg(int) op; 504 syscallarg(void *) parms; 505 } */ *uap = v; 506 struct riscv_sync_icache_args args; 507 int error = 0; 508 509 switch (SCARG(uap, op)) { 510 case RISCV_SYNC_ICACHE: 511 if (SCARG(uap, parms) != NULL) 512 error = copyin(SCARG(uap, parms), &args, sizeof(args)); 513 if (error) 514 break; 515 /* 516 * XXX Validate args.addr and args.len before using them. 517 */ 518 pmap_proc_iflush(p->p_p, (vaddr_t)args.addr, args.len); 519 break; 520 default: 521 error = EINVAL; 522 break; 523 } 524 525 return (error); 526 } 527 528 uint64_t mmap_start; 529 uint32_t mmap_size; 530 uint32_t mmap_desc_size; 531 uint32_t mmap_desc_ver; 532 533 EFI_MEMORY_DESCRIPTOR *mmap; 534 535 void collect_kernel_args(const char *); 536 void process_kernel_args(void); 537 538 int pmap_bootstrap_bs_map(bus_space_tag_t, bus_addr_t, 539 bus_size_t, int, bus_space_handle_t *); 540 541 void 542 initriscv(struct riscv_bootparams *rbp) 543 { 544 paddr_t memstart, memend; 545 paddr_t startpa, endpa, pa; 546 vaddr_t vstart, va; 547 struct fdt_head *fh; 548 void *config = (void *)rbp->dtbp_phys; 549 void *fdt = NULL; 550 struct fdt_reg reg; 551 void *node; 552 EFI_PHYSICAL_ADDRESS system_table = 0; 553 int (*map_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int, 554 bus_space_handle_t *); 555 int i; 556 557 /* Set the per-CPU pointer. */ 558 __asm volatile("mv tp, %0" :: "r"(&cpu_info_primary)); 559 560 sbi_init(); 561 562 /* The bootloader has loaded us into a 64MB block. */ 563 memstart = rbp->kern_phys; 564 memend = memstart + 64 * 1024 * 1024; 565 566 /* Bootstrap enough of pmap to enter the kernel proper. */ 567 vstart = pmap_bootstrap(rbp->kern_phys - KERNBASE, rbp->kern_l1pt, 568 KERNBASE, esym, memstart, memend); 569 570 /* Map the FDT header to determine its size. */ 571 va = vstart; 572 startpa = trunc_page((paddr_t)config); 573 endpa = round_page((paddr_t)config + sizeof(struct fdt_head)); 574 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) 575 pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, PMAP_CACHE_WB); 576 fh = (void *)(vstart + ((paddr_t)config - startpa)); 577 if (betoh32(fh->fh_magic) != FDT_MAGIC || betoh32(fh->fh_size) == 0) 578 panic("%s: no FDT", __func__); 579 580 /* Map the remainder of the FDT. */ 581 endpa = round_page((paddr_t)config + betoh32(fh->fh_size)); 582 for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) 583 pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, PMAP_CACHE_WB); 584 config = (void *)(vstart + ((paddr_t)config - startpa)); 585 vstart = va; 586 587 if (!fdt_init(config)) 588 panic("%s: corrupt FDT", __func__); 589 590 node = fdt_find_node("/cpus"); 591 if (node != NULL) { 592 char *prop; 593 int len; 594 595 len = fdt_node_property(node, "timebase-frequency", &prop); 596 if (len == sizeof(uint32_t)) 597 tb_freq = bemtoh32((uint32_t *)prop); 598 } 599 600 node = fdt_find_node("/chosen"); 601 if (node != NULL) { 602 char *prop; 603 int len; 604 static uint8_t lladdr[6]; 605 606 len = fdt_node_property(node, "boot-hartid", &prop); 607 if (len == sizeof(boot_hart)) 608 boot_hart = bemtoh32((uint32_t *)prop); 609 610 len = fdt_node_property(node, "bootargs", &prop); 611 if (len > 0) 612 collect_kernel_args(prop); 613 614 len = fdt_node_property(node, "openbsd,boothowto", &prop); 615 if (len == sizeof(boothowto)) 616 boothowto = bemtoh32((uint32_t *)prop); 617 618 len = fdt_node_property(node, "openbsd,bootduid", &prop); 619 if (len == sizeof(bootduid)) 620 memcpy(bootduid, prop, sizeof(bootduid)); 621 622 len = fdt_node_property(node, "openbsd,bootmac", &prop); 623 if (len == sizeof(lladdr)) { 624 memcpy(lladdr, prop, sizeof(lladdr)); 625 bootmac = lladdr; 626 } 627 628 len = fdt_node_property(node, "openbsd,sr-bootuuid", &prop); 629 #if NSOFTRAID > 0 630 if (len == sizeof(sr_bootuuid)) 631 memcpy(&sr_bootuuid, prop, sizeof(sr_bootuuid)); 632 #endif 633 if (len > 0) 634 explicit_bzero(prop, len); 635 636 len = fdt_node_property(node, "openbsd,sr-bootkey", &prop); 637 #if NSOFTRAID > 0 638 if (len == sizeof(sr_bootkey)) 639 memcpy(&sr_bootkey, prop, sizeof(sr_bootkey)); 640 #endif 641 if (len > 0) 642 explicit_bzero(prop, len); 643 644 len = fdt_node_property(node, "openbsd,uefi-mmap-start", &prop); 645 if (len == sizeof(mmap_start)) 646 mmap_start = bemtoh64((uint64_t *)prop); 647 len = fdt_node_property(node, "openbsd,uefi-mmap-size", &prop); 648 if (len == sizeof(mmap_size)) 649 mmap_size = bemtoh32((uint32_t *)prop); 650 len = fdt_node_property(node, "openbsd,uefi-mmap-desc-size", &prop); 651 if (len == sizeof(mmap_desc_size)) 652 mmap_desc_size = bemtoh32((uint32_t *)prop); 653 len = fdt_node_property(node, "openbsd,uefi-mmap-desc-ver", &prop); 654 if (len == sizeof(mmap_desc_ver)) 655 mmap_desc_ver = bemtoh32((uint32_t *)prop); 656 657 len = fdt_node_property(node, "openbsd,uefi-system-table", &prop); 658 if (len == sizeof(system_table)) 659 system_table = bemtoh64((uint64_t *)prop); 660 661 len = fdt_node_property(node, "openbsd,dma-constraint", &prop); 662 if (len == sizeof(dma_constraint)) { 663 dma_constraint.ucr_low = bemtoh64((uint64_t *)prop); 664 dma_constraint.ucr_high = bemtoh64((uint64_t *)prop + 1); 665 } 666 } 667 668 process_kernel_args(); 669 670 proc0paddr = (struct user *)rbp->kern_stack; 671 672 msgbufaddr = (caddr_t)vstart; 673 msgbufphys = pmap_steal_avail(round_page(MSGBUFSIZE), PAGE_SIZE, NULL); 674 vstart += round_page(MSGBUFSIZE); 675 676 zero_page = vstart; 677 vstart += MAXCPUS * PAGE_SIZE; 678 copy_src_page = vstart; 679 vstart += MAXCPUS * PAGE_SIZE; 680 copy_dst_page = vstart; 681 vstart += MAXCPUS * PAGE_SIZE; 682 683 /* Relocate the FDT to safe memory. */ 684 if (fdt_get_size(config) != 0) { 685 uint32_t csize, size = round_page(fdt_get_size(config)); 686 paddr_t pa; 687 vaddr_t va; 688 689 pa = pmap_steal_avail(size, PAGE_SIZE, NULL); 690 memcpy((void *)PHYS_TO_DMAP(pa), config, size); 691 for (va = vstart, csize = size; csize > 0; 692 csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE) 693 pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB); 694 695 fdt = (void *)vstart; 696 vstart += size; 697 } 698 699 /* Relocate the EFI memory map too. */ 700 if (mmap_start != 0) { 701 uint32_t csize, size = round_page(mmap_size); 702 paddr_t pa, startpa, endpa; 703 vaddr_t va; 704 705 startpa = trunc_page(mmap_start); 706 endpa = round_page(mmap_start + mmap_size); 707 for (pa = startpa, va = vstart; pa < endpa; 708 pa += PAGE_SIZE, va += PAGE_SIZE) 709 pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB); 710 pa = pmap_steal_avail(size, PAGE_SIZE, NULL); 711 memcpy((void *)PHYS_TO_DMAP(pa), 712 (caddr_t)vstart + (mmap_start - startpa), mmap_size); 713 pmap_kremove(vstart, endpa - startpa); 714 715 for (va = vstart, csize = size; csize > 0; 716 csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE) 717 pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, PMAP_CACHE_WB); 718 719 mmap = (void *)vstart; 720 vstart += size; 721 } 722 723 /* No more KVA stealing after this point. */ 724 virtual_avail = vstart; 725 726 /* Now we can reinit the FDT, using the virtual address. */ 727 if (fdt) 728 fdt_init(fdt); 729 730 map_func_save = riscv64_bs_tag._space_map; 731 riscv64_bs_tag._space_map = pmap_bootstrap_bs_map; 732 733 consinit(); 734 735 riscv64_bs_tag._space_map = map_func_save; 736 737 pmap_avail_fixup(); 738 739 uvmexp.pagesize = PAGE_SIZE; 740 uvm_setpagesize(); 741 742 /* Make what's left of the initial 64MB block available to UVM. */ 743 pmap_physload_avail(); 744 745 /* Make all other physical memory available to UVM. */ 746 if (mmap && mmap_desc_ver == EFI_MEMORY_DESCRIPTOR_VERSION) { 747 EFI_MEMORY_DESCRIPTOR *desc = mmap; 748 749 /* 750 * Load all memory marked as EfiConventionalMemory, 751 * EfiBootServicesCode or EfiBootServicesData. 752 * Don't bother with blocks smaller than 64KB. The 753 * initial 64MB memory block should be marked as 754 * EfiLoaderData so it won't be added here. 755 */ 756 for (i = 0; i < mmap_size / mmap_desc_size; i++) { 757 printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n", 758 desc->Type, desc->PhysicalStart, 759 desc->VirtualStart, desc->NumberOfPages, 760 desc->Attribute); 761 if ((desc->Type == EfiConventionalMemory || 762 desc->Type == EfiBootServicesCode || 763 desc->Type == EfiBootServicesData) && 764 desc->NumberOfPages >= 16) { 765 reg.addr = desc->PhysicalStart; 766 reg.size = ptoa(desc->NumberOfPages); 767 memreg_add(®); 768 } 769 desc = NextMemoryDescriptor(desc, mmap_desc_size); 770 } 771 } else { 772 node = fdt_find_node("/memory"); 773 if (node == NULL) 774 panic("%s: no memory specified", __func__); 775 776 for (i = 0; nmemreg < nitems(memreg); i++) { 777 if (fdt_get_reg(node, i, ®)) 778 break; 779 if (reg.size == 0) 780 continue; 781 memreg_add(®); 782 } 783 } 784 785 /* Remove reserved memory. */ 786 node = fdt_find_node("/reserved-memory"); 787 if (node) { 788 for (node = fdt_child_node(node); node; 789 node = fdt_next_node(node)) { 790 if (fdt_get_reg(node, 0, ®)) 791 continue; 792 if (reg.size == 0) 793 continue; 794 memreg_remove(®); 795 } 796 } 797 798 /* Remove the initial 64MB block. */ 799 reg.addr = memstart; 800 reg.size = memend - memstart; 801 memreg_remove(®); 802 803 for (i = 0; i < nmemreg; i++) { 804 paddr_t start = memreg[i].addr; 805 paddr_t end = start + memreg[i].size; 806 807 uvm_page_physload(atop(start), atop(end), 808 atop(start), atop(end), 0); 809 } 810 811 /* 812 * Determine physical RAM size from the /memory nodes in the 813 * FDT. There can be multiple nodes and each node can contain 814 * multiple ranges. 815 */ 816 node = fdt_find_node("/memory"); 817 if (node == NULL) 818 panic("%s: no memory specified", __func__); 819 while (node) { 820 const char *s = fdt_node_name(node); 821 if (strncmp(s, "memory", 6) == 0 && 822 (s[6] == '\0' || s[6] == '@')) { 823 for (i = 0; i < VM_PHYSSEG_MAX; i++) { 824 if (fdt_get_reg(node, i, ®)) 825 break; 826 if (reg.size == 0) 827 continue; 828 physmem += atop(reg.size); 829 } 830 } 831 832 node = fdt_next_node(node); 833 } 834 835 kmeminit_nkmempages(); 836 837 /* 838 * Make sure that we have enough KVA to initialize UVM. In 839 * particular, we need enough KVA to be able to allocate the 840 * vm_page structures and nkmempages for malloc(9). 841 */ 842 pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 1024 * 1024 * 1024 + 843 physmem * sizeof(struct vm_page) + ptoa(nkmempages)); 844 845 #ifdef DDB 846 db_machine_init(); 847 848 /* Firmware doesn't load symbols. */ 849 ddb_init(); 850 851 if (boothowto & RB_KDB) 852 db_enter(); 853 #endif 854 855 softintr_init(); 856 splraise(IPL_IPI); 857 } 858 859 char bootargs[256]; 860 861 void 862 collect_kernel_args(const char *args) 863 { 864 /* Make a local copy of the bootargs */ 865 strlcpy(bootargs, args, sizeof(bootargs)); 866 } 867 868 void 869 process_kernel_args(void) 870 { 871 char *cp = bootargs; 872 873 if (*cp == 0) 874 return; 875 876 /* Skip the kernel image filename */ 877 while (*cp != ' ' && *cp != 0) 878 cp++; 879 880 if (*cp != 0) 881 *cp++ = 0; 882 883 while (*cp == ' ') 884 cp++; 885 886 boot_args = cp; 887 888 printf("bootargs: %s\n", boot_args); 889 890 /* Setup pointer to boot flags */ 891 while (*cp != '-') 892 if (*cp++ == '\0') 893 return; 894 895 while (*++cp != 0) { 896 switch (*cp) { 897 case 'a': 898 boothowto |= RB_ASKNAME; 899 break; 900 case 'c': 901 boothowto |= RB_CONFIG; 902 break; 903 case 'd': 904 boothowto |= RB_KDB; 905 break; 906 case 's': 907 boothowto |= RB_SINGLE; 908 break; 909 default: 910 printf("unknown option `%c'\n", *cp); 911 break; 912 } 913 } 914 } 915 916 /* 917 * Allow bootstrap to steal KVA after machdep has given it back to pmap. 918 */ 919 int 920 pmap_bootstrap_bs_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, 921 int flags, bus_space_handle_t *bshp) 922 { 923 u_long startpa, pa, endpa; 924 vaddr_t va; 925 926 va = virtual_avail; /* steal memory from virtual avail. */ 927 928 startpa = trunc_page(bpa); 929 endpa = round_page((bpa + size)); 930 931 *bshp = (bus_space_handle_t)(va + (bpa - startpa)); 932 933 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) 934 pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, 935 PMAP_CACHE_DEV); 936 937 virtual_avail = va; 938 939 return 0; 940 } 941 942 void 943 memreg_add(const struct fdt_reg *reg) 944 { 945 int i; 946 947 for (i = 0; i < nmemreg; i++) { 948 if (reg->addr == memreg[i].addr + memreg[i].size) { 949 memreg[i].size += reg->size; 950 return; 951 } 952 if (reg->addr + reg->size == memreg[i].addr) { 953 memreg[i].addr = reg->addr; 954 memreg[i].size += reg->size; 955 return; 956 } 957 } 958 959 if (nmemreg >= nitems(memreg)) 960 return; 961 962 memreg[nmemreg++] = *reg; 963 } 964 965 void 966 memreg_remove(const struct fdt_reg *reg) 967 { 968 uint64_t start = reg->addr; 969 uint64_t end = reg->addr + reg->size; 970 int i, j; 971 972 for (i = 0; i < nmemreg; i++) { 973 uint64_t memstart = memreg[i].addr; 974 uint64_t memend = memreg[i].addr + memreg[i].size; 975 976 if (end <= memstart) 977 continue; 978 if (start >= memend) 979 continue; 980 981 if (start <= memstart) 982 memstart = MIN(end, memend); 983 if (end >= memend) 984 memend = MAX(start, memstart); 985 986 if (start > memstart && end < memend) { 987 if (nmemreg < nitems(memreg)) { 988 memreg[nmemreg].addr = end; 989 memreg[nmemreg].size = memend - end; 990 nmemreg++; 991 } 992 memend = start; 993 } 994 memreg[i].addr = memstart; 995 memreg[i].size = memend - memstart; 996 } 997 998 /* Remove empty slots. */ 999 for (i = nmemreg - 1; i >= 0; i--) { 1000 if (memreg[i].size == 0) { 1001 for (j = i; (j + 1) < nmemreg; j++) 1002 memreg[j] = memreg[j + 1]; 1003 nmemreg--; 1004 } 1005 } 1006 } 1007