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