machdep.c revision 1.49 1 /* $NetBSD: machdep.c,v 1.49 2007/02/28 04:21:52 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.49 2007/02/28 04:21:52 thorpej Exp $");
42
43 #include "opt_ddb.h"
44 #include "opt_kgdb.h"
45 #include "opt_compat_sunos.h"
46 #include "opt_panicbutton.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/proc.h>
52 #include <sys/buf.h>
53 #include <sys/reboot.h>
54 #include <sys/conf.h>
55 #include <sys/file.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 #include <sys/ksyms.h>
70 #ifdef KGDB
71 #include <sys/kgdb.h>
72 #endif
73 #include <sys/boot_flag.h>
74
75 #include <uvm/uvm_extern.h>
76
77 #include <sys/sysctl.h>
78
79 #include <machine/cpu.h>
80 #include <machine/reg.h>
81 #include <machine/psl.h>
82 #include <machine/pte.h>
83 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */
84
85 #include <dev/cons.h>
86
87 #if defined(DDB)
88 #include <machine/db_machdep.h>
89 #include <ddb/db_sym.h>
90 #include <ddb/db_extern.h>
91 #endif
92
93 #include "ksyms.h"
94
95 /*
96 * Info for CTL_HW
97 */
98 char machine[] = MACHINE;
99 char cpu_model[60];
100
101 /* Our exported CPU info; we can have only one. */
102 struct cpu_info cpu_info_store;
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 * PAGE_SIZE,
178 avail_end + i * PAGE_SIZE, 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 #if NKSYMS || defined(DDB) || defined(LKM)
227 {
228 extern char end[];
229 extern int *esym;
230
231 ksyms_init(*(int *)&end, ((int *)&end) + 1, esym);
232 }
233 #endif
234 #ifdef DDB
235 if (boothowto & RB_KDB)
236 cpu_Debugger();
237 #endif
238 }
239
240 /*
241 * cpu_startup: allocate memory for variable-sized tables.
242 */
243 void
244 cpu_startup()
245 {
246 vaddr_t minaddr, maxaddr;
247 char pbuf[9];
248 extern void greeting __P((void));
249
250 if (fputype != FPU_NONE)
251 m68k_make_fpu_idle_frame();
252
253 /*
254 * Initialize the kernel crash dump header.
255 */
256 cpu_init_kcore_hdr();
257
258 /*
259 * Good {morning,afternoon,evening,night}.
260 */
261 printf("%s%s", copyright, version);
262 identifycpu();
263
264 format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
265 printf("total memory = %s\n", pbuf);
266
267 minaddr = 0;
268 /*
269 * Allocate a submap for exec arguments. This map effectively
270 * limits the number of processes exec'ing at any time.
271 */
272 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
273 16*NCARGS, VM_MAP_PAGEABLE, false, NULL);
274
275 /*
276 * Allocate a submap for physio
277 */
278 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
279 VM_PHYS_SIZE, 0, false, NULL);
280
281 /*
282 * Finally, allocate mbuf cluster submap.
283 */
284 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
285 nmbclusters * mclbytes, VM_MAP_INTRSAFE,
286 false, NULL);
287
288 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
289 printf("avail memory = %s\n", pbuf);
290
291 /*
292 * Say "Hi" to the world
293 */
294 greeting();
295 }
296
297 /*
298 * Set registers on exec.
299 */
300 void
301 setregs(l, pack, stack)
302 struct lwp *l;
303 struct exec_package *pack;
304 u_long stack;
305 {
306 struct frame *frame = (struct frame *)l->l_md.md_regs;
307 extern int fputype;
308
309 frame->f_sr = PSL_USERSET;
310 frame->f_pc = pack->ep_entry & ~1;
311 frame->f_regs[D0] = 0;
312 frame->f_regs[D1] = 0;
313 frame->f_regs[D2] = 0;
314 frame->f_regs[D3] = 0;
315 frame->f_regs[D4] = 0;
316 frame->f_regs[D5] = 0;
317 frame->f_regs[D6] = 0;
318 frame->f_regs[D7] = 0;
319 frame->f_regs[A0] = 0;
320 frame->f_regs[A1] = 0;
321 frame->f_regs[A2] = (int)l->l_proc->p_psstr;
322 frame->f_regs[A3] = 0;
323 frame->f_regs[A4] = 0;
324 frame->f_regs[A5] = 0;
325 frame->f_regs[A6] = 0;
326 frame->f_regs[SP] = stack;
327
328 /* restore a null state frame */
329 l->l_addr->u_pcb.pcb_fpregs.fpf_null = 0;
330 if (fputype)
331 m68881_restore(&l->l_addr->u_pcb.pcb_fpregs);
332 }
333
334 void
335 identifycpu()
336 {
337 extern int cputype;
338 const char *cpu;
339
340 bzero(cpu_model, sizeof(cpu_model));
341 switch (cputype) {
342 case CPU_68030:
343 cpu = "MC68030 CPU+MMU, MC68882 FPU";
344 machtype = LUNA_I;
345 cpuspeed = 20; delay_divisor = 102; /* 20MHz 68030 */
346 hz = 60;
347 break;
348 #if defined(M68040)
349 case CPU_68040:
350 cpu = "MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches";
351 machtype = LUNA_II;
352 cpuspeed = 25; delay_divisor = 300; /* 25MHz 68040 */
353 break;
354 #endif
355 default:
356 panic("unknown CPU type");
357 }
358 strcpy(cpu_model, cpu);
359 printf("%s\n", cpu_model);
360 }
361
362 /*
363 * machine dependent system variables.
364 */
365 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
366 {
367
368 sysctl_createv(clog, 0, NULL, NULL,
369 CTLFLAG_PERMANENT,
370 CTLTYPE_NODE, "machdep", NULL,
371 NULL, 0, NULL, 0,
372 CTL_MACHDEP, CTL_EOL);
373
374 sysctl_createv(clog, 0, NULL, NULL,
375 CTLFLAG_PERMANENT,
376 CTLTYPE_STRUCT, "console_device", NULL,
377 sysctl_consdev, 0, NULL, sizeof(dev_t),
378 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
379 }
380
381 int waittime = -1;
382
383 void
384 cpu_reboot(howto, bootstr)
385 volatile int howto; /* XXX to shutup GCC XXX */
386 char *bootstr;
387 {
388 extern void doboot __P((void));
389
390 /* take a snap shot before clobbering any registers */
391 if (curlwp && curlwp->l_addr)
392 savectx(&curlwp->l_addr->u_pcb);
393
394 /* If system is hold, just halt. */
395 if (cold) {
396 howto |= RB_HALT;
397 goto haltsys;
398 }
399
400 boothowto = howto;
401 if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
402 waittime = 0;
403 vfs_shutdown();
404 /*
405 * If we've been adjusting the clock, the todr
406 * will be out of synch; adjust it now.
407 */
408 resettodr();
409 }
410
411 /* Disable interrupts. */
412 splhigh();
413
414 /* If rebooting and a dump is requested, do it. */
415 if (howto & RB_DUMP)
416 dumpsys();
417
418 haltsys:
419 /* Run any shutdown hooks. */
420 doshutdownhooks();
421
422 /* Finally, halt/reboot the system. */
423 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
424 u_int8_t *pio = (void *)0x4d000000;
425
426 printf("power is going down.\n");
427 DELAY(100000);
428 pio[3] = 0x94;
429 pio[2] = 0 << 4;
430 for (;;) /* NOP */;
431 }
432 if (howto & RB_HALT) {
433 printf("System halted. Hit any key to reboot.\n\n");
434 (void)cngetc();
435 }
436
437 printf("rebooting...\n");
438 DELAY(100000);
439 doboot();
440 /*NOTREACHED*/
441 while (1) ;
442 }
443
444 /*
445 * Initialize the kernel crash dump header.
446 */
447 void
448 cpu_init_kcore_hdr()
449 {
450 cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
451 struct m68k_kcore_hdr *m = &h->un._m68k;
452 extern char end[];
453
454 bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr));
455
456 /*
457 * Initialize the `dispatcher' portion of the header.
458 */
459 strcpy(h->name, machine);
460 h->page_size = PAGE_SIZE;
461 h->kernbase = KERNBASE;
462
463 /*
464 * Fill in information about our MMU configuration.
465 */
466 m->mmutype = mmutype;
467 m->sg_v = SG_V;
468 m->sg_frame = SG_FRAME;
469 m->sg_ishift = SG_ISHIFT;
470 m->sg_pmask = SG_PMASK;
471 m->sg40_shift1 = SG4_SHIFT1;
472 m->sg40_mask2 = SG4_MASK2;
473 m->sg40_shift2 = SG4_SHIFT2;
474 m->sg40_mask3 = SG4_MASK3;
475 m->sg40_shift3 = SG4_SHIFT3;
476 m->sg40_addr1 = SG4_ADDR1;
477 m->sg40_addr2 = SG4_ADDR2;
478 m->pg_v = PG_V;
479 m->pg_frame = PG_FRAME;
480
481 /*
482 * Initialize pointer to kernel segment table.
483 */
484 m->sysseg_pa = (u_int32_t)(pmap_kernel()->pm_stpa);
485
486 /*
487 * Initialize relocation value such that:
488 *
489 * pa = (va - KERNBASE) + reloc
490 *
491 * Since we're linked and loaded at the same place,
492 * and the kernel is mapped va == pa, this is 0.
493 */
494 m->reloc = 0;
495
496 /*
497 * Define the end of the relocatable range.
498 */
499 m->relocend = (u_int32_t)end;
500
501 /*
502 * The luna68k has one contiguous memory segment.
503 */
504 m->ram_segs[0].start = 0 /* lowram */;
505 m->ram_segs[0].size = ctob(physmem);
506 }
507
508 /*
509 * Compute the size of the machine-dependent crash dump header.
510 * Returns size in disk blocks.
511 */
512
513 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
514 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
515
516 int
517 cpu_dumpsize()
518 {
519
520 return btodb(MDHDRSIZE);
521 }
522
523 /*
524 * Called by dumpsys() to dump the machine-dependent header.
525 */
526 int
527 cpu_dump(dump, blknop)
528 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
529 daddr_t *blknop;
530 {
531 int buf[MDHDRSIZE / sizeof(int)];
532 cpu_kcore_hdr_t *chdr;
533 kcore_seg_t *kseg;
534 int error;
535
536 kseg = (kcore_seg_t *)buf;
537 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
538 sizeof(int)];
539
540 /* Create the segment header. */
541 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
542 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
543
544 bcopy(&cpu_kcore_hdr, chdr, sizeof(cpu_kcore_hdr_t));
545 error = (*dump)(dumpdev, *blknop, (caddr_t)buf, sizeof(buf));
546 *blknop += btodb(sizeof(buf));
547 return (error);
548 }
549
550 /*
551 * These variables are needed by /sbin/savecore
552 */
553 u_int32_t dumpmag = 0x8fca0101; /* magic number */
554 int dumpsize = 0; /* pages */
555 long dumplo = 0; /* blocks */
556
557 /*
558 * This is called by main to set dumplo and dumpsize.
559 * Dumps always skip the first PAGE_SIZE of disk space
560 * in case there might be a disk label stored there.
561 * If there is extra space, put dump at the end to
562 * reduce the chance that swapping trashes it.
563 */
564 void
565 cpu_dumpconf()
566 {
567 const struct bdevsw *bdev;
568 int chdrsize; /* size of dump header */
569 int nblks; /* size of dump area */
570
571 if (dumpdev == NODEV)
572 return;
573 bdev = bdevsw_lookup(dumpdev);
574 if (bdev == NULL) {
575 dumpdev = NODEV;
576 return;
577 }
578 if (bdev->d_psize == NULL)
579 return;
580 nblks = (*bdev->d_psize)(dumpdev);
581 chdrsize = cpu_dumpsize();
582
583 dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
584
585 /*
586 * Check do see if we will fit. Note we always skip the
587 * first PAGE_SIZE in case there is a disk label there.
588 */
589 if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
590 dumpsize = 0;
591 dumplo = -1;
592 return;
593 }
594
595 /*
596 * Put dump at the end of the partition.
597 */
598 dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
599 }
600
601 /*
602 * Dump physical memory onto the dump device. Called by cpu_reboot().
603 */
604 void
605 dumpsys()
606 {
607 const struct bdevsw *bdev;
608 daddr_t blkno; /* current block to write */
609 /* dump routine */
610 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
611 int pg; /* page being dumped */
612 paddr_t maddr; /* PA being dumped */
613 int error; /* error code from (*dump)() */
614
615 /* XXX initialized here because of gcc lossage */
616 maddr = 0 /* lowram */;
617 pg = 0;
618
619 /* Make sure dump device is valid. */
620 if (dumpdev == NODEV)
621 return;
622 bdev = bdevsw_lookup(dumpdev);
623 if (bdev == NULL)
624 return;
625 if (dumpsize == 0) {
626 cpu_dumpconf();
627 if (dumpsize == 0)
628 return;
629 }
630 if (dumplo <= 0) {
631 printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
632 minor(dumpdev));
633 return;
634 }
635 dump = bdev->d_dump;
636 blkno = dumplo;
637
638 printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
639 minor(dumpdev), dumplo);
640
641 printf("dump ");
642
643 /* Write the dump header. */
644 error = cpu_dump(dump, &blkno);
645 if (error)
646 goto bad;
647
648 for (pg = 0; pg < dumpsize; pg++) {
649 #define NPGMB (1024*1024/PAGE_SIZE)
650 /* print out how many MBs we have dumped */
651 if (pg && (pg % NPGMB) == 0)
652 printf("%d ", pg / NPGMB);
653 #undef NPGMB
654 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
655 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
656
657 pmap_update(pmap_kernel());
658 error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
659 bad:
660 switch (error) {
661 case 0:
662 maddr += PAGE_SIZE;
663 blkno += btodb(PAGE_SIZE);
664 break;
665
666 case ENXIO:
667 printf("device bad\n");
668 return;
669
670 case EFAULT:
671 printf("device not ready\n");
672 return;
673
674 case EINVAL:
675 printf("area improper\n");
676 return;
677
678 case EIO:
679 printf("i/o error\n");
680 return;
681
682 case EINTR:
683 printf("aborted from console\n");
684 return;
685
686 default:
687 printf("error %d\n", error);
688 return;
689 }
690 }
691 printf("succeeded\n");
692 }
693
694 void
695 straytrap(pc, evec)
696 int pc;
697 u_short evec;
698 {
699 printf("unexpected trap (vector offset %x) from %x\n",
700 evec & 0xFFF, pc);
701 }
702
703 int *nofault;
704
705 int
706 badaddr(addr, nbytes)
707 register caddr_t addr;
708 int nbytes;
709 {
710 register int i;
711 label_t faultbuf;
712
713 #ifdef lint
714 i = *addr; if (i) return (0);
715 #endif
716
717 nofault = (int *) &faultbuf;
718 if (setjmp((label_t *)nofault)) {
719 nofault = (int *) 0;
720 return(1);
721 }
722
723 switch (nbytes) {
724 case 1:
725 i = *(volatile char *)addr;
726 break;
727
728 case 2:
729 i = *(volatile short *)addr;
730 break;
731
732 case 4:
733 i = *(volatile int *)addr;
734 break;
735
736 default:
737 panic("badaddr: bad request");
738 }
739 nofault = (int *) 0;
740 return (0);
741 }
742
743 void luna68k_abort __P((const char *));
744
745 static int innmihand; /* simple mutex */
746
747 /*
748 * Level 7 interrupts are caused by e.g. the ABORT switch.
749 *
750 * If we have DDB, then break into DDB on ABORT. In a production
751 * environment, bumping the ABORT switch would be bad, so we enable
752 * panic'ing on ABORT with the kernel option "PANICBUTTON".
753 */
754 void
755 nmihand(frame)
756 struct frame frame;
757 {
758 /* Prevent unwanted recursion */
759 if (innmihand)
760 return;
761 innmihand = 1;
762
763 luna68k_abort("ABORT SWITCH");
764 }
765
766 /*
767 * Common code for handling ABORT signals from buttons, switches,
768 * serial lines, etc.
769 */
770 void
771 luna68k_abort(cp)
772 const char *cp;
773 {
774 #ifdef DDB
775 printf("%s\n", cp);
776 cpu_Debugger();
777 #else
778 #ifdef PANICBUTTON
779 panic(cp);
780 #else
781 printf("%s ignored\n", cp);
782 #endif /* PANICBUTTON */
783 #endif /* DDB */
784 }
785
786 /*
787 * cpu_exec_aout_makecmds():
788 * CPU-dependent a.out format hook for execve().
789 *
790 * Determine of the given exec package refers to something which we
791 * understand and, if so, set up the vmcmds for it.
792 */
793 int
794 cpu_exec_aout_makecmds(l, epp)
795 struct lwp *l;
796 struct exec_package *epp;
797 {
798 int error = ENOEXEC;
799 #ifdef COMPAT_SUNOS
800 extern sunos_exec_aout_makecmds
801 __P((struct proc *, struct exec_package *));
802 if ((error = sunos_exec_aout_makecmds(l->l_proc, epp)) == 0)
803 return 0;
804 #endif
805 return error;
806 }
807
808 #if 1
809
810 struct consdev *cn_tab = &syscons;
811
812 #else
813
814 /*
815 * romcons is useful until m68k TC register is initialized.
816 */
817 int romcngetc __P((dev_t));
818 void romcnputc __P((dev_t, int));
819
820 struct consdev romcons = {
821 NULL,
822 NULL,
823 romcngetc,
824 romcnputc,
825 nullcnpollc,
826 makedev(7, 0), /* XXX */
827 CN_DEAD,
828 };
829 struct consdev *cn_tab = &romcons;
830
831 #define __ ((int **)0x41000000)
832 #define GETC() (*(int (*)())__[6])()
833 #define PUTC(x) (*(void (*)())__[7])(x)
834
835 #define ROMPUTC(x) \
836 ({ \
837 register _r; \
838 __asm volatile (" \
839 movc %%vbr,%0 ; \
840 movel %0,%%sp@- ; \
841 clrl %0 ; \
842 movc %0,%%vbr" \
843 : "=r" (_r)); \
844 PUTC(x); \
845 __asm volatile (" \
846 movel %%sp@+,%0 ; \
847 movc %0,%%vbr" \
848 : "=r" (_r)); \
849 })
850
851 #define ROMGETC() \
852 ({ \
853 register _r, _c; \
854 __asm volatile (" \
855 movc %%vbr,%0 ; \
856 movel %0,%%sp@- ; \
857 clrl %0 ; \
858 movc %0,%%vbr" \
859 : "=r" (_r)); \
860 _c = GETC(); \
861 __asm volatile (" \
862 movel %%sp@+,%0 ; \
863 movc %0,%%vbr" \
864 : "=r" (_r)); \
865 _c; \
866 })
867
868 void
869 romcnputc(dev, c)
870 dev_t dev;
871 int c;
872 {
873 int s;
874
875 s = splhigh();
876 ROMPUTC(c);
877 splx(s);
878 }
879
880 int
881 romcngetc(dev)
882 dev_t dev;
883 {
884 int s, c;
885
886 do {
887 s = splhigh();
888 c = ROMGETC();
889 splx(s);
890 } while (c == -1);
891 return c;
892 }
893 #endif
894