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