Home | History | Annotate | Line # | Download | only in sun2
      1 /*	$NetBSD: machdep.c,v 1.100 2026/04/28 03:29:10 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1990, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * the Systems Programming Group of the University of Utah Computer
      9  * Science Department.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  *	from: Utah Hdr: machdep.c 1.74 92/12/20
     36  *	from: @(#)machdep.c	8.10 (Berkeley) 4/20/94
     37  */
     38 
     39 /*
     40  * Copyright (c) 2001 Matthew Fredette.
     41  * Copyright (c) 1994, 1995 Gordon W. Ross
     42  * Copyright (c) 1993 Adam Glass
     43  * Copyright (c) 1988 University of Utah.
     44  *
     45  * This code is derived from software contributed to Berkeley by
     46  * the Systems Programming Group of the University of Utah Computer
     47  * Science Department.
     48  *
     49  * Redistribution and use in source and binary forms, with or without
     50  * modification, are permitted provided that the following conditions
     51  * are met:
     52  * 1. Redistributions of source code must retain the above copyright
     53  *    notice, this list of conditions and the following disclaimer.
     54  * 2. Redistributions in binary form must reproduce the above copyright
     55  *    notice, this list of conditions and the following disclaimer in the
     56  *    documentation and/or other materials provided with the distribution.
     57  * 3. All advertising materials mentioning features or use of this software
     58  *    must display the following acknowledgement:
     59  *	This product includes software developed by the University of
     60  *	California, Berkeley and its contributors.
     61  * 4. Neither the name of the University nor the names of its contributors
     62  *    may be used to endorse or promote products derived from this software
     63  *    without specific prior written permission.
     64  *
     65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     75  * SUCH DAMAGE.
     76  *
     77  *	from: Utah Hdr: machdep.c 1.74 92/12/20
     78  *	from: @(#)machdep.c	8.10 (Berkeley) 4/20/94
     79  */
     80 
     81 /*-
     82  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
     83  * All rights reserved.
     84  *
     85  * This code is derived from software contributed to The NetBSD Foundation
     86  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
     87  * NASA Ames Research Center.
     88  *
     89  * Redistribution and use in source and binary forms, with or without
     90  * modification, are permitted provided that the following conditions
     91  * are met:
     92  * 1. Redistributions of source code must retain the above copyright
     93  *    notice, this list of conditions and the following disclaimer.
     94  * 2. Redistributions in binary form must reproduce the above copyright
     95  *    notice, this list of conditions and the following disclaimer in the
     96  *    documentation and/or other materials provided with the distribution.
     97  *
     98  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     99  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    100  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    101  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
    102  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    103  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    104  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    105  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    106  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    107  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    108  * POSSIBILITY OF SUCH DAMAGE.
    109  */
    110 
    111 /*
    112  * Copyright (c) 1992, 1993
    113  *	The Regents of the University of California.  All rights reserved.
    114  *
    115  * This software was developed by the Computer Systems Engineering group
    116  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
    117  * contributed to Berkeley.
    118  *
    119  * All advertising materials mentioning features or use of this software
    120  * must display the following acknowledgement:
    121  *	This product includes software developed by the University of
    122  *	California, Lawrence Berkeley Laboratory.
    123  *
    124  * Redistribution and use in source and binary forms, with or without
    125  * modification, are permitted provided that the following conditions
    126  * are met:
    127  * 1. Redistributions of source code must retain the above copyright
    128  *    notice, this list of conditions and the following disclaimer.
    129  * 2. Redistributions in binary form must reproduce the above copyright
    130  *    notice, this list of conditions and the following disclaimer in the
    131  *    documentation and/or other materials provided with the distribution.
    132  * 3. Neither the name of the University nor the names of its contributors
    133  *    may be used to endorse or promote products derived from this software
    134  *    without specific prior written permission.
    135  *
    136  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    137  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    138  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    139  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    140  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    141  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    142  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    143  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    144  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    145  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    146  * SUCH DAMAGE.
    147  *
    148  *	@(#)machdep.c	8.6 (Berkeley) 1/14/94
    149  */
    150 
    151 #include <sys/cdefs.h>
    152 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.100 2026/04/28 03:29:10 thorpej Exp $");
    153 
    154 #include "opt_ddb.h"
    155 #include "opt_fpu_emulate.h"
    156 #include "opt_kgdb.h"
    157 #include "opt_modular.h"
    158 
    159 #include <sys/param.h>
    160 #include <sys/buf.h>
    161 #include <sys/conf.h>
    162 #include <sys/core.h>
    163 #include <sys/cpu.h>
    164 #include <sys/device.h>
    165 #include <sys/exec.h>
    166 #include <sys/vmem.h>
    167 #include <sys/file.h>
    168 #include <sys/ioctl.h>
    169 #include <sys/kcore.h>
    170 #include <sys/kernel.h>
    171 #include <sys/ksyms.h>
    172 #include <sys/mbuf.h>
    173 #include <sys/module.h>
    174 #include <sys/mount.h>
    175 #include <sys/msgbuf.h>
    176 #include <sys/proc.h>
    177 #include <sys/reboot.h>
    178 #include <sys/syscallargs.h>
    179 #include <sys/sysctl.h>
    180 #include <sys/systm.h>
    181 #include <sys/tty.h>
    182 #include <sys/vnode.h>
    183 
    184 #ifdef	KGDB
    185 #include <sys/kgdb.h>
    186 #endif
    187 
    188 #include <uvm/uvm.h> /* XXX: not _extern ... need vm_map_create */
    189 
    190 #include <dev/cons.h>
    191 #include <dev/mm.h>
    192 
    193 #define _SUN68K_BUS_DMA_PRIVATE
    194 #include <machine/autoconf.h>
    195 #include <machine/bus.h>
    196 #include <machine/cpu.h>
    197 #include <machine/dvma.h>
    198 #include <machine/idprom.h>
    199 #include <machine/intr.h>
    200 #include <machine/kcore.h>
    201 #include <machine/pcb.h>
    202 #include <machine/pmap.h>
    203 #include <machine/promlib.h>
    204 #include <machine/psl.h>
    205 #include <machine/pte.h>
    206 #include <machine/reg.h>
    207 
    208 #if defined(DDB)
    209 #include <machine/db_machdep.h>
    210 #include <ddb/db_extern.h>
    211 #include <ddb/db_sym.h>
    212 #endif
    213 
    214 #include <dev/vme/vmereg.h>
    215 #include <dev/vme/vmevar.h>
    216 
    217 #include <sun2/sun2/control.h>
    218 #include <sun2/sun2/enable.h>
    219 #include <sun2/sun2/machdep.h>
    220 
    221 #include <sun68k/sun68k/vme_sun68k.h>
    222 
    223 #include "ksyms.h"
    224 
    225 /* Defined in locore.s */
    226 extern char kernel_text[];
    227 /* Defined by the linker */
    228 extern char etext[];
    229 /* Defined in vfs_bio.c */
    230 extern u_int bufpages;
    231 
    232 extern void *msgbufaddr;
    233 
    234 /* Virtual page frame for /dev/mem (see mem.c) */
    235 vaddr_t vmmap;
    236 
    237 /* Soft copy of the enable register. */
    238 volatile u_short enable_reg_soft = ENABLE_REG_SOFT_UNDEF;
    239 
    240 /*
    241  * dvmamap is used to manage DVMA memory.
    242  */
    243 vmem_t *dvma_arena;
    244 
    245 /* Our private scratch page for dumping the MMU. */
    246 static vaddr_t dumppage;
    247 
    248 char	kernel_arch[16] = "sun2";	/* XXX needs a sysctl node */
    249 
    250 /*
    251  * cpu_startup: allocate memory for variable-sized tables,
    252  * initialize CPU, and do autoconfiguration.
    253  *
    254  * This is called early in init_main.c:main(), after the
    255  * kernel memory allocator is ready for use, but before
    256  * the creation of processes 1,2, and mountroot, etc.
    257  */
    258 void
    259 cpu_startup(void)
    260 {
    261 #if NKSYMS || defined(DDB) || defined(MODULAR)
    262 	{
    263 		extern int nsym;
    264 		extern char *ssym, *esym;
    265 
    266 		ksyms_addsyms_elf(nsym, ssym, esym);
    267 	}
    268 #endif /* DDB */
    269 
    270 	/*
    271 	 * XXX fredette - we force a small number of buffers
    272 	 * to help me debug this on my low-memory machine.
    273 	 * this should go away at some point, allowing the
    274 	 * normal automatic buffer-sizing to happen.
    275 	 */
    276 	bufpages = 37;
    277 
    278 	/*
    279 	 * Get scratch page for dumpsys().
    280 	 */
    281 	if ((dumppage = uvm_km_alloc(kernel_map, PAGE_SIZE,0, UVM_KMF_WIRED))
    282 	    == 0)
    283 		panic("startup: alloc dumppage");
    284 
    285 	cpu_startup_common();
    286 
    287 	/*
    288 	 * Allocate a virtual page (for use by /dev/mem)
    289 	 * This page is handed to pmap_enter() therefore
    290 	 * it has to be in the normal kernel VA range.
    291 	 */
    292 	vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
    293 	    UVM_KMF_VAONLY | UVM_KMF_WAITVA);
    294 
    295 	/*
    296 	 * Allocate DMA map for devices on the bus.
    297 	 */
    298 	dvma_arena = vmem_create("dvmamap", DVMA_MAP_BASE, DVMA_MAP_AVAIL,
    299 				 PAGE_SIZE,		/* quantum */
    300 				 NULL,			/* importfn */
    301 				 NULL,			/* releasefn */
    302 				 NULL,			/* source */
    303 				 0,			/* qcache_max */
    304 				 VM_SLEEP,
    305 				 IPL_VM);
    306 	if (dvma_arena == NULL)
    307 		panic("unable to allocate DVMA map");
    308 }
    309 
    310 /*
    311  * machine dependent system variables.
    312  */
    313 #if 0	/* XXX - Not yet... */
    314 static int
    315 sysctl_machdep_root_device(SYSCTLFN_ARGS)
    316 {
    317 	struct sysctlnode node = *rnode;
    318 
    319 	node.sysctl_data = some permutation on root_device;
    320 	node.sysctl_size = strlen(root_device) + 1;
    321 	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    322 }
    323 #endif
    324 
    325 static int
    326 sysctl_machdep_booted_kernel(SYSCTLFN_ARGS)
    327 {
    328 	struct sysctlnode node = *rnode;
    329 	char *cp;
    330 
    331 	cp = prom_getbootfile();
    332 	if (cp == NULL || cp[0] == '\0')
    333 		return (ENOENT);
    334 
    335 	node.sysctl_data = cp;
    336 	node.sysctl_size = strlen(cp) + 1;
    337 	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    338 }
    339 
    340 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    341 {
    342 
    343 	sysctl_createv(clog, 0, NULL, NULL,
    344 		       CTLFLAG_PERMANENT,
    345 		       CTLTYPE_NODE, "machdep", NULL,
    346 		       NULL, 0, NULL, 0,
    347 		       CTL_MACHDEP, CTL_EOL);
    348 
    349 	sysctl_createv(clog, 0, NULL, NULL,
    350 		       CTLFLAG_PERMANENT,
    351 		       CTLTYPE_STRUCT, "console_device", NULL,
    352 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    353 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    354 #if 0	/* XXX - Not yet... */
    355 	sysctl_createv(clog, 0, NULL, NULL,
    356 		       CTLFLAG_PERMANENT,
    357 		       CTLTYPE_STRING, "root_device", NULL,
    358 		       sysctl_machdep_root_device, 0, NULL, 0,
    359 		       CTL_MACHDEP, CPU_ROOT_DEVICE, CTL_EOL);
    360 #endif
    361 	sysctl_createv(clog, 0, NULL, NULL,
    362 		       CTLFLAG_PERMANENT,
    363 		       CTLTYPE_STRING, "booted_kernel", NULL,
    364 		       sysctl_machdep_booted_kernel, 0, NULL, 0,
    365 		       CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL);
    366 }
    367 
    368 void
    369 machine_halt(void)
    370 {
    371 	prom_halt();
    372 }
    373 
    374 void
    375 machine_reboot(int howto, char *bootstr)
    376 {
    377 	char *p;
    378 	char default_boot_string[8];
    379 
    380 	if (bootstr == NULL) {
    381 		/*
    382 		 * Build our own boot string with an empty
    383 		 * boot device/file and (maybe) some flags.
    384 		 * The PROM will supply the device/file name.
    385 		 */
    386 		p = default_boot_string;
    387 		*p = '\0';
    388 
    389 		if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) {
    390 			/* Append the boot flags. */
    391 			*p++ = ' ';
    392 			*p++ = '-';
    393 			if (howto & RB_KDB)
    394 				*p++ = 'd';
    395 			if (howto & RB_ASKNAME)
    396 				*p++ = 'a';
    397 			if (howto & RB_SINGLE)
    398 				*p++ = 's';
    399 			*p = '\0';
    400 		}
    401 		bootstr = default_boot_string;
    402 	}
    403 	prom_boot(bootstr);
    404 }
    405 
    406 /*
    407  * These variables are needed by /sbin/savecore
    408  */
    409 uint32_t dumpmag = 0x8fca0101;	/* magic number */
    410 int 	dumpsize = 0;		/* pages */
    411 long	dumplo = 0; 		/* blocks */
    412 
    413 #define	DUMP_EXTRA 	3	/* CPU-dependent extra pages */
    414 
    415 /*
    416  * This is called by main to set dumplo, dumpsize.
    417  * Dumps always skip the first PAGE_SIZE of disk space
    418  * in case there might be a disk label stored there.
    419  * If there is extra space, put dump at the end to
    420  * reduce the chance that swapping trashes it.
    421  */
    422 void
    423 cpu_dumpconf(void)
    424 {
    425 	int devblks;	/* size of dump device in blocks */
    426 	int dumpblks;	/* size of dump image in blocks */
    427 
    428 	if (dumpdev == NODEV)
    429 		return;
    430 
    431 	devblks = bdev_size(dumpdev);
    432 	if (devblks <= ctod(1))
    433 		return;
    434 	devblks &= ~(ctod(1)-1);
    435 
    436 	/*
    437 	 * Note: savecore expects dumpsize to be the
    438 	 * number of pages AFTER the dump header.
    439 	 */
    440 	dumpsize = physmem;
    441 
    442 	/* Position dump image near end of space, page aligned. */
    443 	dumpblks = ctod(physmem + DUMP_EXTRA);
    444 	dumplo = devblks - dumpblks;
    445 
    446 	/* If it does not fit, truncate it by moving dumplo. */
    447 	/* Note: Must force signed comparison. */
    448 	if (dumplo < ((long)ctod(1))) {
    449 		dumplo = ctod(1);
    450 		dumpsize = dtoc(devblks - dumplo) - DUMP_EXTRA;
    451 	}
    452 }
    453 
    454 /* Note: gdb looks for "dumppcb" in a kernel crash dump. */
    455 struct pcb dumppcb;
    456 extern paddr_t avail_start;
    457 
    458 /*
    459  * Write a crash dump.  The format while in swap is:
    460  *   kcore_seg_t cpu_hdr;
    461  *   cpu_kcore_hdr_t cpu_data;
    462  *   padding (PAGE_SIZE-sizeof(kcore_seg_t))
    463  *   pagemap (2*PAGE_SIZE)
    464  *   physical memory...
    465  */
    466 void
    467 dumpsys(void)
    468 {
    469 	const struct bdevsw *dsw;
    470 	kcore_seg_t	*kseg_p;
    471 	cpu_kcore_hdr_t *chdr_p;
    472 	struct sun2_kcore_hdr *sh;
    473 	char *vaddr;
    474 	paddr_t paddr;
    475 	int psize, todo, chunk;
    476 	daddr_t blkno;
    477 	int error = 0;
    478 
    479 	if (dumpdev == NODEV)
    480 		return;
    481 	dsw = bdevsw_lookup(dumpdev);
    482 	if (dsw == NULL || dsw->d_psize == NULL)
    483 		return;
    484 	if (dumppage == 0)
    485 		return;
    486 
    487 	/*
    488 	 * For dumps during autoconfiguration,
    489 	 * if dump device has already configured...
    490 	 */
    491 	if (dumpsize == 0)
    492 		cpu_dumpconf();
    493 	if (dumplo <= 0) {
    494 		printf("\ndump to dev %u,%u not possible\n",
    495 		    major(dumpdev), minor(dumpdev));
    496 		return;
    497 	}
    498 	savectx(&dumppcb);
    499 
    500 	psize = bdev_size(dumpdev);
    501 	if (psize == -1) {
    502 		printf("dump area unavailable\n");
    503 		return;
    504 	}
    505 
    506 	printf("\ndumping to dev %u,%u offset %ld\n",
    507 	    major(dumpdev), minor(dumpdev), dumplo);
    508 
    509 	/*
    510 	 * Prepare the dump header, including MMU state.
    511 	 */
    512 	blkno = dumplo;
    513 	todo = dumpsize;	/* pages */
    514 	vaddr = (char*)dumppage;
    515 	memset(vaddr, 0, PAGE_SIZE);
    516 
    517 	/* Set pointers to all three parts. */
    518 	kseg_p = (kcore_seg_t *)vaddr;
    519 	chdr_p = (cpu_kcore_hdr_t *) (kseg_p + 1);
    520 	sh = &chdr_p->un._sun2;
    521 
    522 	/* Fill in kcore_seg_t part. */
    523 	CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
    524 	kseg_p->c_size = (ctob(DUMP_EXTRA) - sizeof(*kseg_p));
    525 
    526 	/* Fill in cpu_kcore_hdr_t part. */
    527 	strncpy(chdr_p->name, kernel_arch, sizeof(chdr_p->name));
    528 	chdr_p->page_size = PAGE_SIZE;
    529 	chdr_p->kernbase = KERNBASE;
    530 
    531 	/* Fill in the sun2_kcore_hdr part (MMU state). */
    532 	pmap_kcore_hdr(sh);
    533 
    534 	/* Write out the dump header. */
    535 	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    536 	if (error)
    537 		goto fail;
    538 	blkno += btodb(PAGE_SIZE);
    539 
    540 	/* translation RAM (pages zero through seven) */
    541 	for(chunk = 0; chunk < (PAGE_SIZE * 8); chunk += PAGE_SIZE) {
    542 		pmap_get_pagemap((int*)vaddr, chunk);
    543 		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    544 		if (error)
    545 			goto fail;
    546 		blkno += btodb(PAGE_SIZE);
    547 	}
    548 
    549 	/*
    550 	 * Now dump physical memory.  Have to do it in two chunks.
    551 	 * The first chunk is "unmanaged" (by the VM code) and its
    552 	 * range of physical addresses is not allow in pmap_enter.
    553 	 * However, that segment is mapped linearly, so we can just
    554 	 * use the virtual mappings already in place.  The second
    555 	 * chunk is done the normal way, using pmap_enter.
    556 	 *
    557 	 * Note that vaddr==(paddr+KERNBASE) for paddr=0 through etext.
    558 	 */
    559 
    560 	/* Do the first chunk (0 <= PA < avail_start) */
    561 	paddr = 0;
    562 	chunk = btoc(avail_start);
    563 	if (chunk > todo)
    564 		chunk = todo;
    565 	do {
    566 		if ((todo & 0xf) == 0)
    567 			printf_nolog("\r%4d", todo);
    568 		vaddr = (char*)(paddr + KERNBASE);
    569 		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    570 		if (error)
    571 			goto fail;
    572 		paddr += PAGE_SIZE;
    573 		blkno += btodb(PAGE_SIZE);
    574 		--todo;
    575 	} while (--chunk > 0);
    576 
    577 	/* Do the second chunk (avail_start <= PA < dumpsize) */
    578 	vaddr = (char*)vmmap;	/* Borrow /dev/mem VA */
    579 	do {
    580 		if ((todo & 0xf) == 0)
    581 			printf_nolog("\r%4d", todo);
    582 		pmap_kenter_pa(vmmap, paddr | PMAP_NC, VM_PROT_READ, 0);
    583 		pmap_update(pmap_kernel());
    584 		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    585 		pmap_kremove(vmmap, PAGE_SIZE);
    586 		pmap_update(pmap_kernel());
    587 		if (error)
    588 			goto fail;
    589 		paddr += PAGE_SIZE;
    590 		blkno += btodb(PAGE_SIZE);
    591 	} while (--todo > 0);
    592 
    593 	printf("\rdump succeeded\n");
    594 	return;
    595 fail:
    596 	printf(" dump error=%d\n", error);
    597 }
    598 
    599 /* straptrap() in trap.c */
    600 
    601 /* from hp300: badaddr() */
    602 
    603 /* XXX: parityenable() ? */
    604 /* regdump() moved to regdump.c */
    605 
    606 #if 0
    607 /*
    608  * Soft interrupt support.
    609  */
    610 void
    611 isr_soft_request(int level)
    612 {
    613 	u_char bit;
    614 
    615 	if ((level < _IPL_SOFT_LEVEL_MIN) || (level > _IPL_SOFT_LEVEL_MAX))
    616 		return;
    617 
    618 	bit = 1 << level;
    619 	enable_reg_or(bit);
    620 }
    621 
    622 void
    623 isr_soft_clear(int level)
    624 {
    625 	u_char bit;
    626 
    627 	if ((level < _IPL_SOFT_LEVEL_MIN) || (level > _IPL_SOFT_LEVEL_MAX))
    628 		return;
    629 
    630 	bit = 1 << level;
    631 	enable_reg_and(~bit);
    632 }
    633 #endif
    634 
    635 /*
    636  * Like _bus_dmamap_load(), but for raw memory allocated with
    637  * bus_dmamem_alloc().
    638  */
    639 int
    640 _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map, bus_dma_segment_t *segs,
    641     int nsegs, bus_size_t size, int flags)
    642 {
    643 	struct vm_page *m;
    644 	paddr_t pa;
    645 	vmem_addr_t dva;
    646 	bus_size_t sgsize;
    647 	struct pglist *mlist;
    648 	int pagesz = PAGE_SIZE;
    649 	int error;
    650 
    651 	/*
    652 	 * Make sure that on error condition we return "no valid mappings".
    653 	 */
    654 	map->dm_nsegs = 0;
    655 	map->dm_mapsize = 0;
    656 
    657 	/* Allocate DVMA addresses */
    658 	sgsize = (size + pagesz - 1) & -pagesz;
    659 
    660 	/*
    661 	 * If the device can see our entire 24-bit address space,
    662 	 * we can use any properly aligned virtual addresses.
    663 	 */
    664 	if ((map->_dm_flags & BUS_DMA_24BIT) != 0) {
    665 		dva = _bus_dma_valloc_skewed(sgsize, map->_dm_boundary,
    666 					     pagesz, 0);
    667 		if (dva == 0)
    668 			return (ENOMEM);
    669 	}
    670 
    671 	/*
    672 	 * Otherwise, we need virtual addresses in DVMA space.
    673 	 */
    674 	else {
    675 		const vm_flag_t vmflags = VM_BESTFIT |
    676 		    ((flags & BUS_DMA_NOWAIT) ? VM_NOSLEEP : VM_SLEEP);
    677 
    678 		error = vmem_xalloc(dvma_arena, sgsize,
    679 				    0,			/* alignment */
    680 				    0,			/* phase */
    681 				    map->_dm_boundary,	/* nocross */
    682 				    VMEM_ADDR_MIN,	/* minaddr */
    683 				    VMEM_ADDR_MAX,	/* maxaddr */
    684 				    vmflags,
    685 				    &dva);
    686 		if (error)
    687 			return (error);
    688 	}
    689 
    690 	/* Fill in the segment. */
    691 	map->dm_segs[0].ds_addr = dva;
    692 	map->dm_segs[0].ds_len = size;
    693 	map->dm_segs[0]._ds_va = dva;
    694 	map->dm_segs[0]._ds_sgsize = sgsize;
    695 
    696 	/* Map physical pages into MMU */
    697 	mlist = segs[0]._ds_mlist;
    698 	for (m = TAILQ_FIRST(mlist); m != NULL; m = TAILQ_NEXT(m,pageq.queue)) {
    699 		if (sgsize == 0)
    700 			panic("_bus_dmamap_load_raw: size botch");
    701 		pa = VM_PAGE_TO_PHYS(m);
    702 		pmap_enter(pmap_kernel(), dva,
    703 			   (pa & -pagesz) | PMAP_NC,
    704 			   VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
    705 
    706 		dva += pagesz;
    707 		sgsize -= pagesz;
    708 	}
    709 	pmap_update(pmap_kernel());
    710 
    711 	/* Make the map truly valid. */
    712 	map->dm_nsegs = 1;
    713 	map->dm_mapsize = size;
    714 
    715 	return (0);
    716 }
    717 
    718 /*
    719  * load DMA map with a linear buffer.
    720  */
    721 int
    722 _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
    723     bus_size_t buflen, struct proc *p, int flags)
    724 {
    725 	bus_size_t sgsize;
    726 	vaddr_t va = (vaddr_t)buf;
    727 	int pagesz = PAGE_SIZE;
    728 	vmem_addr_t dva;
    729 	pmap_t pmap;
    730 	int rv __diagused;
    731 
    732 	/*
    733 	 * Make sure that on error condition we return "no valid mappings".
    734 	 */
    735 	map->dm_nsegs = 0;
    736 	map->dm_mapsize = 0;
    737 
    738 	if (buflen > map->_dm_size)
    739 		return (EINVAL);
    740 
    741 	/*
    742 	 * A 24-bit device can see all of our kernel address space, so
    743 	 * if we have KVAs, we can just load them as-is, no mapping
    744 	 * necessary.
    745 	 */
    746 	if ((map->_dm_flags & BUS_DMA_24BIT) != 0 && p == NULL) {
    747 		/*
    748 		 * XXX Need to implement "don't DMA across this boundary".
    749 		 */
    750 		if (map->_dm_boundary != 0)
    751 			panic("bus_dmamap_load: boundaries not implemented");
    752 		map->dm_mapsize = buflen;
    753 		map->dm_nsegs = 1;
    754 		map->dm_segs[0].ds_addr = (bus_addr_t)va;
    755 		map->dm_segs[0].ds_len = buflen;
    756 		map->_dm_flags |= _BUS_DMA_DIRECTMAP;
    757 		return (0);
    758 	}
    759 
    760 	/*
    761 	 * Allocate a region in DVMA space.
    762 	 */
    763 	sgsize = m68k_round_page(buflen + (va & (pagesz - 1)));
    764 
    765 	const vm_flag_t vmflags = VM_BESTFIT |
    766 	    ((flags & BUS_DMA_NOWAIT) ? VM_NOSLEEP : VM_SLEEP);
    767 
    768 	if (vmem_xalloc(dvma_arena, sgsize,
    769 			0,			/* alignment */
    770 			0,			/* phase */
    771 			map->_dm_boundary,	/* nocross */
    772 			VMEM_ADDR_MIN,		/* minaddr */
    773 			VMEM_ADDR_MAX,		/* maxaddr */
    774 			vmflags,
    775 			&dva) != 0) {
    776 		return (ENOMEM);
    777 	}
    778 
    779 	/* Fill in the segment. */
    780 	map->dm_segs[0].ds_addr = dva + (va & (pagesz - 1));
    781 	map->dm_segs[0].ds_len = buflen;
    782 	map->dm_segs[0]._ds_va = dva;
    783 	map->dm_segs[0]._ds_sgsize = sgsize;
    784 
    785 	/*
    786 	 * Now map the DVMA addresses we allocated to point to the
    787 	 * pages of the caller's buffer.
    788 	 */
    789 	if (p != NULL)
    790 		pmap = p->p_vmspace->vm_map.pmap;
    791 	else
    792 		pmap = pmap_kernel();
    793 
    794 	for (; buflen > 0; ) {
    795 		paddr_t pa;
    796 		/*
    797 		 * Get the physical address for this page.
    798 		 */
    799 		rv = pmap_extract(pmap, va, &pa);
    800 #ifdef	DIAGNOSTIC
    801 		if (!rv)
    802 			panic("_bus_dmamap_load: no page");
    803 #endif	/* DIAGNOSTIC */
    804 
    805 		/*
    806 		 * Compute the segment size, and adjust counts.
    807 		 */
    808 		sgsize = pagesz - (va & (pagesz - 1));
    809 		if (buflen < sgsize)
    810 			sgsize = buflen;
    811 
    812 		pmap_enter(pmap_kernel(), dva,
    813 			   (pa & -pagesz) | PMAP_NC,
    814 			   VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
    815 
    816 		dva += pagesz;
    817 		va += sgsize;
    818 		buflen -= sgsize;
    819 	}
    820 	pmap_update(pmap_kernel());
    821 
    822 	/* Make the map truly valid. */
    823 	map->dm_nsegs = 1;
    824 	map->dm_mapsize = map->dm_segs[0].ds_len;
    825 
    826 	return (0);
    827 }
    828 
    829 /*
    830  * unload a DMA map.
    831  */
    832 void
    833 _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
    834 {
    835 	bus_dma_segment_t *segs = map->dm_segs;
    836 	int nsegs = map->dm_nsegs;
    837 	int flags = map->_dm_flags;
    838 	bus_addr_t dva;
    839 	bus_size_t len;
    840 
    841 	if (nsegs != 1)
    842 		panic("_bus_dmamem_unload: nsegs = %d", nsegs);
    843 
    844 	/*
    845 	 * _BUS_DMA_DIRECTMAP is set iff this map was loaded using
    846 	 * _bus_dmamap_load for a 24-bit device.
    847 	 */
    848 	if ((flags & _BUS_DMA_DIRECTMAP) != 0) {
    849 		/* Nothing to release */
    850 		map->_dm_flags &= ~_BUS_DMA_DIRECTMAP;
    851 	}
    852 
    853 	/*
    854 	 * Otherwise, this map was loaded using _bus_dmamap_load for a
    855 	 * non-24-bit device, or using _bus_dmamap_load_raw.
    856 	 */
    857 	else {
    858 		dva = segs[0]._ds_va & -PAGE_SIZE;
    859 		len = segs[0]._ds_sgsize;
    860 
    861 		/*
    862 		 * Unmap the DVMA addresses.
    863 		 */
    864 		pmap_remove(pmap_kernel(), dva, dva + len);
    865 		pmap_update(pmap_kernel());
    866 
    867 		/*
    868 		 * Free the DVMA addresses.
    869 		 */
    870 		if ((flags & BUS_DMA_24BIT) != 0) {
    871 			/*
    872 			 * This map was loaded using _bus_dmamap_load_raw
    873 			 * for a 24-bit device.
    874 			 */
    875 			uvm_unmap(kernel_map, dva, dva + len);
    876 		} else {
    877 			/*
    878 			 * This map was loaded using _bus_dmamap_load or
    879 			 * _bus_dmamap_load_raw for a non-24-bit device.
    880 			 */
    881 			vmem_xfree(dvma_arena, dva, len);
    882 		}
    883 	}
    884 
    885 	/* Mark the mappings as invalid. */
    886 	map->dm_mapsize = 0;
    887 	map->dm_nsegs = 0;
    888 }
    889 
    890 /*
    891  * Translate a VME address and address modifier
    892  * into a CPU physical address and page type.
    893  */
    894 int
    895 vmebus_translate(vme_am_t mod, vme_addr_t addr, bus_type_t *btp,
    896     bus_addr_t *bap)
    897 {
    898 	bus_addr_t base;
    899 
    900 	switch(mod) {
    901 #define _DS (VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA)
    902 
    903 	case (VME_AM_A16|_DS):
    904 		base = 0x00ff0000;
    905 		break;
    906 
    907 	case (VME_AM_A24|_DS):
    908 		base = 0;
    909 		break;
    910 
    911 	default:
    912 		return (ENOENT);
    913 #undef _DS
    914 	}
    915 
    916 	*bap = base | addr;
    917 	*btp = (*bap & 0x800000 ? PMAP_VME8 : PMAP_VME0);
    918 	return (0);
    919 }
    920 
    921 /*
    922  * If we can find a mapping that was established by the PROM, use it.
    923  */
    924 int
    925 find_prom_map(paddr_t pa, bus_type_t iospace, int len, vaddr_t *vap)
    926 {
    927 	u_long	pf;
    928 	int	pgtype;
    929 	vaddr_t	va, eva;
    930 	int	sme;
    931 	u_long	pte;
    932 	int	saved_ctx;
    933 
    934 	/*
    935 	 * The mapping must fit entirely within one page.
    936 	 */
    937 	if ((((u_long)pa & PGOFSET) + len) > PAGE_SIZE)
    938 		return EINVAL;
    939 
    940 	pf = PA_PGNUM(pa);
    941 	pgtype = iospace << PG_MOD_SHIFT;
    942 	saved_ctx = kernel_context();
    943 
    944 	/*
    945 	 * Walk the PROM address space, looking for a page with the
    946 	 * mapping we want.
    947 	 */
    948 	for (va = SUN_MONSTART; va < SUN_MONEND; ) {
    949 
    950 		/*
    951 		 * Make sure this segment is mapped.
    952 		 */
    953 		sme = get_segmap(va);
    954 		if (sme == SEGINV) {
    955 			va += NBSG;
    956 			continue;			/* next segment */
    957 		}
    958 
    959 		/*
    960 		 * Walk the pages of this segment.
    961 		 */
    962 		for(eva = va + NBSG; va < eva; va += PAGE_SIZE) {
    963 			pte = get_pte(va);
    964 
    965 			if ((pte & (PG_VALID | PG_TYPE)) ==
    966 				(PG_VALID | pgtype) &&
    967 			    PG_PFNUM(pte) == pf)
    968 			{
    969 				/*
    970 				 * Found the PROM mapping.
    971 				 * note: preserve page offset
    972 				 */
    973 				*vap = (va | ((vaddr_t)pa & PGOFSET));
    974 				restore_context(saved_ctx);
    975 				return 0;
    976 			}
    977 		}
    978 	}
    979 	restore_context(saved_ctx);
    980 	return ENOENT;
    981 }
    982 
    983 bool
    984 mm_md_direct_mapped_phys(paddr_t paddr, vaddr_t *vaddr)
    985 {
    986 
    987 	if (paddr >= avail_start)
    988 		return false;
    989 	*vaddr = paddr;
    990 	return true;
    991 }
    992 
    993 /*
    994  * Allow access to the PROM mapping similar to uvm_kernacc().
    995  */
    996 int
    997 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
    998 {
    999 
   1000 	if ((vaddr_t)ptr < SUN2_PROM_BASE || (vaddr_t)ptr > SUN2_MONEND) {
   1001 		*handled = false;
   1002 		return 0;
   1003 	}
   1004 
   1005 	*handled = true;
   1006 	/* Read in the PROM itself is OK, write not. */
   1007 	if ((prot & VM_PROT_WRITE) == 0)
   1008 		return 0;
   1009 	return EFAULT;
   1010 }
   1011