1/* $NetBSD: machdep.c,v 1.58 2024/03/05 14:15:28 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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/* 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 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 67 * from: Utah Hdr: machdep.c 1.63 91/04/24 68 */ 69 70#include <sys/cdefs.h> 71__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.58 2024/03/05 14:15:28 thorpej Exp $"); 72 73#include "opt_algor_p4032.h" 74#include "opt_algor_p5064.h" 75#include "opt_algor_p6032.h" 76 77#include "opt_ddb.h" 78#include "opt_kgdb.h" 79 80#include "opt_memsize.h" 81#include "opt_ethaddr.h" 82 83#include <sys/param.h> 84#include <sys/boot_flag.h> 85#include <sys/buf.h> 86#include <sys/bus.h> 87#include <sys/device.h> 88#include <sys/kernel.h> 89#include <sys/kcore.h> 90#include <sys/ksyms.h> 91#include <sys/lwp.h> 92#include <sys/mount.h> 93#include <sys/reboot.h> 94#include <sys/systm.h> 95#include <sys/termios.h> 96#include <sys/cpu.h> 97 98#include <net/if.h> 99#include <net/if_ether.h> 100 101#include <uvm/uvm_extern.h> 102 103#include <dev/cons.h> 104 105#include <mips/locore.h> 106#include <mips/pcb.h> 107 108#ifdef DDB 109#include <mips/db_machdep.h> 110#include <ddb/db_extern.h> 111#endif 112 113#include <machine/pmon.h> 114#include <algor/autoconf.h> 115 116#include <algor/pci/vtpbcvar.h> 117 118#include "ksyms.h" 119 120#include "com.h" 121#if NCOM > 0 122#include <dev/ic/comreg.h> 123#include <dev/ic/comvar.h> 124 125int comcnrate = TTYDEF_SPEED; 126#endif /* NCOM > 0 */ 127 128#if defined(ALGOR_P4032) + \ 129 defined(ALGOR_P5064) + \ 130 defined(ALGOR_P6032) + \ 131 0 != 1 132#error Must configure exactly one platform. 133#endif 134 135#ifdef ALGOR_P4032 136#include <algor/algor/algor_p4032reg.h> 137#include <algor/algor/algor_p4032var.h> 138struct p4032_config p4032_configuration; 139#endif 140 141#ifdef ALGOR_P5064 142#include <algor/algor/algor_p5064reg.h> 143#include <algor/algor/algor_p5064var.h> 144struct p5064_config p5064_configuration; 145#endif 146 147#ifdef ALGOR_P6032 148#include <algor/algor/algor_p6032reg.h> 149#include <algor/algor/algor_p6032var.h> 150struct p6032_config p6032_configuration; 151#endif 152 153/* Maps for VM objects. */ 154struct vm_map *phys_map = NULL; 155 156int maxmem; /* max memory per process */ 157 158int mem_cluster_cnt; 159phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 160 161char algor_ethaddr[ETHER_ADDR_LEN]; 162 163void mach_init(int, char *[], char *[]); /* XXX */ 164 165int cpuspeed = 150; /* XXX XXX XXX */ 166 167/* The ALGOR kernels only support little endian */ 168CTASSERT(_BYTE_ORDER == _LITTLE_ENDIAN); 169 170void 171mach_init(int argc, char *argv[], char *envp[]) 172{ 173 extern char kernel_text[], edata[], end[]; 174 vaddr_t kernstart, kernend; 175 vsize_t size; 176 const char *cp; 177 char *cp0; 178 size_t i; 179 180 /* 181 * First, find the start and end of the kernel and clear 182 * the BSS segment. Account for a bit of space for the 183 * bootstrap stack. 184 */ 185 led_display('b', 's', 's', ' '); 186 kernstart = (vaddr_t) mips_trunc_page(kernel_text) - 2 * NBPG; 187 kernend = (vaddr_t) mips_round_page(end); 188 memset(edata, 0, kernend - (vaddr_t)edata); 189 190 /* 191 * Copy the exception-dispatch code down to the exception vector. 192 * Initialize the locore function vector. Clear out the I- and 193 * D-caches. 194 * 195 * We can no longer call into PMON after this. 196 */ 197 led_display('v', 'e', 'c', 'i'); 198 mips_vector_init(NULL, false); 199 200 /* 201 * Initialize PAGE_SIZE-dependent variables. 202 */ 203 led_display('p', 'g', 's', 'z'); 204 uvm_md_init(); 205 206 /* 207 * Initialize bus space tags and bring up the console. 208 */ 209#if defined(ALGOR_P4032) 210 { 211 struct p4032_config *acp = &p4032_configuration; 212 struct vtpbc_config *vt = &vtpbc_configuration; 213 bus_space_handle_t sh; 214 215 cpu_setmodel("Algorithmics P-4032"); 216 217 vt->vt_addr = MIPS_PHYS_TO_KSEG1(P4032_V962PBC); 218 vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P4032_PCICFG); 219 vt->vt_adbase = 11; 220 221 led_display('v', '9', '6', '2'); 222 vtpbc_init(&acp->ac_pc, vt); 223 224 led_display('l', 'i', 'o', ' '); 225 algor_p4032loc_bus_io_init(&acp->ac_lociot, acp); 226 227 led_display('i', 'o', ' ', ' '); 228 algor_p4032_bus_io_init(&acp->ac_iot, acp); 229 230 led_display('m', 'e', 'm', ' '); 231 algor_p4032_bus_mem_init(&acp->ac_memt, acp); 232 233 led_display('d', 'm', 'a', ' '); 234 algor_p4032_dma_init(acp); 235#if NCOM > 0 236 /* 237 * Delay to allow firmware putchars to complete. 238 * FIFO depth * character time. 239 * character time = (1000000 / (defaultrate / 10)) 240 */ 241 led_display('c', 'o', 'n', 's'); 242 DELAY(160000000 / comcnrate); 243 if (comcnattach(&acp->ac_lociot, P4032_COM1, comcnrate, 244 COM_FREQ, COM_TYPE_NORMAL, 245 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) 246 panic("p4032: unable to initialize serial console"); 247#else 248 panic("p4032: not configured to use serial console"); 249#endif /* NCOM > 0 */ 250 251 led_display('h', 'z', ' ', ' '); 252 bus_space_map(&acp->ac_lociot, P4032_RTC, 2, 0, &sh); 253 algor_p4032_cal_timer(&acp->ac_lociot, sh); 254 bus_space_unmap(&acp->ac_lociot, sh, 2); 255 } 256#elif defined(ALGOR_P5064) 257 { 258 struct p5064_config *acp = &p5064_configuration; 259 struct vtpbc_config *vt = &vtpbc_configuration; 260 bus_space_handle_t sh; 261 262 cpu_setmodel("Algorithmics P-5064"); 263 264 vt->vt_addr = MIPS_PHYS_TO_KSEG1(P5064_V360EPC); 265 vt->vt_cfgbase = MIPS_PHYS_TO_KSEG1(P5064_PCICFG); 266 vt->vt_adbase = 24; 267 268 led_display('v', '3', '6', '0'); 269 vtpbc_init(&acp->ac_pc, vt); 270 271 led_display('i', 'o', ' ', ' '); 272 algor_p5064_bus_io_init(&acp->ac_iot, acp); 273 274 led_display('m', 'e', 'm', ' '); 275 algor_p5064_bus_mem_init(&acp->ac_memt, acp); 276 277 led_display('d', 'm', 'a', ' '); 278 algor_p5064_dma_init(acp); 279#if NCOM > 0 280 /* 281 * Delay to allow firmware putchars to complete. 282 * FIFO depth * character time. 283 * character time = (1000000 / (defaultrate / 10)) 284 */ 285 led_display('c', 'o', 'n', 's'); 286 DELAY(160000000 / comcnrate); 287 if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate, 288 COM_FREQ, COM_TYPE_NORMAL, 289 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) 290 panic("p5064: unable to initialize serial console"); 291#else 292 panic("p5064: not configured to use serial console"); 293#endif /* NCOM > 0 */ 294 295 led_display('h', 'z', ' ', ' '); 296 bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh); 297 algor_p5064_cal_timer(&acp->ac_iot, sh); 298 bus_space_unmap(&acp->ac_iot, sh, 2); 299 } 300#elif defined(ALGOR_P6032) 301 { 302 struct p6032_config *acp = &p6032_configuration; 303 struct bonito_config *bc = &acp->ac_bonito; 304 bus_space_handle_t sh; 305 306 cpu_setmodel("Algorithmics P-6032"); 307 308 bc->bc_adbase = 11; 309 310 led_display('b','n','t','o'); 311 bonito_pci_init(&acp->ac_pc, bc); 312 313 led_display('i','o',' ',' '); 314 algor_p6032_bus_io_init(&acp->ac_iot, acp); 315 316 led_display('m','e','m',' '); 317 algor_p6032_bus_mem_init(&acp->ac_memt, acp); 318 319 led_display('d','m','a',' '); 320 algor_p6032_dma_init(acp); 321#if NCOM > 0 322 /* 323 * Delay to allow firmware putchars to complete. 324 * FIFO depth * character time. 325 * character time = (1000000 / (defaultrate / 10)) 326 */ 327 led_display('c','o','n','s'); 328 DELAY(160000000 / comcnrate); 329 if (comcnattach(&acp->ac_iot, 0x3f8, comcnrate, 330 COM_FREQ, COM_TYPE_NORMAL, 331 (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0) 332 panic("p6032: unable to initialize serial console"); 333#else 334 panic("p6032: not configured to use serial console"); 335#endif /* NCOM > 0 */ 336 337 led_display('h','z',' ',' '); 338 bus_space_map(&acp->ac_iot, 0x70, 2, 0, &sh); 339 algor_p6032_cal_timer(&acp->ac_iot, sh); 340 bus_space_unmap(&acp->ac_iot, sh, 2); 341 } 342#endif /* ALGOR_P4032 || ALGOR_P5064 || ALGOR_P6032 */ 343 344 /* 345 * The Algorithmics boards have PMON firmware; set up our 346 * PMON state. 347 */ 348 led_display('p', 'm', 'o', 'n'); 349 pmon_init(envp); 350 351 /* 352 * Get the Ethernet address of the on-board Ethernet. 353 */ 354#if defined(ETHADDR) 355 cp = ETHADDR; 356#else 357 cp = pmon_getenv("ethaddr"); 358#endif 359 if (cp != NULL) { 360 for (i = 0; i < ETHER_ADDR_LEN; i++) { 361 algor_ethaddr[i] = strtoul(cp, &cp0, 16); 362 cp = cp0 + 1; 363 } 364 } 365 366 /* 367 * Get the boot options. 368 */ 369 led_display('b', 'o', 'p', 't'); 370 boothowto = 0; 371 if (argc > 1) { 372#ifdef _LP64 373 cp = (void *)(intptr_t)((int32_t *)argv)[1]; 374#else 375 cp = argv[1]; 376#endif 377 for (; cp != NULL && *cp != '\0'; cp++) { 378 switch (*cp) { 379#if defined(KGDB) || defined(DDB) 380 case 'd': /* break into kernel debugger */ 381 boothowto |= RB_KDB; 382 break; 383#endif 384 385 case 'h': /* always halt, never reboot */ 386 boothowto |= RB_HALT; 387 break; 388 389 case 'n': /* askname */ 390 boothowto |= RB_ASKNAME; 391 break; 392 393 case 's': /* single-user mode */ 394 boothowto |= RB_SINGLE; 395 break; 396 397 case 'q': /* quiet boot */ 398 boothowto |= AB_QUIET; 399 break; 400 401 case 'v': /* verbose boot */ 402 boothowto |= AB_VERBOSE; 403 break; 404 405 case '-': 406 /* 407 * Just ignore this. It's not required, 408 * but it's common for it to be passed 409 * regardless. 410 */ 411 break; 412 413 default: 414 printf("Unrecognized boto flag '%c'.\n", *cp); 415 break; 416 } 417 } 418 } 419 420 /* 421 * Determine the memory size. Use the `memsize' PMON 422 * variable. If that's not available, panic. 423 * 424 * Note: Reserve the first page! That's where the trap 425 * vectors are located. 426 */ 427#if defined(MEMSIZE) 428 size = MEMSIZE; 429#else 430 if ((cp = pmon_getenv("memsize")) != NULL) 431 size = strtoul(cp, NULL, 0); 432 else { 433 printf("FATAL: `memsize' PMON variable not set. Set it to\n"); 434 printf(" the amount of memory (in MB) and try again.\n"); 435 printf(" Or, build a kernel with the `MEMSIZE' " 436 "option.\n"); 437 panic("algor_init"); 438 } 439#endif /* MEMSIZE */ 440 /* 441 * Deal with 2 different conventions of the contents 442 * of the memsize variable -- if it's > 1024, assume 443 * it's already in bytes, not megabytes. 444 */ 445 if (size < 1024) { 446 printf("Memory size: %#"PRIxVSIZE" (%"PRIxVSIZE")\n", 447 size * 1024 * 1024, size); 448 size *= 1024 * 1024; 449 } else 450 printf("Memory size: %#"PRIxVSIZE"\n", size); 451 452 mem_clusters[mem_cluster_cnt].start = PAGE_SIZE; 453 mem_clusters[mem_cluster_cnt].size = 454 size - mem_clusters[mem_cluster_cnt].start; 455 mem_cluster_cnt++; 456 457 /* 458 * Load the physical memory clusters into the VM system. 459 */ 460 led_display('v', 'm', 'p', 'g'); 461 for (i = 0; i < mem_cluster_cnt; i++) { 462 physmem += atop(mem_clusters[i].size); 463 } 464 if (physmem == 0) 465 panic("can't happen: system seems to have no memory!"); 466 maxmem = physmem; 467 468 static const struct mips_vmfreelist isadma = { 469 .fl_start = 8*1024*1024, 470 .fl_end = 16*1024*1024, 471 .fl_freelist = VM_FREELIST_ISADMA, 472 }; 473 mips_page_physload(kernstart, kernend, 474 mem_clusters, mem_cluster_cnt, &isadma, 1); 475 476 /* 477 * Initialize message buffer (at end of core). 478 */ 479 mips_init_msgbuf(); 480 481 /* 482 * Initialize the virtual memory system. 483 */ 484 led_display('p', 'm', 'a', 'p'); 485 pmap_bootstrap(); 486 487 /* 488 * Allocate uarea page for lwp0 and set it. 489 */ 490 led_display('u', 's', 'p', 'c'); 491 mips_init_lwp0_uarea(); 492 493 /* 494 * Initialize debuggers, and break into them, if appropriate. 495 */ 496 if (boothowto & RB_KDB) { 497#if defined(DDB) 498 Debugger(); 499#endif 500 } 501} 502 503void 504consinit(void) 505{ 506 507 /* 508 * Everything related to console initialization is done 509 * in mach_init(). 510 */ 511 led_display('N', 'B', 'S', 'D'); 512} 513 514void 515cpu_startup(void) 516{ 517 /* 518 * Virtual memory is bootstrapped -- notify the bus spaces 519 * that memory allocation is now safe. 520 */ 521#if defined(ALGOR_P4032) 522 struct p4032_config * const acp = &p4032_configuration; 523 524 acp->ac_mallocsafe = 1; 525#elif defined(ALGOR_P5064) 526 struct p5064_config * const acp = &p5064_configuration; 527 528 acp->ac_mallocsafe = 1; 529#elif defined(ALGOR_P6032) 530 struct p6032_config * const acp = &p6032_configuration; 531 532 acp->ac_mallocsafe = 1; 533#endif 534 cpu_startup_common(); 535} 536 537int waittime = -1; 538 539void 540cpu_reboot(int howto, char *bootstr) 541{ 542 int tmp; 543 544 /* Take a snapshot before clobbering any registers. */ 545 savectx(curpcb); 546 547 /* If "always halt" was specified as a boot flag, obey. */ 548 if (boothowto & RB_HALT) 549 howto |= RB_HALT; 550 551 boothowto = howto; 552 553 /* If system is cold, just halt. */ 554 if (cold) { 555 boothowto |= RB_HALT; 556 goto haltsys; 557 } 558 559 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 560 waittime = 0; 561 vfs_shutdown(); 562 } 563 564 /* Disable interrupts. */ 565 (void) splhigh(); 566 567 if (boothowto & RB_DUMP) 568 dumpsys(); 569 570 haltsys: 571 /* Run any shutdown hooks. */ 572 doshutdownhooks(); 573 574 pmf_system_shutdown(boothowto); 575 576 if (boothowto & RB_HALT) { 577 printf("\n"); 578 printf("The operating system has halted.\n"); 579 printf("Please press any key to return to the monitor.\n\n"); 580 led_display('h','a','l','t'); 581 cnpollc(1); 582 (void) cngetc(); 583 cnpollc(0); 584 } 585 586 printf("Returning to the monitor...\n\n"); 587 led_display('r', 'v', 'e', 'c'); 588 /* Jump to the reset vector. */ 589 __asm volatile("li %0, 0xbfc00000; jr %0; nop" 590 : "=r" (tmp) 591 : /* no inputs */ 592 : "memory"); 593 led_display('R', 'S', 'T', 'F'); 594 for (;;) 595 /* spin forever */ ; 596} 597