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