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