machdep.c revision 1.1 1 /* $NetBSD: machdep.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
40
41 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $");
42
43 #include "opt_ddb.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/map.h>
49 #include <sys/proc.h>
50 #include <sys/buf.h>
51 #include <sys/reboot.h>
52 #include <sys/conf.h>
53 #include <sys/file.h>
54 #include <sys/clist.h>
55 #include <sys/callout.h>
56 #include <sys/device.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 KGDB
70 #include <sys/kgdb.h>
71 #endif
72
73 #include <vm/vm.h>
74 #include <vm/vm_map.h>
75 #include <vm/vm_kern.h>
76 #include <vm/vm_page.h>
77
78 #include <uvm/uvm_extern.h>
79
80 #include <sys/sysctl.h>
81
82 #include <machine/cpu.h>
83 #include <machine/reg.h>
84 #include <machine/psl.h>
85 #include <machine/pte.h>
86 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */
87
88 #include <dev/cons.h>
89
90 #if defined(DDB)
91 #include <machine/db_machdep.h>
92 #include <ddb/db_sym.h>
93 #include <ddb/db_extern.h>
94 #endif
95
96 /*
97 * Info for CTL_HW
98 */
99 char machine[] = MACHINE;
100 char cpu_model[60];
101 extern char version[];
102
103 extern char kernel_text[];
104 extern char etext[];
105
106 vm_map_t exec_map = NULL;
107 vm_map_t mb_map = NULL;
108 vm_map_t phys_map = NULL;
109
110 caddr_t msgbufaddr;
111 int maxmem; /* max memory per process */
112 int physmem; /* set by locore */
113 /*
114 * safepri is a safe priority for sleep to set for a spin-wait
115 * during autoconfiguration or after a panic.
116 */
117 int safepri = PSL_LOWIPL;
118
119 void luna68k_init __P((void));
120 void identifycpu __P((void));
121 void dumpsys __P((void));
122
123 void straytrap __P((int, u_short));
124 void nmihand __P((struct frame));
125
126 int cpu_dumpsize __P((void));
127 int cpu_dump __P((int (*)(dev_t, daddr_t, caddr_t, size_t), daddr_t *));
128 void cpu_init_kcore_hdr __P((void));
129
130 /*
131 * Machine-independent crash dump header info.
132 */
133 cpu_kcore_hdr_t cpu_kcore_hdr;
134
135 int machtype; /* model: 1 for LUNA-1, 2 for LUNA-2 */
136 int sysconsole; /* console: 0 for ttya, 1 for video */
137
138 extern struct consdev syscons;
139 extern void omfb_cnattach __P((void));
140 extern void ws_cnattach __P((void));
141 extern void syscnattach __P((int));
142
143 /*
144 * On the 68020/68030, the value of delay_divisor is roughly
145 * 2048 / cpuspeed (where cpuspeed is in MHz).
146 *
147 * On the 68040/68060(?), the value of delay_divisor is roughly
148 * 759 / cpuspeed (where cpuspeed is in MHz).
149 * XXX -- is the above formula correct?
150 */
151 int cpuspeed = 25; /* only used for printing later */
152 int delay_divisor = 300; /* for delay() loop count */
153
154 /*
155 * Early initialization, before main() is called.
156 */
157 void
158 luna68k_init()
159 {
160 int i;
161
162 extern paddr_t avail_start, avail_end;
163
164 /*
165 * Tell the VM system about available physical memory. The
166 * luna68k only has one segment.
167 */
168 uvm_page_physload(atop(avail_start), atop(avail_end),
169 atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
170
171 /*
172 * Initialize error message buffer (at end of core).
173 * avail_end was pre-decremented in pmap_bootstrap to compensate.
174 */
175 for (i = 0; i < btoc(MSGBUFSIZE); i++)
176 pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * NBPG,
177 avail_end + i * NBPG, VM_PROT_READ|VM_PROT_WRITE,
178 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
179 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
180 }
181
182 /*
183 * Console initialization: called early on from main,
184 */
185 void
186 consinit()
187 {
188 volatile unsigned char *pio0 = (void *)0x49000000;
189 int sw1, i;
190 char *cp;
191 extern char bootarg[64];
192
193 pio0[3] = 0xb6;
194 pio0[2] = 1 << 6; /* enable parity check */
195
196 pio0[3] = 0xb6;
197 sw1 = pio0[0]; /* dipssw1 value */
198 sw1 ^= 0xff;
199 sysconsole = !(sw1 & 0x2); /* console selection */
200
201 boothowto = 0;
202 i = 0;
203 /*
204 * 'bootarg' has;
205 * "<args of x command> ENADDR=<addr> HOST=<host> SERVER=<name>"
206 * where <addr> is MAC address of which network loader used (not
207 * necessarily same as one at 0x4101.FFE0), <host> and <name>
208 * are the values of HOST and SERVER environment variables,
209 *
210 * NetBSD/luna68k cares only the first argment; any of "sda".
211 */
212 for (cp = bootarg; *cp != ' '; cp++) {
213 switch (*cp) {
214 case 's':
215 boothowto |= RB_SINGLE;
216 break;
217 case 'd':
218 boothowto |= RB_KDB;
219 break;
220 case 'a':
221 boothowto |= RB_ASKNAME;
222 break;
223 }
224 if (i++ >= sizeof(bootarg))
225 break;
226 }
227 if (boothowto == 0)
228 boothowto = (sw1 & 0x1) ? RB_SINGLE : 0;
229
230 if (sysconsole == 0)
231 syscnattach(0);
232 else {
233 omfb_cnattach();
234 ws_cnattach();
235 }
236
237 #ifdef DDB
238 {
239 extern int end;
240 extern int *esym;
241
242 ddb_init(*(int *)&end, ((int *)&end) + 1, esym);
243 }
244 if (boothowto & RB_KDB)
245 cpu_Debugger();
246 #endif
247 }
248
249 /*
250 * cpu_startup: allocate memory for variable-sized tables.
251 */
252 void
253 cpu_startup()
254 {
255 int i;
256 caddr_t v;
257 int base, residual;
258 vaddr_t minaddr, maxaddr;
259 vsize_t size;
260 char pbuf[9];
261 extern void greeting __P((void));
262
263 /*
264 * Initialize the kernel crash dump header.
265 */
266 cpu_init_kcore_hdr();
267
268 /*
269 * Good {morning,afternoon,evening,night}.
270 */
271 printf(version);
272 identifycpu();
273
274 format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
275 printf("total memory = %s\n", pbuf);
276
277 /*
278 * Find out how much space we need, allocate it,
279 * and then give everything true virtual addresses.
280 */
281 size = (int)allocsys(NULL, NULL);
282 if ((v = (caddr_t)uvm_km_alloc(kernel_map, round_page(size))) == 0)
283 panic("startup: no room for tables");
284 if (allocsys(v, NULL) - v != size)
285 panic("startup: table size inconsistency");
286
287 /*
288 * Now allocate buffers proper. They are different than the above
289 * in that they usually occupy more virtual memory than physical.
290 */
291 size = MAXBSIZE * nbuf;
292 if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
293 NULL, UVM_UNKNOWN_OFFSET,
294 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
295 UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
296 panic("startup: cannot allocate VM for buffers");
297 minaddr = (vaddr_t)buffers;
298 if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
299 /* don't want to alloc more physical mem than needed */
300 bufpages = btoc(MAXBSIZE) * nbuf;
301 }
302 base = bufpages / nbuf;
303 residual = bufpages % nbuf;
304 for (i = 0; i < nbuf; i++) {
305 vsize_t curbufsize;
306 vaddr_t curbuf;
307 struct vm_page *pg;
308
309 /*
310 * Each buffer has MAXBSIZE bytes of VM space allocated. Of
311 * that MAXBSIZE space, we allocate and map (base+1) pages
312 * for the first "residual" buffers, and then we allocate
313 * "base" pages for the rest.
314 */
315 curbuf = (vsize_t) buffers + (i * MAXBSIZE);
316 curbufsize = NBPG * ((i < residual) ? (base+1) : base);
317
318 while (curbufsize) {
319 pg = uvm_pagealloc(NULL, 0, NULL, 0);
320 if (pg == NULL)
321 panic("cpu_startup: not enough memory for "
322 "buffer cache");
323 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg),
324 VM_PROT_READ|VM_PROT_WRITE);
325 curbuf += PAGE_SIZE;
326 curbufsize -= PAGE_SIZE;
327 }
328 }
329
330 /*
331 * Allocate a submap for exec arguments. This map effectively
332 * limits the number of processes exec'ing at any time.
333 */
334 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
335 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
336
337 /*
338 * Allocate a submap for physio
339 */
340 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
341 VM_PHYS_SIZE, 0, FALSE, NULL);
342
343 /*
344 * Finally, allocate mbuf cluster submap.
345 */
346 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
347 nmbclusters * mclbytes, VM_MAP_INTRSAFE,
348 FALSE, NULL);
349
350 /*
351 * Initialize callouts
352 */
353 callfree = callout;
354 for (i = 1; i < ncallout; i++)
355 callout[i-1].c_next = &callout[i];
356 callout[i-1].c_next = NULL;
357
358 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
359 printf("avail memory = %s\n", pbuf);
360 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG);
361 printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
362
363 /*
364 * Tell the VM system that the area before the text segment
365 * is invalid.
366 *
367 * XXX Should just change KERNBASE and VM_MIN_KERNEL_ADDRESS,
368 * XXX but not right now.
369 */
370 if (uvm_map_protect(kernel_map, 0, round_page(&kernel_text),
371 UVM_PROT_NONE, TRUE) != KERN_SUCCESS)
372 panic("can't mark pre-text pages off-limits");
373
374 /*
375 * Tell the VM system that writing to kernel text isn't allowed.
376 * If we don't, we might end up COW'ing the text segment!
377 */
378 if (uvm_map_protect(kernel_map, trunc_page(&kernel_text),
379 trunc_page(&etext), UVM_PROT_READ|UVM_PROT_EXEC, TRUE)
380 != KERN_SUCCESS)
381 panic("can't protect kernel text");
382
383 /*
384 * Set up buffers, so they can be used to read disk labels.
385 */
386 bufinit();
387
388 /*
389 * Say "Hi" to the world
390 */
391 greeting();
392 }
393
394 /*
395 * Set registers on exec.
396 */
397 void
398 setregs(p, pack, stack)
399 register struct proc *p;
400 struct exec_package *pack;
401 u_long stack;
402 {
403 struct frame *frame = (struct frame *)p->p_md.md_regs;
404 extern int fputype;
405
406 frame->f_sr = PSL_USERSET;
407 frame->f_pc = pack->ep_entry & ~1;
408 frame->f_regs[D0] = 0;
409 frame->f_regs[D1] = 0;
410 frame->f_regs[D2] = 0;
411 frame->f_regs[D3] = 0;
412 frame->f_regs[D4] = 0;
413 frame->f_regs[D5] = 0;
414 frame->f_regs[D6] = 0;
415 frame->f_regs[D7] = 0;
416 frame->f_regs[A0] = 0;
417 frame->f_regs[A1] = 0;
418 frame->f_regs[A2] = (int)PS_STRINGS;
419 frame->f_regs[A3] = 0;
420 frame->f_regs[A4] = 0;
421 frame->f_regs[A5] = 0;
422 frame->f_regs[A6] = 0;
423 frame->f_regs[SP] = stack;
424
425 /* restore a null state frame */
426 p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;
427 if (fputype)
428 m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);
429 }
430
431 void
432 identifycpu()
433 {
434 extern int cputype;
435 char *cpu;
436
437 bzero(cpu_model, sizeof(cpu_model));
438 switch (cputype) {
439 case CPU_68030:
440 cpu = "MC68030 CPU+MMU, MC68882 FPU";
441 machtype = LUNA_I;
442 cpuspeed = 20; delay_divisor = 102; /* 20MHz 68030 */
443 hz = 60;
444 break;
445 #ifdef M68040
446 case CPU_68040:
447 cpu = "MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches";
448 machtype = LUNA_II;
449 cpuspeed = 25; delay_divisor = 300; /* 25MHz 68040 */
450 break;
451 #endif
452 default:
453 panic("unknown CPU type");
454 }
455 strcpy(cpu_model, cpu);
456 printf("%s\n", cpu_model);
457 }
458
459 /*
460 * machine dependent system variables.
461 */
462 int
463 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
464 int *name;
465 u_int namelen;
466 void *oldp;
467 size_t *oldlenp;
468 void *newp;
469 size_t newlen;
470 struct proc *p;
471 {
472 dev_t consdev;
473
474 /* all sysctl names at this level are terminal */
475 if (namelen != 1)
476 return (ENOTDIR); /* overloaded */
477
478 switch (name[0]) {
479 case CPU_CONSDEV:
480 if (cn_tab != NULL)
481 consdev = cn_tab->cn_dev;
482 else
483 consdev = NODEV;
484 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
485 sizeof consdev));
486 default:
487 return (EOPNOTSUPP);
488 }
489 /* NOTREACHED */
490 }
491
492 int waittime = -1;
493
494 void
495 cpu_reboot(howto, bootstr)
496 volatile int howto; /* XXX to shutup GCC XXX */
497 char *bootstr;
498 {
499 extern void doboot __P((void));
500
501 /* take a snap shot before clobbering any registers */
502 if (curproc && curproc->p_addr)
503 savectx(&curproc->p_addr->u_pcb);
504
505 /* If system is hold, just halt. */
506 if (cold) {
507 howto |= RB_HALT;
508 goto haltsys;
509 }
510
511 boothowto = howto;
512 if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
513 waittime = 0;
514 vfs_shutdown();
515 /*
516 * If we've been adjusting the clock, the todr
517 * will be out of synch; adjust it now.
518 */
519 resettodr();
520 }
521
522 /* Disable interrupts. */
523 splhigh();
524
525 /* If rebooting and a dump is requested, do it. */
526 if (howto & RB_DUMP)
527 dumpsys();
528
529 haltsys:
530 /* Run any shutdown hooks. */
531 doshutdownhooks();
532
533 /* Finally, halt/reboot the system. */
534 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
535 u_int8_t *pio = (void *)0x4d000000;
536
537 printf("power is going down.\n");
538 DELAY(100000);
539 pio[3] = 0x94;
540 pio[2] = 0 << 4;
541 for (;;) /* NOP */;
542 }
543 if (howto & RB_HALT) {
544 printf("System halted. Hit any key to reboot.\n\n");
545 (void)cngetc();
546 }
547
548 printf("rebooting...\n");
549 DELAY(100000);
550 doboot();
551 /*NOTREACHED*/
552 while (1) ;
553 }
554
555 /*
556 * Initialize the kernel crash dump header.
557 */
558 void
559 cpu_init_kcore_hdr()
560 {
561 cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
562 struct m68k_kcore_hdr *m = &h->un._m68k;
563 extern char end[];
564
565 bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr));
566
567 /*
568 * Initialize the `dispatcher' portion of the header.
569 */
570 strcpy(h->name, machine);
571 h->page_size = NBPG;
572 h->kernbase = KERNBASE;
573
574 /*
575 * Fill in information about our MMU configuration.
576 */
577 m->mmutype = mmutype;
578 m->sg_v = SG_V;
579 m->sg_frame = SG_FRAME;
580 m->sg_ishift = SG_ISHIFT;
581 m->sg_pmask = SG_PMASK;
582 m->sg40_shift1 = SG4_SHIFT1;
583 m->sg40_mask2 = SG4_MASK2;
584 m->sg40_shift2 = SG4_SHIFT2;
585 m->sg40_mask3 = SG4_MASK3;
586 m->sg40_shift3 = SG4_SHIFT3;
587 m->sg40_addr1 = SG4_ADDR1;
588 m->sg40_addr2 = SG4_ADDR2;
589 m->pg_v = PG_V;
590 m->pg_frame = PG_FRAME;
591
592 /*
593 * Initialize pointer to kernel segment table.
594 */
595 m->sysseg_pa = (u_int32_t)(pmap_kernel()->pm_stpa);
596
597 /*
598 * Initialize relocation value such that:
599 *
600 * pa = (va - KERNBASE) + reloc
601 *
602 * Since we're linked and loaded at the same place,
603 * and the kernel is mapped va == pa, this is 0.
604 */
605 m->reloc = 0;
606
607 /*
608 * Define the end of the relocatable range.
609 */
610 m->relocend = (u_int32_t)end;
611
612 /*
613 * The luna68k has one contiguous memory segment.
614 */
615 m->ram_segs[0].start = 0 /* lowram */;
616 m->ram_segs[0].size = ctob(physmem);
617 }
618
619 /*
620 * Compute the size of the machine-dependent crash dump header.
621 * Returns size in disk blocks.
622 */
623 int
624 cpu_dumpsize()
625 {
626 int size;
627
628 size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t));
629 return (btodb(roundup(size, dbtob(1))));
630 }
631
632 /*
633 * Called by dumpsys() to dump the machine-dependent header.
634 */
635 int
636 cpu_dump(dump, blknop)
637 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
638 daddr_t *blknop;
639 {
640 int buf[dbtob(1) / sizeof(int)];
641 cpu_kcore_hdr_t *chdr;
642 kcore_seg_t *kseg;
643 int error;
644
645 kseg = (kcore_seg_t *)buf;
646 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
647 sizeof(int)];
648
649 /* Create the segment header. */
650 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
651 kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t));
652
653 bcopy(&cpu_kcore_hdr, chdr, sizeof(cpu_kcore_hdr_t));
654 error = (*dump)(dumpdev, *blknop, (caddr_t)buf, sizeof(buf));
655 *blknop += btodb(sizeof(buf));
656 return (error);
657 }
658
659 /*
660 * These variables are needed by /sbin/savecore
661 */
662 u_long dumpmag = 0x8fca0101; /* magic number */
663 int dumpsize = 0; /* pages */
664 long dumplo = 0; /* blocks */
665
666 /*
667 * This is called by main to set dumplo and dumpsize.
668 * Dumps always skip the first NBPG of disk space
669 * in case there might be a disk label stored there.
670 * If there is extra space, put dump at the end to
671 * reduce the chance that swapping trashes it.
672 */
673 void
674 cpu_dumpconf()
675 {
676 int chdrsize; /* size of dump header */
677 int nblks; /* size of dump area */
678 int maj;
679
680 if (dumpdev == NODEV)
681 return;
682 maj = major(dumpdev);
683 if (maj < 0 || maj >= nblkdev)
684 panic("dumpconf: bad dumpdev=0x%x", dumpdev);
685 if (bdevsw[maj].d_psize == NULL)
686 return;
687 nblks = (*bdevsw[maj].d_psize)(dumpdev);
688 chdrsize = cpu_dumpsize();
689
690 dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
691
692 /*
693 * Check do see if we will fit. Note we always skip the
694 * first NBPG in case there is a disk label there.
695 */
696 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
697 dumpsize = 0;
698 dumplo = -1;
699 return;
700 }
701
702 /*
703 * Put dump at the end of the partition.
704 */
705 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
706 }
707
708 /*
709 * Dump physical memory onto the dump device. Called by cpu_reboot().
710 */
711 void
712 dumpsys()
713 {
714 daddr_t blkno; /* current block to write */
715 /* dump routine */
716 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
717 int pg; /* page being dumped */
718 paddr_t maddr; /* PA being dumped */
719 int error; /* error code from (*dump)() */
720
721 /* XXX initialized here because of gcc lossage */
722 maddr = 0 /* lowram */;
723 pg = 0;
724
725 /* Don't put dump messages in msgbuf. */
726 msgbufenabled = 0;
727
728 /* Make sure dump device is valid. */
729 if (dumpdev == NODEV)
730 return;
731 if (dumpsize == 0) {
732 cpu_dumpconf();
733 if (dumpsize == 0)
734 return;
735 }
736 if (dumplo <= 0) {
737 printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
738 minor(dumpdev));
739 return;
740 }
741 dump = bdevsw[major(dumpdev)].d_dump;
742 blkno = dumplo;
743
744 printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
745 minor(dumpdev), dumplo);
746
747 printf("dump ");
748
749 /* Write the dump header. */
750 error = cpu_dump(dump, &blkno);
751 if (error)
752 goto bad;
753
754 for (pg = 0; pg < dumpsize; pg++) {
755 #define NPGMB (1024*1024/NBPG)
756 /* print out how many MBs we have dumped */
757 if (pg && (pg % NPGMB) == 0)
758 printf("%d ", pg / NPGMB);
759 #undef NPGMB
760 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
761 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
762
763 error = (*dump)(dumpdev, blkno, vmmap, NBPG);
764 bad:
765 switch (error) {
766 case 0:
767 maddr += NBPG;
768 blkno += btodb(NBPG);
769 break;
770
771 case ENXIO:
772 printf("device bad\n");
773 return;
774
775 case EFAULT:
776 printf("device not ready\n");
777 return;
778
779 case EINVAL:
780 printf("area improper\n");
781 return;
782
783 case EIO:
784 printf("i/o error\n");
785 return;
786
787 case EINTR:
788 printf("aborted from console\n");
789 return;
790
791 default:
792 printf("error %d\n", error);
793 return;
794 }
795 }
796 printf("succeeded\n");
797 }
798
799 void
800 straytrap(pc, evec)
801 int pc;
802 u_short evec;
803 {
804 printf("unexpected trap (vector offset %x) from %x\n",
805 evec & 0xFFF, pc);
806 }
807
808 int *nofault;
809
810 int
811 badaddr(addr, nbytes)
812 register caddr_t addr;
813 int nbytes;
814 {
815 register int i;
816 label_t faultbuf;
817
818 #ifdef lint
819 i = *addr; if (i) return (0);
820 #endif
821
822 nofault = (int *) &faultbuf;
823 if (setjmp((label_t *)nofault)) {
824 nofault = (int *) 0;
825 return(1);
826 }
827
828 switch (nbytes) {
829 case 1:
830 i = *(volatile char *)addr;
831 break;
832
833 case 2:
834 i = *(volatile short *)addr;
835 break;
836
837 case 4:
838 i = *(volatile int *)addr;
839 break;
840
841 default:
842 panic("badaddr: bad request");
843 }
844 nofault = (int *) 0;
845 return (0);
846 }
847
848 void luna68k_abort __P((char *));
849
850 static int innmihand; /* simple mutex */
851
852 /*
853 * Level 7 interrupts are caused by e.g. the ABORT switch.
854 *
855 * If we have DDB, then break into DDB on ABORT. In a production
856 * environment, bumping the ABORT switch would be bad, so we enable
857 * panic'ing on ABORT with the kernel option "PANICBUTTON".
858 */
859 void
860 nmihand(frame)
861 struct frame frame;
862 {
863 /* Prevent unwanted recursion */
864 if (innmihand)
865 return;
866 innmihand = 1;
867
868 luna68k_abort("ABORT SWITCH");
869 }
870
871 /*
872 * Common code for handling ABORT signals from buttons, switches,
873 * serial lines, etc.
874 */
875 void
876 luna68k_abort(cp)
877 char *cp;
878 {
879 #ifdef DDB
880 printf("%s\n", cp);
881 cpu_Debugger();
882 #else
883 #ifdef PANICBUTTON
884 panic(cp);
885 #else
886 printf("%s ignored\n", cp);
887 #endif /* PANICBUTTON */
888 #endif /* DDB */
889 }
890
891 /*
892 * cpu_exec_aout_makecmds():
893 * cpu-dependent a.out format hook for execve().
894 *
895 * Determine of the given exec package refers to something which we
896 * understand and, if so, set up the vmcmds for it.
897 */
898 int
899 cpu_exec_aout_makecmds(p, epp)
900 struct proc *p;
901 struct exec_package *epp;
902 {
903 int error = ENOEXEC;
904 #ifdef COMPAT_SUNOS
905 extern sunos_exec_aout_makecmds
906 __P((struct proc *, struct exec_package *));
907 if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
908 return 0;
909 #endif
910 return error;
911 }
912
913 /*
914 * Return the best possible estimate of the time in the timeval
915 * to which tvp points. Unfortunately, we can't read the hardware registers.
916 * We guarantee that the time will be greater than the value obtained by a
917 * previous call.
918 */
919 void
920 microtime(tvp)
921 register struct timeval *tvp;
922 {
923 int s = splclock();
924 static struct timeval lasttime;
925
926 *tvp = time;
927 #ifdef notdef
928 tvp->tv_usec += clkread();
929 while (tvp->tv_usec > 1000000) {
930 tvp->tv_sec++;
931 tvp->tv_usec -= 1000000;
932 }
933 #endif
934 if (tvp->tv_sec == lasttime.tv_sec &&
935 tvp->tv_usec <= lasttime.tv_usec &&
936 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
937 tvp->tv_sec++;
938 tvp->tv_usec -= 1000000;
939 }
940 lasttime = *tvp;
941 splx(s);
942 }
943
944 #ifndef ROMCONS
945
946 struct consdev *cn_tab = &syscons;
947
948 #else
949
950 /*
951 * romcons is useful until m68k TC register is initialized.
952 */
953 int romcngetc __P((dev_t));
954 void romcnputc __P((dev_t, int));
955
956 struct consdev romcons = {
957 NULL,
958 NULL,
959 romcngetc,
960 romcnputc,
961 nullcnpollc,
962 makedev(7, 0), /* XXX */
963 CN_DEAD,
964 };
965 struct consdev *cn_tab = &romcons;
966
967 extern int romcall __P((int, int));
968
969 #define ROMGETC() romcall(6, 0)
970 #define ROMPUTC(x) romcall(7, x)
971
972 void
973 romcnputc(dev, c)
974 dev_t dev;
975 int c;
976 {
977 ROMPUTC(c);
978 }
979
980 int
981 romcngetc(dev)
982 dev_t dev;
983 {
984 int c;
985
986 do {
987 c = ROMGETC();
988 } while (c == -1);
989 return c;
990 }
991 #endif
992