1 /* $OpenBSD: machdep.c,v 1.74 2023/01/07 17:29:37 miod Exp $ */ 2 3 /* 4 * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/buf.h> 21 #include <sys/exec.h> 22 #include <sys/exec_elf.h> 23 #include <sys/mount.h> 24 #include <sys/msgbuf.h> 25 #include <sys/proc.h> 26 #include <sys/reboot.h> 27 #include <sys/signalvar.h> 28 #include <sys/syscallargs.h> 29 #include <sys/sysctl.h> 30 #include <sys/systm.h> 31 #include <sys/user.h> 32 33 #include <machine/cpufunc.h> 34 #include <machine/fpu.h> 35 #include <machine/opal.h> 36 #include <machine/pcb.h> 37 #include <machine/psl.h> 38 #include <machine/trap.h> 39 40 #include <net/if.h> 41 #include <uvm/uvm_extern.h> 42 43 #include <dev/ofw/fdt.h> 44 #include <dev/ofw/openfirm.h> 45 #include <dev/cons.h> 46 47 #ifdef DDB 48 #include <machine/db_machdep.h> 49 #include <ddb/db_extern.h> 50 #include <ddb/db_interface.h> 51 #endif 52 53 int cacheline_size = 128; 54 55 struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; 56 struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; 57 58 int cold = 1; 59 int safepri = 0; 60 int physmem; 61 paddr_t physmax; 62 63 struct vm_map *exec_map; 64 struct vm_map *phys_map; 65 66 char machine[] = MACHINE; 67 68 struct user *proc0paddr; 69 70 caddr_t ssym, esym; 71 72 extern char _start[], _end[]; 73 extern char __bss_start[]; 74 75 extern uint64_t opal_base; 76 extern uint64_t opal_entry; 77 int opal_have_console_flush; 78 79 extern char trapcode[], trapcodeend[]; 80 extern char hvtrapcode[], hvtrapcodeend[]; 81 extern char rsttrapcode[], rsttrapcodeend[]; 82 extern char slbtrapcode[], slbtrapcodeend[]; 83 extern char generictrap[]; 84 extern char generichvtrap[]; 85 extern char kern_slbtrap[]; 86 extern char cpu_idle_restore_context[]; 87 88 extern char initstack[]; 89 90 struct fdt_reg memreg[VM_PHYSSEG_MAX]; 91 int nmemreg; 92 93 #ifdef DDB 94 struct fdt_reg initrd_reg; 95 #endif 96 97 void memreg_add(const struct fdt_reg *); 98 void memreg_remove(const struct fdt_reg *); 99 100 uint8_t *bootmac = NULL; 101 102 void parse_bootargs(const char *); 103 const char *parse_bootduid(const char *); 104 const char *parse_bootmac(const char *); 105 106 paddr_t fdt_pa; 107 size_t fdt_size; 108 109 int stdout_node; 110 int stdout_speed; 111 112 static int 113 atoi(const char *s) 114 { 115 int n, neg; 116 117 n = 0; 118 neg = 0; 119 120 while (*s == '-') { 121 s++; 122 neg = !neg; 123 } 124 125 while (*s != '\0') { 126 if (*s < '0' || *s > '9') 127 break; 128 129 n = (10 * n) + (*s - '0'); 130 s++; 131 } 132 133 return (neg ? -n : n); 134 } 135 136 void * 137 fdt_find_cons(void) 138 { 139 char *alias = "serial0"; 140 char buf[128]; 141 char *stdout = NULL; 142 char *p; 143 void *node; 144 145 /* First check if "stdout-path" is set. */ 146 node = fdt_find_node("/chosen"); 147 if (node) { 148 if (fdt_node_property(node, "stdout-path", &stdout) > 0) { 149 if (strchr(stdout, ':') != NULL) { 150 strlcpy(buf, stdout, sizeof(buf)); 151 if ((p = strchr(buf, ':')) != NULL) { 152 *p++ = '\0'; 153 stdout_speed = atoi(p); 154 } 155 stdout = buf; 156 } 157 if (stdout[0] != '/') { 158 /* It's an alias. */ 159 alias = stdout; 160 stdout = NULL; 161 } 162 } 163 } 164 165 /* Perform alias lookup if necessary. */ 166 if (stdout == NULL) { 167 node = fdt_find_node("/aliases"); 168 if (node) 169 fdt_node_property(node, alias, &stdout); 170 } 171 172 /* Lookup the physical address of the interface. */ 173 if (stdout) { 174 node = fdt_find_node(stdout); 175 if (node) { 176 stdout_node = OF_finddevice(stdout); 177 return (node); 178 } 179 } 180 181 return (NULL); 182 } 183 184 void 185 init_powernv(void *fdt, void *tocbase) 186 { 187 struct fdt_reg reg; 188 register_t uspace; 189 paddr_t trap; 190 uint64_t msr; 191 void *node; 192 char *prop; 193 int len; 194 int i; 195 196 /* Store pointer to our struct cpu_info. */ 197 __asm volatile ("mtsprg0 %0" :: "r"(cpu_info_primary)); 198 199 /* Clear BSS. */ 200 memset(__bss_start, 0, _end - __bss_start); 201 202 if (!fdt_init(fdt) || fdt_get_size(fdt) == 0) 203 panic("no FDT"); 204 205 /* Get OPAL base and entry addresses from FDT. */ 206 node = fdt_find_node("/ibm,opal"); 207 if (node) { 208 fdt_node_property(node, "opal-base-address", &prop); 209 opal_base = bemtoh64((uint64_t *)prop); 210 fdt_node_property(node, "opal-entry-address", &prop); 211 opal_entry = bemtoh64((uint64_t *)prop); 212 fdt_node_property(node, "compatible", &prop); 213 214 opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE); 215 216 /* 217 * The following call will fail on Power ISA 2.0x CPUs, 218 * but that is fine since they don't support Radix Tree 219 * translation. On Power ISA 3.0 CPUs this will make 220 * the full TLB available. 221 */ 222 opal_reinit_cpus(OPAL_REINIT_CPUS_MMU_HASH); 223 224 /* Older firmware doesn't implement OPAL_CONSOLE_FLUSH. */ 225 if (opal_check_token(OPAL_CONSOLE_FLUSH) == OPAL_TOKEN_PRESENT) 226 opal_have_console_flush = 1; 227 } 228 229 /* At this point we can call OPAL runtime services and use printf(9). */ 230 printf("Hello, World!\n"); 231 232 /* Stash these such that we can remap the FDT later. */ 233 fdt_pa = (paddr_t)fdt; 234 fdt_size = fdt_get_size(fdt); 235 236 fdt_find_cons(); 237 238 /* 239 * Initialize all traps with the stub that calls the generic 240 * trap handler. 241 */ 242 for (trap = EXC_RST; trap < EXC_END; trap += 32) 243 memcpy((void *)trap, trapcode, trapcodeend - trapcode); 244 245 /* Hypervisor interrupts needs special handling. */ 246 memcpy((void *)EXC_HDSI, hvtrapcode, hvtrapcodeend - hvtrapcode); 247 memcpy((void *)EXC_HISI, hvtrapcode, hvtrapcodeend - hvtrapcode); 248 memcpy((void *)EXC_HEA, hvtrapcode, hvtrapcodeend - hvtrapcode); 249 memcpy((void *)EXC_HMI, hvtrapcode, hvtrapcodeend - hvtrapcode); 250 memcpy((void *)EXC_HFAC, hvtrapcode, hvtrapcodeend - hvtrapcode); 251 memcpy((void *)EXC_HVI, hvtrapcode, hvtrapcodeend - hvtrapcode); 252 253 /* System reset trap needs special handling. */ 254 memcpy((void *)EXC_RST, rsttrapcode, rsttrapcodeend - rsttrapcode); 255 256 /* SLB trap needs special handling as well. */ 257 memcpy((void *)EXC_DSE, slbtrapcode, slbtrapcodeend - slbtrapcode); 258 259 *((void **)TRAP_ENTRY) = generictrap; 260 *((void **)TRAP_HVENTRY) = generichvtrap; 261 *((void **)TRAP_SLBENTRY) = kern_slbtrap; 262 *((void **)TRAP_RSTENTRY) = cpu_idle_restore_context; 263 264 /* Make the stubs visible to the CPU. */ 265 __syncicache(EXC_RSVD, EXC_END - EXC_RSVD); 266 267 /* We're now ready to take traps. */ 268 msr = mfmsr(); 269 mtmsr(msr | (PSL_ME|PSL_RI)); 270 271 cpu_init_features(); 272 cpu_init(); 273 274 /* Add all memory. */ 275 node = fdt_find_node("/"); 276 for (node = fdt_child_node(node); node; node = fdt_next_node(node)) { 277 len = fdt_node_property(node, "device_type", &prop); 278 if (len <= 0) 279 continue; 280 if (strcmp(prop, "memory") != 0) 281 continue; 282 for (i = 0; nmemreg < nitems(memreg); i++) { 283 if (fdt_get_reg(node, i, ®)) 284 break; 285 if (reg.size == 0) 286 continue; 287 memreg_add(®); 288 physmem += atop(reg.size); 289 physmax = MAX(physmax, reg.addr + reg.size); 290 } 291 } 292 293 /* Remove reserved memory. */ 294 node = fdt_find_node("/reserved-memory"); 295 if (node) { 296 for (node = fdt_child_node(node); node; 297 node = fdt_next_node(node)) { 298 if (fdt_get_reg(node, 0, ®)) 299 continue; 300 if (reg.size == 0) 301 continue; 302 memreg_remove(®); 303 } 304 } 305 306 /* Remove interrupt vectors. */ 307 reg.addr = trunc_page(EXC_RSVD); 308 reg.size = round_page(EXC_END); 309 memreg_remove(®); 310 311 /* Remove kernel. */ 312 reg.addr = trunc_page((paddr_t)_start); 313 reg.size = round_page((paddr_t)_end) - reg.addr; 314 memreg_remove(®); 315 316 /* Remove FDT. */ 317 reg.addr = trunc_page((paddr_t)fdt); 318 reg.size = round_page((paddr_t)fdt + fdt_get_size(fdt)) - reg.addr; 319 memreg_remove(®); 320 321 #ifdef DDB 322 /* Load symbols from initrd. */ 323 db_machine_init(); 324 if (initrd_reg.size != 0) 325 memreg_remove(&initrd_reg); 326 ssym = (caddr_t)initrd_reg.addr; 327 esym = ssym + initrd_reg.size; 328 #endif 329 330 pmap_bootstrap(); 331 uvm_setpagesize(); 332 333 for (i = 0; i < nmemreg; i++) { 334 paddr_t start = memreg[i].addr; 335 paddr_t end = start + memreg[i].size; 336 337 uvm_page_physload(atop(start), atop(end), 338 atop(start), atop(end), 0); 339 } 340 341 /* Enable translation. */ 342 msr = mfmsr(); 343 mtmsr(msr | (PSL_DR|PSL_IR)); 344 isync(); 345 346 initmsgbuf((caddr_t)uvm_pageboot_alloc(MSGBUFSIZE), MSGBUFSIZE); 347 348 proc0paddr = (struct user *)initstack; 349 proc0.p_addr = proc0paddr; 350 curpcb = &proc0.p_addr->u_pcb; 351 uspace = (register_t)proc0paddr + USPACE - FRAMELEN; 352 proc0.p_md.md_regs = (struct trapframe *)uspace; 353 } 354 355 void 356 memreg_add(const struct fdt_reg *reg) 357 { 358 int i; 359 360 for (i = 0; i < nmemreg; i++) { 361 if (reg->addr == memreg[i].addr + memreg[i].size) { 362 memreg[i].size += reg->size; 363 return; 364 } 365 if (reg->addr + reg->size == memreg[i].addr) { 366 memreg[i].addr = reg->addr; 367 memreg[i].size += reg->size; 368 return; 369 } 370 } 371 372 if (nmemreg >= nitems(memreg)) 373 return; 374 375 memreg[nmemreg++] = *reg; 376 } 377 378 void 379 memreg_remove(const struct fdt_reg *reg) 380 { 381 uint64_t start = reg->addr; 382 uint64_t end = reg->addr + reg->size; 383 int i, j; 384 385 for (i = 0; i < nmemreg; i++) { 386 uint64_t memstart = memreg[i].addr; 387 uint64_t memend = memreg[i].addr + memreg[i].size; 388 389 if (end <= memstart) 390 continue; 391 if (start >= memend) 392 continue; 393 394 if (start <= memstart) 395 memstart = MIN(end, memend); 396 if (end >= memend) 397 memend = MAX(start, memstart); 398 399 if (start > memstart && end < memend) { 400 if (nmemreg < nitems(memreg)) { 401 memreg[nmemreg].addr = end; 402 memreg[nmemreg].size = memend - end; 403 nmemreg++; 404 } 405 memend = start; 406 } 407 memreg[i].addr = memstart; 408 memreg[i].size = memend - memstart; 409 } 410 411 /* Remove empty slots. */ 412 for (i = nmemreg - 1; i >= 0; i--) { 413 if (memreg[i].size == 0) { 414 for (j = i; (j + 1) < nmemreg; j++) 415 memreg[j] = memreg[j + 1]; 416 nmemreg--; 417 } 418 } 419 } 420 421 #define R_PPC64_RELATIVE 22 422 #define ELF_R_TYPE_RELATIVE R_PPC64_RELATIVE 423 424 /* 425 * Disable optimization for this function to prevent clang from 426 * generating jump tables that need relocation. 427 */ 428 __attribute__((optnone)) void 429 self_reloc(Elf_Dyn *dynamic, Elf_Addr base) 430 { 431 Elf_Word relasz = 0, relaent = sizeof(Elf_RelA); 432 Elf_RelA *rela = NULL; 433 Elf_Addr *addr; 434 Elf_Dyn *dynp; 435 436 for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { 437 switch (dynp->d_tag) { 438 case DT_RELA: 439 rela = (Elf_RelA *)(dynp->d_un.d_ptr + base); 440 break; 441 case DT_RELASZ: 442 relasz = dynp->d_un.d_val; 443 break; 444 case DT_RELAENT: 445 relaent = dynp->d_un.d_val; 446 break; 447 } 448 } 449 450 while (relasz > 0) { 451 switch (ELF_R_TYPE(rela->r_info)) { 452 case ELF_R_TYPE_RELATIVE: 453 addr = (Elf_Addr *)(base + rela->r_offset); 454 *addr = base + rela->r_addend; 455 break; 456 } 457 rela = (Elf_RelA *)((caddr_t)rela + relaent); 458 relasz -= relaent; 459 } 460 } 461 462 void * 463 opal_phys(void *va) 464 { 465 paddr_t pa; 466 467 pmap_extract(pmap_kernel(), (vaddr_t)va, &pa); 468 return (void *)pa; 469 } 470 471 void 472 opal_printf(const char *fmt, ...) 473 { 474 static char buf[256]; 475 uint64_t len; 476 va_list ap; 477 478 va_start(ap, fmt); 479 len = vsnprintf(buf, sizeof(buf), fmt, ap); 480 if (len == (uint64_t)-1) 481 len = 0; 482 else if (len >= sizeof(buf)) 483 len = sizeof(buf) - 1; 484 va_end(ap); 485 486 opal_console_write(0, opal_phys(&len), opal_phys(buf)); 487 } 488 489 int64_t 490 opal_do_console_flush(int64_t term_number) 491 { 492 uint64_t events; 493 int64_t error; 494 495 if (opal_have_console_flush) { 496 error = opal_console_flush(term_number); 497 if (error == OPAL_BUSY_EVENT) { 498 opal_poll_events(NULL); 499 error = OPAL_BUSY; 500 } 501 return error; 502 } else { 503 opal_poll_events(opal_phys(&events)); 504 if (events & OPAL_EVENT_CONSOLE_OUTPUT) 505 return OPAL_BUSY; 506 return OPAL_SUCCESS; 507 } 508 } 509 510 void 511 opal_cnprobe(struct consdev *cd) 512 { 513 } 514 515 void 516 opal_cninit(struct consdev *cd) 517 { 518 } 519 520 int 521 opal_cngetc(dev_t dev) 522 { 523 uint64_t len; 524 char ch; 525 526 for (;;) { 527 len = 1; 528 opal_console_read(0, opal_phys(&len), opal_phys(&ch)); 529 if (len) 530 return ch; 531 opal_poll_events(NULL); 532 } 533 } 534 535 void 536 opal_cnputc(dev_t dev, int c) 537 { 538 uint64_t len = 1; 539 char ch = c; 540 int64_t error; 541 542 opal_console_write(0, opal_phys(&len), opal_phys(&ch)); 543 while (1) { 544 error = opal_do_console_flush(0); 545 if (error != OPAL_BUSY && error != OPAL_PARTIAL) 546 break; 547 delay(1); 548 } 549 } 550 551 void 552 opal_cnpollc(dev_t dev, int on) 553 { 554 } 555 556 struct consdev opal_consdev = { 557 .cn_probe = opal_cnprobe, 558 .cn_init = opal_cninit, 559 .cn_getc = opal_cngetc, 560 .cn_putc = opal_cnputc, 561 .cn_pollc = opal_cnpollc, 562 }; 563 564 struct consdev *cn_tab = &opal_consdev; 565 566 int 567 copyin(const void *uaddr, void *kaddr, size_t len) 568 { 569 pmap_t pm = curproc->p_vmspace->vm_map.pmap; 570 vaddr_t kva; 571 vsize_t klen; 572 int error; 573 574 while (len > 0) { 575 error = pmap_set_user_slb(pm, (vaddr_t)uaddr, &kva, &klen); 576 if (error) 577 return error; 578 if (klen > len) 579 klen = len; 580 error = kcopy((const void *)kva, kaddr, klen); 581 pmap_unset_user_slb(); 582 if (error) 583 return error; 584 585 uaddr = (const char *)uaddr + klen; 586 kaddr = (char *)kaddr + klen; 587 len -= klen; 588 } 589 590 return 0; 591 } 592 593 int 594 copyin32(const uint32_t *uaddr, uint32_t *kaddr) 595 { 596 return copyin(uaddr, kaddr, sizeof(uint32_t)); 597 } 598 599 int 600 copyout(const void *kaddr, void *uaddr, size_t len) 601 { 602 pmap_t pm = curproc->p_vmspace->vm_map.pmap; 603 vaddr_t kva; 604 vsize_t klen; 605 int error; 606 607 while (len > 0) { 608 error = pmap_set_user_slb(pm, (vaddr_t)uaddr, &kva, &klen); 609 if (error) 610 return error; 611 if (klen > len) 612 klen = len; 613 error = kcopy(kaddr, (void *)kva, klen); 614 pmap_unset_user_slb(); 615 if (error) 616 return error; 617 618 kaddr = (const char *)kaddr + klen; 619 uaddr = (char *)uaddr + klen; 620 len -= klen; 621 } 622 623 return 0; 624 } 625 626 /* in locore.S */ 627 extern int copystr(const void *, void *, size_t, size_t *) 628 __attribute__ ((__bounded__(__string__,2,3))); 629 630 int 631 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 632 { 633 pmap_t pm = curproc->p_vmspace->vm_map.pmap; 634 vaddr_t kva; 635 vsize_t klen; 636 size_t count, total; 637 int error = 0; 638 639 if (len == 0) 640 return ENAMETOOLONG; 641 642 total = 0; 643 while (len > 0) { 644 error = pmap_set_user_slb(pm, (vaddr_t)uaddr, &kva, &klen); 645 if (error) 646 goto out; 647 if (klen > len) 648 klen = len; 649 error = copystr((const void *)kva, kaddr, klen, &count); 650 total += count; 651 pmap_unset_user_slb(); 652 if (error == 0 || error == EFAULT) 653 goto out; 654 655 uaddr = (const char *)uaddr + klen; 656 kaddr = (char *)kaddr + klen; 657 len -= klen; 658 } 659 660 out: 661 if (done) 662 *done = total; 663 return error; 664 } 665 666 int 667 copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) 668 { 669 pmap_t pm = curproc->p_vmspace->vm_map.pmap; 670 vaddr_t kva; 671 vsize_t klen; 672 size_t count, total; 673 int error = 0; 674 675 if (len == 0) 676 return ENAMETOOLONG; 677 678 total = 0; 679 while (len > 0) { 680 error = pmap_set_user_slb(pm, (vaddr_t)uaddr, &kva, &klen); 681 if (error) 682 goto out; 683 if (klen > len) 684 klen = len; 685 error = copystr(kaddr, (void *)kva, klen, &count); 686 total += count; 687 pmap_unset_user_slb(); 688 if (error == 0 || error == EFAULT) 689 goto out; 690 691 kaddr = (const char *)kaddr + klen; 692 uaddr = (char *)uaddr + klen; 693 len -= klen; 694 } 695 696 out: 697 if (done) 698 *done = total; 699 return error; 700 } 701 702 void 703 need_resched(struct cpu_info *ci) 704 { 705 ci->ci_want_resched = 1; 706 707 /* There's a risk we'll be called before the idle threads start */ 708 if (ci->ci_curproc) { 709 aston(ci->ci_curproc); 710 cpu_kick(ci); 711 } 712 } 713 714 void 715 cpu_startup(void) 716 { 717 vaddr_t minaddr, maxaddr, va; 718 paddr_t pa, epa; 719 void *fdt; 720 void *node; 721 char *prop; 722 int len; 723 724 printf("%s", version); 725 726 printf("real mem = %lu (%luMB)\n", ptoa(physmem), 727 ptoa(physmem)/1024/1024); 728 729 /* 730 * Allocate a submap for exec arguments. This map effectively 731 * limits the number of processes exec'ing at any time. 732 */ 733 minaddr = vm_map_min(kernel_map); 734 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 735 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 736 737 /* 738 * Allocate a submap for physio. 739 */ 740 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 741 VM_PHYS_SIZE, 0, FALSE, NULL); 742 743 /* 744 * Set up buffers, so they can be used to read disk labels. 745 */ 746 bufinit(); 747 748 printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), 749 ptoa(uvmexp.free)/1024/1024); 750 751 /* Remap the FDT. */ 752 pa = trunc_page(fdt_pa); 753 epa = round_page(fdt_pa + fdt_size); 754 va = (vaddr_t)km_alloc(epa - pa, &kv_any, &kp_none, &kd_waitok); 755 fdt = (void *)(va + (fdt_pa & PAGE_MASK)); 756 while (pa < epa) { 757 pmap_kenter_pa(va, pa, PROT_READ | PROT_WRITE); 758 va += PAGE_SIZE; 759 pa += PAGE_SIZE; 760 } 761 762 if (!fdt_init(fdt) || fdt_get_size(fdt) == 0) 763 panic("can't remap FDT"); 764 765 intr_init(); 766 767 node = fdt_find_node("/chosen"); 768 if (node) { 769 len = fdt_node_property(node, "bootargs", &prop); 770 if (len > 0) 771 parse_bootargs(prop); 772 773 len = fdt_node_property(node, "openbsd,boothowto", &prop); 774 if (len == sizeof(boothowto)) 775 boothowto = bemtoh32((uint32_t *)prop); 776 777 len = fdt_node_property(node, "openbsd,bootduid", &prop); 778 if (len == sizeof(bootduid)) 779 memcpy(bootduid, prop, sizeof(bootduid)); 780 } 781 782 if (boothowto & RB_CONFIG) { 783 #ifdef BOOT_CONFIG 784 user_config(); 785 #else 786 printf("kernel does not support -c; continuing..\n"); 787 #endif 788 } 789 } 790 791 void 792 parse_bootargs(const char *bootargs) 793 { 794 const char *cp = bootargs; 795 796 if (strncmp(cp, "bootduid=", strlen("bootduid=")) == 0) 797 cp = parse_bootduid(cp + strlen("bootduid=")); 798 799 if (strncmp(cp, "bootmac=", strlen("bootmac=")) == 0) 800 cp = parse_bootmac(cp + strlen("bootmac=")); 801 802 while (*cp != '-') 803 if (*cp++ == '\0') 804 return; 805 cp++; 806 807 while (*cp != 0) { 808 switch(*cp) { 809 case 'a': 810 boothowto |= RB_ASKNAME; 811 break; 812 case 'c': 813 boothowto |= RB_CONFIG; 814 break; 815 case 'd': 816 boothowto |= RB_KDB; 817 break; 818 case 's': 819 boothowto |= RB_SINGLE; 820 break; 821 default: 822 printf("unknown option `%c'\n", *cp); 823 break; 824 } 825 cp++; 826 } 827 } 828 829 const char * 830 parse_bootduid(const char *bootarg) 831 { 832 const char *cp = bootarg; 833 uint64_t duid = 0; 834 int digit, count = 0; 835 836 while (count < 16) { 837 if (*cp >= '0' && *cp <= '9') 838 digit = *cp - '0'; 839 else if (*cp >= 'a' && *cp <= 'f') 840 digit = *cp - 'a' + 10; 841 else 842 break; 843 duid *= 16; 844 duid += digit; 845 count++; 846 cp++; 847 } 848 849 if (count > 0) { 850 memcpy(&bootduid, &duid, sizeof(bootduid)); 851 return cp; 852 } 853 854 return bootarg; 855 } 856 857 const char * 858 parse_bootmac(const char *bootarg) 859 { 860 static uint8_t lladdr[6]; 861 const char *cp = bootarg; 862 int digit, count = 0; 863 864 memset(lladdr, 0, sizeof(lladdr)); 865 866 while (count < 12) { 867 if (*cp >= '0' && *cp <= '9') 868 digit = *cp - '0'; 869 else if (*cp >= 'a' && *cp <= 'f') 870 digit = *cp - 'a' + 10; 871 else if (*cp == ':') { 872 cp++; 873 continue; 874 } else 875 break; 876 lladdr[count / 2] |= digit << (4 * !(count % 2)); 877 count++; 878 cp++; 879 } 880 881 if (count > 0) { 882 bootmac = lladdr; 883 return cp; 884 } 885 886 return bootarg; 887 } 888 889 #define PSL_USER \ 890 (PSL_SF | PSL_HV | PSL_EE | PSL_PR | PSL_ME | PSL_IR | PSL_DR | PSL_RI) 891 892 void 893 setregs(struct proc *p, struct exec_package *pack, u_long stack, 894 struct ps_strings *arginfo) 895 { 896 struct trapframe *frame = p->p_md.md_regs; 897 struct pcb *pcb = &p->p_addr->u_pcb; 898 899 memset(frame, 0, sizeof(*frame)); 900 frame->fixreg[1] = stack; 901 frame->fixreg[3] = arginfo->ps_nargvstr; 902 frame->fixreg[4] = (register_t)arginfo->ps_argvstr; 903 frame->fixreg[5] = (register_t)arginfo->ps_envstr; 904 frame->fixreg[6] = (register_t)pack->ep_auxinfo; 905 frame->fixreg[12] = pack->ep_entry; 906 frame->srr0 = pack->ep_entry; 907 frame->srr1 = PSL_USER; 908 909 memset(&pcb->pcb_slb, 0, sizeof(pcb->pcb_slb)); 910 memset(&pcb->pcb_fpstate, 0, sizeof(pcb->pcb_fpstate)); 911 pcb->pcb_flags = 0; 912 } 913 914 int 915 sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip, 916 int info, int onstack) 917 { 918 struct proc *p = curproc; 919 struct pcb *pcb = &p->p_addr->u_pcb; 920 struct trapframe *tf = p->p_md.md_regs; 921 struct sigframe *fp, frame; 922 siginfo_t *sip = NULL; 923 int i; 924 925 /* Allocate space for the signal handler context. */ 926 if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && 927 !sigonstack(tf->fixreg[1]) && onstack) 928 fp = (struct sigframe *) 929 trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); 930 else 931 fp = (struct sigframe *)tf->fixreg[1]; 932 933 fp = (struct sigframe *)(STACKALIGN(fp - 1) - 288); 934 935 /* Save FPU state to PCB if necessary. */ 936 if (pcb->pcb_flags & (PCB_FPU|PCB_VEC|PCB_VSX) && 937 tf->srr1 & (PSL_FPU|PSL_VEC|PSL_VSX)) { 938 tf->srr1 &= ~(PSL_FPU|PSL_VEC|PSL_VSX); 939 save_vsx(p); 940 } 941 942 /* Build stack frame for signal trampoline. */ 943 memset(&frame, 0, sizeof(frame)); 944 frame.sf_signum = sig; 945 946 /* Save register context. */ 947 for (i = 0; i < 32; i++) 948 frame.sf_sc.sc_reg[i] = tf->fixreg[i]; 949 frame.sf_sc.sc_lr = tf->lr; 950 frame.sf_sc.sc_cr = tf->cr; 951 frame.sf_sc.sc_xer = tf->xer; 952 frame.sf_sc.sc_ctr = tf->ctr; 953 frame.sf_sc.sc_pc = tf->srr0; 954 frame.sf_sc.sc_ps = PSL_USER; 955 frame.sf_sc.sc_vrsave = tf->vrsave; 956 957 /* Copy the saved FPU state into the frame if necessary. */ 958 if (pcb->pcb_flags & (PCB_FPU|PCB_VEC|PCB_VSX)) { 959 memcpy(frame.sf_sc.sc_vsx, pcb->pcb_fpstate.fp_vsx, 960 sizeof(pcb->pcb_fpstate.fp_vsx)); 961 frame.sf_sc.sc_fpscr = pcb->pcb_fpstate.fp_fpscr; 962 frame.sf_sc.sc_vscr = pcb->pcb_fpstate.fp_vscr; 963 } 964 965 /* Save signal mask. */ 966 frame.sf_sc.sc_mask = mask; 967 968 if (info) { 969 sip = &fp->sf_si; 970 frame.sf_si = *ksip; 971 } 972 973 frame.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie; 974 if (copyout(&frame, fp, sizeof(frame))) 975 return 1; 976 977 /* 978 * Build context to run handler in. 979 */ 980 tf->fixreg[1] = (register_t)fp; 981 tf->fixreg[3] = sig; 982 tf->fixreg[4] = (register_t)sip; 983 tf->fixreg[5] = (register_t)&fp->sf_sc; 984 tf->fixreg[12] = (register_t)catcher; 985 986 tf->srr0 = p->p_p->ps_sigcode; 987 988 return 0; 989 } 990 991 int 992 sys_sigreturn(struct proc *p, void *v, register_t *retval) 993 { 994 struct sys_sigreturn_args /* { 995 syscallarg(struct sigcontext *) sigcntxp; 996 } */ *uap = v; 997 struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); 998 struct trapframe *tf = p->p_md.md_regs; 999 struct pcb *pcb = &p->p_addr->u_pcb; 1000 int error; 1001 int i; 1002 1003 if (PROC_PC(p) != p->p_p->ps_sigcoderet) { 1004 sigexit(p, SIGILL); 1005 return EPERM; 1006 } 1007 1008 if ((error = copyin(scp, &ksc, sizeof ksc))) 1009 return error; 1010 1011 if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) { 1012 sigexit(p, SIGILL); 1013 return EFAULT; 1014 } 1015 1016 /* Prevent reuse of the sigcontext cookie */ 1017 ksc.sc_cookie = 0; 1018 (void)copyout(&ksc.sc_cookie, (caddr_t)scp + 1019 offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie)); 1020 1021 /* Make sure the processor mode has not been tampered with. */ 1022 if (ksc.sc_ps != PSL_USER) 1023 return EINVAL; 1024 1025 /* Restore register context. */ 1026 for (i = 0; i < 32; i++) 1027 tf->fixreg[i] = ksc.sc_reg[i]; 1028 tf->lr = ksc.sc_lr; 1029 tf->cr = ksc.sc_cr; 1030 tf->xer = ksc.sc_xer; 1031 tf->ctr = ksc.sc_ctr; 1032 tf->srr0 = ksc.sc_pc; 1033 tf->srr1 = ksc.sc_ps; 1034 tf->vrsave = ksc.sc_vrsave; 1035 1036 /* Write saved FPU state back to PCB if necessary. */ 1037 if (pcb->pcb_flags & (PCB_FPU|PCB_VEC|PCB_VSX)) { 1038 memcpy(pcb->pcb_fpstate.fp_vsx, ksc.sc_vsx, 1039 sizeof(pcb->pcb_fpstate.fp_vsx)); 1040 pcb->pcb_fpstate.fp_fpscr = ksc.sc_fpscr; 1041 pcb->pcb_fpstate.fp_vscr = ksc.sc_vscr; 1042 } 1043 1044 /* Restore signal mask. */ 1045 p->p_sigmask = ksc.sc_mask & ~sigcantmask; 1046 1047 return EJUSTRETURN; 1048 } 1049 1050 /* 1051 * Notify the current process (p) that it has a signal pending, 1052 * process as soon as possible. 1053 */ 1054 void 1055 signotify(struct proc *p) 1056 { 1057 aston(p); 1058 cpu_kick(p->p_cpu); 1059 } 1060 1061 void cpu_switchto_asm(struct proc *, struct proc *); 1062 1063 void 1064 cpu_switchto(struct proc *old, struct proc *new) 1065 { 1066 if (old) { 1067 struct pcb *pcb = &old->p_addr->u_pcb; 1068 struct trapframe *tf = old->p_md.md_regs; 1069 1070 if (pcb->pcb_flags & (PCB_FPU|PCB_VEC|PCB_VSX) && 1071 tf->srr1 & (PSL_FPU|PSL_VEC|PSL_VSX)) { 1072 tf->srr1 &= ~(PSL_FPU|PSL_VEC|PSL_VSX); 1073 save_vsx(old); 1074 } 1075 1076 pmap_clear_user_slb(); 1077 } 1078 1079 cpu_switchto_asm(old, new); 1080 } 1081 1082 /* 1083 * machine dependent system variables. 1084 */ 1085 1086 int 1087 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 1088 size_t newlen, struct proc *p) 1089 { 1090 int altivec = 1; /* Altivec is always supported */ 1091 1092 /* All sysctl names at this level are terminal. */ 1093 if (namelen != 1) 1094 return ENOTDIR; /* overloaded */ 1095 1096 switch (name[0]) { 1097 case CPU_ALTIVEC: 1098 return (sysctl_rdint(oldp, oldlenp, newp, altivec)); 1099 default: 1100 return EOPNOTSUPP; 1101 } 1102 /* NOTREACHED */ 1103 } 1104 1105 void 1106 consinit(void) 1107 { 1108 } 1109 1110 void 1111 opal_powerdown(void) 1112 { 1113 int64_t error; 1114 1115 do { 1116 error = opal_cec_power_down(0); 1117 if (error == OPAL_BUSY_EVENT) 1118 opal_poll_events(NULL); 1119 } while (error == OPAL_BUSY || error == OPAL_BUSY_EVENT); 1120 1121 if (error != OPAL_SUCCESS) 1122 return; 1123 1124 /* Wait for the actual powerdown to happen. */ 1125 for (;;) 1126 opal_poll_events(NULL); 1127 } 1128 1129 int waittime = -1; 1130 1131 __dead void 1132 boot(int howto) 1133 { 1134 if ((howto & RB_RESET) != 0) 1135 goto doreset; 1136 1137 if (cold) { 1138 if ((howto & RB_USERREQ) == 0) 1139 howto |= RB_HALT; 1140 goto haltsys; 1141 } 1142 1143 boothowto = howto; 1144 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 1145 waittime = 0; 1146 vfs_shutdown(curproc); 1147 1148 if ((howto & RB_TIMEBAD) == 0) { 1149 resettodr(); 1150 } else { 1151 printf("WARNING: not updating battery clock\n"); 1152 } 1153 } 1154 if_downall(); 1155 1156 uvm_shutdown(); 1157 splhigh(); 1158 cold = 1; 1159 1160 haltsys: 1161 config_suspend_all(DVACT_POWERDOWN); 1162 1163 if ((howto & RB_HALT) != 0) { 1164 if ((howto & RB_POWERDOWN) != 0) 1165 opal_powerdown(); 1166 1167 printf("\n"); 1168 printf("The operating system has halted.\n"); 1169 printf("Please press any key to reboot.\n\n"); 1170 cngetc(); 1171 } 1172 1173 doreset: 1174 printf("rebooting...\n"); 1175 opal_cec_reboot(); 1176 1177 for (;;) 1178 continue; 1179 /* NOTREACHED */ 1180 } 1181