machdep.c revision 1.34 1 /* $NetBSD: machdep.c,v 1.34 1998/06/09 20:47:18 gwr Exp $ */
2
3 /*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1986, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: Utah Hdr: machdep.c 1.74 92/12/20
41 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94
42 */
43
44 #include "opt_uvm.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/map.h>
50 #include <sys/proc.h>
51 #include <sys/buf.h>
52 #include <sys/reboot.h>
53 #include <sys/conf.h>
54 #include <sys/file.h>
55 #include <sys/clist.h>
56 #include <sys/callout.h>
57 #include <sys/malloc.h>
58 #include <sys/mbuf.h>
59 #include <sys/msgbuf.h>
60 #include <sys/ioctl.h>
61 #include <sys/tty.h>
62 #include <sys/mount.h>
63 #include <sys/user.h>
64 #include <sys/exec.h>
65 #include <sys/core.h>
66 #include <sys/kcore.h>
67 #include <sys/vnode.h>
68 #include <sys/syscallargs.h>
69 #ifdef SYSVMSG
70 #include <sys/msg.h>
71 #endif
72 #ifdef SYSVSEM
73 #include <sys/sem.h>
74 #endif
75 #ifdef SYSVSHM
76 #include <sys/shm.h>
77 #endif
78 #ifdef KGDB
79 #include <sys/kgdb.h>
80 #endif
81
82 #include <vm/vm.h>
83 #include <vm/vm_map.h>
84 #include <vm/vm_kern.h>
85 #include <vm/vm_page.h>
86
87 #if defined(UVM)
88 #include <uvm/uvm.h> /* XXX: not _extern ... need vm_map_create */
89 #endif
90
91 #include <sys/sysctl.h>
92
93 #include <dev/cons.h>
94
95 #include <machine/cpu.h>
96 #include <machine/dvma.h>
97 #include <machine/idprom.h>
98 #include <machine/kcore.h>
99 #include <machine/reg.h>
100 #include <machine/psl.h>
101 #include <machine/pte.h>
102
103 #include <machine/db_machdep.h>
104 #include <ddb/db_sym.h>
105 #include <ddb/db_extern.h>
106
107 #include <sun3/sun3/machdep.h>
108
109 /* Defined in locore.s */
110 extern char kernel_text[];
111 /* Defined by the linker */
112 extern char etext[];
113
114 #if defined(UVM)
115 /* XXX - Gratuitous name changes... */
116 #define kmem_alloc uvm_km_alloc
117 vm_map_t exec_map = NULL;
118 vm_map_t mb_map = NULL;
119 vm_map_t phys_map = NULL;
120 #else
121 vm_map_t buffer_map;
122 #endif
123
124 int physmem;
125 int fputype;
126 caddr_t msgbufaddr;
127
128 /* Virtual page frame for /dev/mem (see mem.c) */
129 vm_offset_t vmmap;
130
131 /*
132 * safepri is a safe priority for sleep to set for a spin-wait
133 * during autoconfiguration or after a panic.
134 */
135 int safepri = PSL_LOWIPL;
136
137 /*
138 * Declare these as initialized data so we can patch them.
139 */
140 int nswbuf = 0;
141 #ifdef NBUF
142 int nbuf = NBUF;
143 #else
144 int nbuf = 0;
145 #endif
146 #ifdef BUFPAGES
147 int bufpages = BUFPAGES;
148 #else
149 int bufpages = 0;
150 #endif
151
152 u_char cpu_machine_id = 0;
153 char *cpu_string = NULL;
154 int cpu_has_vme = 0;
155 int has_iocache = 0;
156
157 static void identifycpu __P((void));
158 static void initcpu __P((void));
159
160 /*
161 * Console initialization: called early on from main,
162 * before vm init or cpu_startup. This system is able
163 * to use the console for output immediately (via PROM)
164 * but can not use it for input until after this point.
165 */
166 void
167 consinit()
168 {
169
170 /*
171 * Switch from the PROM console (output only)
172 * to our own console driver.
173 */
174 cninit();
175
176 #ifdef DDB
177 db_machine_init();
178 {
179 extern int end[];
180 extern char *esym;
181
182 /* symsize, symstart, symend */
183 ddb_init(end[0], end + 1, (int*)esym);
184 }
185 #endif DDB
186
187 /*
188 * Now that the console can do input as well as
189 * output, consider stopping for a debugger.
190 */
191 if (boothowto & RB_KDB) {
192 #ifdef KGDB
193 /* XXX - Ask on console for kgdb_dev? */
194 /* Note: this will just return if kgdb_dev==NODEV */
195 kgdb_connect(1);
196 #else /* KGDB */
197 /* Either DDB or no debugger (just PROM). */
198 Debugger();
199 #endif /* KGDB */
200 }
201 }
202
203 /*
204 * allocsys() - Private routine used by cpu_startup() below.
205 *
206 * Allocate space for system data structures. We are given
207 * a starting virtual address and we return a final virtual
208 * address; along the way we set each data structure pointer.
209 *
210 * We call allocsys() with 0 to find out how much space we want,
211 * allocate that much and fill it with zeroes, and then call
212 * allocsys() again with the correct base virtual address.
213 */
214 #define valloc(name, type, num) \
215 v = (caddr_t)(((name) = (type *)v) + (num))
216 static caddr_t allocsys __P((caddr_t));
217 static caddr_t
218 allocsys(v)
219 register caddr_t v;
220 {
221
222 #ifdef REAL_CLISTS
223 valloc(cfree, struct cblock, nclist);
224 #endif
225 valloc(callout, struct callout, ncallout);
226 #ifdef SYSVSHM
227 valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
228 #endif
229 #ifdef SYSVSEM
230 valloc(sema, struct semid_ds, seminfo.semmni);
231 valloc(sem, struct sem, seminfo.semmns);
232 /* This is pretty disgusting! */
233 valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int));
234 #endif
235 #ifdef SYSVMSG
236 valloc(msgpool, char, msginfo.msgmax);
237 valloc(msgmaps, struct msgmap, msginfo.msgseg);
238 valloc(msghdrs, struct msg, msginfo.msgtql);
239 valloc(msqids, struct msqid_ds, msginfo.msgmni);
240 #endif
241
242 /*
243 * Determine how many buffers to allocate. We allocate
244 * the BSD standard of use 10% of memory for the first 2 Meg,
245 * 5% of remaining. Insure a minimum of 16 buffers.
246 * Allocate 1/2 as many swap buffer headers as file i/o buffers.
247 */
248 if (bufpages == 0) {
249 /* We always have more than 2MB of memory. */
250 bufpages = ((btoc(2 * 1024 * 1024) + physmem) /
251 (20 * CLSIZE));
252 }
253 if (nbuf == 0) {
254 nbuf = bufpages;
255 if (nbuf < 16)
256 nbuf = 16;
257 }
258 if (nswbuf == 0) {
259 nswbuf = (nbuf / 2) &~ 1; /* force even */
260 if (nswbuf > 256)
261 nswbuf = 256; /* sanity */
262 }
263 #if !defined(UVM)
264 valloc(swbuf, struct buf, nswbuf);
265 #endif
266 valloc(buf, struct buf, nbuf);
267 return v;
268 }
269 #undef valloc
270
271 /*
272 * cpu_startup: allocate memory for variable-sized tables,
273 * initialize cpu, and do autoconfiguration.
274 *
275 * This is called early in init_main.c:main(), after the
276 * kernel memory allocator is ready for use, but before
277 * the creation of processes 1,2, and mountroot, etc.
278 */
279 void
280 cpu_startup()
281 {
282 caddr_t v;
283 int sz, i;
284 vm_size_t size;
285 int base, residual;
286 vm_offset_t minaddr, maxaddr;
287
288 /*
289 * Initialize message buffer (for kernel printf).
290 * This is put in physical page zero so it will
291 * always be in the same place after a reboot.
292 * Its mapping was prepared in pmap_bootstrap().
293 * Also, offset some to avoid PROM scribbles.
294 */
295 v = (caddr_t) KERNBASE;
296 msgbufaddr = (caddr_t)(v + MSGBUFOFF);
297 initmsgbuf(msgbufaddr, MSGBUFSIZE);
298
299 /*
300 * Good {morning,afternoon,evening,night}.
301 */
302 printf(version);
303 identifycpu();
304 initfpu(); /* also prints FPU type */
305
306 size = ptoa(physmem);
307 printf("real mem = %dK (0x%lx)\n", (size >> 10), size);
308
309 /*
310 * Find out how much space we need, allocate it,
311 * and then give everything true virtual addresses.
312 */
313 sz = (int)allocsys((caddr_t)0);
314 if ((v = (caddr_t)kmem_alloc(kernel_map, round_page(sz))) == 0)
315 panic("startup: no room for tables");
316 if (allocsys(v) - v != sz)
317 panic("startup: table size inconsistency");
318
319 /*
320 * Now allocate buffers proper. They are different than the above
321 * in that they usually occupy more virtual memory than physical.
322 */
323 size = MAXBSIZE * nbuf;
324 #if defined(UVM)
325 if (uvm_map(kernel_map, (vm_offset_t *) &buffers, round_page(size),
326 NULL, UVM_UNKNOWN_OFFSET,
327 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
328 UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
329 panic("startup: cannot allocate VM for buffers");
330 minaddr = (vm_offset_t)buffers;
331 #else
332 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
333 &maxaddr, size, TRUE);
334 minaddr = (vm_offset_t)buffers;
335 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
336 &minaddr, size, FALSE) != KERN_SUCCESS)
337 panic("startup: cannot allocate buffers");
338 #endif /* UVM */
339 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
340 /* don't want to alloc more physical mem than needed */
341 bufpages = btoc(MAXBSIZE) * nbuf;
342 }
343 base = bufpages / nbuf;
344 residual = bufpages % nbuf;
345 for (i = 0; i < nbuf; i++) {
346 #if defined(UVM)
347 vm_size_t curbufsize;
348 vm_offset_t curbuf;
349 struct vm_page *pg;
350
351 /*
352 * Each buffer has MAXBSIZE bytes of VM space allocated. Of
353 * that MAXBSIZE space, we allocate and map (base+1) pages
354 * for the first "residual" buffers, and then we allocate
355 * "base" pages for the rest.
356 */
357 curbuf = (vm_offset_t) buffers + (i * MAXBSIZE);
358 curbufsize = CLBYTES * ((i < residual) ? (base+1) : base);
359
360 while (curbufsize) {
361 pg = uvm_pagealloc(NULL, 0, NULL);
362 if (pg == NULL)
363 panic("cpu_startup: not enough memory for "
364 "buffer cache");
365 #if defined(PMAP_NEW)
366 pmap_kenter_pgs(curbuf, &pg, 1);
367 #else
368 pmap_enter(kernel_map->pmap, curbuf,
369 VM_PAGE_TO_PHYS(pg), VM_PROT_ALL, TRUE);
370 #endif
371 curbuf += PAGE_SIZE;
372 curbufsize -= PAGE_SIZE;
373 }
374 #else /* ! UVM */
375 vm_size_t curbufsize;
376 vm_offset_t curbuf;
377
378 /*
379 * First <residual> buffers get (base+1) physical pages
380 * allocated for them. The rest get (base) physical pages.
381 *
382 * The rest of each buffer occupies virtual space,
383 * but has no physical memory allocated for it.
384 */
385 curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
386 curbufsize = CLBYTES * (i < residual ? base+1 : base);
387 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
388 vm_map_simplify(buffer_map, curbuf);
389 #endif /* UVM */
390 }
391
392 /*
393 * Allocate a submap for exec arguments. This map effectively
394 * limits the number of processes exec'ing at any time.
395 */
396 #if defined(UVM)
397 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
398 16*NCARGS, TRUE, FALSE, NULL);
399 #else
400 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
401 16*NCARGS, TRUE);
402 #endif
403
404 /*
405 * We don't use a submap for physio, and use a separate map
406 * for DVMA allocations. Our vmapbuf just maps pages into
407 * the kernel map (any kernel mapping is OK) and then the
408 * device drivers clone the kernel mappings into DVMA space.
409 */
410
411 /*
412 * Finally, allocate mbuf cluster submap.
413 */
414 #if defined(UVM)
415 mb_map = uvm_km_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
416 VM_MBUF_SIZE, FALSE, FALSE, NULL);
417 #else
418 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
419 VM_MBUF_SIZE, FALSE);
420 #endif
421
422 /*
423 * Initialize callouts
424 */
425 callfree = callout;
426 for (i = 1; i < ncallout; i++)
427 callout[i-1].c_next = &callout[i];
428 callout[i-1].c_next = NULL;
429
430 #if defined(UVM)
431 size = ptoa(uvmexp.free);
432 #else
433 size = ptoa(cnt.v_free_count);
434 #endif
435 printf("avail mem = %dK (0x%lx)\n", (size >> 10), size);
436 printf("using %d buffers containing %d bytes of memory\n",
437 nbuf, bufpages * CLBYTES);
438
439 /*
440 * Tell the VM system that writing to kernel text isn't allowed.
441 * If we don't, we might end up COW'ing the text segment!
442 */
443 #if defined(UVM)
444 if (uvm_map_protect(kernel_map, (vm_offset_t) kernel_text,
445 m68k_trunc_page((vm_offset_t) etext),
446 UVM_PROT_READ|UVM_PROT_EXEC, TRUE) != KERN_SUCCESS)
447 panic("can't protect kernel text");
448 #else
449 if (vm_map_protect(kernel_map, (vm_offset_t) kernel_text,
450 m68k_trunc_page((vm_offset_t) etext),
451 VM_PROT_READ|VM_PROT_EXECUTE, TRUE) != KERN_SUCCESS)
452 panic("can't protect kernel text");
453 #endif
454
455 /*
456 * Allocate a virtual page (for use by /dev/mem)
457 * This page is handed to pmap_enter() therefore
458 * it has to be in the normal kernel VA range.
459 */
460 #if defined(UVM)
461 vmmap = uvm_km_valloc_wait(kernel_map, NBPG);
462 #else
463 vmmap = kmem_alloc_wait(kernel_map, NBPG);
464 #endif
465
466 /*
467 * Create the DVMA maps.
468 */
469 dvma_init();
470
471 /*
472 * Set up CPU-specific registers, cache, etc.
473 */
474 initcpu();
475
476 /*
477 * Set up buffers, so they can be used to read disk labels.
478 */
479 bufinit();
480
481 /*
482 * Configure the system.
483 */
484 configure();
485 }
486
487 /*
488 * Set registers on exec.
489 */
490 void
491 setregs(p, pack, stack)
492 struct proc *p;
493 struct exec_package *pack;
494 u_long stack;
495 {
496 struct trapframe *tf = (struct trapframe *)p->p_md.md_regs;
497
498 tf->tf_sr = PSL_USERSET;
499 tf->tf_pc = pack->ep_entry & ~1;
500 tf->tf_regs[D0] = 0;
501 tf->tf_regs[D1] = 0;
502 tf->tf_regs[D2] = 0;
503 tf->tf_regs[D3] = 0;
504 tf->tf_regs[D4] = 0;
505 tf->tf_regs[D5] = 0;
506 tf->tf_regs[D6] = 0;
507 tf->tf_regs[D7] = 0;
508 tf->tf_regs[A0] = 0;
509 tf->tf_regs[A1] = 0;
510 tf->tf_regs[A2] = (int)PS_STRINGS;
511 tf->tf_regs[A3] = 0;
512 tf->tf_regs[A4] = 0;
513 tf->tf_regs[A5] = 0;
514 tf->tf_regs[A6] = 0;
515 tf->tf_regs[SP] = stack;
516
517 /* restore a null state frame */
518 p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;
519 if (fputype)
520 m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);
521
522 p->p_md.md_flags = 0;
523 }
524
525 /*
526 * Info for CTL_HW
527 */
528 char machine[16] = MACHINE; /* from <machine/param.h> */
529 char cpu_model[120];
530
531 /*
532 * XXX - Should empirically estimate the divisor...
533 * Note that the value of delay_divisor is roughly
534 * 2048 / cpuclock (where cpuclock is in MHz).
535 */
536 int delay_divisor = 62; /* assume the fastest (33 MHz) */
537
538 void
539 identifycpu()
540 {
541 u_char machtype;
542
543 machtype = identity_prom.idp_machtype;
544 if ((machtype & IDM_ARCH_MASK) != IDM_ARCH_SUN3X) {
545 printf("Bad IDPROM arch!\n");
546 sunmon_abort();
547 }
548
549 cpu_machine_id = machtype;
550 switch (cpu_machine_id) {
551
552 case SUN3X_MACH_80:
553 cpu_string = "80"; /* Hydra */
554 delay_divisor = 102; /* 20 MHz */
555 cpu_has_vme = FALSE;
556 break;
557
558 case SUN3X_MACH_470:
559 cpu_string = "470"; /* Pegasus */
560 delay_divisor = 62; /* 33 MHz */
561 cpu_has_vme = TRUE;
562 break;
563
564 default:
565 printf("unknown sun3x model\n");
566 sunmon_abort();
567 }
568
569 /* Other stuff? (VAC, mc6888x version, etc.) */
570 sprintf(cpu_model, "Sun-3X (3/%s)", cpu_string);
571
572 printf("Model: %s\n", cpu_model);
573 }
574
575 /*
576 * machine dependent system variables.
577 */
578 int
579 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
580 int *name;
581 u_int namelen;
582 void *oldp;
583 size_t *oldlenp;
584 void *newp;
585 size_t newlen;
586 struct proc *p;
587 {
588 int error;
589 dev_t consdev;
590
591 /* all sysctl names at this level are terminal */
592 if (namelen != 1)
593 return (ENOTDIR); /* overloaded */
594
595 switch (name[0]) {
596 case CPU_CONSDEV:
597 if (cn_tab != NULL)
598 consdev = cn_tab->cn_dev;
599 else
600 consdev = NODEV;
601 error = sysctl_rdstruct(oldp, oldlenp, newp,
602 &consdev, sizeof consdev);
603 break;
604
605 #if 0 /* XXX - Not yet... */
606 case CPU_ROOT_DEVICE:
607 error = sysctl_rdstring(oldp, oldlenp, newp, root_device);
608 break;
609
610 case CPU_BOOTED_KERNEL:
611 error = sysctl_rdstring(oldp, oldlenp, newp, booted_kernel);
612 break;
613 #endif
614
615 default:
616 error = EOPNOTSUPP;
617 }
618 return (error);
619 }
620
621 /* See: sig_machdep.c */
622
623 /*
624 * Do a sync in preparation for a reboot.
625 * XXX - This could probably be common code.
626 * XXX - And now, most of it is in vfs_shutdown()
627 * XXX - Put waittime checks in there too?
628 */
629 int waittime = -1; /* XXX - Who else looks at this? -gwr */
630 static void
631 reboot_sync __P((void))
632 {
633
634 /* Check waittime here to localize its use to this function. */
635 if (waittime >= 0)
636 return;
637 waittime = 0;
638 vfs_shutdown();
639 }
640
641 /*
642 * Common part of the BSD and SunOS reboot system calls.
643 */
644 __dead void
645 cpu_reboot(howto, user_boot_string)
646 int howto;
647 char *user_boot_string;
648 {
649 /* Note: this string MUST be static! */
650 static char bootstr[128];
651 char *p;
652
653 /* If system is cold, just halt. (early panic?) */
654 if (cold)
655 goto haltsys;
656
657 /* Un-blank the screen if appropriate. */
658 cnpollc(1);
659
660 if ((howto & RB_NOSYNC) == 0) {
661 reboot_sync();
662 /*
663 * If we've been adjusting the clock, the todr
664 * will be out of synch; adjust it now.
665 *
666 * XXX - However, if the kernel has been sitting in ddb,
667 * the time will be way off, so don't set the HW clock!
668 * XXX - Should do sanity check against HW clock. -gwr
669 */
670 /* resettodr(); */
671 }
672
673 /* Disable interrupts. */
674 splhigh();
675
676 /* Write out a crash dump if asked. */
677 if (howto & RB_DUMP)
678 dumpsys();
679
680 /* run any shutdown hooks */
681 doshutdownhooks();
682
683 if (howto & RB_HALT) {
684 haltsys:
685 printf("Kernel halted.\n");
686 #if 0
687 /*
688 * This calls the PROM monitor "exit_to_mon" function
689 * which appears to have problems... SunOS uses the
690 * "abort" function when you halt (bug work-around?)
691 * so we might as well do the same.
692 */
693 sunmon_halt(); /* provokes PROM monitor bug */
694 #else
695 sunmon_abort();
696 #endif
697 }
698
699 /*
700 * Automatic reboot.
701 */
702 if (user_boot_string)
703 strncpy(bootstr, user_boot_string, sizeof(bootstr));
704 else {
705 /*
706 * Build our own boot string with an empty
707 * boot device/file and (maybe) some flags.
708 * The PROM will supply the device/file name.
709 */
710 p = bootstr;
711 *p = '\0';
712 if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) {
713 /* Append the boot flags. */
714 *p++ = ' ';
715 *p++ = '-';
716 if (howto & RB_KDB)
717 *p++ = 'd';
718 if (howto & RB_ASKNAME)
719 *p++ = 'a';
720 if (howto & RB_SINGLE)
721 *p++ = 's';
722 *p = '\0';
723 }
724 }
725 printf("Kernel rebooting...\n");
726 sunmon_reboot(bootstr);
727 for (;;) ;
728 /*NOTREACHED*/
729 }
730
731 /*
732 * These variables are needed by /sbin/savecore
733 */
734 u_long dumpmag = 0x8fca0101; /* magic number */
735 int dumpsize = 0; /* pages */
736 long dumplo = 0; /* blocks */
737
738 /*
739 * This is called by main to set dumplo, dumpsize.
740 * Dumps always skip the first CLBYTES of disk space
741 * in case there might be a disk label stored there.
742 * If there is extra space, put dump at the end to
743 * reduce the chance that swapping trashes it.
744 */
745 void
746 cpu_dumpconf()
747 {
748 int nblks; /* size of dump area */
749 int maj;
750 int (*getsize)__P((dev_t));
751
752 /* Validate space in page zero for the kcore header. */
753 if (MSGBUFOFF < (sizeof(kcore_seg_t) + sizeof(cpu_kcore_hdr_t)))
754 panic("cpu_dumpconf: MSGBUFOFF too small");
755
756 if (dumpdev == NODEV)
757 return;
758
759 maj = major(dumpdev);
760 if (maj < 0 || maj >= nblkdev)
761 panic("dumpconf: bad dumpdev=0x%x", dumpdev);
762 getsize = bdevsw[maj].d_psize;
763 if (getsize == NULL)
764 return;
765 nblks = (*getsize)(dumpdev);
766 if (nblks <= ctod(1))
767 return;
768
769 /* Position dump image near end of space, page aligned. */
770 dumpsize = physmem; /* pages */
771 dumplo = nblks - ctod(dumpsize);
772 dumplo &= ~(ctod(1)-1);
773
774 /* If it does not fit, truncate it by moving dumplo. */
775 /* Note: Must force signed comparison. */
776 if (dumplo < ((long)ctod(1))) {
777 dumplo = ctod(1);
778 dumpsize = dtoc(nblks - dumplo);
779 }
780 }
781
782 /* Note: gdb looks for "dumppcb" in a kernel crash dump. */
783 struct pcb dumppcb;
784
785 /*
786 * Write a crash dump. The format while in swap is:
787 * kcore_seg_t cpu_hdr;
788 * cpu_kcore_hdr_t cpu_data;
789 * padding (NBPG-sizeof(kcore_seg_t))
790 * pagemap (2*NBPG)
791 * physical memory...
792 */
793 void
794 dumpsys()
795 {
796 struct bdevsw *dsw;
797 kcore_seg_t *kseg_p;
798 cpu_kcore_hdr_t *chdr_p;
799 struct sun3x_kcore_hdr *sh;
800 phys_ram_seg_t *crs_p;
801 char *vaddr;
802 vm_offset_t paddr;
803 int psize, todo, seg, segsz;
804 daddr_t blkno;
805 int error = 0;
806
807 msgbufenabled = 0;
808 if (dumpdev == NODEV)
809 return;
810
811 /*
812 * For dumps during autoconfiguration,
813 * if dump device has already configured...
814 */
815 if (dumpsize == 0)
816 cpu_dumpconf();
817 if (dumplo <= 0) {
818 printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
819 minor(dumpdev));
820 return;
821 }
822 savectx(&dumppcb);
823
824 dsw = &bdevsw[major(dumpdev)];
825 psize = (*(dsw->d_psize))(dumpdev);
826 if (psize == -1) {
827 printf("dump area unavailable\n");
828 return;
829 }
830
831 printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
832 minor(dumpdev), dumplo);
833
834 /*
835 * We put the dump header is in physical page zero,
836 * so there is no extra work here to write it out.
837 * All we do is initialize the header.
838 */
839
840 /* Set pointers to all three parts. */
841 kseg_p = (kcore_seg_t *)KERNBASE;
842 chdr_p = (cpu_kcore_hdr_t *) (kseg_p + 1);
843 sh = &chdr_p->un._sun3x;
844
845 /* Fill in kcore_seg_t part. */
846 CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
847 kseg_p->c_size = sizeof(*chdr_p);
848
849 /* Fill in cpu_kcore_hdr_t part. */
850 /* Can NOT use machine[] as the name! */
851 strncpy(chdr_p->name, "sun3x", sizeof(chdr_p->name));
852 chdr_p->page_size = NBPG;
853 chdr_p->kernbase = KERNBASE;
854
855 /* Fill in the sun3x_kcore_hdr part. */
856 pmap_kcore_hdr(sh);
857
858 /*
859 * Now dump physical memory. Note that physical memory
860 * might NOT be congiguous, so do it by segments.
861 */
862
863 blkno = dumplo;
864 todo = dumpsize; /* pages */
865 vaddr = (char*)vmmap; /* Borrow /dev/mem VA */
866
867 for (seg = 0; seg < SUN3X_NPHYS_RAM_SEGS; seg++) {
868 crs_p = &sh->ram_segs[seg];
869 paddr = crs_p->start;
870 segsz = crs_p->size;
871 /*
872 * Our header lives in the first little bit of
873 * physical memory (not written separately), so
874 * we have to adjust the first ram segment size
875 * and start address to reflect the stolen RAM.
876 * (Nothing interesing in that RAM anyway 8^).
877 */
878 if (seg == 0) {
879 int adj = sizeof(*kseg_p) + sizeof(*chdr_p);
880 crs_p->start += adj;
881 crs_p->size -= adj;
882 }
883
884 while (todo && (segsz > 0)) {
885
886 /* Print pages left after every 16. */
887 if ((todo & 0xf) == 0)
888 printf("\r%4d", todo);
889
890 /* Make a temporary mapping for the page. */
891 pmap_enter(pmap_kernel(), vmmap, paddr | PMAP_NC,
892 VM_PROT_READ, FALSE);
893 error = (*dsw->d_dump)(dumpdev, blkno, vaddr, NBPG);
894 pmap_remove(pmap_kernel(), vmmap, vmmap + NBPG);
895 if (error)
896 goto fail;
897 paddr += NBPG;
898 segsz -= NBPG;
899 blkno += btodb(NBPG);
900 todo--;
901 }
902 }
903 printf("\rdump succeeded\n");
904 return;
905 fail:
906 printf(" dump error=%d\n", error);
907 }
908
909 static void
910 initcpu()
911 {
912 /* XXX: Enable RAM parity/ECC checking? */
913 /* XXX: parityenable(); */
914
915 #ifdef HAVECACHE
916 cache_enable();
917 #endif
918 }
919
920 /* straptrap() in trap.c */
921
922 /* from hp300: badaddr() */
923 /* peek_byte(), peek_word() moved to bus_subr.c */
924
925 /* XXX: parityenable() ? */
926 /* regdump() moved to regdump.c */
927
928 /*
929 * cpu_exec_aout_makecmds():
930 * cpu-dependent a.out format hook for execve().
931 *
932 * Determine if the given exec package refers to something which we
933 * understand and, if so, set up the vmcmds for it.
934 */
935 int
936 cpu_exec_aout_makecmds(p, epp)
937 struct proc *p;
938 struct exec_package *epp;
939 {
940 return ENOEXEC;
941 }
942