Home | History | Annotate | Line # | Download | only in cesfic
      1 /*	$NetBSD: machdep.c,v 1.74 2024/03/05 14:15:29 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988 University of Utah.
      5  * Copyright (c) 1982, 1986, 1990, 1993
      6  *	The Regents of the University of California.  All rights reserved.
      7  *
      8  * This code is derived from software contributed to Berkeley by
      9  * the Systems Programming Group of the University of Utah Computer
     10  * Science Department.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  * from: Utah $Hdr: machdep.c 1.74 92/12/20$
     37  *
     38  *	@(#)machdep.c	8.10 (Berkeley) 4/20/94
     39  */
     40 
     41 #include <sys/cdefs.h>
     42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.74 2024/03/05 14:15:29 thorpej Exp $");
     43 
     44 #include "opt_bufcache.h"
     45 #include "opt_ddb.h"
     46 #include "opt_kgdb.h"
     47 #include "opt_compat_netbsd.h"
     48 #include "opt_sysv.h"
     49 #include "opt_panicbutton.h"
     50 #include "opt_modular.h"
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/buf.h>
     55 #include <sys/callout.h>
     56 #include <sys/conf.h>
     57 #include <sys/exec.h>
     58 #include <sys/exec_aout.h>		/* for MID_* */
     59 #include <sys/file.h>
     60 #include <sys/ioctl.h>
     61 #include <sys/kernel.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/vnode.h>
     71 #include <sys/ksyms.h>
     72 #include <sys/module.h>
     73 #include <sys/cpu.h>
     74 #include <sys/kgdb.h>
     75 
     76 #include <machine/db_machdep.h>
     77 #include <ddb/db_sym.h>
     78 #include <ddb/db_extern.h>
     79 
     80 #include <machine/autoconf.h>
     81 #include <machine/cpu.h>
     82 #include <machine/reg.h>
     83 #include <machine/pcb.h>
     84 #include <machine/psl.h>
     85 #include <machine/pte.h>
     86 
     87 #define	MAXMEM	64*1024	/* XXX - from cmap.h */
     88 
     89 #include <uvm/uvm_extern.h>
     90 
     91 #include <sys/sysctl.h>
     92 #include <sys/device.h>
     93 #include <dev/cons.h>
     94 #include <dev/mm.h>
     95 #include <dev/ic/z8530reg.h>
     96 #include <machine/z8530var.h>
     97 #include <cesfic/dev/zsvar.h>
     98 
     99 #include "ksyms.h"
    100 
    101 /* the following is used externally (sysctl_hw) */
    102 char machine[] = MACHINE;		/* CPU "architecture" */
    103 
    104 /* Our exported CPU info; we can have only one. */
    105 struct cpu_info cpu_info_store;
    106 
    107 struct vm_map *phys_map = NULL;
    108 
    109 /*
    110  * Declare these as initialized data so we can patch them.
    111  */
    112 /*int	maxmem;*/			/* max memory per process */
    113 extern psize_t physmem;			/* max supported memory, changes to actual */
    114 
    115 extern	u_int lowram;
    116 
    117 void fic_init(void);
    118 
    119 /* prototypes for local functions */
    120 void    identifycpu(void);
    121 char	*hexstr(int, int);
    122 
    123 /* functions called from locore.s */
    124 void    dumpsys(void);
    125 void    straytrap(int, u_short);
    126 void	nmihand(struct frame);
    127 
    128 int	delay_divisor;		/* delay constant */
    129 
    130 extern void sicinit(void*);
    131 
    132 void fic_init(void)
    133 {
    134 	int i;
    135 
    136 	extern paddr_t avail_start, avail_end;
    137 
    138 	boothowto = RB_SINGLE; /* XXX for now */
    139 	boothowto |= RB_KDB; /* XXX for now */
    140 
    141 	delay_divisor = 30; /* XXX */
    142 
    143 	/*
    144 	 * Tell the VM system about available physical memory.  The
    145 	 * fic uses one segment.
    146 	 */
    147 	uvm_page_physload(atop(avail_start), atop(avail_end),
    148 	    atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT);
    149 
    150 	/*
    151 	 * map and init interrupt controller
    152 	 */
    153 	physaccess((void*)virtual_avail, (void*)0x44000000,
    154 	    PAGE_SIZE, PG_RW|PG_CI);
    155 	sicinit((void*)virtual_avail);
    156 	virtual_avail += PAGE_SIZE;
    157 
    158 	/*
    159 	 * Initialize error message buffer (at end of core).
    160 	 * avail_end was pre-decremented in pmap_bootstrap to compensate.
    161 	 */
    162 	for (i = 0; i < btoc(MSGBUFSIZE); i++)
    163 		pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * PAGE_SIZE,
    164 		    avail_end + i * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE,
    165 		    VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED);
    166 	pmap_update(pmap_kernel());
    167 	initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE));
    168 }
    169 
    170 int
    171 zs_check_kgdb(struct zs_chanstate *cs, int dev)
    172 {
    173 
    174 	if((boothowto & RB_KDB) && (dev == makedev(10, 0)))
    175 		return (1);
    176 	return (0);
    177 }
    178 
    179 void zs_kgdb_cnputc(dev_t, int);
    180 void zs_kgdb_cnputc(dev_t dev, int c)
    181 {
    182 	zscnputc(dev, c);
    183 }
    184 int zs_kgdb_cngetc(dev_t);
    185 int zs_kgdb_cngetc(dev_t dev)
    186 {
    187 	return (zscngetc(dev));
    188 }
    189 
    190 /*
    191  * Console initialization: called early on from main,
    192  * before vm init or startup.  Do enough configuration
    193  * to choose and initialize a console.
    194  */
    195 extern void sic_enable_int(int, int, int, int, int);
    196 void
    197 consinit(void)
    198 {
    199 
    200 	/*
    201 	 * Initialize the console before we print anything out.
    202 	 */
    203 	physaccess((void*)virtual_avail,
    204 	    (void*)0x58000000, PAGE_SIZE, PG_RW|PG_CI);
    205 	zs_cnattach((void*)virtual_avail);
    206 	virtual_avail += PAGE_SIZE;
    207 
    208 #ifdef KGDB
    209         kgdb_dev = 1;
    210         kgdb_attach((void*)zscngetc, (void*)zscnputc, (void *)0);
    211 
    212 	if (boothowto & RB_KDB) {
    213 		kgdb_connect(1);
    214 		zscons.cn_putc = zs_kgdb_cnputc;
    215 		zscons.cn_getc = zs_kgdb_cngetc;
    216 	}
    217 #endif
    218 #ifdef DDB
    219 	if (boothowto & RB_KDB)
    220 		Debugger();
    221 #endif
    222 	sic_enable_int(39, 2, 1, 7, 0); /* NMI */
    223 }
    224 
    225 /*
    226  * cpu_startup: allocate memory for variable-sized tables,
    227  * initialize CPU, and do autoconfiguration.
    228  */
    229 void
    230 cpu_startup(void)
    231 {
    232 	vaddr_t minaddr, maxaddr;
    233 #ifdef DEBUG
    234 	extern int pmapdebug;
    235 	int opmapdebug = pmapdebug;
    236 
    237 	pmapdebug = 0;
    238 #endif
    239 
    240 	cpu_setmodel("FIC8234");
    241 	if (fputype != FPU_NONE)
    242 		m68k_make_fpu_idle_frame();
    243 
    244 	/*
    245 	 * Good {morning,afternoon,evening,night}.
    246 	 */
    247 	printf("%s%s", copyright, version);
    248 	identifycpu();
    249 	printf("real mem  = %d\n", ctob(physmem));
    250 
    251 	minaddr = 0;
    252 
    253 	/*
    254 	 * Allocate a submap for physio
    255 	 */
    256 	phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    257 				   VM_PHYS_SIZE, 0, false, NULL);
    258 
    259 #ifdef DEBUG
    260 	pmapdebug = opmapdebug;
    261 #endif
    262 	printf("avail mem = %ld\n", ptoa(uvm_availmem(false)));
    263 }
    264 
    265 /*
    266  * Info for CTL_HW
    267  */
    268 
    269 void
    270 identifycpu(void)
    271 {
    272 	printf("%s\n", cpu_getmodel());
    273 	printf("delay constant: %d\n", delay_divisor);
    274 }
    275 
    276 /*
    277  * machine dependent system variables.
    278  */
    279 SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
    280 {
    281 
    282 	sysctl_createv(clog, 0, NULL, NULL,
    283 		       CTLFLAG_PERMANENT,
    284 		       CTLTYPE_NODE, "machdep", NULL,
    285 		       NULL, 0, NULL, 0,
    286 		       CTL_MACHDEP, CTL_EOL);
    287 
    288 	sysctl_createv(clog, 0, NULL, NULL,
    289 		       CTLFLAG_PERMANENT,
    290 		       CTLTYPE_STRUCT, "console_device", NULL,
    291 		       sysctl_consdev, 0, NULL, sizeof(dev_t),
    292 		       CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
    293 }
    294 
    295 int	waittime = -1;
    296 
    297 void
    298 cpu_reboot(int howto, char *bootstr)
    299 {
    300 	struct pcb *pcb = lwp_getpcb(curlwp);
    301 
    302 	/* take a snap shot before clobbering any registers */
    303 	if (pcb != NULL)
    304 		savectx(pcb);
    305 
    306 	/* If system is cold, just halt. */
    307 	if (cold) {
    308 		howto |= RB_HALT;
    309 		goto haltsys;
    310 	}
    311 
    312 	boothowto = howto;
    313 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
    314 		waittime = 0;
    315 		vfs_shutdown();
    316 	}
    317 
    318 	/* Disable interrupts. */
    319 	splhigh();
    320 
    321 	/* If rebooting and a dump is requested do it. */
    322 	if (howto & RB_DUMP)
    323 		dumpsys();
    324 
    325  haltsys:
    326 	/* Run any shutdown hooks. */
    327 	doshutdownhooks();
    328 
    329 	pmf_system_shutdown(boothowto);
    330 
    331 #if defined(PANICWAIT) && !defined(DDB)
    332 	if ((howto & RB_HALT) == 0 && panicstr) {
    333 		printf("hit any key to reboot...\n");
    334 		cnpollc(1);
    335 		(void)cngetc();
    336 		cnpollc(0);
    337 		printf("\n");
    338 	}
    339 #endif
    340 
    341 	/* Finally, halt/reboot the system. */
    342 	if (howto & RB_HALT) {
    343 		printf("System halted.  Hit any key to reboot.\n\n");
    344 		cnpollc(1);
    345 		(void)cngetc();
    346 		cnpollc(0);
    347 	}
    348 
    349 	printf("rebooting...\n");
    350 	DELAY(1000000);
    351 	doboot();
    352 	/*NOTREACHED*/
    353 }
    354 
    355 /*
    356  * These variables are needed by /sbin/savecore
    357  */
    358 u_int32_t dumpmag = 0x8fca0101;	/* magic number */
    359 int	dumpsize = 0;		/* pages */
    360 long	dumplo = 0;		/* blocks */
    361 
    362 /*
    363  * This is called by main to set dumplo and dumpsize.
    364  * Dumps always skip the first CLBYTES of disk space
    365  * in case there might be a disk label stored there.
    366  * If there is extra space, put dump at the end to
    367  * reduce the chance that swapping trashes it.
    368  */
    369 void
    370 cpu_dumpconf(void)
    371 {
    372 	int nblks;	/* size of dump area */
    373 
    374 	if (dumpdev == NODEV)
    375 		return;
    376 	nblks = bdev_size(dumpdev);
    377 	if (nblks <= ctod(1))
    378 		return;
    379 
    380 	/*
    381 	 * XXX include the final RAM page which is not included in physmem.
    382 	 */
    383 	dumpsize = physmem + 1;
    384 
    385 	/* Always skip the first CLBYTES, in case there is a label there. */
    386 	if (dumplo < ctod(1))
    387 		dumplo = ctod(1);
    388 
    389 	/* Put dump at end of partition, and make it fit. */
    390 	if (dumpsize > dtoc(nblks - dumplo))
    391 		dumpsize = dtoc(nblks - dumplo);
    392 	if (dumplo < nblks - ctod(dumpsize))
    393 		dumplo = nblks - ctod(dumpsize);
    394 }
    395 
    396 /*
    397  * Dump physical memory onto the dump device.  Called by doadump()
    398  * in locore.s or by cpu_reboot() here in machdep.c
    399  */
    400 void
    401 dumpsys(void)
    402 {
    403 	const struct bdevsw *bdev;
    404 	daddr_t blkno;		/* current block to write */
    405 				/* dump routine */
    406 	int (*dump)(dev_t, daddr_t, void *, size_t);
    407 	int pg;			/* page being dumped */
    408 	vm_offset_t maddr;	/* PA being dumped */
    409 	int error;		/* error code from (*dump)() */
    410 
    411 	/* Don't put dump messages in msgbuf. */
    412 	msgbufmapped = 0;
    413 
    414 	/* Make sure dump device is valid. */
    415 	if (dumpdev == NODEV)
    416 		return;
    417 	bdev = bdevsw_lookup(dumpdev);
    418 	if (bdev == NULL)
    419 		return;
    420 	if (dumpsize == 0) {
    421 		cpu_dumpconf();
    422 		if (dumpsize == 0)
    423 			return;
    424 	}
    425 	if (dumplo < 0)
    426 		return;
    427 	dump = bdev->d_dump;
    428 	blkno = dumplo;
    429 
    430 	printf("\ndumping to dev %"PRIx64", offset %ld\n", dumpdev, dumplo);
    431 
    432 	printf("dump ");
    433 	maddr = lowram;
    434 	for (pg = 0; pg < dumpsize; pg++) {
    435 #define NPGMB	(1024*1024/PAGE_SIZE)
    436 		/* print out how many MBs we have dumped */
    437 		if (pg && (pg % NPGMB) == 0)
    438 			printf("%d ", pg / NPGMB);
    439 #undef NPGMB
    440 		pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, maddr,
    441 		    VM_PROT_READ, VM_PROT_READ|PMAP_WIRED);
    442 		pmap_update(pmap_kernel());
    443 
    444 		error = (*dump)(dumpdev, blkno, vmmap, PAGE_SIZE);
    445 		switch (error) {
    446 		case 0:
    447 			maddr += PAGE_SIZE;
    448 			blkno += btodb(PAGE_SIZE);
    449 			break;
    450 
    451 		case ENXIO:
    452 			printf("device bad\n");
    453 			return;
    454 
    455 		case EFAULT:
    456 			printf("device not ready\n");
    457 			return;
    458 
    459 		case EINVAL:
    460 			printf("area improper\n");
    461 			return;
    462 
    463 		case EIO:
    464 			printf("i/o error\n");
    465 			return;
    466 
    467 		case EINTR:
    468 			printf("aborted from console\n");
    469 			return;
    470 
    471 		default:
    472 			printf("error %d\n", error);
    473 			return;
    474 		}
    475 	}
    476 	printf("succeeded\n");
    477 }
    478 
    479 void
    480 straytrap(int pc, u_short evec)
    481 {
    482 	printf("unexpected trap (vector offset %x) from %x\n",
    483 	       evec & 0xFFF, pc);
    484 }
    485 
    486 /* XXX should change the interface, and make one badaddr() function */
    487 
    488 int	*nofault;
    489 
    490 int
    491 badaddr(void *addr)
    492 {
    493 	int i;
    494 	label_t	faultbuf;
    495 
    496 	nofault = (int *) &faultbuf;
    497 	if (setjmp((label_t *)nofault)) {
    498 		nofault = (int *) 0;
    499 		return (1);
    500 	}
    501 	i = *(volatile short *)addr;
    502 	__USE(i);
    503 	nofault = (int *) 0;
    504 	return (0);
    505 }
    506 
    507 int
    508 badbaddr(void *addr)
    509 {
    510 	int i;
    511 	label_t	faultbuf;
    512 
    513 	nofault = (int *) &faultbuf;
    514 	if (setjmp((label_t *)nofault)) {
    515 		nofault = (int *) 0;
    516 		return (1);
    517 	}
    518 	i = *(volatile char *)addr;
    519 	__USE(i);
    520 	nofault = (int *) 0;
    521 	return (0);
    522 }
    523 
    524 #ifdef PANICBUTTON
    525 /*
    526  * Declare these so they can be patched.
    527  */
    528 int panicbutton = 1;	/* non-zero if panic buttons are enabled */
    529 int candbdiv = 2;	/* give em half a second (hz / candbdiv) */
    530 
    531 void	candbtimer(void *);
    532 
    533 int crashandburn;
    534 
    535 void
    536 candbtimer(void *arg)
    537 {
    538 
    539 	crashandburn = 0;
    540 }
    541 #endif /* PANICBUTTON */
    542 
    543 static int innmihand;	/* simple mutex */
    544 
    545 /*
    546  * Level 7 interrupts can be caused by the keyboard or parity errors.
    547  */
    548 void
    549 nmihand(struct frame frame)
    550 {
    551 
    552 	/* Prevent unwanted recursion. */
    553 	if (innmihand)
    554 		return;
    555 	innmihand = 1;
    556 
    557 	printf("NMI\n");
    558 #if defined(DDB) || defined(KGDB)
    559 	Debugger();
    560 #endif
    561 
    562 	innmihand = 0;
    563 }
    564 
    565 
    566 /*
    567  * cpu_exec_aout_makecmds():
    568  *	CPU-dependent a.out format hook for execve().
    569  *
    570  * Determine of the given exec package refers to something which we
    571  * understand and, if so, set up the vmcmds for it.
    572  *
    573  * XXX what are the special cases for the hp300?
    574  * XXX why is this COMPAT_NOMID?  was something generating
    575  *	hp300 binaries with an a_mid of 0?  i thought that was only
    576  *	done on little-endian machines...  -- cgd
    577  */
    578 int
    579 cpu_exec_aout_makecmds(struct lwp *l, struct exec_package *epp)
    580 {
    581 #if defined(COMPAT_NOMID) || defined(COMPAT_44)
    582 	u_long midmag, magic;
    583 	u_short mid;
    584 	int error;
    585 	struct exec *execp = epp->ep_hdr;
    586 
    587 	midmag = ntohl(execp->a_midmag);
    588 	mid = (midmag >> 16) & 0xffff;
    589 	magic = midmag & 0xffff;
    590 
    591 	midmag = mid << 16 | magic;
    592 
    593 	switch (midmag) {
    594 #ifdef COMPAT_NOMID
    595 	case (MID_ZERO << 16) | ZMAGIC:
    596 		error = exec_aout_prep_oldzmagic(l, epp);
    597 		return (error);
    598 #endif
    599 #ifdef COMPAT_44
    600 	case (MID_HP300 << 16) | ZMAGIC:
    601 		error = exec_aout_prep_oldzmagic(l, epp);
    602 		return (error);
    603 #endif
    604 	}
    605 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */
    606 
    607 	return ENOEXEC;
    608 }
    609 
    610 int
    611 mm_md_physacc(paddr_t pa, vm_prot_t prot)
    612 {
    613 
    614 	return (pa < lowram || pa >= 0xfffffffc) ? EFAULT : 0;
    615 }
    616 
    617 #ifdef MODULAR
    618 /*
    619  * Push any modules loaded by the bootloader etc.
    620  */
    621 void
    622 module_init_md(void)
    623 {
    624 }
    625 #endif
    626