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
atoi(const char * s)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 *
fdt_find_cons(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
init_powernv(void * fdt,void * tocbase)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
memreg_add(const struct fdt_reg * reg)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
memreg_remove(const struct fdt_reg * reg)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
self_reloc(Elf_Dyn * dynamic,Elf_Addr base)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 *
opal_phys(void * va)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
opal_printf(const char * fmt,...)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
opal_do_console_flush(int64_t term_number)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
opal_cnprobe(struct consdev * cd)511 opal_cnprobe(struct consdev *cd)
512 {
513 }
514
515 void
opal_cninit(struct consdev * cd)516 opal_cninit(struct consdev *cd)
517 {
518 }
519
520 int
opal_cngetc(dev_t dev)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
opal_cnputc(dev_t dev,int c)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
opal_cnpollc(dev_t dev,int on)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
copyin(const void * uaddr,void * kaddr,size_t len)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
copyin32(const uint32_t * uaddr,uint32_t * kaddr)594 copyin32(const uint32_t *uaddr, uint32_t *kaddr)
595 {
596 return copyin(uaddr, kaddr, sizeof(uint32_t));
597 }
598
599 int
copyout(const void * kaddr,void * uaddr,size_t len)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
copyinstr(const void * uaddr,void * kaddr,size_t len,size_t * done)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
copyoutstr(const void * kaddr,void * uaddr,size_t len,size_t * done)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
need_resched(struct cpu_info * ci)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
cpu_startup(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
parse_bootargs(const char * bootargs)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 *
parse_bootduid(const char * bootarg)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 *
parse_bootmac(const char * bootarg)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
setregs(struct proc * p,struct exec_package * pack,u_long stack,struct ps_strings * arginfo)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
sendsig(sig_t catcher,int sig,sigset_t mask,const siginfo_t * ksip,int info,int onstack)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
sys_sigreturn(struct proc * p,void * v,register_t * retval)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
signotify(struct proc * p)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
cpu_switchto(struct proc * old,struct proc * new)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
cpu_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)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
consinit(void)1106 consinit(void)
1107 {
1108 }
1109
1110 void
opal_powerdown(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
boot(int howto)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