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