xref: /openbsd-src/sys/arch/macppc/macppc/machdep.c (revision bb00e81153b2ff3fcf42c8955e50b70f573a8323)
1 /*	$OpenBSD: machdep.c,v 1.200 2023/10/24 13:20:10 claudio Exp $	*/
2 /*	$NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6  * Copyright (C) 1995, 1996 TooLs GmbH.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by TooLs GmbH.
20  * 4. The name of TooLs GmbH may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/buf.h>
37 #include <sys/timeout.h>
38 #include <sys/exec.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/mount.h>
42 #include <sys/msgbuf.h>
43 #include <sys/pool.h>
44 #include <sys/sysctl.h>
45 #include <sys/proc.h>
46 #include <sys/signalvar.h>
47 #include <sys/reboot.h>
48 #include <sys/syscallargs.h>
49 #include <sys/syslog.h>
50 #include <sys/extent.h>
51 #include <sys/systm.h>
52 #include <sys/user.h>
53 #include <sys/conf.h>
54 #include <sys/core.h>
55 #include <sys/kcore.h>
56 
57 #include <net/if.h>
58 #include <uvm/uvm_extern.h>
59 
60 #include <dev/cons.h>
61 
62 #include <machine/pmap.h>
63 #include <powerpc/powerpc.h>
64 #include <machine/trap.h>
65 #include <machine/autoconf.h>
66 #include <machine/bus.h>
67 #include <machine/pio.h>
68 #include <machine/intr.h>
69 
70 #include <dev/pci/pcivar.h>
71 
72 #include <arch/macppc/macppc/ofw_machdep.h>
73 #include <dev/ofw/openfirm.h>
74 
75 #include "adb.h"
76 #if NADB > 0
77 #include <arch/macppc/dev/adbvar.h>
78 #endif
79 
80 #ifdef DDB
81 #include <machine/db_machdep.h>
82 #include <ddb/db_interface.h>
83 #include <ddb/db_access.h>
84 #include <ddb/db_sym.h>
85 #include <ddb/db_extern.h>
86 #endif
87 
88 #include <powerpc/reg.h>
89 #include <powerpc/fpu.h>
90 
91 /*
92  * Global variables used here and there
93  */
94 extern struct user *proc0paddr;
95 struct pool ppc_vecpl;
96 
97 struct uvm_constraint_range  dma_constraint = { 0x0, (paddr_t)-1 };
98 struct uvm_constraint_range *uvm_md_constraints[] = { NULL };
99 
100 struct vm_map *exec_map = NULL;
101 struct vm_map *phys_map = NULL;
102 
103 int ppc_malloc_ok = 0;
104 
105 char *bootpath;
106 char bootpathbuf[512];
107 
108 /* from autoconf.c */
109 extern void parseofwbp(char *);
110 
111 struct firmware *fw = NULL;
112 
113 #ifdef DDB
114 void * startsym, *endsym;
115 #endif
116 
117 #ifdef APERTURE
118 int allowaperture = 0;
119 #endif
120 int lid_action = 1;
121 int pwr_action = 1;
122 
123 void dumpsys(void);
124 void *ppc_intr_establish(void *lcv, pci_intr_handle_t ih, int type,
125     int level, int (*func)(void *), void *arg, const char *name);
126 
127 
128 /*
129  * Extent maps to manage I/O. Allocate storage for 8 regions in each.
130  */
131 static long devio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)];
132 struct extent *devio_ex;
133 
134 /* XXX, called from asm */
135 void initppc(u_int startkernel, u_int endkernel, char *args);
136 
137 void
initppc(u_int startkernel,u_int endkernel,char * args)138 initppc(u_int startkernel, u_int endkernel, char *args)
139 {
140 	extern void *trapcode; extern int trapsize;
141 	extern void *dsitrap; extern int dsisize;
142 	extern void *isitrap; extern int isisize;
143 	extern void *alitrap; extern int alisize;
144 	extern void *decrint; extern int decrsize;
145 	extern void *tlbimiss; extern int tlbimsize;
146 	extern void *tlbdlmiss; extern int tlbdlmsize;
147 	extern void *tlbdsmiss; extern int tlbdsmsize;
148 #ifdef DDB
149 	extern void *ddblow; extern int ddbsize;
150 #endif
151 	extern void callback(void *);
152 	extern void *msgbuf_addr;
153 	int exc;
154 
155 	proc0.p_cpu = &cpu_info[0];
156 	proc0.p_addr = proc0paddr;
157 	bzero(proc0.p_addr, sizeof *proc0.p_addr);
158 
159 	curpcb = &proc0paddr->u_pcb;
160 
161 	curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel();
162 
163 	cpu_bootstrap();
164 
165 	/*
166 	 * Initialize pmap module.
167 	 */
168 	pmap_bootstrap(startkernel, endkernel);
169 
170 	/*
171 	 * Set up trap vectors
172 	 */
173 	for (exc = EXC_RSVD; exc < EXC_END; exc += 0x100) {
174 		switch (exc) {
175 		default:
176 			bcopy(&trapcode, (void *)exc, (size_t)&trapsize);
177 			break;
178 		case EXC_EXI:
179 			/*
180 			 * This one is (potentially) installed during autoconf
181 			 */
182 			break;
183 
184 		case EXC_DSI:
185 			bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
186 			break;
187 		case EXC_ISI:
188 			bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize);
189 			break;
190 		case EXC_ALI:
191 			bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
192 			break;
193 		case EXC_DECR:
194 			bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize);
195 			break;
196 		case EXC_IMISS:
197 			bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize);
198 			break;
199 		case EXC_DLMISS:
200 			bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize);
201 			break;
202 		case EXC_DSMISS:
203 			bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize);
204 			break;
205 		case EXC_PGM:
206 		case EXC_TRC:
207 		case EXC_BPT:
208 #if defined(DDB)
209 			bcopy(&ddblow, (void *)exc, (size_t)&ddbsize);
210 #endif
211 			break;
212 		}
213 	}
214 
215 	/* Grr, ALTIVEC_UNAVAIL is a vector not ~0xff aligned: 0x0f20 */
216 	bcopy(&trapcode, (void *)EXC_VEC, (size_t)&trapsize);
217 
218 	/*
219 	 * since trapsize is > 0x20, we just overwrote the EXC_PERF handler
220 	 * since we do not use it, we will "share" it with the EXC_VEC,
221 	 * we dont support EXC_VEC either.
222 	 * should be a 'ba 0xf20 written' at address 0xf00, but we
223 	 * do not generate EXC_PERF exceptions...
224 	 */
225 
226 	syncicache((void *)EXC_RST, EXC_END - EXC_RST);
227 
228 	/*
229 	 * Now enable translation (and machine checks/recoverable interrupts).
230 	 */
231 	pmap_enable_mmu();
232 
233 	/*
234 	 * use the memory provided by pmap_bootstrap for message buffer
235 	 */
236 	initmsgbuf(msgbuf_addr, MSGBUFSIZE);
237 
238 	/*
239 	 * Look at arguments passed to us and compute boothowto.
240 	 */
241 	boothowto = RB_AUTOBOOT;
242 
243 	/*
244 	 * Parse arg string.
245 	 */
246 
247 	/* make a copy of the args! */
248 	strncpy(bootpathbuf, args, 512);
249 	bootpath= &bootpathbuf[0];
250 	while ( *++bootpath && *bootpath != ' ');
251 	if (*bootpath) {
252 		*bootpath++ = 0;
253 		while (*bootpath) {
254 			switch (*bootpath++) {
255 			case 'a':
256 				boothowto |= RB_ASKNAME;
257 				break;
258 			case 's':
259 				boothowto |= RB_SINGLE;
260 				break;
261 			case 'd':
262 				boothowto |= RB_KDB;
263 				break;
264 			case 'c':
265 				boothowto |= RB_CONFIG;
266 				break;
267 			case 'R':
268 				boothowto |= RB_GOODRANDOM;
269 				break;
270 			default:
271 				break;
272 			}
273 		}
274 	}
275 	bootpath = &bootpathbuf[0];
276 	parseofwbp(bootpath);
277 
278 #ifdef DDB
279 	ddb_init();
280 	db_machine_init();
281 #endif
282 
283 	/*
284 	 * Set up extents for pci mappings
285 	 * Is this too late?
286 	 *
287 	 * what are good start and end values here??
288 	 * 0x0 - 0x80000000 mcu bus
289 	 * MAP A				MAP B
290 	 * 0x80000000 - 0xbfffffff io		0x80000000 - 0xefffffff mem
291 	 * 0xc0000000 - 0xffffffff mem		0xf0000000 - 0xffffffff io
292 	 *
293 	 * of course bsd uses 0xe and 0xf
294 	 * So the BSD PPC memory map will look like this
295 	 * 0x0 - 0x80000000 memory (whatever is filled)
296 	 * 0x80000000 - 0xdfffffff (pci space, memory or io)
297 	 * 0xe0000000 - kernel vm segment
298 	 * 0xf0000000 - kernel map segment (user space mapped here)
299 	 */
300 
301 	devio_ex = extent_create("devio", 0x80000000, 0xffffffff, M_DEVBUF,
302 		(caddr_t)devio_ex_storage, sizeof(devio_ex_storage),
303 		EX_NOCOALESCE|EX_NOWAIT);
304 
305 	/* while using openfirmware, run userconfig */
306 	if (boothowto & RB_CONFIG) {
307 #ifdef BOOT_CONFIG
308 		user_config();
309 #else
310 		printf("kernel does not support -c; continuing..\n");
311 #endif
312 	}
313 
314 #ifdef DDB
315 	if (boothowto & RB_KDB)
316 		db_enter();
317 #endif
318 
319 	/*
320 	 * Replace with real console.
321 	 */
322 	ofwconprobe();
323 	consinit();
324 
325         pool_init(&ppc_vecpl, sizeof(struct vreg), 16, IPL_NONE, 0, "ppcvec",
326 	    NULL);
327 
328 }
329 
330 void
install_extint(void (* handler)(void))331 install_extint(void (*handler)(void))
332 {
333 	void extint(void);
334 	void extsize(void);
335 	extern u_long extint_call;
336 	long offset = (u_long)handler - (u_long)&extint_call;
337 	int omsr, msr;
338 
339 #ifdef DIAGNOSTIC
340 	if (offset > 0x1ffffff || offset < -0x1ffffff)
341 		panic("install_extint: too far away");
342 #endif
343 	omsr = ppc_mfmsr();
344 	msr = omsr & ~PSL_EE;
345 	ppc_mtmsr(msr);
346 	offset &= 0x3ffffff;
347 	extint_call = (extint_call & 0xfc000003) | offset;
348 	bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize);
349 	syncicache((void *)&extint_call, sizeof extint_call);
350 	syncicache((void *)EXC_EXI, (size_t)&extsize);
351 	ppc_mtmsr(omsr);
352 }
353 
354 /*
355  * safepri is a safe priority for sleep to set for a spin-wait
356  * during autoconfiguration or after a panic.
357  */
358 int   safepri = 0;
359 
360 /*
361  * Machine dependent startup code.
362  */
363 void
cpu_startup(void)364 cpu_startup(void)
365 {
366 	vaddr_t minaddr, maxaddr;
367 
368 	proc0.p_addr = proc0paddr;
369 
370 	printf("%s", version);
371 
372 	printf("real mem = %llu (%lluMB)\n",
373 	    (unsigned long long)ptoa((psize_t)physmem),
374 	    (unsigned long long)ptoa((psize_t)physmem)/1024U/1024U);
375 
376 	/*
377 	 * Allocate a submap for exec arguments.  This map effectively
378 	 * limits the number of processes exec'ing at any time.
379 	 */
380 	minaddr = vm_map_min(kernel_map);
381 	exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS,
382 	    VM_MAP_PAGEABLE, FALSE, NULL);
383 
384 	/*
385 	 * Allocate a submap for physio
386 	 */
387 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
388 	    VM_PHYS_SIZE, 0, FALSE, NULL);
389 	ppc_malloc_ok = 1;
390 
391 	printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free),
392 	    ptoa(uvmexp.free) / 1024 / 1024);
393 
394 	/*
395 	 * Set up the buffers.
396 	 */
397 	bufinit();
398 }
399 
400 /*
401  * consinit
402  * Initialize system console.
403  */
404 void
consinit(void)405 consinit(void)
406 {
407 	static int cons_initted = 0;
408 
409 	if (cons_initted)
410 		return;
411 	cninit();
412 	cons_initted = 1;
413 }
414 
415 /*
416  * Clear registers on exec
417  */
418 void
setregs(struct proc * p,struct exec_package * pack,u_long stack,struct ps_strings * arginfo)419 setregs(struct proc *p, struct exec_package *pack, u_long stack,
420     struct ps_strings *arginfo)
421 {
422 	u_int32_t newstack;
423 	u_int32_t pargs;
424 	struct trapframe *tf = trapframe(p);
425 
426 	pargs = -roundup(-stack + 8, 16);
427 	newstack = (u_int32_t)(pargs - 32);
428 
429 	memset(tf, 0, sizeof *tf);
430 	tf->fixreg[1] = newstack;
431 	tf->fixreg[3] = arginfo->ps_nargvstr;
432 	tf->fixreg[4] = (register_t)arginfo->ps_argvstr;
433 	tf->fixreg[5] = (register_t)arginfo->ps_envstr;
434 	tf->fixreg[6] = arginfo->ps_nenvstr;
435 	tf->srr0 = pack->ep_entry;
436 	tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
437 	p->p_addr->u_pcb.pcb_flags = 0;
438 }
439 
440 /*
441  * Send a signal to process.
442  */
443 int
sendsig(sig_t catcher,int sig,sigset_t mask,const siginfo_t * ksip,int info,int onstack)444 sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip,
445     int info, int onstack)
446 {
447 	struct proc *p = curproc;
448 	struct trapframe *tf;
449 	struct sigframe *fp, frame;
450 
451 	bzero(&frame, sizeof(frame));
452 	frame.sf_signum = sig;
453 
454 	tf = trapframe(p);
455 
456 	/*
457 	 * Allocate stack space for signal handler.
458 	 */
459 	if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 &&
460 	    !sigonstack(tf->fixreg[1]) &&
461 	    onstack)
462 		fp = (struct sigframe *)
463 		    trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size);
464 	else
465 		fp = (struct sigframe *)tf->fixreg[1];
466 
467 	fp = (struct sigframe *)((int)(fp - 1) & ~0xf);
468 
469 	/*
470 	 * Generate signal context for SYS_sigreturn.
471 	 */
472 	frame.sf_sc.sc_mask = mask;
473 	frame.sf_sip = NULL;
474 	bcopy(tf, &frame.sf_sc.sc_frame, sizeof *tf);
475 	if (info) {
476 		frame.sf_sip = &fp->sf_si;
477 		frame.sf_si = *ksip;
478 	}
479 	frame.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
480 	if (copyout(&frame, fp, sizeof frame) != 0)
481 		return 1;
482 
483 	tf->fixreg[1] = (int)fp;
484 	tf->lr = (int)catcher;
485 	tf->fixreg[3] = (int)sig;
486 	tf->fixreg[4] = info ? (int)&fp->sf_si : 0;
487 	tf->fixreg[5] = (int)&fp->sf_sc;
488 	tf->srr0 = p->p_p->ps_sigcode;
489 
490 	return 0;
491 }
492 
493 /*
494  * System call to cleanup state after a signal handler returns.
495  */
496 int
sys_sigreturn(struct proc * p,void * v,register_t * retval)497 sys_sigreturn(struct proc *p, void *v, register_t *retval)
498 {
499 	struct sys_sigreturn_args /* {
500 		syscallarg(struct sigcontext *) sigcntxp;
501 	} */ *uap = v;
502 	struct sigcontext ksc, *scp = SCARG(uap, sigcntxp);
503 	struct trapframe *tf;
504 	int error;
505 
506 	if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
507 		sigexit(p, SIGILL);
508 		return (EPERM);
509 	}
510 
511 	if ((error = copyin(scp, &ksc, sizeof ksc)))
512 		return error;
513 
514 	if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
515 		sigexit(p, SIGILL);
516 		return (EFAULT);
517 	}
518 
519 	/* Prevent reuse of the sigcontext cookie */
520 	ksc.sc_cookie = 0;
521 	(void)copyout(&ksc.sc_cookie, (caddr_t)scp +
522 	    offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie));
523 
524 	tf = trapframe(p);
525 	ksc.sc_frame.srr1 &= ~PSL_VEC;
526 	ksc.sc_frame.srr1 |= (tf->srr1 & PSL_VEC);
527 	if ((ksc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
528 		return EINVAL;
529 	bcopy(&ksc.sc_frame, tf, sizeof *tf);
530 	p->p_sigmask = ksc.sc_mask & ~sigcantmask;
531 	return EJUSTRETURN;
532 }
533 
534 const struct sysctl_bounded_args cpuctl_vars[] = {
535 	{ CPU_ALTIVEC, &ppc_altivec, SYSCTL_INT_READONLY },
536 	{ CPU_LIDACTION, &lid_action, 0, 2 },
537 	{ CPU_PWRACTION, &pwr_action, 0, 2 },
538 };
539 
540 /*
541  * Machine dependent system variables.
542  */
543 int
cpu_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)544 cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
545     size_t newlen, struct proc *p)
546 {
547 	/* all sysctl names at this level are terminal */
548 	if (namelen != 1)
549 		return ENOTDIR;
550 	switch (name[0]) {
551 	case CPU_ALLOWAPERTURE:
552 #ifdef APERTURE
553 		if (securelevel > 0)
554 			return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
555 			    &allowaperture));
556 		else
557 			return (sysctl_int(oldp, oldlenp, newp, newlen,
558 			    &allowaperture));
559 #else
560 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
561 #endif
562 	default:
563 		return (sysctl_bounded_arr(cpuctl_vars, nitems(cpuctl_vars),
564 		    name, namelen, oldp, oldlenp, newp, newlen));
565 	}
566 }
567 
568 
569 u_long dumpmag = 0x04959fca;			/* magic number */
570 int dumpsize = 0;			/* size of dump in pages */
571 long dumplo = -1;			/* blocks */
572 
573 /*
574  * This is called by configure to set dumplo and dumpsize.
575  * Dumps always skip the first CLBYTES of disk space
576  * in case there might be a disk label stored there.
577  * If there is extra space, put dump at the end to
578  * reduce the chance that swapping trashes it.
579  */
580 void dumpconf(void);
581 
582 void
dumpconf(void)583 dumpconf(void)
584 {
585 	int nblks;	/* size of dump area */
586 	int i;
587 
588 	if (dumpdev == NODEV ||
589 	    (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
590 		return;
591 	if (nblks <= ctod(1))
592 		return;
593 
594 	/* Always skip the first block, in case there is a label there. */
595 	if (dumplo < ctod(1))
596 		dumplo = ctod(1);
597 
598         for (i = 0; i < ndumpmem; i++)
599 		dumpsize = max(dumpsize, dumpmem[i].end);
600 
601 	/* Put dump at end of partition, and make it fit. */
602 	if (dumpsize > dtoc(nblks - dumplo - 1))
603 		dumpsize = dtoc(nblks - dumplo - 1);
604 	if (dumplo < nblks - ctod(dumpsize) - 1)
605 		dumplo = nblks - ctod(dumpsize) - 1;
606 
607 }
608 
609 #define BYTES_PER_DUMP  (PAGE_SIZE)  /* must be a multiple of pagesize */
610 static vaddr_t dumpspace;
611 
612 int
reserve_dumppages(caddr_t p)613 reserve_dumppages(caddr_t p)
614 {
615 	dumpspace = (vaddr_t)p;
616 	return BYTES_PER_DUMP;
617 }
618 
619 /*
620  * cpu_dump: dump machine-dependent kernel core dump headers.
621  */
622 int cpu_dump(void);
623 int
cpu_dump(void)624 cpu_dump(void)
625 {
626 	int (*dump) (dev_t, daddr_t, caddr_t, size_t);
627 	long buf[dbtob(1) / sizeof (long)];
628 	kcore_seg_t	*segp;
629 
630 	dump = bdevsw[major(dumpdev)].d_dump;
631 
632 	segp = (kcore_seg_t *)buf;
633 
634 	/*
635 	 * Generate a segment header.
636 	 */
637 	CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
638 	segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
639 
640 	return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
641 }
642 
643 void
dumpsys(void)644 dumpsys(void)
645 {
646 #if 0
647 	u_int npg;
648 	u_int i, j;
649 	daddr_t blkno;
650 	int (*dump) (dev_t, daddr_t, caddr_t, size_t);
651 	char *str;
652 	int maddr;
653 	extern int msgbufmapped;
654 	int error;
655 
656 	/* save registers */
657 
658 	msgbufmapped = 0;	/* don't record dump msgs in msgbuf */
659 	if (dumpdev == NODEV)
660 		return;
661 	/*
662 	 * For dumps during autoconfiguration,
663 	 * if dump device has already configured...
664 	 */
665 	if (dumpsize == 0)
666 		dumpconf();
667 	if (dumplo < 0)
668 		return;
669 	printf("dumping to dev %x, offset %ld\n", dumpdev, dumplo);
670 
671 	error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
672 	if (error == -1) {
673 		printf("area unavailable\n");
674 		delay (10000000);
675 		return;
676 	}
677 
678 	dump = bdevsw[major(dumpdev)].d_dump;
679 	error = cpu_dump();
680 	for (i = 0; !error && i < ndumpmem; i++) {
681 		npg = dumpmem[i].end - dumpmem[i].start;
682 		maddr = ptoa(dumpmem[i].start);
683 		blkno = dumplo + btodb(maddr) + 1;
684 
685 		for (j = npg; j;
686 			j--, maddr += PAGE_SIZE, blkno+= btodb(PAGE_SIZE))
687 		{
688 			/* Print out how many MBs we have to go. */
689                         if (dbtob(blkno - dumplo) % (1024 * 1024) < NBPG)
690                                 printf("%d ",
691                                     (ptoa(dumpsize) - maddr) / (1024 * 1024));
692 
693 			pmap_enter(pmap_kernel(), dumpspace, maddr,
694 				PROT_READ, PMAP_WIRED);
695 			if ((error = (*dump)(dumpdev, blkno,
696 			    (caddr_t)dumpspace, PAGE_SIZE)) != 0)
697 				break;
698 		}
699 	}
700 
701 	switch (error) {
702 
703 	case 0:         str = "succeeded\n\n";                  break;
704 	case ENXIO:     str = "device bad\n\n";                 break;
705 	case EFAULT:    str = "device not ready\n\n";           break;
706 	case EINVAL:    str = "area improper\n\n";              break;
707 	case EIO:       str = "i/o error\n\n";                  break;
708 	case EINTR:     str = "aborted from console\n\n";       break;
709 	default:        str = "error %d\n\n";                   break;
710 	}
711 	printf(str, error);
712 
713 #else
714 	printf("dumpsys() - no yet supported\n");
715 
716 #endif
717 	delay(5000000);         /* 5 seconds */
718 
719 }
720 
721 /*
722  * Halt or reboot the machine after syncing/dumping according to howto.
723  */
724 __dead void
boot(int howto)725 boot(int howto)
726 {
727 	static int syncing;
728 
729 	if ((howto & RB_RESET) != 0)
730 		goto doreset;
731 
732 	if (cold) {
733 		if ((howto & RB_USERREQ) == 0)
734 			howto |= RB_HALT;
735 		goto haltsys;
736 	}
737 
738 	boothowto = howto;
739 	if ((howto & RB_NOSYNC) == 0 && !syncing) {
740 		syncing = 1;
741 		vfs_shutdown(curproc);
742 
743 		if ((howto & RB_TIMEBAD) == 0) {
744 			resettodr();
745 		} else {
746 			printf("WARNING: not updating battery clock\n");
747 		}
748 	}
749 	if_downall();
750 
751 	uvm_shutdown();
752 	splhigh();
753 	cold = 1;
754 
755 	if ((howto & RB_DUMP) != 0)
756 		dumpsys();
757 
758 haltsys:
759 	config_suspend_all(DVACT_POWERDOWN);
760 
761 	if ((howto & RB_HALT) != 0) {
762 		if ((howto & RB_POWERDOWN) != 0) {
763 #if NADB > 0
764 			delay(1000000);
765 			adb_poweroff();
766 			printf("WARNING: adb powerdown failed!\n");
767 #endif
768 			OF_interpret("shut-down", 0);
769 		}
770 
771 		printf("halted\n\n");
772 		OF_exit();
773 	}
774 doreset:
775 	printf("rebooting\n\n");
776 
777 #if NADB > 0
778 	adb_restart();  /* not return */
779 #endif
780 
781 	OF_interpret("reset-all", 0);
782 	OF_exit();
783 	printf("boot failed, spinning\n");
784 	for (;;)
785 		continue;
786 	/* NOTREACHED */
787 }
788 
789 typedef void  (void_f) (void);
790 void_f *pending_int_f = NULL;
791 
792 /* call the bus/interrupt controller specific pending interrupt handler
793  * would be nice if the offlevel interrupt code was handled here
794  * instead of being in each of the specific handler code
795  */
796 void
do_pending_int(void)797 do_pending_int(void)
798 {
799 	if (pending_int_f != NULL) {
800 		(*pending_int_f)();
801 	}
802 }
803 
804 /*
805  * Notify the current process (p) that it has a signal pending,
806  * process as soon as possible.
807  */
808 void
signotify(struct proc * p)809 signotify(struct proc *p)
810 {
811 	aston(p);
812 	cpu_unidle(p->p_cpu);
813 }
814 
815 #ifdef MULTIPROCESSOR
816 void
cpu_unidle(struct cpu_info * ci)817 cpu_unidle(struct cpu_info *ci)
818 {
819 	if (ci != curcpu())
820 		ppc_send_ipi(ci, PPC_IPI_NOP);
821 }
822 #endif
823 
824 int ppc_configed_intr_cnt = 0;
825 struct intrhand ppc_configed_intr[MAX_PRECONF_INTR];
826 
827 /*
828  * True if the system has any non-level interrupts which are shared
829  * on the same pin.
830  */
831 int	intr_shared_edge;
832 
833 void *
ppc_intr_establish(void * lcv,pci_intr_handle_t ih,int type,int level,int (* func)(void *),void * arg,const char * name)834 ppc_intr_establish(void *lcv, pci_intr_handle_t ih, int type, int level,
835     int (*func)(void *), void *arg, const char *name)
836 {
837 	if (ppc_configed_intr_cnt < MAX_PRECONF_INTR) {
838 		ppc_configed_intr[ppc_configed_intr_cnt].ih_fun = func;
839 		ppc_configed_intr[ppc_configed_intr_cnt].ih_arg = arg;
840 		ppc_configed_intr[ppc_configed_intr_cnt].ih_type = type;
841 		ppc_configed_intr[ppc_configed_intr_cnt].ih_level = level;
842 		ppc_configed_intr[ppc_configed_intr_cnt].ih_irq = ih;
843 		ppc_configed_intr[ppc_configed_intr_cnt].ih_what = name;
844 		ppc_configed_intr_cnt++;
845 	} else {
846 		panic("ppc_intr_establish called before interrupt controller"
847 			" configured: driver %s too many interrupts", name);
848 	}
849 	/* disestablish is going to be tricky to supported for these :-) */
850 	return (void *)ppc_configed_intr_cnt;
851 }
852 
853 intr_establish_t *intr_establish_func = (intr_establish_t *)ppc_intr_establish;
854 intr_disestablish_t *intr_disestablish_func;
855 
856 intr_send_ipi_t ppc_no_send_ipi;
857 intr_send_ipi_t *intr_send_ipi_func = ppc_no_send_ipi;
858 
859 void
ppc_no_send_ipi(struct cpu_info * ci,int id)860 ppc_no_send_ipi(struct cpu_info *ci, int id)
861 {
862 	panic("ppc_send_ipi called: no ipi function");
863 }
864 
865 void
ppc_send_ipi(struct cpu_info * ci,int id)866 ppc_send_ipi(struct cpu_info *ci, int id)
867 {
868 	(*intr_send_ipi_func)(ci, id);
869 }
870 
871 /* bcopy(), error on fault */
872 int
kcopy(const void * from,void * to,size_t size)873 kcopy(const void *from, void *to, size_t size)
874 {
875 	faultbuf env;
876 	void *oldh = curproc->p_addr->u_pcb.pcb_onfault;
877 
878 	if (setfault(&env)) {
879 		curproc->p_addr->u_pcb.pcb_onfault = oldh;
880 		return EFAULT;
881 	}
882 	bcopy(from, to, size);
883 	curproc->p_addr->u_pcb.pcb_onfault = oldh;
884 
885 	return 0;
886 }
887 
888 /* prototype for locore function */
889 void cpu_switchto_asm(struct proc *oldproc, struct proc *newproc);
890 
891 void
cpu_switchto(struct proc * oldproc,struct proc * newproc)892 cpu_switchto(struct proc *oldproc, struct proc *newproc)
893 {
894 	/*
895 	 * if this CPU is running a new process, flush the
896 	 * FPU/Altivec context to avoid an IPI.
897 	 */
898 #ifdef MULTIPROCESSOR
899 	struct cpu_info *ci = curcpu();
900 	if (ci->ci_fpuproc)
901 		save_fpu();
902 	if (ci->ci_vecproc)
903 		save_vec(ci->ci_vecproc);
904 #endif
905 
906 	cpu_switchto_asm(oldproc, newproc);
907 }
908