Home | History | Annotate | Line # | Download | only in newsmips
      1 /*	$NetBSD: machdep.c,v 1.123 2024/03/05 14:15:33 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988 University of Utah.
      5  * Copyright (c) 1992, 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, The Mach Operating System project at
     11  * Carnegie-Mellon University and Ralph Campbell.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  * 1. Redistributions of source code must retain the above copyright
     17  *    notice, this list of conditions and the following disclaimer.
     18  * 2. Redistributions in binary form must reproduce the above copyright
     19  *    notice, this list of conditions and the following disclaimer in the
     20  *    documentation and/or other materials provided with the distribution.
     21  * 3. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  *
     37  *	@(#)machdep.c	8.3 (Berkeley) 1/12/94
     38  */
     39 
     40 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     41 
     42 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.123 2024/03/05 14:15:33 thorpej Exp $");
     43 
     44 /* from: Utah Hdr: machdep.c 1.63 91/04/24 */
     45 
     46 #include "opt_ddb.h"
     47 #include "opt_execfmt.h"
     48 #include "opt_modular.h"
     49 
     50 #define __INTR_PRIVATE
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/signalvar.h>
     55 #include <sys/kernel.h>
     56 #include <sys/proc.h>
     57 #include <sys/buf.h>
     58 #include <sys/reboot.h>
     59 #include <sys/conf.h>
     60 #include <sys/file.h>
     61 #include <sys/mbuf.h>
     62 #include <sys/msgbuf.h>
     63 #include <sys/ioctl.h>
     64 #include <sys/device.h>
     65 #include <sys/exec.h>
     66 #include <sys/mount.h>
     67 #include <sys/syscallargs.h>
     68 #include <sys/kcore.h>
     69 #include <sys/ksyms.h>
     70 #include <sys/cpu.h>
     71 #include <sys/intr.h>
     72 
     73 #include <uvm/uvm_extern.h>
     74 
     75 #include <ufs/mfs/mfs_extern.h>		/* mfs_initminiroot() */
     76 
     77 #include <mips/cache.h>
     78 #include <mips/locore.h>
     79 
     80 #include <machine/reg.h>
     81 #include <machine/psl.h>
     82 #include <machine/pte.h>
     83 #include <machine/autoconf.h>
     84 #include <machine/bootinfo.h>
     85 #include <machine/apbus.h>
     86 #include <machine/apcall.h>
     87 
     88 
     89 #define	_NEWSMIPS_BUS_DMA_PRIVATE
     90 #include <machine/bus.h>
     91 
     92 #ifdef DDB
     93 #include <machine/db_machdep.h>
     94 #include <ddb/db_access.h>
     95 #include <ddb/db_extern.h>
     96 #include <ddb/db_sym.h>
     97 #endif
     98 
     99 #include <machine/adrsmap.h>
    100 #include <machine/machConst.h>
    101 #include <newsmips/newsmips/machid.h>
    102 #include <dev/cons.h>
    103 
    104 #include "ksyms.h"
    105 
    106 /* maps for VM objects */
    107 
    108 struct vm_map *phys_map = NULL;
    109 
    110 char *bootinfo = NULL;		/* pointer to bootinfo structure */
    111 int systype;			/* what type of NEWS we are */
    112 struct apbus_sysinfo *_sip = NULL;
    113 void *sccport0a;
    114 
    115 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
    116 int mem_cluster_cnt;
    117 
    118 struct idrom idrom;
    119 void (*hardware_intr)(int, vaddr_t, uint32_t);
    120 void (*enable_intr)(void);
    121 void (*disable_intr)(void);
    122 void (*enable_timer)(void);
    123 
    124 /*
    125  *  Local functions.
    126  */
    127 
    128 /* initialize bss, etc. from kernel start, before main() is called. */
    129 void mach_init(int, int, int, int);
    130 
    131 void prom_halt(int) __attribute__((__noreturn__));
    132 void to_monitor(int) __attribute__((__noreturn__));
    133 
    134 #ifdef DEBUG
    135 /* stacktrace code violates prototypes to get callee's registers */
    136 extern void stacktrace(void); /*XXX*/
    137 #endif
    138 
    139 extern u_long bootdev;
    140 extern char edata[], end[];
    141 
    142 /*
    143  * Do all the stuff that locore normally does before calling main().
    144  * Process arguments passed to us by the prom monitor.
    145  * Return the first page address following the system.
    146  */
    147 void
    148 mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem)
    149 {
    150 	u_long first, last;
    151 	char *kernend;
    152 	const char *model;
    153 	struct btinfo_magic *bi_magic;
    154 	struct btinfo_bootarg *bi_arg;
    155 	struct btinfo_systype *bi_systype;
    156 #if NKSYMS || defined(DDB) || defined(MODULAR)
    157 	struct btinfo_symtab *bi_sym;
    158 	int nsym = 0;
    159 	char *ssym, *esym;
    160 
    161 	ssym = esym = NULL;	/* XXX: gcc */
    162 #endif
    163 	bi_arg = NULL;
    164 
    165 	bootinfo = (void *)BOOTINFO_ADDR;	/* XXX */
    166 	bi_magic = lookup_bootinfo(BTINFO_MAGIC);
    167 	if (bi_magic && bi_magic->magic == BOOTINFO_MAGIC) {
    168 		bi_arg = lookup_bootinfo(BTINFO_BOOTARG);
    169 		if (bi_arg) {
    170 			x_boothowto = bi_arg->howto;
    171 			x_bootdev = bi_arg->bootdev;
    172 			x_maxmem = bi_arg->maxmem;
    173 		}
    174 #if NKSYMS || defined(DDB) || defined(MODULAR)
    175 		bi_sym = lookup_bootinfo(BTINFO_SYMTAB);
    176 		if (bi_sym) {
    177 			nsym = bi_sym->nsym;
    178 			ssym = (void *)bi_sym->ssym;
    179 			esym = (void *)bi_sym->esym;
    180 		}
    181 #endif
    182 
    183 		bi_systype = lookup_bootinfo(BTINFO_SYSTYPE);
    184 		if (bi_systype)
    185 			systype = bi_systype->type;
    186 	} else {
    187 		/*
    188 		 * Running kernel is loaded by non-native loader;
    189 		 * clear the BSS segment here.
    190 		 */
    191 		memset(edata, 0, end - edata);
    192 	}
    193 
    194 	if (systype == 0)
    195 		systype = NEWS3400;	/* XXX compatibility for old boot */
    196 
    197 #ifdef news3400
    198 	if (systype == NEWS3400) {
    199 		sccport0a = (void *)SCCPORT0A;
    200 	}
    201 #endif
    202 
    203 #if defined(news5000) || defined(news4000)
    204 	if (systype == NEWS5000 || systype == NEWS4000) {
    205 		int i;
    206 		char *bspec = (char *)x_bootdev;
    207 
    208 		if (bi_arg == NULL)
    209 			panic("%s requires BTINFO_BOOTARG to boot",
    210 			    systype == NEWS5000 ? "news5000" : "news4000");
    211 
    212 		_sip = (void *)bi_arg->sip;
    213 		x_maxmem = _sip->apbsi_memsize;
    214 		x_maxmem -= 0x00100000;	/* reserve 1MB for ROM monitor */
    215 		if (strncmp(bspec, "scsi", 4) == 0) {
    216 			x_bootdev = (5 << 28) | 0;	 /* magic, sd */
    217 			bspec += 4;
    218 			if (*bspec != '(' /*)*/)
    219 				goto bootspec_end;
    220 			i = strtoul(bspec + 1, &bspec, 10);
    221 			x_bootdev |= (i << 24);		/* bus */
    222 			if (*bspec != ',')
    223 				goto bootspec_end;
    224 			i = strtoul(bspec + 1, &bspec, 10);
    225 			x_bootdev |= (i / 10) << 20;	/* controller */
    226 			x_bootdev |= (i % 10) << 16;	/* unit */
    227 			if (*bspec != ',')
    228 				goto bootspec_end;
    229 			i = strtoul(bspec + 1, &bspec, 10);
    230 			x_bootdev |= (i << 8);		/* partition */
    231 		}
    232  bootspec_end:
    233 		sccport0a = (systype == NEWS5000) ?
    234 		    (void *)NEWS5000_SCCPORT0A : (void *)NEWS4000_SCCPORT0A;
    235 		consinit();
    236 	}
    237 #endif /* news5000 || news4000 */
    238 
    239 	/*
    240 	 * Save parameters into kernel work area.
    241 	 */
    242 	*(int *)(MIPS_PHYS_TO_KSEG1(MACH_MAXMEMSIZE_ADDR)) = x_maxmem;
    243 	*(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTDEV_ADDR)) = x_bootdev;
    244 	*(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTSW_ADDR)) = x_boothowto;
    245 
    246 	kernend = (char *)mips_round_page(end);
    247 #if NKSYMS || defined(DDB) || defined(MODULAR)
    248 	if (nsym)
    249 		kernend = (char *)mips_round_page(esym);
    250 #endif
    251 
    252 	uvm_md_init();
    253 
    254 	boothowto = x_boothowto;
    255 	bootdev = x_bootdev;
    256 	physmem = btoc(x_maxmem);
    257 
    258 	/*
    259 	 * Now that we know how much memory we have, initialize the
    260 	 * mem cluster array.
    261 	 */
    262 	mem_clusters[0].start = 0;		/* XXX is this correct? */
    263 	mem_clusters[0].size  = ctob(physmem);
    264 	mem_cluster_cnt = 1;
    265 
    266 	/*
    267 	 * Copy exception-dispatch code down to exception vector.
    268 	 * Initialize locore-function vector.
    269 	 * Clear out the I and D caches.
    270 	 */
    271 	mips_vector_init(NULL, false);
    272 
    273 	/*
    274 	 * We know the CPU type now.  Initialize our DMA tags (might
    275 	 * need this early).
    276 	 */
    277 	newsmips_bus_dma_init();
    278 
    279 #if NKSYMS || defined(DDB) || defined(MODULAR)
    280 	if (nsym)
    281 		ksyms_addsyms_elf(esym - ssym, ssym, esym);
    282 #endif
    283 
    284 #ifdef KADB
    285 	boothowto |= RB_KDB;
    286 #endif
    287 
    288 	/*
    289 	 * Check to see if a mini-root was loaded into memory. It resides
    290 	 * at the start of the next page just after the end of BSS.
    291 	 */
    292 	if (boothowto & RB_MINIROOT)
    293 		kernend += round_page(mfs_initminiroot(kernend));
    294 
    295 	/*
    296 	 * Load the rest of the available pages into the VM system.
    297 	 */
    298 	first = round_page(MIPS_KSEG0_TO_PHYS(kernend));
    299 	last = mem_clusters[0].start + mem_clusters[0].size;
    300 	uvm_page_physload(atop(first), atop(last), atop(first), atop(last),
    301 	    VM_FREELIST_DEFAULT);
    302 
    303 	/*
    304 	 * Initialize error message buffer (at end of core).
    305 	 */
    306 	mips_init_msgbuf();
    307 
    308 	/*
    309 	 * Initialize the virtual memory system.
    310 	 */
    311 	pmap_bootstrap();
    312 
    313 	/*
    314 	 * Allocate uarea page for lwp0 and set it.
    315 	 */
    316 	mips_init_lwp0_uarea();
    317 
    318 	/*
    319 	 * Determine what model of computer we are running on.
    320 	 */
    321 	switch (systype) {
    322 #ifdef news3400
    323 	case NEWS3400:
    324 		news3400_init();
    325 		cpu_setmodel("%s", idrom.id_machine);
    326 		model = cpu_getmodel();
    327 		if (strcmp(model, "news3400") == 0 ||
    328 		    strcmp(model, "news3200") == 0 ||
    329 		    strcmp(model, "news3700") == 0) {
    330 			/*
    331 			 * Set up interrupt handling and I/O addresses.
    332 			 */
    333 			hardware_intr = news3400_intr;
    334 			cpuspeed = 10;
    335 		} else {
    336 			printf("kernel not configured for machine %s\n", model);
    337 		}
    338 		break;
    339 #endif
    340 
    341 #ifdef news5000
    342 	case NEWS5000:
    343 		news5000_init();
    344 		cpu_setmodel("%s", idrom.id_machine);
    345 		model = cpu_getmodel();
    346 		if (strcmp(model, "news5000") == 0 ||
    347 		    strcmp(model, "news5900") == 0) {
    348 			/*
    349 			 * Set up interrupt handling and I/O addresses.
    350 			 */
    351 			hardware_intr = news5000_intr;
    352 			cpuspeed = 50;	/* ??? XXX */
    353 		} else {
    354 			printf("kernel not configured for machine %s\n", model);
    355 		}
    356 		break;
    357 #endif
    358 
    359 #ifdef news4000
    360 	case NEWS4000:
    361 		news4000_init();
    362 		cpu_setmodel("%s", idrom.id_machine);
    363 		model = cpu_getmodel();
    364 		if (strcmp(model, "news4000") == 0) {
    365 			/*
    366 			 * Set up interrupt handling and I/O addresses.
    367 			 */
    368 			hardware_intr = news4000_intr;
    369 			cpuspeed = 40;  /* ??? XXX */
    370 		} else {
    371 			printf("kernel not configured for machine %s\n", model);
    372 		}
    373 		break;
    374 #endif
    375 
    376 	default:
    377 		printf("kernel not configured for systype %d\n", systype);
    378 		break;
    379 	}
    380 }
    381 
    382 void
    383 mips_machdep_cache_config(void)
    384 {
    385 	/* All r4k news boxen have a 1MB L2 cache. */
    386 	if (CPUISMIPS3)
    387 		mips_cache_info.mci_sdcache_size = 1024 * 1024;
    388 }
    389 
    390 /*
    391  * cpu_startup: allocate memory for variable-sized tables,
    392  * initialize CPU, and do autoconfiguration.
    393  */
    394 void
    395 cpu_startup(void)
    396 {
    397 	printf("SONY NET WORK STATION, Model %s, ", idrom.id_model);
    398 	printf("Machine ID #%d\n", idrom.id_serial);
    399 
    400 	cpu_startup_common();
    401 }
    402 
    403 /*
    404  * lookup_bootinfo:
    405  * Look up information in bootinfo of boot loader.
    406  */
    407 void *
    408 lookup_bootinfo(int type)
    409 {
    410 	struct btinfo_common *bt;
    411 	char *help = bootinfo;
    412 
    413 	/* Check for a bootinfo record first. */
    414 	if (help == NULL)
    415 		return NULL;
    416 
    417 	do {
    418 		bt = (struct btinfo_common *)help;
    419 		if (bt->type == type)
    420 			return (void *)help;
    421 		help += bt->next;
    422 	} while (bt->next != 0 &&
    423 		(size_t)help < (size_t)bootinfo + BOOTINFO_SIZE);
    424 
    425 	return NULL;
    426 }
    427 
    428 /*
    429  * call PROM to halt or reboot.
    430  */
    431 void
    432 prom_halt(int howto)
    433 
    434 {
    435 #if defined(news5000) || defined(news4000)
    436 	if (systype == NEWS5000 || systype == NEWS4000)
    437 		apcall_exit(howto);
    438 #endif
    439 #ifdef news3400
    440 	if (systype == NEWS3400)
    441 		to_monitor(howto);
    442 #endif
    443 	for (;;);
    444 }
    445 
    446 int	waittime = -1;
    447 
    448 void
    449 cpu_reboot(volatile int howto, char *bootstr)
    450 {
    451 
    452 	/* take a snap shot before clobbering any registers */
    453 	savectx(curpcb);
    454 
    455 #ifdef DEBUG
    456 	if (panicstr)
    457 		stacktrace();
    458 #endif
    459 
    460 	/* If system is cold, just halt. */
    461 	if (cold) {
    462 		howto |= RB_HALT;
    463 		goto haltsys;
    464 	}
    465 
    466 	/* If "always halt" was specified as a boot flag, obey. */
    467 	if ((boothowto & RB_HALT) != 0)
    468 		howto |= RB_HALT;
    469 
    470 	boothowto = howto;
    471 	if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
    472 		/*
    473 		 * Synchronize the disks....
    474 		 */
    475 		waittime = 0;
    476 		vfs_shutdown();
    477 	}
    478 
    479 	/* Disable interrupts. */
    480 	disable_intr();
    481 
    482 	splhigh();
    483 
    484 	/* If rebooting and a dump is requested do it. */
    485 #if 0
    486 	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
    487 #else
    488 	if (howto & RB_DUMP)
    489 #endif
    490 		dumpsys();
    491 
    492 haltsys:
    493 
    494 	/* run any shutdown hooks */
    495 	doshutdownhooks();
    496 
    497 	pmf_system_shutdown(boothowto);
    498 
    499 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN)
    500 		prom_halt(0x80);	/* rom monitor RB_PWOFF */
    501 
    502 	/* Finally, halt/reboot the system. */
    503 	printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting...");
    504 	prom_halt(howto & RB_HALT);
    505 	/*NOTREACHED*/
    506 }
    507 
    508 void
    509 delay(int n)
    510 {
    511 
    512 	DELAY(n);
    513 }
    514 
    515 void
    516 cpu_intr(int ppl, vaddr_t pc, uint32_t status)
    517 {
    518 	curcpu()->ci_data.cpu_nintr++;
    519 
    520 	/* device interrupts */
    521 	(*hardware_intr)(ppl, pc, status);
    522 }
    523