Home | History | Annotate | Line # | Download | only in sun3
      1 /*	$NetBSD: machdep.c,v 1.226 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) 1994, 1995 Gordon W. Ross
     41  * Copyright (c) 1993 Adam Glass
     42  * Copyright (c) 1988 University of Utah.
     43  *
     44  * This code is derived from software contributed to Berkeley by
     45  * the Systems Programming Group of the University of Utah Computer
     46  * Science Department.
     47  *
     48  * Redistribution and use in source and binary forms, with or without
     49  * modification, are permitted provided that the following conditions
     50  * are met:
     51  * 1. Redistributions of source code must retain the above copyright
     52  *    notice, this list of conditions and the following disclaimer.
     53  * 2. Redistributions in binary form must reproduce the above copyright
     54  *    notice, this list of conditions and the following disclaimer in the
     55  *    documentation and/or other materials provided with the distribution.
     56  * 3. All advertising materials mentioning features or use of this software
     57  *    must display the following acknowledgement:
     58  *	This product includes software developed by the University of
     59  *	California, Berkeley and its contributors.
     60  * 4. Neither the name of the University nor the names of its contributors
     61  *    may be used to endorse or promote products derived from this software
     62  *    without specific prior written permission.
     63  *
     64  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     65  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     66  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     67  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     68  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     69  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     70  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     71  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     72  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     73  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     74  * SUCH DAMAGE.
     75  *
     76  *	from: Utah Hdr: machdep.c 1.74 92/12/20
     77  *	from: @(#)machdep.c	8.10 (Berkeley) 4/20/94
     78  */
     79 
     80 #include <sys/cdefs.h>
     81 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.226 2026/04/28 03:29:10 thorpej Exp $");
     82 
     83 #include "opt_ddb.h"
     84 #include "opt_kgdb.h"
     85 #include "opt_modular.h"
     86 
     87 #include <sys/param.h>
     88 #include <sys/systm.h>
     89 #include <sys/kernel.h>
     90 #include <sys/proc.h>
     91 #include <sys/buf.h>
     92 #include <sys/reboot.h>
     93 #include <sys/conf.h>
     94 #include <sys/file.h>
     95 #include <sys/device.h>
     96 #include <sys/mbuf.h>
     97 #include <sys/msgbuf.h>
     98 #include <sys/ioctl.h>
     99 #include <sys/tty.h>
    100 #include <sys/mount.h>
    101 #include <sys/exec.h>
    102 #include <sys/core.h>
    103 #include <sys/kcore.h>
    104 #include <sys/vnode.h>
    105 #include <sys/syscallargs.h>
    106 #include <sys/ksyms.h>
    107 #include <sys/module.h>
    108 #include <sys/cpu.h>
    109 #ifdef	KGDB
    110 #include <sys/kgdb.h>
    111 #endif
    112 
    113 #include <uvm/uvm.h> /* XXX: not _extern ... need vm_map_create */
    114 
    115 #include <sys/sysctl.h>
    116 
    117 #include <dev/cons.h>
    118 #include <dev/mm.h>
    119 
    120 #include <machine/cpu.h>
    121 #include <machine/dvma.h>
    122 #include <machine/idprom.h>
    123 #include <machine/kcore.h>
    124 #include <machine/mon.h>
    125 #include <machine/reg.h>
    126 #include <machine/pcb.h>
    127 #include <machine/psl.h>
    128 #include <machine/pte.h>
    129 
    130 #if defined(DDB)
    131 #include <machine/db_machdep.h>
    132 #include <ddb/db_sym.h>
    133 #include <ddb/db_extern.h>
    134 #endif
    135 
    136 #include <sun3/sun3/machdep.h>
    137 
    138 CTASSERT(sizeof(struct frame) == 76 /* F_t */ + 84 /* F_u */);
    139 
    140 #include "ksyms.h"
    141 
    142 /* Defined in locore.s */
    143 extern char kernel_text[];
    144 /* Defined by the linker */
    145 extern char etext[];
    146 
    147 /* kernel_arch specific values required by module(9) */
    148 const vaddr_t kernbase = KERNBASE3;
    149 const vaddr_t kern_end = KERN_END3;
    150 
    151 extern void *msgbufaddr;
    152 
    153 /* Virtual page frame for /dev/mem (see mem.c) */
    154 vaddr_t vmmap;
    155 
    156 /* Our private scratch page for dumping the MMU. */
    157 static vaddr_t dumppage;
    158 
    159 char	kernel_arch[16] = "sun3";	/* XXX needs a sysctl node */
    160 
    161 static void initcpu(void);
    162 
    163 /*
    164  * Console initialization: called early on from main,
    165  * before vm init or cpu_startup.  This system is able
    166  * to use the console for output immediately (via PROM)
    167  * but can not use it for input until after this point.
    168  */
    169 void
    170 consinit(void)
    171 {
    172 
    173 	/*
    174 	 * Switch from the PROM console (output only)
    175 	 * to our own console driver.
    176 	 */
    177 	cninit();
    178 
    179 #if NKSYMS || defined(DDB) || defined(MODULAR)
    180 	{
    181 		extern int nsym;
    182 		extern char *ssym, *esym;
    183 
    184 		ksyms_addsyms_elf(nsym, ssym, esym);
    185 	}
    186 #endif /* DDB */
    187 
    188 	/*
    189 	 * Now that the console can do input as well as
    190 	 * output, consider stopping for a debugger.
    191 	 */
    192 	if (boothowto & RB_KDB) {
    193 #ifdef KGDB
    194 		/* XXX - Ask on console for kgdb_dev? */
    195 		/* Note: this will just return if kgdb_dev==NODEV */
    196 		kgdb_connect(1);
    197 #else	/* KGDB */
    198 		/* Either DDB or no debugger (just PROM). */
    199 		Debugger();
    200 #endif	/* KGDB */
    201 	}
    202 }
    203 
    204 /*
    205  * cpu_startup: allocate memory for variable-sized tables,
    206  * initialize CPU, and do autoconfiguration.
    207  *
    208  * This is called early in init_main.c:main(), after the
    209  * kernel memory allocator is ready for use, but before
    210  * the creation of processes 1,2, and mountroot, etc.
    211  */
    212 void
    213 cpu_startup(void)
    214 {
    215 	/* Set the FPU bit in the "system enable register" */
    216 	enable_fpu(1);
    217 
    218 	/*
    219 	 * Get scratch page for dumpsys().
    220 	 */
    221 	dumppage = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED);
    222 	if (dumppage == 0)
    223 		panic("startup: alloc dumppage");
    224 
    225 	cpu_startup_common();
    226 
    227 	/*
    228 	 * Allocate a virtual page (for use by /dev/mem)
    229 	 * This page is handed to pmap_enter() therefore
    230 	 * it has to be in the normal kernel VA range.
    231 	 */
    232 	vmmap = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
    233 	    UVM_KMF_VAONLY | UVM_KMF_WAITVA);
    234 
    235 	/*
    236 	 * Create the DVMA maps.
    237 	 */
    238 	dvma_init();
    239 
    240 	/*
    241 	 * Set up CPU-specific registers, cache, etc.
    242 	 */
    243 	initcpu();
    244 
    245 	if (fputype == FPU_NONE) {
    246 		/* Might as well turn the enable bit back off. */
    247 		enable_fpu(0);
    248 	}
    249 }
    250 
    251 /*
    252  * machine dependent system variables.
    253  */
    254 #if 0   /* XXX - Not yet... */
    255 static int
    256 sysctl_machdep_root_device(SYSCTLFN_ARGS)
    257 {
    258 	struct sysctlnode node = *rnode;
    259 
    260 	node.sysctl_data = some permutation on root_device;
    261 	node.sysctl_size = strlen(root_device) + 1;
    262 	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    263 }
    264 
    265 static int
    266 sysctl_machdep_booted_kernel(SYSCTLFN_ARGS)
    267 {
    268 	struct sysctlnode node = *rnode;
    269 
    270 	node.sysctl_data = some permutation on booted_kernel;
    271 	node.sysctl_size = strlen(booted_kernel) + 1;
    272 	return (sysctl_lookup(SYSCTLFN_CALL(&node)));
    273 }
    274 #endif
    275 
    276 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    277 {
    278 
    279 	sysctl_createv(clog, 0, NULL, NULL,
    280 		       CTLFLAG_PERMANENT,
    281 		       CTLTYPE_NODE, "machdep", NULL,
    282 		       NULL, 0, NULL, 0,
    283 		       CTL_MACHDEP, CTL_EOL);
    284 
    285 	sysctl_createv(clog, 0, NULL, NULL,
    286 		       CTLFLAG_PERMANENT,
    287 		       CTLTYPE_STRUCT, "console_device", NULL,
    288 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    289 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    290 #if 0	/* XXX - Not yet... */
    291 	sysctl_createv(clog, 0, NULL, NULL,
    292 		       CTLFLAG_PERMANENT,
    293 		       CTLTYPE_STRING, "root_device", NULL,
    294 		       sysctl_machdep_root_device, 0, NULL, 0,
    295 		       CTL_MACHDEP, CPU_ROOT_DEVICE, CTL_EOL);
    296 	sysctl_createv(clog, 0, NULL, NULL,
    297 		       CTLFLAG_PERMANENT,
    298 		       CTLTYPE_STRING, "booted_kernel", NULL,
    299 		       sysctl_machdep_booted_kernel, 0, NULL, 0,
    300 		       CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL);
    301 #endif
    302 }
    303 
    304 void
    305 machine_halt(void)
    306 {
    307 	sunmon_halt();
    308 }
    309 
    310 void
    311 machine_reboot(int howto, char *bootstr)
    312 {
    313 	char *p;
    314 	char default_boot_string[8];
    315 
    316 	if (bootstr == NULL) {
    317 		/*
    318 		 * Build our own boot string with an empty
    319 		 * boot device/file and (maybe) some flags.
    320 		 * The PROM will supply the device/file name.
    321 		 */
    322 		p = default_boot_string;
    323 		*p = '\0';
    324 
    325 		if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) {
    326 			/* Append the boot flags. */
    327 			*p++ = ' ';
    328 			*p++ = '-';
    329 			if (howto & RB_KDB)
    330 				*p++ = 'd';
    331 			if (howto & RB_ASKNAME)
    332 				*p++ = 'a';
    333 			if (howto & RB_SINGLE)
    334 				*p++ = 's';
    335 			*p = '\0';
    336 		}
    337 		bootstr = default_boot_string;
    338 	}
    339 	sunmon_reboot(bootstr);
    340 }
    341 
    342 /*
    343  * These variables are needed by /sbin/savecore
    344  */
    345 uint32_t dumpmag = 0x8fca0101;	/* magic number */
    346 int	dumpsize = 0;		/* pages */
    347 long	dumplo = 0;		/* blocks */
    348 
    349 #define	DUMP_EXTRA	3	/* CPU-dependent extra pages */
    350 
    351 /*
    352  * This is called by main to set dumplo, dumpsize.
    353  * Dumps always skip the first PAGE_SIZE of disk space
    354  * in case there might be a disk label stored there.
    355  * If there is extra space, put dump at the end to
    356  * reduce the chance that swapping trashes it.
    357  */
    358 void
    359 cpu_dumpconf(void)
    360 {
    361 	int devblks;	/* size of dump device in blocks */
    362 	int dumpblks;	/* size of dump image in blocks */
    363 
    364 	if (dumpdev == NODEV)
    365 		return;
    366 
    367 	devblks = bdev_size(dumpdev);
    368 	if (devblks <= ctod(1))
    369 		return;
    370 	devblks &= ~(ctod(1)-1);
    371 
    372 	/*
    373 	 * Note: savecore expects dumpsize to be the
    374 	 * number of pages AFTER the dump header.
    375 	 */
    376 	dumpsize = physmem;
    377 
    378 	/* Position dump image near end of space, page aligned. */
    379 	dumpblks = ctod(physmem + DUMP_EXTRA);
    380 	dumplo = devblks - dumpblks;
    381 
    382 	/* If it does not fit, truncate it by moving dumplo. */
    383 	/* Note: Must force signed comparison. */
    384 	if (dumplo < ((long)ctod(1))) {
    385 		dumplo = ctod(1);
    386 		dumpsize = dtoc(devblks - dumplo) - DUMP_EXTRA;
    387 	}
    388 }
    389 
    390 /* Note: gdb looks for "dumppcb" in a kernel crash dump. */
    391 struct pcb dumppcb;
    392 extern paddr_t avail_start;
    393 
    394 /*
    395  * Write a crash dump.  The format while in swap is:
    396  *   kcore_seg_t cpu_hdr;
    397  *   cpu_kcore_hdr_t cpu_data;
    398  *   padding (PAGE_SIZE-sizeof(kcore_seg_t))
    399  *   pagemap (2*PAGE_SIZE)
    400  *   physical memory...
    401  */
    402 void
    403 dumpsys(void)
    404 {
    405 	const struct bdevsw *dsw;
    406 	kcore_seg_t	*kseg_p;
    407 	cpu_kcore_hdr_t *chdr_p;
    408 	struct sun3_kcore_hdr *sh;
    409 	char *vaddr;
    410 	paddr_t paddr;
    411 	int psize, todo, chunk;
    412 	daddr_t blkno;
    413 	int error = 0;
    414 
    415 	if (dumpdev == NODEV)
    416 		return;
    417 	if (dumppage == 0)
    418 		return;
    419 	dsw = bdevsw_lookup(dumpdev);
    420 	if (dsw == NULL || dsw->d_psize == NULL)
    421 		return;
    422 
    423 	/*
    424 	 * For dumps during autoconfiguration,
    425 	 * if dump device has already configured...
    426 	 */
    427 	if (dumpsize == 0)
    428 		cpu_dumpconf();
    429 	if (dumplo <= 0) {
    430 		printf("\ndump to dev %u,%u not possible\n",
    431 		    major(dumpdev), minor(dumpdev));
    432 		return;
    433 	}
    434 	savectx(&dumppcb);
    435 
    436 	psize = bdev_size(dumpdev);
    437 	if (psize == -1) {
    438 		printf("dump area unavailable\n");
    439 		return;
    440 	}
    441 
    442 	printf("\ndumping to dev %u,%u offset %ld\n",
    443 	    major(dumpdev), minor(dumpdev), dumplo);
    444 
    445 	/*
    446 	 * Prepare the dump header, including MMU state.
    447 	 */
    448 	blkno = dumplo;
    449 	todo = dumpsize;	/* pages */
    450 	vaddr = (char*)dumppage;
    451 	memset(vaddr, 0, PAGE_SIZE);
    452 
    453 	/* Set pointers to all three parts. */
    454 	kseg_p = (kcore_seg_t *)vaddr;
    455 	chdr_p = (cpu_kcore_hdr_t *) (kseg_p + 1);
    456 	sh = &chdr_p->un._sun3;
    457 
    458 	/* Fill in kcore_seg_t part. */
    459 	CORE_SETMAGIC(*kseg_p, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
    460 	kseg_p->c_size = (ctob(DUMP_EXTRA) - sizeof(*kseg_p));
    461 
    462 	/* Fill in cpu_kcore_hdr_t part. */
    463 	strncpy(chdr_p->name, kernel_arch, sizeof(chdr_p->name));
    464 	chdr_p->page_size = PAGE_SIZE;
    465 	chdr_p->kernbase = KERNBASE3;
    466 
    467 	/* Fill in the sun3_kcore_hdr part (MMU state). */
    468 	pmap_kcore_hdr(sh);
    469 
    470 	/* Write out the dump header. */
    471 	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    472 	if (error)
    473 		goto fail;
    474 	blkno += btodb(PAGE_SIZE);
    475 
    476 	/* translation RAM (page zero) */
    477 	pmap_get_pagemap((int*)vaddr, 0);
    478 	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    479 	if (error)
    480 		goto fail;
    481 	blkno += btodb(PAGE_SIZE);
    482 
    483 	/* translation RAM (page one) */
    484 	pmap_get_pagemap((int*)vaddr, PAGE_SIZE);
    485 	error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    486 	if (error)
    487 		goto fail;
    488 	blkno += btodb(PAGE_SIZE);
    489 
    490 	/*
    491 	 * Now dump physical memory.  Have to do it in two chunks.
    492 	 * The first chunk is "unmanaged" (by the VM code) and its
    493 	 * range of physical addresses is not allow in pmap_enter.
    494 	 * However, that segment is mapped linearly, so we can just
    495 	 * use the virtual mappings already in place.  The second
    496 	 * chunk is done the normal way, using pmap_enter.
    497 	 *
    498 	 * Note that vaddr==(paddr+KERNBASE) for paddr=0 through etext.
    499 	 */
    500 
    501 	/* Do the first chunk (0 <= PA < avail_start) */
    502 	paddr = 0;
    503 	chunk = btoc(avail_start);
    504 	if (chunk > todo)
    505 		chunk = todo;
    506 	do {
    507 		if ((todo & 0xf) == 0)
    508 			printf_nolog("\r%4d", todo);
    509 		vaddr = (char*)(paddr + KERNBASE3);
    510 		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    511 		if (error)
    512 			goto fail;
    513 		paddr += PAGE_SIZE;
    514 		blkno += btodb(PAGE_SIZE);
    515 		--todo;
    516 	} while (--chunk > 0);
    517 
    518 	/* Do the second chunk (avail_start <= PA < dumpsize) */
    519 	vaddr = (char*)vmmap;	/* Borrow /dev/mem VA */
    520 	do {
    521 		if ((todo & 0xf) == 0)
    522 			printf_nolog("\r%4d", todo);
    523 		pmap_kenter_pa(vmmap, paddr | PMAP_NC, VM_PROT_READ, 0);
    524 		pmap_update(pmap_kernel());
    525 		error = (*dsw->d_dump)(dumpdev, blkno, vaddr, PAGE_SIZE);
    526 		pmap_kremove(vmmap, PAGE_SIZE);
    527 		pmap_update(pmap_kernel());
    528 		if (error)
    529 			goto fail;
    530 		paddr += PAGE_SIZE;
    531 		blkno += btodb(PAGE_SIZE);
    532 	} while (--todo > 0);
    533 
    534 	printf("\rdump succeeded\n");
    535 	return;
    536 fail:
    537 	printf(" dump error=%d\n", error);
    538 }
    539 
    540 static void
    541 initcpu(void)
    542 {
    543 	/* XXX: Enable RAM parity/ECC checking? */
    544 	/* XXX: parityenable(); */
    545 
    546 #ifdef	HAVECACHE
    547 	cache_enable();
    548 #endif
    549 }
    550 
    551 /* straptrap() in trap.c */
    552 
    553 /* from hp300: badaddr() */
    554 /* peek_byte(), peek_word() moved to bus_subr.c */
    555 
    556 /* XXX: parityenable() ? */
    557 /* regdump() moved to regdump.c */
    558 
    559 bool
    560 mm_md_direct_mapped_phys(paddr_t paddr, vaddr_t *vaddr)
    561 {
    562 
    563 	if (paddr >= avail_start)
    564 		return false;
    565 	*vaddr = KERNBASE3 + paddr;
    566 	return true;
    567 }
    568 
    569 /*
    570  * Allow access to the PROM mapping similar to uvm_kernacc().
    571  */
    572 int
    573 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
    574 {
    575 
    576 	if ((vaddr_t)ptr < SUN3_PROM_BASE || (vaddr_t)ptr > SUN3_MONEND) {
    577 		*handled = false;
    578 		return 0;
    579 	}
    580 
    581 	*handled = true;
    582 	/* Read in the PROM itself is OK. */
    583 	if ((prot & VM_PROT_WRITE) == 0)
    584 		return 0;
    585 
    586 	/* PROM data page is OK for read/write. */
    587 	if ((vaddr_t)ptr >= SUN3_MONSHORTPAGE &&
    588 	    (vaddr_t)ptr < SUN3_MONSHORTPAGE + PAGE_SIZE)
    589 		return 0;
    590 	return EFAULT;
    591 }
    592