xref: /netbsd-src/sys/arch/virt68k/virt68k/machdep.c (revision f36002f244a49908fef9cba8789032bdbf48d572)
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