xref: /openbsd/sys/arch/powerpc64/powerpc64/machdep.c (revision c645b2d7)
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, &reg))
284 				break;
285 			if (reg.size == 0)
286 				continue;
287 			memreg_add(&reg);
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, &reg))
299 				continue;
300 			if (reg.size == 0)
301 				continue;
302 			memreg_remove(&reg);
303 		}
304 	}
305 
306 	/* Remove interrupt vectors. */
307 	reg.addr = trunc_page(EXC_RSVD);
308 	reg.size = round_page(EXC_END);
309 	memreg_remove(&reg);
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(&reg);
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(&reg);
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