Home | History | Annotate | Line # | Download | only in hp300
      1 /*	$NetBSD: machdep.c,v 1.252 2025/12/20 10:51:03 skrll 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.252 2025/12/20 10:51:03 skrll Exp $");
     43 
     44 #include "opt_ddb.h"
     45 #include "opt_compat_netbsd.h"
     46 #include "opt_fpu_emulate.h"
     47 #include "opt_modular.h"
     48 #include "opt_panicbutton.h"
     49 
     50 #include <sys/param.h>
     51 #include <sys/systm.h>
     52 #include <sys/callout.h>
     53 #include <sys/buf.h>
     54 #include <sys/conf.h>
     55 #include <sys/exec.h>
     56 #include <sys/exec_aout.h>		/* for MID_* */
     57 #include <sys/file.h>
     58 #include <sys/ioctl.h>
     59 #include <sys/kernel.h>
     60 #include <sys/device.h>
     61 #include <sys/malloc.h>
     62 #include <sys/mbuf.h>
     63 #include <sys/mount.h>
     64 #include <sys/msgbuf.h>
     65 #include <sys/proc.h>
     66 #include <sys/reboot.h>
     67 #include <sys/signalvar.h>
     68 #include <sys/syscallargs.h>
     69 #include <sys/tty.h>
     70 #include <sys/core.h>
     71 #include <sys/kcore.h>
     72 #include <sys/vnode.h>
     73 #include <sys/ksyms.h>
     74 #include <sys/module.h>
     75 #include <sys/cpu.h>
     76 
     77 #ifdef DDB
     78 #include <machine/db_machdep.h>
     79 #include <ddb/db_sym.h>
     80 #include <ddb/db_extern.h>
     81 #endif /* DDB */
     82 #include <sys/exec_elf.h>
     83 
     84 #include <machine/autoconf.h>
     85 #include <machine/bootinfo.h>
     86 #include <machine/bus.h>
     87 #include <machine/cpu.h>
     88 #include <machine/hp300spu.h>
     89 #include <machine/reg.h>
     90 #include <machine/pcb.h>
     91 #include <machine/psl.h>
     92 #include <machine/pte.h>
     93 
     94 #include <machine/kcore.h>	/* XXX should be pulled in by sys/kcore.h */
     95 
     96 #include <dev/cons.h>
     97 #include <dev/mm.h>
     98 
     99 #define	MAXMEM	64*1024	/* XXX - from cmap.h */
    100 #include <uvm/uvm_extern.h>
    101 
    102 #include <sys/sysctl.h>
    103 
    104 #include "opt_useleds.h"
    105 
    106 #ifdef USELEDS
    107 #include <hp300/hp300/leds.h>
    108 #endif
    109 
    110 #include "ksyms.h"
    111 
    112 /* the following is used externally (sysctl_hw) */
    113 char	machine[] = MACHINE;	/* from <machine/param.h> */
    114 
    115 /* Our exported CPU info; we can have only one. */
    116 struct cpu_info cpu_info_store;
    117 
    118 struct vm_map *phys_map = NULL;
    119 
    120 extern paddr_t avail_start, avail_end;
    121 
    122 /*
    123  * bootinfo base (physical and virtual).  The bootinfo is placed, by
    124  * the boot loader, into the first page of kernel text, which is zero
    125  * filled (see locore.s) and not mapped at 0.  It is remapped to a
    126  * different address in pmap_bootstrap().
    127  */
    128 paddr_t	bootinfo_pa;
    129 vaddr_t	bootinfo_va;
    130 
    131 int	maxmem;			/* max memory per process */
    132 
    133 extern	u_int lowram;
    134 extern	short exframesize[];
    135 
    136 /* prototypes for local functions */
    137 static void	parityenable(void);
    138 static int	parityerror(struct frame *);
    139 static int	parityerrorfind(void);
    140 static void	identifycpu(void);
    141 static void	initcpu(void);
    142 
    143 static int	cpu_dumpsize(void);
    144 static int	cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
    145 static void	cpu_init_kcore_hdr(void);
    146 
    147 /* functions called from locore.s */
    148 void    dumpsys(void);
    149 void	machine_init(paddr_t);
    150 void    straytrap(int, u_short);
    151 void	nmihand(struct frame);
    152 
    153 /*
    154  * Machine-dependent crash dump header info.
    155  */
    156 static cpu_kcore_hdr_t cpu_kcore_hdr;
    157 
    158 /*
    159  * Note that the value of delay_divisor is roughly
    160  * 2048 / cpuspeed (where cpuspeed is in MHz) on 68020
    161  * and 68030 systems.  See clock.c for the delay
    162  * calibration algorithm.
    163  */
    164 int	cpuspeed;		/* relative CPU speed; XXX skewed on 68040 */
    165 int	delay_divisor;		/* delay constant */
    166 
    167 #ifdef __HAVE_NEW_PMAP_68K
    168 /*
    169  * machine_bootmap[] is checked in pmap_bootstrap1() of the new m68k pmap
    170  * and it allocates kernel address space for intio devices.
    171  */
    172 #define PMBM_INTIO	0
    173 #define PMBM_EXTIO	1
    174 #define PMBM_BOOTINFO	2
    175 #define PMBM_MAXADDR	3
    176 const struct pmap_bootmap machine_bootmap[] = {
    177 	{ .pmbm_vaddr_ptr = (vaddr_t *)&intiobase,
    178 	  .pmbm_paddr = INTIOBASE,
    179 	  .pmbm_size  = INTIOSIZE,
    180 	  .pmbm_flags = PMBM_F_CI },
    181 
    182 	{ .pmbm_vaddr_ptr = (vaddr_t *)&extiobase,
    183 	  .pmbm_paddr = 0,	/* VAONLY, so no PA mappings */
    184 	  .pmbm_size  = ctob(EIOMAPSIZE),
    185 	  .pmbm_flags = PMBM_F_VAONLY | PMBM_F_CI },
    186 
    187 	{ .pmbm_vaddr_ptr = &bootinfo_va,
    188 	  .pmbm_paddr = 0,	/* VAONLY, so no PA mappings */
    189 	  .pmbm_size  = ctob(1),
    190 	  .pmbm_flags = PMBM_F_VAONLY },
    191 
    192 	/* Last page of RAM is mapped VA==PA for the MMU trampoline. */
    193 	{ .pmbm_vaddr = MAXADDR,
    194 	  .pmbm_paddr = MAXADDR,
    195 	  .pmbm_size  = PAGE_SIZE,
    196 	  .pmbm_flags = PMBM_F_FIXEDVA | PMBM_F_CI },
    197 
    198 	{ .pmbm_vaddr = -1 },
    199 };
    200 
    201 /*
    202  * The new 68k pmap utilizes the MAXADDR page as the NULL segment table
    203  * to save a page, so we have to preserve PROM workarea for the next reboot.
    204  * This preservation area is much less than a page size, so the trade-off
    205  * seems worth it.
    206  */
    207 #define	BOOTWORKSTART	0xfffffdc0U	/* from hp300/stand/common/srt0.S */
    208 #define	BOOTWORKSIZE	(0U - BOOTWORKSTART)
    209 static char bootwork_savearea[BOOTWORKSIZE];
    210 #endif /* __HAVE_NEW_PMAP_68K */
    211 
    212 /*
    213  * Early initialization, before main() is called.
    214  */
    215 void
    216 machine_init(paddr_t nextpa)
    217 {
    218 	struct btinfo_magic *bt_mag;
    219 	int i;
    220 
    221 #ifdef CACHE_HAVE_VAC
    222 	/*
    223 	 * Determine VA aliasing distance if any
    224 	 */
    225 	switch (machineid) {
    226 	case HP_320:
    227 		pmap_init_vac(16 * 1024);
    228 		break;
    229 	case HP_350:
    230 		pmap_init_vac(32 * 1024);
    231 		break;
    232 	default:
    233 		break;
    234 	}
    235 #endif
    236 
    237 #ifdef __HAVE_NEW_PMAP_68K
    238 	/*
    239 	 * We've used NULL_SEGTAB_PA in <machine/pmap.h> to use the
    240 	 * reserved last-page-of-RAM as the NULL segment table.  But,
    241 	 * we copied code into that page (the MMU trampoline) and it
    242 	 * also contains the PROM's work area.  Preserve the PROM work
    243 	 * area and zero it out now.
    244 	 */
    245 	memcpy(bootwork_savearea, (void *)BOOTWORKSTART, BOOTWORKSIZE);
    246 	memset((void *)MAXADDR, 0, PAGE_SIZE);
    247 #endif
    248 
    249 	/*
    250 	 * Tell the VM system about available physical memory.  The
    251 	 * hp300 only has one segment.
    252 	 */
    253 	avail_start = nextpa;
    254 	avail_end = m68k_ptob(maxmem) - \
    255 	    (m68k_round_page(MSGBUFSIZE) + m68k_ptob(1));
    256 
    257 	uvm_page_physload(atop(avail_start), atop(avail_end),
    258 	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
    259 
    260 	/* Calibrate the delay loop. */
    261 	hp300_calibrate_delay();
    262 
    263 	/*
    264 	 * Initialize error message buffer (at end of core).
    265 	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
    266 	 */
    267 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
    268 		pmap_kenter_pa((vaddr_t)msgbufaddr + i * PAGE_SIZE,
    269 		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, 0);
    270 	pmap_update(pmap_kernel());
    271 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
    272 
    273 	/*
    274 	 * Map in the bootinfo page, and make sure the bootinfo
    275 	 * exists by searching for the MAGIC record.  If it's not
    276 	 * there, disable bootinfo.
    277 	 */
    278 #ifndef __HAVE_NEW_PMAP_68K
    279 	bootinfo_va = virtual_avail;
    280 	virtual_avail += PAGE_SIZE;
    281 #endif
    282 	pmap_enter(pmap_kernel(), bootinfo_va, bootinfo_pa,
    283 	    VM_PROT_READ|VM_PROT_WRITE,
    284 	    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
    285 	pmap_update(pmap_kernel());
    286 	bt_mag = lookup_bootinfo(BTINFO_MAGIC);
    287 	if (bt_mag == NULL ||
    288 	    bt_mag->magic1 != BOOTINFO_MAGIC1 ||
    289 	    bt_mag->magic2 != BOOTINFO_MAGIC2) {
    290 		pmap_remove(pmap_kernel(), bootinfo_va,
    291 		    bootinfo_va + PAGE_SIZE);
    292 		pmap_update(pmap_kernel());
    293 #ifndef __HAVE_NEW_PMAP_68K
    294 		virtual_avail -= PAGE_SIZE;
    295 #endif
    296 		bootinfo_va = 0;
    297 	}
    298 }
    299 
    300 /*
    301  * Console initialization: called early on from main,
    302  * before vm init or startup.  Do enough configuration
    303  * to choose and initialize a console.
    304  */
    305 void
    306 consinit(void)
    307 {
    308 
    309 	/*
    310 	 * Initialize the external I/O extent map.
    311 	 */
    312 	iomap_init();
    313 
    314 	/*
    315 	 * Initialize the console before we print anything out.
    316 	 */
    317 
    318 	hp300_cninit();
    319 
    320 	/*
    321 	 * Issue a warning if the boot loader didn't provide bootinfo.
    322 	 */
    323 	if (bootinfo_va != 0)
    324 		printf("bootinfo found at 0x%08lx\n", bootinfo_pa);
    325 	else
    326 		printf("WARNING: boot loader did not provide bootinfo\n");
    327 
    328 #if NKSYMS || defined(DDB) || defined(MODULAR)
    329 	{
    330 		extern int end;
    331 		extern int *esym;
    332 
    333 		ksyms_addsyms_elf((int)esym - (int)&end - sizeof(Elf32_Ehdr),
    334 		    (void *)&end, esym);
    335 	}
    336 #endif
    337 #ifdef DDB
    338 	if (boothowto & RB_KDB)
    339 		Debugger();
    340 #endif
    341 }
    342 
    343 /*
    344  * cpu_startup: allocate memory for variable-sized tables,
    345  * initialize CPU
    346  */
    347 void
    348 cpu_startup(void)
    349 {
    350 	vaddr_t minaddr, maxaddr;
    351 	char pbuf[9];
    352 #if defined(DEBUG) && !defined(__HAVE_NEW_PMAP_68K)
    353 	extern int pmapdebug;
    354 	int opmapdebug = pmapdebug;
    355 
    356 	pmapdebug = 0;
    357 #endif
    358 
    359 	hp300_cninit_deferred();
    360 
    361 	if (fputype != FPU_NONE)
    362 		m68k_make_fpu_idle_frame();
    363 
    364 	/*
    365 	 * Initialize the kernel crash dump header.
    366 	 */
    367 	cpu_init_kcore_hdr();
    368 
    369 	/*
    370 	 * Good {morning,afternoon,evening,night}.
    371 	 */
    372 	printf("%s%s", copyright, version);
    373 	identifycpu();
    374 	format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
    375 	printf("total memory = %s\n", pbuf);
    376 
    377 	minaddr = 0;
    378 
    379 	/*
    380 	 * Allocate a submap for physio
    381 	 */
    382 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    383 	    VM_PHYS_SIZE, 0, false, NULL);
    384 
    385 #if defined(DEBUG) && !defined(__HAVE_NEW_PMAP_68K)
    386 	pmapdebug = opmapdebug;
    387 #endif
    388 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvm_availmem(false)));
    389 	printf("avail memory = %s\n", pbuf);
    390 
    391 	/*
    392 	 * Set up CPU-specific registers, cache, etc.
    393 	 */
    394 	initcpu();
    395 }
    396 
    397 struct hp300_model {
    398 	int id;
    399 	int mmuid;
    400 	const char *name;
    401 	const char *speed;
    402 };
    403 
    404 static const struct hp300_model hp300_models[] = {
    405 	{ HP_320,	-1,		"320",		"16.67"	},
    406 	{ HP_330,	-1,		"318/319/330",	"16.67"	},
    407 	{ HP_340,	-1,		"340",		"16.67"	},
    408 	{ HP_345,	-1,		"345",		"50"	},
    409 	{ HP_350,	-1,		"350",		"25"	},
    410 	{ HP_360,	-1,		"360",		"25"	},
    411 	{ HP_362,	-1,		"362",		"25"	},
    412 	{ HP_370,	-1,		"370",		"33.33"	},
    413 	{ HP_375,	-1,		"375",		"50"	},
    414 	{ HP_380,	-1,		"380",		"25"	},
    415 	{ HP_382,	-1,		"382",		"25"	},
    416 	{ HP_385,	-1,		"385",		"33"	},
    417 	{ HP_400,	-1,		"400",		"50"	},
    418 	{ HP_425,	MMUID_425_T,	"425t",		"25"	},
    419 	{ HP_425,	MMUID_425_S,	"425s",		"25"	},
    420 	{ HP_425,	MMUID_425_E,	"425e",		"25"	},
    421 	{ HP_425,	-1,		"425",		"25"	},
    422 	{ HP_433,	MMUID_433_T,	"433t",		"33"	},
    423 	{ HP_433,	MMUID_433_S,	"433s",		"33"	},
    424 	{ HP_433,	-1,		"433",		"33"	},
    425 	{ 0,		-1,		NULL,		NULL	},
    426 };
    427 
    428 static void
    429 identifycpu(void)
    430 {
    431 	const char *t, *cpu, *s, *mmu;
    432 	int i;
    433 	char fpu[64], cache[64];
    434 
    435 	/*
    436 	 * Find the model number.
    437 	 */
    438 	for (t = s = NULL, i = 0; hp300_models[i].name != NULL; i++) {
    439 		if (hp300_models[i].id == machineid) {
    440 			if (hp300_models[i].mmuid != -1 &&
    441 			    hp300_models[i].mmuid != mmuid)
    442 				continue;
    443 			t = hp300_models[i].name;
    444 			s = hp300_models[i].speed;
    445 			break;
    446 		}
    447 	}
    448 	if (t == NULL) {
    449 		printf("\nunknown machineid %d\n", machineid);
    450 		goto lose;
    451 	}
    452 
    453 	/*
    454 	 * ...and the CPU type.
    455 	 */
    456 	switch (cputype) {
    457 	case CPU_68040:
    458 		cpu = "MC68040";
    459 		break;
    460 	case CPU_68030:
    461 		cpu = "MC68030";
    462 		break;
    463 	case CPU_68020:
    464 		cpu = "MC68020";
    465 		break;
    466 	default:
    467 		printf("\nunknown cputype %d\n", cputype);
    468 		goto lose;
    469 	}
    470 
    471 
    472 	/*
    473 	 * ...and the MMU type.
    474 	 */
    475 	switch (mmutype) {
    476 	case MMU_68040:
    477 	case MMU_68030:
    478 		mmu = "+MMU";
    479 		break;
    480 	case MMU_68851:
    481 		mmu = ", MC68851 MMU";
    482 		break;
    483 	case MMU_HP:
    484 		mmu = ", HP MMU";
    485 		break;
    486 	default:
    487 		printf("%s\nunknown MMU type %d\n", cpu, mmutype);
    488 		panic("startup");
    489 	}
    490 
    491 	/*
    492 	 * ...and the FPU type.
    493 	 */
    494 	fpu[0] = '\0';
    495 	switch (fputype) {
    496 	case FPU_68040:
    497 		strlcpy(fpu, "+FPU", sizeof(fpu));
    498 		break;
    499 	case FPU_68882:
    500 		snprintf(fpu, sizeof(fpu), ", %sMHz MC68882 FPU", s);
    501 		break;
    502 	case FPU_68881:
    503 		snprintf(fpu, sizeof(fpu), ", %sMHz MC68881 FPU",
    504 		    machineid == HP_350 ? "20" : "16.67");
    505 		break;
    506 	case FPU_NONE:
    507 #ifdef FPU_EMULATE
    508 		strlcpy(fpu, ", emulated FPU", sizeof(fpu));
    509 #else
    510 		strlcpy(fpu, ", no FPU", sizeof(fpu));
    511 #endif
    512 		break;
    513 	default:
    514 		strlcpy(fpu, ", unknown FPU", sizeof(fpu));
    515 	}
    516 
    517 	/*
    518 	 * ...and finally, the cache type.
    519 	 */
    520 	cache[0] = '\0';
    521 	if (cputype == CPU_68040)
    522 		snprintf(cache, sizeof(cache),
    523 		    ", 4k on-chip physical I/D caches");
    524 	else {
    525 		switch (ectype) {
    526 		case EC_VIRT:
    527 			snprintf(cache, sizeof(cache),
    528 			    ", %dK virtual-address cache",
    529 			    machineid == HP_320 ? 16 : 32);
    530 			break;
    531 		case EC_PHYS:
    532 			snprintf(cache, sizeof(cache),
    533 			    ", %dK physical-address cache",
    534 			    machineid == HP_370 ? 64 : 32);
    535 			break;
    536 		}
    537 	}
    538 
    539 	cpu_setmodel("HP 9000/%s (%sMHz %s CPU%s%s%s)", t, s, cpu,
    540 	    mmu, fpu, cache);
    541 	printf("%s\n", cpu_getmodel());
    542 #ifdef DIAGNOSTIC
    543 	printf("cpu: delay divisor %d", delay_divisor);
    544 	if (mmuid)
    545 		printf(", mmuid %d", mmuid);
    546 	printf("\n");
    547 #endif
    548 
    549 	/*
    550 	 * Now that we have told the user what they have,
    551 	 * let them know if that machine type isn't configured.
    552 	 */
    553 	switch (machineid) {
    554 	case -1:		/* keep compilers happy */
    555 #if !defined(HP320)
    556 	case HP_320:
    557 #endif
    558 #if !defined(HP330)
    559 	case HP_330:
    560 #endif
    561 #if !defined(HP340)
    562 	case HP_340:
    563 #endif
    564 #if !defined(HP345)
    565 	case HP_345:
    566 #endif
    567 #if !defined(HP350)
    568 	case HP_350:
    569 #endif
    570 #if !defined(HP360)
    571 	case HP_360:
    572 #endif
    573 #if !defined(HP362)
    574 	case HP_362:
    575 #endif
    576 #if !defined(HP370)
    577 	case HP_370:
    578 #endif
    579 #if !defined(HP375)
    580 	case HP_375:
    581 #endif
    582 #if !defined(HP380)
    583 	case HP_380:
    584 #endif
    585 #if !defined(HP382)
    586 	case HP_382:
    587 #endif
    588 #if !defined(HP385)
    589 	case HP_385:
    590 #endif
    591 #if !defined(HP400)
    592 	case HP_400:
    593 #endif
    594 #if !defined(HP425)
    595 	case HP_425:
    596 #endif
    597 #if !defined(HP433)
    598 	case HP_433:
    599 #endif
    600 		panic("SPU type not configured");
    601 	default:
    602 		break;
    603 	}
    604 
    605 	return;
    606  lose:
    607 	panic("startup");
    608 }
    609 
    610 /*
    611  * machine dependent system variables.
    612  */
    613 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    614 {
    615 	static bool broken_rmc;
    616 
    617 	broken_rmc = (cputype == M68020);
    618 
    619 	sysctl_createv(clog, 0, NULL, NULL,
    620 	    CTLFLAG_PERMANENT,
    621 	    CTLTYPE_NODE, "machdep", NULL,
    622 	    NULL, 0, NULL, 0,
    623 	    CTL_MACHDEP, CTL_EOL);
    624 
    625 	sysctl_createv(clog, 0, NULL, NULL,
    626 	    CTLFLAG_PERMANENT,
    627 	    CTLTYPE_STRUCT, "console_device", NULL,
    628 	    sysctl_consdev, 0, NULL, sizeof(dev_t),
    629 	    CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    630 
    631 	sysctl_createv(clog, 0, NULL, NULL,
    632 	    CTLFLAG_PERMANENT,
    633 	    CTLTYPE_BOOL, "broken_rmc", NULL,
    634 	    NULL, 0, &broken_rmc, 0,
    635 	    CTL_MACHDEP, CPU_BROKEN_RMC, CTL_EOL);
    636 }
    637 
    638 int	waittime = -1;
    639 
    640 void
    641 cpu_reboot(int howto, char *bootstr)
    642 {
    643 	struct pcb *pcb = lwp_getpcb(curlwp);
    644 
    645 	/* take a snap shot before clobbering any registers */
    646 	if (pcb != NULL)
    647 		savectx(pcb);
    648 
    649 	/* If system is cold, just halt. */
    650 	if (cold) {
    651 		howto |= RB_HALT;
    652 		goto haltsys;
    653 	}
    654 
    655 	boothowto = howto;
    656 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
    657 		waittime = 0;
    658 		vfs_shutdown();
    659 	}
    660 
    661 	/* Disable interrupts. */
    662 	splhigh();
    663 
    664 	/* If rebooting and a dump is requested do it. */
    665 	if (howto & RB_DUMP)
    666 		dumpsys();
    667 
    668  haltsys:
    669 	/* Run any shutdown hooks. */
    670 	doshutdownhooks();
    671 
    672 	pmf_system_shutdown(boothowto);
    673 
    674 #if defined(PANICWAIT) && !defined(DDB)
    675 	if ((howto & RB_HALT) == 0 && panicstr) {
    676 		printf("hit any key to reboot...\n");
    677 		cnpollc(true);
    678 		(void)cngetc();
    679 		cnpollc(false);
    680 		printf("\n");
    681 	}
    682 #endif
    683 
    684 	/* Finally, halt/reboot the system. */
    685 	if (howto & RB_HALT) {
    686 		printf("System halted.  Hit any key to reboot.\n\n");
    687 		cnpollc(true);
    688 		(void)cngetc();
    689 		cnpollc(false);
    690 	}
    691 
    692 	printf("rebooting...\n");
    693 	DELAY(1000000);
    694 
    695 #ifdef __HAVE_NEW_PMAP_68K
    696 	/* Restore the PROM work area first. */
    697 	memcpy((void *)BOOTWORKSTART, bootwork_savearea, BOOTWORKSIZE);
    698 #endif
    699 	doboot();
    700 	/* NOTREACHED */
    701 }
    702 
    703 /*
    704  * Initialize the kernel crash dump header.
    705  */
    706 static void
    707 cpu_init_kcore_hdr(void)
    708 {
    709 	phys_ram_seg_t *ram_segs = pmap_init_kcore_hdr(&cpu_kcore_hdr);
    710 
    711 	/* hp300 has one contiguous memory segment. */
    712 	ram_segs[0].start = lowram;
    713 	ram_segs[0].size  = ctob(physmem);
    714 }
    715 
    716 /*
    717  * Compute the size of the machine-dependent crash dump header.
    718  * Returns size in disk blocks.
    719  */
    720 
    721 #define CHDRSIZE (ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)))
    722 #define MDHDRSIZE roundup(CHDRSIZE, dbtob(1))
    723 
    724 static int
    725 cpu_dumpsize(void)
    726 {
    727 
    728 	return btodb(MDHDRSIZE);
    729 }
    730 
    731 /*
    732  * Called by dumpsys() to dump the machine-dependent header.
    733  */
    734 static int
    735 cpu_dump(int (*dump)(dev_t, daddr_t, void *, size_t), daddr_t *blknop)
    736 {
    737 	int buf[MDHDRSIZE / sizeof(int)];
    738 	cpu_kcore_hdr_t *chdr;
    739 	kcore_seg_t *kseg;
    740 	int error;
    741 
    742 	kseg = (kcore_seg_t *)buf;
    743 	chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) /
    744 	    sizeof(int)];
    745 
    746 	/* Create the segment header. */
    747 	CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
    748 	kseg->c_size = MDHDRSIZE - ALIGN(sizeof(kcore_seg_t));
    749 
    750 	memcpy(chdr, &cpu_kcore_hdr, sizeof(cpu_kcore_hdr_t));
    751 	error = (*dump)(dumpdev, *blknop, (void *)buf, sizeof(buf));
    752 	*blknop += btodb(sizeof(buf));
    753 	return error;
    754 }
    755 
    756 /*
    757  * These variables are needed by /sbin/savecore
    758  */
    759 uint32_t dumpmag = 0x8fca0101;	/* magic number */
    760 int	dumpsize = 0;		/* pages */
    761 long	dumplo = 0;		/* blocks */
    762 
    763 /*
    764  * This is called by main to set dumplo and dumpsize.
    765  * Dumps always skip the first PAGE_SIZE of disk space
    766  * in case there might be a disk label stored there.
    767  * If there is extra space, put dump at the end to
    768  * reduce the chance that swapping trashes it.
    769  */
    770 void
    771 cpu_dumpconf(void)
    772 {
    773 	int chdrsize;	/* size of dump header */
    774 	int nblks;	/* size of dump area */
    775 
    776 	if (dumpdev == NODEV)
    777 		return;
    778 	nblks = bdev_size(dumpdev);
    779 	chdrsize = cpu_dumpsize();
    780 
    781 	dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size);
    782 
    783 	/*
    784 	 * Check do see if we will fit.  Note we always skip the
    785 	 * first PAGE_SIZE in case there is a disk label there.
    786 	 */
    787 	if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) {
    788 		dumpsize = 0;
    789 		dumplo = -1;
    790 		return;
    791 	}
    792 
    793 	/*
    794 	 * Put dump at the end of the partition.
    795 	 */
    796 	dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize;
    797 }
    798 
    799 /*
    800  * Dump physical memory onto the dump device.  Called by cpu_reboot().
    801  */
    802 void
    803 dumpsys(void)
    804 {
    805 	const struct bdevsw *bdev;
    806 	daddr_t blkno;		/* current block to write */
    807 				/* dump routine */
    808 	int (*dump)(dev_t, daddr_t, void *, size_t);
    809 	int pg;			/* page being dumped */
    810 	paddr_t maddr;		/* PA being dumped */
    811 	int error;		/* error code from (*dump)() */
    812 
    813 	/* XXX initialized here because of gcc lossage */
    814 	maddr = lowram;
    815 	pg = 0;
    816 
    817 	/* Make sure dump device is valid. */
    818 	if (dumpdev == NODEV)
    819 		return;
    820 	bdev = bdevsw_lookup(dumpdev);
    821 	if (bdev == NULL)
    822 		return;
    823 	if (dumpsize == 0) {
    824 		cpu_dumpconf();
    825 		if (dumpsize == 0)
    826 			return;
    827 	}
    828 	if (dumplo <= 0) {
    829 		printf("\ndump to dev %u,%u not possible\n",
    830 		    major(dumpdev), minor(dumpdev));
    831 		return;
    832 	}
    833 	dump = bdev->d_dump;
    834 	blkno = dumplo;
    835 
    836 	printf("\ndumping to dev %u,%u offset %ld\n",
    837 	    major(dumpdev), minor(dumpdev), dumplo);
    838 
    839 	printf("dump ");
    840 
    841 	/* Write the dump header. */
    842 	error = cpu_dump(dump, &blkno);
    843 	if (error)
    844 		goto bad;
    845 
    846 	for (pg = 0; pg < dumpsize; pg++) {
    847 #define NPGMB	(1024*1024/PAGE_SIZE)
    848 		/* print out how many MBs we have dumped */
    849 		if (pg && (pg % NPGMB) == 0)
    850 			printf("%d ", pg / NPGMB);
    851 #undef NPGMB
    852 		pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr,
    853 		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
    854 
    855 		pmap_update(pmap_kernel());
    856 		error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
    857  bad:
    858 		switch (error) {
    859 		case 0:
    860 			maddr += PAGE_SIZE;
    861 			blkno += btodb(PAGE_SIZE);
    862 			break;
    863 
    864 		case ENXIO:
    865 			printf("device bad\n");
    866 			return;
    867 
    868 		case EFAULT:
    869 			printf("device not ready\n");
    870 			return;
    871 
    872 		case EINVAL:
    873 			printf("area improper\n");
    874 			return;
    875 
    876 		case EIO:
    877 			printf("i/o error\n");
    878 			return;
    879 
    880 		case EINTR:
    881 			printf("aborted from console\n");
    882 			return;
    883 
    884 		default:
    885 			printf("error %d\n", error);
    886 			return;
    887 		}
    888 	}
    889 	printf("succeeded\n");
    890 }
    891 
    892 static void
    893 initcpu(void)
    894 {
    895 
    896 	parityenable();
    897 #ifdef USELEDS
    898 	ledinit();
    899 #endif
    900 }
    901 
    902 void
    903 straytrap(int pc, u_short evec)
    904 {
    905 	printf("unexpected trap (vector offset %x) from %x\n",
    906 	       evec & 0xFFF, pc);
    907 }
    908 
    909 /* XXX should change the interface, and make one badaddr() function */
    910 
    911 int	*nofault;
    912 
    913 int
    914 badaddr(void *addr)
    915 {
    916 	int i;
    917 	label_t	faultbuf;
    918 
    919 	nofault = (int *)&faultbuf;
    920 	if (setjmp((label_t *)nofault)) {
    921 		nofault = (int *)0;
    922 		return 1;
    923 	}
    924 	i = *(volatile short *)addr;
    925 	__USE(i);
    926 	nofault = (int *)0;
    927 	return 0;
    928 }
    929 
    930 int
    931 badbaddr(void *addr)
    932 {
    933 	int i;
    934 	label_t	faultbuf;
    935 
    936 	nofault = (int *)&faultbuf;
    937 	if (setjmp((label_t *)nofault)) {
    938 		nofault = (int *)0;
    939 		return 1;
    940 	}
    941 	i = *(volatile char *)addr;
    942 	__USE(i);
    943 	nofault = (int *) 0;
    944 	return 0;
    945 }
    946 
    947 /*
    948  * lookup_bootinfo:
    949  *
    950  *	Look up information in bootinfo from boot loader.
    951  */
    952 void *
    953 lookup_bootinfo(int type)
    954 {
    955 	struct btinfo_common *bt;
    956 	char *help = (char *)bootinfo_va;
    957 
    958 	/* Check for a bootinfo record first. */
    959 	if (help == NULL)
    960 		return NULL;
    961 
    962 	do {
    963 		bt = (struct btinfo_common *)help;
    964 		if (bt->type == type)
    965 			return help;
    966 		help += bt->next;
    967 	} while (bt->next != 0 &&
    968 		 (size_t)help < (size_t)bootinfo_va + BOOTINFO_SIZE);
    969 
    970 	return NULL;
    971 }
    972 
    973 #if defined(PANICBUTTON) && !defined(DDB)
    974 /*
    975  * Declare these so they can be patched.
    976  */
    977 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
    978 int candbdiv = 2;	/* give em half a second (hz / candbdiv) */
    979 
    980 static void	candbtimer(void *);
    981 
    982 int crashandburn;
    983 
    984 callout_t candbtimer_ch;
    985 
    986 void
    987 candbtimer(void *arg)
    988 {
    989 
    990 	crashandburn = 0;
    991 }
    992 #endif /* PANICBUTTON & !DDB */
    993 
    994 static int innmihand;	/* simple mutex */
    995 
    996 /*
    997  * Level 7 interrupts can be caused by HIL keyboards (in cooked mode only,
    998  * but we run them in raw mode) or parity errors.
    999  */
   1000 void
   1001 nmihand(struct frame frame)
   1002 {
   1003 
   1004 	/* Prevent unwanted recursion. */
   1005 	if (innmihand)
   1006 		return;
   1007 	innmihand = 1;
   1008 
   1009 	if (parityerror(&frame))
   1010 		return;
   1011 	/* panic?? */
   1012 	printf("unexpected level 7 interrupt ignored\n");
   1013 
   1014 	innmihand = 0;
   1015 }
   1016 
   1017 /*
   1018  * Parity error section.  Contains magic.
   1019  */
   1020 #define PARREG		((volatile short *)IIOV(0x5B0000))
   1021 static int gotparmem = 0;
   1022 #ifdef DEBUG
   1023 int ignorekperr = 0;	/* ignore kernel parity errors */
   1024 #endif
   1025 
   1026 /*
   1027  * Enable parity detection
   1028  */
   1029 static void
   1030 parityenable(void)
   1031 {
   1032 	label_t	faultbuf;
   1033 
   1034 	nofault = (int *)&faultbuf;
   1035 	if (setjmp((label_t *)nofault)) {
   1036 		nofault = (int *)0;
   1037 		printf("Parity detection disabled\n");
   1038 		return;
   1039 	}
   1040 	*PARREG = 1;
   1041 	nofault = (int *)0;
   1042 	gotparmem = 1;
   1043 }
   1044 
   1045 /*
   1046  * Determine if level 7 interrupt was caused by a parity error
   1047  * and deal with it if it was.  Returns 1 if it was a parity error.
   1048  */
   1049 static int
   1050 parityerror(struct frame *fp)
   1051 {
   1052 	if (!gotparmem)
   1053 		return 0;
   1054 	*PARREG = 0;
   1055 	DELAY(10);
   1056 	*PARREG = 1;
   1057 	if (panicstr) {
   1058 		printf("parity error after panic ignored\n");
   1059 		return 1;
   1060 	}
   1061 	if (!parityerrorfind())
   1062 		printf("WARNING: transient parity error ignored\n");
   1063 	else if (USERMODE(fp->f_sr)) {
   1064 		printf("pid %d: parity error\n", curproc->p_pid);
   1065 		uprintf("sorry, pid %d killed due to memory parity error\n",
   1066 		    curproc->p_pid);
   1067 		psignal(curproc, SIGKILL);
   1068 #ifdef DEBUG
   1069 	} else if (ignorekperr) {
   1070 		printf("WARNING: kernel parity error ignored\n");
   1071 #endif
   1072 	} else {
   1073 		regdump((struct trapframe *)fp, 128);
   1074 		panic("kernel parity error");
   1075 	}
   1076 	return 1;
   1077 }
   1078 
   1079 /*
   1080  * Yuk!  There has got to be a better way to do this!
   1081  * Searching all of memory with interrupts blocked can lead to disaster.
   1082  */
   1083 static int
   1084 parityerrorfind(void)
   1085 {
   1086 	static label_t parcatch;
   1087 	static int looking = 0;
   1088 	volatile int pg, o, s;
   1089 	volatile int *ip;
   1090 	int i;
   1091 	int found;
   1092 
   1093 	/*
   1094 	 * If looking is true we are searching for a known parity error
   1095 	 * and it has just occurred.  All we do is return to the higher
   1096 	 * level invocation.
   1097 	 */
   1098 	if (looking)
   1099 		longjmp(&parcatch);
   1100 	s = splhigh();
   1101 	/*
   1102 	 * If setjmp returns true, the parity error we were searching
   1103 	 * for has just occurred (longjmp above) at the current pg+o
   1104 	 */
   1105 	if (setjmp(&parcatch)) {
   1106 		printf("Parity error at 0x%x\n", ctob(pg)|o);
   1107 		found = 1;
   1108 		goto done;
   1109 	}
   1110 	/*
   1111 	 * If we get here, a parity error has occurred for the first time
   1112 	 * and we need to find it.  We turn off any external caches and
   1113 	 * loop thru memory, testing every longword til a fault occurs and
   1114 	 * we regain control at setjmp above.  Note that because of the
   1115 	 * setjmp, pg and o need to be volatile or their values will be lost.
   1116 	 */
   1117 	looking = 1;
   1118 	ecacheoff();
   1119 	for (pg = btoc(lowram); pg < btoc(lowram)+physmem; pg++) {
   1120 		pmap_enter(pmap_kernel(), (vaddr_t)vmmap, ctob(pg),
   1121 		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
   1122 		pmap_update(pmap_kernel());
   1123 		ip = (int *)vmmap;
   1124 		for (o = 0; o < PAGE_SIZE; o += sizeof(int))
   1125 			i = *ip++;
   1126 	}
   1127 	__USE(i);
   1128 	/*
   1129 	 * Getting here implies no fault was found.  Should never happen.
   1130 	 */
   1131 	printf("Couldn't locate parity error\n");
   1132 	found = 0;
   1133  done:
   1134 	looking = 0;
   1135 	pmap_remove(pmap_kernel(), (vaddr_t)vmmap, (vaddr_t)&vmmap[PAGE_SIZE]);
   1136 	pmap_update(pmap_kernel());
   1137 	ecacheon();
   1138 	splx(s);
   1139 	return found;
   1140 }
   1141 
   1142 /*
   1143  * cpu_exec_aout_makecmds():
   1144  *	CPU-dependent a.out format hook for execve().
   1145  *
   1146  * Determine of the given exec package refers to something which we
   1147  * understand and, if so, set up the vmcmds for it.
   1148  *
   1149  * XXX what are the special cases for the hp300?
   1150  * XXX why is this COMPAT_NOMID?  was something generating
   1151  *	hp300 binaries with an a_mid of 0?  i thought that was only
   1152  *	done on little-endian machines...  -- cgd
   1153  */
   1154 int
   1155 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
   1156 {
   1157 #if defined(COMPAT_NOMID) || defined(COMPAT_44)
   1158 	u_long midmag, magic;
   1159 	u_short mid;
   1160 	int error;
   1161 	struct exec *execp = epp->ep_hdr;
   1162 
   1163 	midmag = ntohl(execp->a_midmag);
   1164 	mid = (midmag >> 16) & 0xffff;
   1165 	magic = midmag & 0xffff;
   1166 
   1167 	midmag = mid << 16 | magic;
   1168 
   1169 	switch (midmag) {
   1170 #ifdef COMPAT_NOMID
   1171 	case (MID_ZERO << 16) | ZMAGIC:
   1172 		error = exec_aout_prep_oldzmagic(l, epp);
   1173 		return error;
   1174 #endif
   1175 #ifdef COMPAT_44
   1176 	case (MID_HP300 << 16) | ZMAGIC:
   1177 		error = exec_aout_prep_oldzmagic(l, epp);
   1178 		return error;
   1179 #endif
   1180 	}
   1181 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
   1182 
   1183 	return ENOEXEC;
   1184 }
   1185 
   1186 int
   1187 mm_md_physacc(paddr_t pa, vm_prot_t prot)
   1188 {
   1189 
   1190 	/*
   1191 	 * On the hp300, physical RAM is always located at the end of
   1192 	 * the physical address space, i.e. from 0xffffffff to lowram.
   1193 	 */
   1194 	return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0;
   1195 }
   1196 
   1197 int
   1198 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
   1199 {
   1200 
   1201 	/*
   1202 	 * Do not allow reading intio or dio device space.  This could lead
   1203 	 * to corruption of device registers.
   1204 	 */
   1205 	*handled = false;
   1206 	return (ISIIOVA(ptr) || ((uint8_t *)ptr >= extiobase &&
   1207 	    (uint8_t *)ptr < extiobase + (EIOMAPSIZE * PAGE_SIZE)))
   1208 	    ? EFAULT : 0;
   1209 }
   1210 
   1211 #ifdef MODULAR
   1212 /*
   1213  * Push any modules loaded by the bootloader etc.
   1214  */
   1215 void
   1216 module_init_md(void)
   1217 {
   1218 }
   1219 #endif
   1220