xref: /openbsd/sys/arch/powerpc64/powerpc64/machdep.c (revision 905646f0)
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, &reg))
192 				break;
193 			if (reg.size == 0)
194 				continue;
195 			memreg_add(&reg);
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, &reg))
207 				continue;
208 			if (reg.size == 0)
209 				continue;
210 			memreg_remove(&reg);
211 		}
212 	}
213 
214 	/* Remove interrupt vectors. */
215 	reg.addr = trunc_page(EXC_RSVD);
216 	reg.size = round_page(EXC_LAST);
217 	memreg_remove(&reg);
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(&reg);
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(&reg);
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