Home | History | Annotate | Line # | Download | only in hpcmips
      1 /*	$NetBSD: machdep.c,v 1.126 2024/03/05 14:15:32 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999 Shin Takemura, All rights reserved.
      5  * Copyright (c) 1999-2001 SATO Kazumi, All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  *
     30  */
     31 
     32 /*
     33  * Copyright (c) 1988 University of Utah.
     34  * Copyright (c) 1992, 1993
     35  *	The Regents of the University of California.  All rights reserved.
     36  *
     37  * This code is derived from software contributed to Berkeley by
     38  * the Systems Programming Group of the University of Utah Computer
     39  * Science Department, The Mach Operating System project at
     40  * Carnegie-Mellon University and Ralph Campbell.
     41  *
     42  * Redistribution and use in source and binary forms, with or without
     43  * modification, are permitted provided that the following conditions
     44  * are met:
     45  * 1. Redistributions of source code must retain the above copyright
     46  *    notice, this list of conditions and the following disclaimer.
     47  * 2. Redistributions in binary form must reproduce the above copyright
     48  *    notice, this list of conditions and the following disclaimer in the
     49  *    documentation and/or other materials provided with the distribution.
     50  * 3. Neither the name of the University nor the names of its contributors
     51  *    may be used to endorse or promote products derived from this software
     52  *    without specific prior written permission.
     53  *
     54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     64  * SUCH DAMAGE.
     65  *
     66  * from: Utah Hdr: machdep.c 1.63 91/04/24
     67  *
     68  *	@(#)machdep.c	8.3 (Berkeley) 1/12/94
     69  */
     70 
     71 #include <sys/cdefs.h>
     72 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.126 2024/03/05 14:15:32 thorpej Exp $");
     73 
     74 #include "opt_vr41xx.h"
     75 #include "opt_tx39xx.h"
     76 #include "opt_boot_standalone.h"
     77 #include "opt_modular.h"
     78 #include "opt_spec_platform.h"
     79 #include "biconsdev.h"
     80 #include "opt_ddb.h"
     81 #include "opt_kgdb.h"
     82 #include "opt_rtc_offset.h"
     83 #include "opt_kloader.h"
     84 #include "opt_kloader_kernel_path.h"
     85 #include "debug_hpc.h"
     86 #include "opt_md.h"
     87 #include "opt_memsize.h"
     88 #include "opt_no_symbolsz_entry.h"
     89 
     90 #include <sys/param.h>
     91 #include <sys/systm.h>
     92 #include <sys/kernel.h>
     93 #include <sys/buf.h>
     94 #include <sys/reboot.h>
     95 #include <sys/mount.h>
     96 #include <sys/boot_flag.h>
     97 #include <sys/ksyms.h>
     98 #include <sys/device.h>
     99 #include <sys/lwp.h>
    100 #include <sys/cpu.h>
    101 
    102 #include <uvm/uvm_extern.h>
    103 
    104 #include <ufs/mfs/mfs_extern.h>	/* mfs_initminiroot() */
    105 #include <dev/cons.h>		/* cntab access (cpu_reboot) */
    106 
    107 #include <machine/locore.h>
    108 #include <machine/psl.h>
    109 #include <machine/sysconf.h>
    110 #include <machine/platid.h>
    111 #include <machine/platid_mask.h>
    112 #include <machine/kloader.h>
    113 #include <machine/debug.h>
    114 
    115 #ifdef KGDB
    116 #include <sys/kgdb.h>
    117 #endif
    118 
    119 #include "ksyms.h"
    120 
    121 #if NKSYMS || defined(DDB) || defined(MODULAR)
    122 #include <machine/db_machdep.h>
    123 #include <ddb/db_sym.h>
    124 #include <ddb/db_extern.h>
    125 #include <sys/exec_elf.h>
    126 #endif
    127 
    128 #if NBICONSDEV > 0
    129 #include <sys/conf.h>
    130 #include <dev/hpc/biconsvar.h>
    131 #include <dev/hpc/bicons.h>
    132 #define biconscnpollc	nullcnpollc
    133 cons_decl(bicons);
    134 static struct consdev bicons __attribute((__unused__)) = cons_init(bicons);
    135 static int __bicons_enable;
    136 #define DPRINTF(arg)	{ if (__bicons_enable) printf arg; }
    137 #else /* NBICONSDEV > 0 */
    138 #define DPRINTF(arg)
    139 #endif /* NBICONSDEV > 0 */
    140 
    141 #include <nfs/rpcv2.h>
    142 #include <nfs/nfsproto.h>
    143 #include <nfs/nfs.h>
    144 #include <nfs/nfsmount.h>
    145 
    146 #ifdef MEMORY_DISK_DYNAMIC
    147 #include <dev/md.h>
    148 #endif
    149 
    150 /* the following is used externally (sysctl_hw) */
    151 static char	hpcmips_cpuname[40];		/* set CPU depend xx_init() */
    152 
    153 int	cpuspeed = 1;			/* approx # instr per usec. */
    154 
    155 /* CPU core switch table */
    156 struct platform platform;
    157 #ifdef VR41XX
    158 extern void	vr_init(void);
    159 #endif
    160 #ifdef TX39XX
    161 extern void	tx_init(void);
    162 #endif
    163 
    164 /* boot environment */
    165 static struct bootinfo bi_copy;
    166 struct bootinfo *bootinfo;
    167 char booted_kernel[128];
    168 extern void makebootdev(const char *);
    169 #ifdef KLOADER
    170 #if !defined(KLOADER_KERNEL_PATH)
    171 #define KLOADER_KERNEL_PATH	"/netbsd"
    172 #endif /* !KLOADER_KERNEL_PATH */
    173 static char kernel_path[] = KLOADER_KERNEL_PATH;
    174 #endif /* KLOADER */
    175 
    176 /* maps for VM objects */
    177 struct vm_map *phys_map;
    178 
    179 /* physical memory */
    180 int	mem_cluster_cnt;
    181 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
    182 
    183 void mach_init(int, char *[], struct bootinfo *);
    184 
    185 #ifdef DEBUG
    186 /* stacktrace code violates prototypes to get callee's registers */
    187 extern void stacktrace(void); /*XXX*/
    188 #endif
    189 
    190 /*
    191  * Do all the stuff that locore normally does before calling main().
    192  * Process arguments passed to us by the boot loader.
    193  * Return the first page address following the system.
    194  */
    195 void
    196 mach_init(int argc, char *argv[], struct bootinfo *bi)
    197 {
    198 	/*
    199 	 * this routines stack is never polluted since stack pointer
    200 	 * is lower than kernel text segment, and at exiting, stack pointer
    201 	 * is changed to proc0.
    202 	 */
    203 #ifdef KLOADER
    204 	struct kloader_bootinfo kbi;
    205 #endif
    206 	extern char edata[], end[];
    207 #if NKSYMS || defined(DDB) || defined(MODULAR)
    208 	extern void *esym;
    209 #endif
    210 	void *kernend;
    211 	char *cp;
    212 	int i;
    213 
    214 	/* clear the BSS segment */
    215 #if NKSYMS || defined(DDB) || defined(MODULAR)
    216 	size_t symbolsz = 0;
    217 	Elf_Ehdr *eh = (void *)end;
    218 	if (memcmp(eh->e_ident, ELFMAG, SELFMAG) == 0 &&
    219 	    eh->e_ident[EI_CLASS] == ELFCLASS) {
    220 		esym = end;
    221 #ifndef NO_SYMBOLSZ_ENTRY
    222 		if (eh->e_entry != 0) {
    223 			/* pbsdboot */
    224 			symbolsz = eh->e_entry;
    225 		} else
    226 #endif
    227 		{
    228 			/* hpcboot */
    229 			Elf_Shdr *sh = (void *)(end + eh->e_shoff);
    230 			for(i = 0; i < eh->e_shnum; i++, sh++)
    231 				if (sh->sh_offset > 0 &&
    232 				    (sh->sh_offset + sh->sh_size) > symbolsz)
    233 					symbolsz = sh->sh_offset + sh->sh_size;
    234 		}
    235 		esym = (char*)esym + symbolsz;
    236 		kernend = (void *)mips_round_page(esym);
    237 		memset(edata, 0, end - edata);
    238 	} else
    239 #endif /* NKSYMS || defined(DDB) || defined(MODULAR) */
    240 	{
    241 		kernend = (void *)mips_round_page(end);
    242 		memset(edata, 0, (char *)kernend - edata);
    243 	}
    244 
    245 #if defined(BOOT_STANDALONE)
    246 #if !defined (SPEC_PLATFORM) || SPEC_PLATFORM == 1
    247 #error specify SPEC_PLATFORM=platid_mask_MACH_xxx_yyy in BOOT_STANDALONE case.
    248 #error see platid_mask.c for platid_mask_MACH_xxx_yyy.
    249 #else
    250 	memcpy(&platid, &SPEC_PLATFORM, sizeof(platid));
    251 #endif
    252 #endif /* defined(BOOT_STANDALONE) && defined(SPEC_PLATFORM) */
    253 	/*
    254 	 *  Arguments are set up by boot loader.
    255 	 */
    256 	if (bi && bi->magic == BOOTINFO_MAGIC) {
    257 		memset(&bi_copy, 0, sizeof(struct bootinfo));
    258 		memcpy(&bi_copy, bi, uimin(bi->length, sizeof(struct bootinfo)));
    259 		bootinfo = &bi_copy;
    260 		if (bootinfo->platid_cpu != 0) {
    261 			platid.dw.dw0 = bootinfo->platid_cpu;
    262 		}
    263 		if (bootinfo->platid_machine != 0) {
    264 			platid.dw.dw1 = bootinfo->platid_machine;
    265 		}
    266 	}
    267 	/* copy boot parameter for kloader */
    268 #ifdef KLOADER
    269 	kloader_bootinfo_set(&kbi, argc, argv, bi, false);
    270 #endif
    271 
    272 	/*
    273 	 * CPU core Specific Function Hooks
    274 	 */
    275 #if defined(VR41XX) && defined(TX39XX)
    276 	if (platid_match(&platid, &platid_mask_CPU_MIPS_VR_41XX))
    277 		vr_init();
    278 	else if (platid_match(&platid, &platid_mask_CPU_MIPS_TX_3900) ||
    279 	    platid_match(&platid, &platid_mask_CPU_MIPS_TX_3920))
    280 		tx_init();
    281 #elif defined(VR41XX)
    282 	vr_init();
    283 #elif defined(TX39XX)
    284 	tx_init();
    285 #else
    286 #error "define TX39XX and/or VR41XX"
    287 #endif
    288 
    289 #if NBICONSDEV > 0
    290 	/*
    291 	 *  bicons don't need actual device initialize.  only bootinfo needed.
    292 	 */
    293 	__bicons_enable = (bicons_init(&bicons) == 0);
    294 	if (__bicons_enable)
    295 		cn_tab = &bicons;
    296 #endif
    297 
    298 	/* Initialize frame buffer (to steal DMA buffer, stay here.) */
    299 #ifdef HPC_DEBUG_LCD
    300 	dbg_lcd_test();
    301 #endif
    302 	(*platform.fb_init)(&kernend);
    303 	kernend = (void *)mips_round_page(kernend);
    304 
    305 	/*
    306 	 * Set the VM page size.
    307 	 */
    308 	uvmexp.pagesize = NBPG; /* Notify the VM system of our page size. */
    309 	uvm_md_init();
    310 
    311 	/*
    312 	 * Copy exception-dispatch code down to exception vector.
    313 	 * Initialize locore-function vector.
    314 	 * Clear out the I and D caches.
    315 	 */
    316 	mips_vector_init(NULL, false);
    317 	intr_init();
    318 
    319 #ifdef DEBUG
    320 	/*
    321 	 * Look at arguments passed to us and compute boothowto.
    322 	 */
    323 	if (bootinfo) {
    324 		DPRINTF(("Bootinfo. available, "));
    325 	}
    326 	DPRINTF(("args: "));
    327 	for (i = 0; i < argc; i++) {
    328 		DPRINTF(("%s ", argv[i]));
    329 	}
    330 	DPRINTF(("\n"));
    331 	DPRINTF(("platform ID: %08lx %08lx\n", platid.dw.dw0, platid.dw.dw1));
    332 #endif /* DEBUG */
    333 
    334 #ifndef RTC_OFFSET
    335 	/*
    336 	 * rtc_offset from bootinfo.timezone set by pbsdboot.exe
    337 	 */
    338 	if (rtc_offset == 0 && bootinfo
    339 	    && bootinfo->timezone > (-12*60)
    340 	    && bootinfo->timezone <= (12*60))
    341 		rtc_offset = bootinfo->timezone;
    342 #endif /* RTC_OFFSET */
    343 
    344 	/* Compute bootdev */
    345 	makebootdev("wd0"); /* default boot device */
    346 
    347 	boothowto = 0;
    348 #ifdef KADB
    349 	boothowto |= RB_KDB;
    350 #endif
    351 	strncpy(booted_kernel, argv[0], sizeof(booted_kernel));
    352 	booted_kernel[sizeof(booted_kernel)-1] = 0;
    353 	for (i = 1; i < argc; i++) {
    354 		for (cp = argv[i]; *cp; cp++) {
    355 			switch (*cp) {
    356 			case 'h': /* XXX, serial console */
    357 				bootinfo->bi_cnuse |= BI_CNUSE_SERIAL;
    358 				break;
    359 
    360 			case 'b':
    361 				/* boot device: -b=sd0 etc. */
    362 				if (strcmp(cp+2, "nfs") == 0)
    363 					rootfstype = MOUNT_NFS;
    364 				else
    365 					makebootdev(cp+2);
    366 				cp += strlen(cp);
    367 				break;
    368 			default:
    369 				BOOT_FLAG(*cp, boothowto);
    370 				break;
    371 			}
    372 		}
    373 	}
    374 	/*
    375 	 * Check to see if a mini-root was loaded into memory. It resides
    376 	 * at the start of the next page just after the end of BSS.
    377 	 */
    378 	if (boothowto & RB_MINIROOT) {
    379 		size_t fssz;
    380 		fssz = round_page(mfs_initminiroot(kernend));
    381 #ifdef MEMORY_DISK_DYNAMIC
    382 		md_root_setconf(kernend, fssz);
    383 #endif /* MEMORY_DISK_DYNAMIC */
    384 		kernend = (char *)kernend + fssz;
    385 	}
    386 
    387 #if NKSYMS || defined(DDB) || defined(MODULAR)
    388 	/* init symbols if present */
    389 	if (esym)
    390 		ksyms_addsyms_elf(symbolsz, &end, esym);
    391 #endif /* DDB */
    392 
    393 	/* Initialize console and KGDB serial port. */
    394 	(*platform.cons_init)();
    395 
    396 #if defined(DDB) || defined(KGDB)
    397 	if (boothowto & RB_KDB) {
    398 #ifdef DDB
    399 		Debugger();
    400 #endif /* DDB */
    401 #ifdef KGDB
    402 		kgdb_debug_init = 1;
    403 		kgdb_connect(1);
    404 #endif /* KGDB */
    405 	}
    406 #endif /* DDB || KGDB */
    407 
    408 	/* Find physical memory regions. */
    409 #ifdef MEMSIZE
    410 	mem_clusters[0].start = 0;
    411 	mem_clusters[0].size = (paddr_t) kernend - MIPS_KSEG0_START;
    412 	mem_clusters[1].start = (paddr_t) kernend - MIPS_KSEG0_START;
    413 	mem_clusters[1].size = MEMSIZE * 0x100000 - mem_clusters[1].start;
    414 	mem_cluster_cnt = 2;
    415 #else
    416 	(*platform.mem_init)((paddr_t)kernend - MIPS_KSEG0_START);
    417 #endif
    418 	/*
    419 	 *  Clear currently unused D-RAM area
    420 	 *  (For reboot Windows CE clearly)
    421 	 */
    422 	{
    423 		u_int32_t sp;
    424 		__asm volatile("move %0, $29" : "=r"(sp));
    425 		KDASSERT(sp > KERNBASE + 0x400);
    426 		memset((void *)(KERNBASE + 0x400), 0, sp - (KERNBASE + 0x400) - 64);
    427 	}
    428 
    429 	printf("mem_cluster_cnt = %d\n", mem_cluster_cnt);
    430 	physmem = 0;
    431 	for (i = 0; i < mem_cluster_cnt; i++) {
    432 		printf("mem_clusters[%d] = {%#"PRIxPADDR",%#"PRIxPSIZE"}\n", i,
    433 		    (paddr_t)mem_clusters[i].start,
    434 		    (psize_t)mem_clusters[i].size);
    435 		physmem += atop(mem_clusters[i].size);
    436 	}
    437 
    438 	mips_page_physload(MIPS_KSEG0_START, (vaddr_t)kernend,
    439 	    mem_clusters, mem_cluster_cnt, NULL, 0);
    440 
    441 	/*
    442 	 * Initialize error message buffer (at end of core).
    443 	 */
    444 	mips_init_msgbuf();
    445 
    446 	/*
    447 	 * Initialize the virtual memory system.
    448 	 */
    449 	pmap_bootstrap();
    450 
    451 	/*
    452 	 * Initialize lwp0's uarea.
    453 	 */
    454 	mips_init_lwp0_uarea();
    455 }
    456 
    457 int
    458 cpuname_printf(const char *fmt, ...)
    459 {
    460 	int len;
    461 	va_list ap;
    462 
    463 	va_start(ap, fmt);
    464 	len = vsnprintf(hpcmips_cpuname, sizeof(hpcmips_cpuname), fmt, ap);
    465 	va_end(ap);
    466 
    467 	return len;
    468 }
    469 
    470 /*
    471  * Machine-dependent startup code.
    472  * allocate memory for variable-sized tables, initialize CPU.
    473  */
    474 void
    475 cpu_startup(void)
    476 {
    477 	cpu_setmodel("%s (%s)", platid_name(&platid), hpcmips_cpuname);
    478 
    479 	/* show again when verbose mode */
    480 	aprint_verbose("total memory banks = %d\n", mem_cluster_cnt);
    481 	for (size_t i = 0; i < mem_cluster_cnt; i++) {
    482 		aprint_verbose("memory bank %zu = "
    483 		    "%#08"PRIxPADDR" %"PRIdPSIZE"KB(%#"PRIxPSIZE")\n", i,
    484 		    (paddr_t)mem_clusters[i].start,
    485 		    (psize_t)mem_clusters[i].size/1024,
    486 		    (psize_t)mem_clusters[i].size);
    487 	}
    488 
    489 	cpu_startup_common();
    490 }
    491 
    492 void
    493 cpu_reboot(int howto, char *bootstr)
    494 {
    495 
    496 	/* take a snap shot before clobbering any registers */
    497 		savectx(curpcb);
    498 
    499 #ifdef DEBUG
    500 	if (panicstr)
    501 		stacktrace();
    502 #endif
    503 
    504 	/* If system is cold, just halt. */
    505 	if (cold) {
    506 		howto |= RB_HALT;
    507 		goto haltsys;
    508 	}
    509 
    510 	/* If "always halt" was specified as a boot flag, obey. */
    511 	if ((boothowto & RB_HALT) != 0) {
    512 		howto |= RB_HALT;
    513 	}
    514 
    515 #ifdef KLOADER
    516 	if ((howto & RB_HALT) == 0) {
    517 		if (howto & RB_STRING)
    518 			kloader_reboot_setup(bootstr);
    519 		else
    520 			kloader_reboot_setup(kernel_path);
    521 	}
    522 #endif
    523 
    524 	boothowto = howto;
    525 	if ((howto & RB_NOSYNC) == 0) {
    526 		/*
    527 		 * Synchronize the disks....
    528 		 */
    529 		vfs_shutdown();
    530 	}
    531 
    532 	/* Disable interrupts. */
    533 	splhigh();
    534 
    535 	/* If rebooting and a dump is requested do it. */
    536 	if (howto & RB_DUMP)
    537 		dumpsys();
    538 
    539  haltsys:
    540 
    541 	/* run any shutdown hooks */
    542 	doshutdownhooks();
    543 
    544 	pmf_system_shutdown(boothowto);
    545 
    546 	/* Finally, halt/reboot the system. */
    547 	if (howto & RB_HALT) {
    548 		printf("halted.\n");
    549 	} else {
    550 #ifdef KLOADER
    551 		kloader_reboot();
    552 		/* NOTREACHED */
    553 #endif
    554 	}
    555 
    556 	(*platform.reboot)(howto, bootstr);
    557 	while(1)
    558 		;
    559 	/*NOTREACHED*/
    560 }
    561 
    562 void
    563 consinit(void)
    564 {
    565 	/* platform.cons_init() do it */
    566 }
    567