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