Home | History | Annotate | Line # | Download | only in sun3
      1 /*	$NetBSD: sunmon.c,v 1.24 2024/01/13 18:51:38 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Adam Glass and Gordon W. Ross.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: sunmon.c,v 1.24 2024/01/13 18:51:38 thorpej Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/reboot.h>
     38 #include <sys/boot_flag.h>
     39 
     40 #include <machine/mon.h>
     41 #include <machine/mc68851.h>
     42 #include <machine/vectors.h>
     43 
     44 #include <m68k/frame.h>
     45 
     46 #include <sun3/sun3/machdep.h>
     47 #include <sun3/sun3/interreg.h>
     48 
     49 static void **sunmon_vbr;
     50 static void *sunmon_vcmd;	/* XXX: always 0? */
     51 
     52 static void tracedump(int);
     53 static void v_handler(int, char *);
     54 
     55 /*
     56  * Prepare for running the PROM monitor
     57  */
     58 static void
     59 _mode_monitor(void)
     60 {
     61 	/* Disable our level-5 clock. */
     62 	set_clk_mode(0, IREG_CLOCK_ENAB_5, 0);
     63 	/* Restore the PROM vector table */
     64 	setvbr(sunmon_vbr);
     65 	/* Enable the PROM NMI clock. */
     66 	set_clk_mode(IREG_CLOCK_ENAB_7, 0, 1);
     67 	/* XXX - Disable watchdog action? */
     68 }
     69 
     70 /*
     71  * Prepare for running the kernel
     72  */
     73 static void
     74 _mode_kernel(void)
     75 {
     76 	/* Disable the PROM NMI clock. */
     77 	set_clk_mode(0, IREG_CLOCK_ENAB_7, 0);
     78 	/* Restore our own vector table */
     79 	setvbr(vectab);
     80 	/* Enable our level-5 clock. */
     81 	set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1);
     82 }
     83 
     84 /*
     85  * This function takes care of restoring enough of the
     86  * hardware state to allow the PROM to run normally.
     87  * The PROM needs: NMI enabled, its own vector table.
     88  * In case of a temporary "drop into PROM", this will
     89  * also put our hardware state back into place after
     90  * the PROM "c" (continue) command is given.
     91  */
     92 void
     93 sunmon_abort(void)
     94 {
     95 	int s = splhigh();
     96 #ifdef	_SUN3X_
     97 	struct mmu_rootptr crp;
     98 #endif
     99 
    100 	_mode_monitor();
    101 	delay(100000);
    102 
    103 #ifdef	_SUN3X_
    104 	getcrp(&crp);
    105 	loadcrp(&mon_crp);
    106 #endif
    107 
    108 	/*
    109 	 * Drop into the PROM in a way that allows a continue.
    110 	 * Already setup "trap #14" in sunmon_init().
    111 	 */
    112 
    113 	__asm(" trap #14 ; _sunmon_continued: nop");
    114 
    115 	/* We have continued from a PROM abort! */
    116 #ifdef	_SUN3X_
    117 	loadcrp(&crp);
    118 #endif
    119 	_mode_kernel();
    120 	splx(s);
    121 }
    122 
    123 void
    124 sunmon_halt(void)
    125 {
    126 	(void) splhigh();
    127 	_mode_monitor();
    128 	*romVectorPtr->vector_cmd = sunmon_vcmd;
    129 #ifdef	_SUN3X_
    130 	loadcrp(&mon_crp);
    131 	/*
    132 	 * The PROM monitor "exit_to_mon" function appears to have problems...
    133 	 * SunOS uses the "abort" function when you halt (bug work-around?)
    134 	 * so we might as well do the same.
    135 	 */
    136 	__asm(" trap #14"); /* mon_exit_to_mon() provokes PROM monitor bug */
    137 #endif
    138 	mon_exit_to_mon();
    139 	/*NOTREACHED*/
    140 }
    141 
    142 /*
    143  * Caller must pass a string that is in our data segment.
    144  */
    145 void
    146 sunmon_reboot(const char *bs)
    147 {
    148 
    149 	(void) splhigh();
    150 	_mode_monitor();
    151 	*romVectorPtr->vector_cmd = sunmon_vcmd;
    152 #ifdef	_SUN3X_
    153 	loadcrp(&mon_crp);
    154 #endif
    155 	mon_reboot(bs);
    156 	mon_exit_to_mon();
    157 	/*NOTREACHED*/
    158 }
    159 
    160 
    161 /*
    162  * Print out a traceback for the caller - can be called anywhere
    163  * within the kernel or from the monitor by typing "g4" (for sun-2
    164  * compatibility) or "w trace".  This causes the monitor to call
    165  * the v_handler() routine which will call tracedump() for these cases.
    166  */
    167 struct funcall_frame {
    168 	struct funcall_frame *fr_savfp;
    169 	int fr_savpc;
    170 	int fr_arg[1];
    171 };
    172 /*VARARGS0*/
    173 static void __noinline
    174 tracedump(int x1)
    175 {
    176 	struct funcall_frame *fp = (struct funcall_frame *)(&x1 - 2);
    177 	u_int stackpage = ((u_int)fp) & ~PGOFSET;
    178 
    179 	mon_printf("Begin traceback...fp = 0x%x\n", fp);
    180 	do {
    181 		if (fp == fp->fr_savfp) {
    182 			mon_printf("FP loop at 0x%x", fp);
    183 			break;
    184 		}
    185 		mon_printf("Called from 0x%x, fp=0x%x, args=0x%x 0x%x 0x%x 0x%x\n",
    186 				   fp->fr_savpc, fp->fr_savfp,
    187 				   fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
    188 		fp = fp->fr_savfp;
    189 	} while ( (((u_int)fp) & ~PGOFSET) == stackpage);
    190 	mon_printf("End traceback...\n");
    191 }
    192 
    193 /*
    194  * Handler for monitor vector cmd -
    195  * For now we just implement the old "g0" and "g4"
    196  * commands and a printf hack.
    197  * [lifted from freed cmu mach3 sun3 port]
    198  */
    199 static void
    200 v_handler(int addr, char *str)
    201 {
    202 
    203 	switch (*str) {
    204 	case '\0':
    205 		/*
    206 		 * No (non-hex) letter was specified on
    207 		 * command line, use only the number given
    208 		 */
    209 		switch (addr) {
    210 		case 0:			/* old g0 */
    211 		case 0xd:		/* 'd'ump short hand */
    212 			_mode_kernel();
    213 			panic("zero");
    214 			/*NOTREACHED*/
    215 
    216 		case 4:			/* old g4 */
    217 			goto do_trace;
    218 
    219 		default:
    220 			goto err;
    221 		}
    222 		break;
    223 
    224 	case 'p':			/* 'p'rint string command */
    225 	case 'P':
    226 		mon_printf("%s\n", (char *)addr);
    227 		break;
    228 
    229 	case '%':			/* p'%'int anything a la printf */
    230 		mon_printf(str, addr);
    231 		mon_printf("\n");
    232 		break;
    233 
    234 	do_trace:
    235 	case 't':			/* 't'race kernel stack */
    236 	case 'T':
    237 		tracedump(addr);
    238 		break;
    239 
    240 	case 'u':			/* d'u'mp hack ('d' look like hex) */
    241 	case 'U':
    242 		goto err;
    243 		break;
    244 
    245 	default:
    246 	err:
    247 		mon_printf("Don't understand 0x%x '%s'\n", addr, str);
    248 	}
    249 }
    250 
    251 /*
    252  * Set the PROM vector handler (for g0, g4, etc.)
    253  * and set boothowto from the PROM arg strings.
    254  *
    255  * Note, args are always:
    256  * argv[0] = boot_device	(i.e. "sd(0,0,0)")
    257  * argv[1] = options	(i.e. "-ds" or NULL)
    258  * argv[2] = NULL
    259  */
    260 void
    261 sunmon_init(void)
    262 {
    263 	struct sunromvec *rvec;
    264 	struct bootparam *bp;
    265 	char **argp;
    266 	char *p;
    267 
    268 	rvec = romVectorPtr;
    269 	bp = *rvec->bootParam;
    270 
    271 	/* Save the PROM monitor Vector Base Register (VBR). */
    272 	sunmon_vbr = getvbr();
    273 
    274 	/* Arrange for "trap #14" to cause a PROM abort. */
    275 	sunmon_vbr[32+14] = romVectorPtr->abortEntry;
    276 
    277 	/* Save and replace the "v command" handler. */
    278 	sunmon_vcmd = *rvec->vector_cmd;
    279 	if (rvec->romvecVersion >= 2)
    280 		*rvec->vector_cmd = v_handler;
    281 
    282 	/* Set boothowto flags from PROM args. */
    283 	argp = bp->argPtr;
    284 
    285 	/* Skip argp[0] (the device string) */
    286 	argp++;
    287 
    288 	/* Have options? */
    289 	if (*argp == NULL)
    290 		return;
    291 	p = *argp;
    292 	if (*p == '-') {
    293 		/* yes, parse options */
    294 #ifdef	DEBUG
    295 		mon_printf("boot option: %s\n", p);
    296 #endif
    297 		for (++p; *p; p++)
    298 			BOOT_FLAG(*p, boothowto);
    299 		argp++;
    300 	}
    301 
    302 #ifdef	DEBUG
    303 	/* Have init name? */
    304 	if (*argp == NULL)
    305 		return;
    306 	p = *argp;
    307 	mon_printf("boot initpath: %s\n", p);
    308 #endif
    309 }
    310