1 /* $NetBSD: machdep.c,v 1.9 2024/03/05 14:15:36 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1986, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah $Hdr: machdep.c 1.74 92/12/20$
37 *
38 * @(#)machdep.c 8.10 (Berkeley) 4/20/94
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.9 2024/03/05 14:15:36 thorpej Exp $");
43
44 #include "opt_ddb.h"
45 #include "opt_m060sp.h"
46 #include "opt_modular.h"
47 #include "opt_m68k_arch.h"
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/signalvar.h>
52 #include <sys/kernel.h>
53 #include <sys/proc.h>
54 #include <sys/buf.h>
55 #include <sys/reboot.h>
56 #include <sys/conf.h>
57 #include <sys/file.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/exec.h>
64 #include <sys/exec_aout.h> /* for MID_* */
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 #include <sys/module.h>
71 #include <sys/device.h>
72 #include <sys/cpu.h>
73 #include <sys/boot_flag.h>
74
75 #include "ksyms.h"
76
77 #if NKSYMS || defined(DDB) || defined(MODULAR)
78 #include <sys/exec_elf.h>
79 #endif
80
81 #include <uvm/uvm_extern.h>
82
83 #include <sys/sysctl.h>
84
85 #include <machine/bootinfo.h>
86 #include <machine/cpu.h>
87 #include <machine/bus.h>
88 #include <machine/pcb.h>
89 #include <machine/psl.h>
90 #include <machine/pte.h>
91 #include <machine/vmparam.h>
92 #include <m68k/include/cacheops.h>
93 #include <dev/cons.h>
94 #include <dev/mm.h>
95
96 #include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */
97
98 #ifdef DDB
99 #include <machine/db_machdep.h>
100 #include <ddb/db_extern.h>
101 #include <ddb/db_output.h>
102 #endif
103
104 /* the following is used externally (sysctl_hw) */
105 char machine[] = MACHINE; /* from <machine/param.h> */
106
107 /* Our exported CPU info; we can have only one. */
108 struct cpu_info cpu_info_store;
109
110 struct vm_map *phys_map = NULL;
111
112 paddr_t msgbufpa; /* PA of message buffer */
113
114 // int maxmem; /* max memory per process */
115
116 extern short exframesize[];
117
118 /* prototypes for local functions */
119 void identifycpu(void);
120 void initcpu(void);
121 void dumpsys(void);
122
123 int cpu_dumpsize(void);
124 int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
125 void cpu_init_kcore_hdr(void);
126 u_long cpu_dump_mempagecnt(void);
127 int cpu_exec_aout_makecmds(struct lwp *, struct exec_package *);
128 void straytrap(int, u_short);
129
130 /*
131 * Machine-independent crash dump header info.
132 */
133 cpu_kcore_hdr_t cpu_kcore_hdr;
134
135 /* Machine-dependent initialization routines. */
136 void virt68k_init(void);
137
138 /*
139 * Machine-dependent bootinfo "console attach" routine.
140 */
141 void
bootinfo_md_cnattach(void (* func)(bus_space_tag_t,bus_space_handle_t),paddr_t addr,paddr_t size)142 bootinfo_md_cnattach(void (*func)(bus_space_tag_t, bus_space_handle_t),
143 paddr_t addr, paddr_t size)
144 {
145 extern struct virt68k_bus_space_tag _mainbus_space_tag;
146 extern paddr_t consdev_addr;
147 bus_space_tag_t bst = &_mainbus_space_tag;
148 bus_space_handle_t bsh;
149
150 if (bus_space_map(bst, addr, size, 0, &bsh) == 0) {
151 func(bst, bsh);
152 }
153 consdev_addr = addr;
154 }
155
156 /*
157 * Early initialization, right before main is called.
158 */
159 void
virt68k_init(void)160 virt68k_init(void)
161 {
162 int i;
163
164 /*
165 * Just use the default pager_map_size for now. We may decide
166 * to make it larger for large memory configs.
167 */
168
169 /*
170 * Tell the VM system about available physical memory.
171 */
172 for (i = 0; i < bootinfo_mem_nsegments_avail; i++) {
173 if (bootinfo_mem_segments_avail[i].mem_size < PAGE_SIZE) {
174 /*
175 * Segment has been completely gobbled up.
176 */
177 continue;
178 }
179
180 paddr_t start = bootinfo_mem_segments_avail[i].mem_addr;
181 psize_t size = bootinfo_mem_segments_avail[i].mem_size;
182
183 printf("Memory segment %d: addr=0x%08lx size=0x%08lx\n", i,
184 start, size);
185
186 KASSERT(atop(start + size) == atop(start) + atop(size));
187
188 uvm_page_physload(atop(start),
189 atop(start) + atop(size),
190 atop(start),
191 atop(start) + atop(size),
192 VM_FREELIST_DEFAULT);
193 }
194
195 /*
196 * Initialize error message buffer (just before kernel text).
197 */
198 for (i = 0; i < btoc(round_page(MSGBUFSIZE)); i++) {
199 pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
200 msgbufpa + i * PAGE_SIZE,
201 VM_PROT_READ|VM_PROT_WRITE, 0);
202 }
203 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
204 pmap_update(pmap_kernel());
205
206 /* Check for RND seed from the loader. */
207 bootinfo_setup_rndseed();
208
209 char flags[32];
210 if (bootinfo_getarg("flags", flags, sizeof(flags))) {
211 for (const char *cp = flags; *cp != '\0'; cp++) {
212 /* Consume 'm' in favor of BI_RAMDISK. */
213 if (*cp == 'm') {
214 continue;
215 }
216 BOOT_FLAG(*cp, boothowto);
217 }
218 }
219 }
220
221 /*
222 * Console initialization: called early on from main,
223 * before vm init or startup. Do enough configuration
224 * to choose and initialize a console.
225 */
226 void
consinit(void)227 consinit(void)
228 {
229
230 /*
231 * The Goldfish TTY console has already been attached when
232 * the bootinfo was parsed.
233 */
234
235 #ifdef DDB
236 if (boothowto & RB_KDB)
237 Debugger();
238 #endif
239 }
240
241 /*
242 * cpu_startup: allocate memory for variable-sized tables,
243 * initialize CPU, and do autoconfiguration.
244 */
245 void
cpu_startup(void)246 cpu_startup(void)
247 {
248 vaddr_t minaddr, maxaddr;
249 char pbuf[9];
250 #ifdef DEBUG
251 extern int pmapdebug;
252 int opmapdebug = pmapdebug;
253
254 pmapdebug = 0;
255 #endif
256
257 /*
258 * If we have an FPU, initialise the cached idle frame
259 */
260 if (fputype != FPU_NONE)
261 m68k_make_fpu_idle_frame();
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("%s%s", copyright, version);
272 identifycpu();
273 format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
274 printf("total memory = %s\n", pbuf);
275
276 minaddr = 0;
277 /*
278 * Allocate a submap for physio
279 */
280 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
281 VM_PHYS_SIZE, 0, false, NULL);
282
283 #ifdef DEBUG
284 pmapdebug = opmapdebug;
285 #endif
286 format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
287 printf("avail memory = %s\n", pbuf);
288
289 if (bootinfo_mem_segments_ignored) {
290 printf("WARNING: ignored %zd bytes of memory in %d segments.\n",
291 bootinfo_mem_segments_ignored_bytes,
292 bootinfo_mem_segments_ignored);
293 }
294
295 /*
296 * Set up CPU-specific registers, cache, etc.
297 */
298 initcpu();
299 }
300
301 static const char *
mmu_string(void)302 mmu_string(void)
303 {
304 switch (mmutype) {
305 case MMU_68851:
306 return ", MC68851 MMU";
307 break;
308
309 case MMU_68030:
310 case MMU_68040:
311 case MMU_68060:
312 return "+MMU";
313
314 default:
315 return "";
316 }
317 }
318
319 static const char *
fpu_string(void)320 fpu_string(void)
321 {
322 switch (fputype) {
323 case FPU_68881:
324 return ", MC68881 FPU";
325
326 case FPU_68882:
327 return ", MC68882 FPU";
328
329 case FPU_68040:
330 case FPU_68060:
331 return "+FPU";
332
333 default:
334 return "";
335 }
336 }
337
338 void
identifycpu(void)339 identifycpu(void)
340 {
341 const char *cpu_str, *mmu_str, *fpu_str, *cache_str;
342 struct bi_record *bi;
343 uint32_t qvers;
344
345 /* Fill in the CPU string. */
346 switch (cputype) {
347 #ifdef M68020
348 case CPU_68020:
349 cpu_str = "MC68020";
350 break;
351 #endif
352
353 #ifdef M68030
354 case CPU_68030:
355 cpu_str = "MC68030";
356 break;
357 #endif
358
359 #ifdef M68040
360 case CPU_68040:
361 cpu_str = "MC68040";
362 break;
363 #endif
364
365 #ifdef M68060
366 case CPU_68060:
367 cpu_str = "MC68060";
368 break;
369 #endif
370
371 default:
372 printf("unknown CPU type");
373 panic("startup");
374 }
375
376 mmu_str = mmu_string();
377 fpu_str = fpu_string();
378
379 switch (cputype) {
380 #if defined(M68040)
381 case CPU_68040:
382 cache_str = ", 4k+4k on-chip physical I/D caches";
383 break;
384 #endif
385 #if defined(M68060)
386 case CPU_68060:
387 cache_str = ", 8k+8k on-chip physical I/D caches";
388 break;
389 #endif
390 default:
391 cache_str = "";
392 break;
393 }
394
395 bi = bootinfo_find(BI_VIRT_QEMU_VERSION);
396 if (bi != NULL) {
397 qvers = bootinfo_get_u32(bi);
398 } else {
399 qvers = 0;
400 }
401
402 cpu_setmodel("Qemu %d.%d.%d: %s%s%s%s",
403 (qvers >> 24) & 0xff,
404 (qvers >> 16) & 0xff,
405 (qvers >> 8) & 0xff,
406 cpu_str, mmu_str, fpu_str, cache_str);
407
408 printf("%s\n", cpu_getmodel());
409 }
410
411 /*
412 * machine dependent system variables.
413 */
414 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
415 {
416
417 sysctl_createv(clog, 0, NULL, NULL,
418 CTLFLAG_PERMANENT,
419 CTLTYPE_NODE, "machdep", NULL,
420 NULL, 0, NULL, 0,
421 CTL_MACHDEP, CTL_EOL);
422
423 sysctl_createv(clog, 0, NULL, NULL,
424 CTLFLAG_PERMANENT,
425 CTLTYPE_STRUCT, "console_device", NULL,
426 sysctl_consdev, 0, NULL, sizeof(dev_t),
427 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
428 }
429
430 /* See: sig_machdep.c */
431
432 int waittime = -1;
433
434 static void (*cpu_reset_func)(void *, int);
435 static void *cpu_reset_func_arg;
436
437 void
cpu_set_reset_func(void (* func)(void *,int),void * arg)438 cpu_set_reset_func(void (*func)(void *, int), void *arg)
439 {
440 if (cpu_reset_func == NULL) {
441 cpu_reset_func = func;
442 cpu_reset_func_arg = arg;
443 }
444 }
445
446 void
cpu_reboot(int howto,char * bootstr)447 cpu_reboot(int howto, char *bootstr)
448 {
449 struct pcb *pcb = lwp_getpcb(curlwp);
450
451 /* take a snap shot before clobbering any registers */
452 if (pcb != NULL)
453 savectx(pcb);
454
455 /* If system is hold, just halt. */
456 if (cold) {
457 howto |= RB_HALT;
458 goto haltsys;
459 }
460
461 boothowto = howto;
462 if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
463 waittime = 0;
464 vfs_shutdown();
465 }
466
467 /* Disable interrupts. */
468 splhigh();
469
470 /* If rebooting and a dump is requested, do it. */
471 if (howto & RB_DUMP)
472 dumpsys();
473
474 haltsys:
475 /* Run any shutdown hooks. */
476 doshutdownhooks();
477
478 pmf_system_shutdown(boothowto);
479
480 #if defined(PANICWAIT) && !defined(DDB)
481 if ((howto & RB_HALT) == 0 && panicstr) {
482 printf("hit any key to reboot...\n");
483 cnpollc(1);
484 (void)cngetc();
485 cnpollc(0);
486 printf("\n");
487 }
488 #endif
489
490 if (cpu_reset_func == NULL) {
491 printf("WARNING: No reset handler, holding here.\n\n");
492 for (;;) {
493 /* spin forever. */
494 }
495 }
496
497 /* Finally, halt/reboot the system. */
498 if (howto & RB_HALT) {
499 printf("halted\n\n");
500 (*cpu_reset_func)(cpu_reset_func_arg, RB_HALT);
501 /* NOTREACHED */
502 } else {
503 printf("rebooting...\n");
504 delay(1000000);
505 (*cpu_reset_func)(cpu_reset_func_arg, RB_AUTOBOOT);
506 /* NOTREACHED */
507 }
508 /* ...but just in case it is... */
509 printf("WARNING: System reset handler failed, holding here.\n\n");
510 for (;;) {
511 /* spin forever. */
512 }
513 }
514
515 /*
516 * Initialize the kernel crash dump header.
517 */
518 void
cpu_init_kcore_hdr(void)519 cpu_init_kcore_hdr(void)
520 {
521 cpu_kcore_hdr_t *h = &cpu_kcore_hdr;
522 struct m68k_kcore_hdr *m = &h->un._m68k;
523 int i;
524 extern char end[];
525
526 memset(&cpu_kcore_hdr, 0, sizeof(cpu_kcore_hdr));
527
528 /*
529 * Initialize the `dispatcher' portion of the header.
530 */
531 strcpy(h->name, machine);
532 h->page_size = PAGE_SIZE;
533 h->kernbase = KERNBASE;
534
535 /*
536 * Fill in information about our MMU configuration.
537 */
538 m->mmutype = mmutype;
539 m->sg_v = SG_V;
540 m->sg_frame = SG_FRAME;
541 m->sg_ishift = SG_ISHIFT;
542 m->sg_pmask = SG_PMASK;
543 m->sg40_shift1 = SG4_SHIFT1;
544 m->sg40_mask2 = SG4_MASK2;
545 m->sg40_shift2 = SG4_SHIFT2;
546 m->sg40_mask3 = SG4_MASK3;
547 m->sg40_shift3 = SG4_SHIFT3;
548 m->sg40_addr1 = SG4_ADDR1;
549 m->sg40_addr2 = SG4_ADDR2;
550 m->pg_v = PG_V;
551 m->pg_frame = PG_FRAME;
552
553 /*
554 * Initialize pointer to kernel segment table.
555 */
556 m->sysseg_pa = (uint32_t)(pmap_kernel()->pm_stpa);
557
558 /*
559 * Initialize relocation value such that:
560 *
561 * pa = (va - KERNBASE) + reloc
562 *
563 * Since we're linked and loaded at the same place,
564 * and the kernel is mapped va == pa, this is 0.
565 */
566 m->reloc = 0;
567
568 /*
569 * Define the end of the relocatable range.
570 */
571 m->relocend = (uint32_t)end;
572
573 for (i = 0; i < bootinfo_mem_nsegments; i++) {
574 m->ram_segs[i].start = bootinfo_mem_segments[i].mem_addr;
575 m->ram_segs[i].size = bootinfo_mem_segments[i].mem_size;
576 }
577 }
578
579 /*
580 * Compute the size of the machine-dependent crash dump header.
581 * Returns size in disk blocks.
582 */
583
584 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
585 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
586
587 int
cpu_dumpsize(void)588 cpu_dumpsize(void)
589 {
590
591 return btodb(MDHDRSIZE);
592 }
593
594 /*
595 * Calculate size of RAM (in pages) to be dumped.
596 */
597 u_long
cpu_dump_mempagecnt(void)598 cpu_dump_mempagecnt(void)
599 {
600 u_long i, n;
601
602 n = 0;
603 for (i = 0; i < bootinfo_mem_nsegments; i++)
604 n += atop(bootinfo_mem_segments[i].mem_size);
605 return n;
606 }
607
608 /*
609 * Called by dumpsys() to dump the machine-dependent header.
610 */
611 int
cpu_dump(int (* dump)(dev_t,daddr_t,void *,size_t),daddr_t * blknop)612 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
613 {
614 int buf[MDHDRSIZE / sizeof(int)];
615 cpu_kcore_hdr_t *chdr;
616 kcore_seg_t *kseg;
617 int error;
618
619 kseg = (kcore_seg_t *)buf;
620 chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
621 sizeof(int)];
622
623 /* Create the segment header. */
624 CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
625 kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
626
627 memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
628 error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
629 *blknop += btodb(sizeof(buf));
630 return error;
631 }
632
633 /*
634 * These variables are needed by /sbin/savecore
635 */
636 uint32_t dumpmag = 0x8fca0101; /* magic number */
637 int dumpsize = 0; /* pages */
638 long dumplo = 0; /* blocks */
639
640 /*
641 * This is called by main to set dumplo and dumpsize.
642 * Dumps always skip the first PAGE_SIZE of disk space
643 * in case there might be a disk label stored there.
644 * If there is extra space, put dump at the end to
645 * reduce the chance that swapping trashes it.
646 */
647 void
cpu_dumpconf(void)648 cpu_dumpconf(void)
649 {
650 int nblks, dumpblks; /* size of dump area */
651
652 if (dumpdev == NODEV)
653 goto bad;
654 nblks = bdev_size(dumpdev);
655 if (nblks <= ctod(1))
656 goto bad;
657
658 dumpblks = cpu_dumpsize();
659 if (dumpblks < 0)
660 goto bad;
661 dumpblks += ctod(cpu_dump_mempagecnt());
662
663 /* If dump won't fit (incl. room for possible label), punt. */
664 if (dumpblks > (nblks - ctod(1)))
665 goto bad;
666
667 /* Put dump at end of partition */
668 dumplo = nblks - dumpblks;
669
670 /* dumpsize is in page units, and doesn't include headers. */
671 dumpsize = cpu_dump_mempagecnt();
672 return;
673
674 bad:
675 dumpsize = 0;
676 }
677
678 /*
679 * Dump physical memory onto the dump device. Called by cpu_reboot().
680 */
681 void
dumpsys(void)682 dumpsys(void)
683 {
684 const struct bdevsw *bdev;
685 u_long totalbytesleft, bytes, i, n, memcl;
686 u_long maddr;
687 int psize;
688 daddr_t blkno;
689 int (*dump)(dev_t, daddr_t, void *, size_t);
690 int error;
691
692 /* XXX Should save registers. */
693
694 if (dumpdev == NODEV)
695 return;
696 bdev = bdevsw_lookup(dumpdev);
697 if (bdev == NULL || bdev->d_psize == NULL)
698 return;
699
700 /*
701 * For dumps during autoconfiguration,
702 * if dump device has already configured...
703 */
704 if (dumpsize == 0)
705 cpu_dumpconf();
706 if (dumplo <= 0) {
707 printf("\ndump to dev %u,%u not possible\n",
708 major(dumpdev), minor(dumpdev));
709 return;
710 }
711 printf("\ndumping to dev %u,%u offset %ld\n",
712 major(dumpdev), minor(dumpdev), dumplo);
713
714 psize = bdev_size(dumpdev);
715 printf("dump ");
716 if (psize == -1) {
717 printf("area unavailable\n");
718 return;
719 }
720
721 /* XXX should purge all outstanding keystrokes. */
722
723 dump = bdev->d_dump;
724 blkno = dumplo;
725
726 if ((error = cpu_dump(dump, &blkno)) != 0)
727 goto err;
728
729 totalbytesleft = ptoa(cpu_dump_mempagecnt());
730
731 for (memcl = 0; memcl < bootinfo_mem_nsegments; memcl++) {
732 maddr = bootinfo_mem_segments[memcl].mem_addr;
733 bytes = bootinfo_mem_segments[memcl].mem_size;
734
735 for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
736
737 /* Print out how many MBs we have left to go. */
738 if ((totalbytesleft % (1024*1024)) == 0)
739 printf_nolog("%ld ",
740 totalbytesleft / (1024 * 1024));
741
742 /* Limit size for next transfer. */
743 n = bytes - i;
744 if (n > PAGE_SIZE)
745 n = PAGE_SIZE;
746
747 pmap_kenter_pa((vaddr_t)vmmap, maddr, VM_PROT_READ, 0);
748 pmap_update(pmap_kernel());
749
750 error = (*dump)(dumpdev, blkno, vmmap, n);
751 if (error)
752 goto err;
753
754 pmap_kremove((vaddr_t)vmmap, PAGE_SIZE);
755 pmap_update(pmap_kernel());
756
757 maddr += n;
758 blkno += btodb(n);
759 }
760 }
761
762 err:
763 switch (error) {
764
765 case ENXIO:
766 printf("device bad\n");
767 break;
768
769 case EFAULT:
770 printf("device not ready\n");
771 break;
772
773 case EINVAL:
774 printf("area improper\n");
775 break;
776
777 case EIO:
778 printf("i/o error\n");
779 break;
780
781 case EINTR:
782 printf("aborted from console\n");
783 break;
784
785 case 0:
786 printf("succeeded\n");
787 break;
788
789 default:
790 printf("error %d\n", error);
791 break;
792 }
793 printf("\n\n");
794 delay(5000);
795 }
796
797 void
initcpu(void)798 initcpu(void)
799 {
800 /* No work to do. */
801 }
802
803 void
straytrap(int pc,u_short evec)804 straytrap(int pc, u_short evec)
805 {
806
807 printf("unexpected trap (vector offset %x) from %x\n",
808 evec & 0xFFF, pc);
809 }
810
811 /*
812 * Level 7 interrupts are caused by e.g. the ABORT switch.
813 *
814 * If we have DDB, then break into DDB on ABORT. In a production
815 * environment, bumping the ABORT switch would be bad, so we enable
816 * panic'ing on ABORT with the kernel option "PANICBUTTON".
817 */
818 int
nmihand(void * arg)819 nmihand(void *arg)
820 {
821
822 printf("NMI ignored.\n");
823
824 return 1;
825 }
826
827 /*
828 * cpu_exec_aout_makecmds():
829 * CPU-dependent a.out format hook for execve().
830 *
831 * Determine of the given exec package refers to something which we
832 * understand and, if so, set up the vmcmds for it.
833 */
834 int
cpu_exec_aout_makecmds(struct lwp * l,struct exec_package * epp)835 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
836 {
837
838 return ENOEXEC;
839 }
840
841 #ifdef MODULAR
842 /*
843 * Push any modules loaded by the bootloader etc.
844 */
845 void
module_init_md(void)846 module_init_md(void)
847 {
848 }
849 #endif
850
851 const uint16_t ipl2psl_table[NIPL] = {
852 [IPL_NONE] = PSL_S | PSL_IPL0,
853 [IPL_SOFTCLOCK] = PSL_S | PSL_IPL1,
854 [IPL_SOFTBIO] = PSL_S | PSL_IPL1,
855 [IPL_SOFTNET] = PSL_S | PSL_IPL1,
856 [IPL_SOFTSERIAL] = PSL_S | PSL_IPL1,
857 [IPL_VM] = PSL_S | PSL_IPL5,
858 [IPL_SCHED] = PSL_S | PSL_IPL6,
859 [IPL_HIGH] = PSL_S | PSL_IPL7,
860 };
861
862 int
mm_md_physacc(paddr_t pa,vm_prot_t prot)863 mm_md_physacc(paddr_t pa, vm_prot_t prot)
864 {
865 psize_t size;
866 int i;
867
868 for (i = 0; i < bootinfo_mem_nsegments; i++) {
869 if (pa < bootinfo_mem_segments[i].mem_addr) {
870 continue;
871 }
872 size = trunc_page(bootinfo_mem_segments[i].mem_size);
873 if (pa >= bootinfo_mem_segments[i].mem_addr + size) {
874 continue;
875 }
876 return 0;
877 }
878 return EFAULT;
879 }
880