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