1 /* $NetBSD: machdep.c,v 1.71 2010/02/08 19:02:30 joerg Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department, The Mach Operating System project at 10 * Carnegie-Mellon University and Ralph Campbell. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 37 */ 38 /* 39 * Copyright (c) 1988 University of Utah. 40 * 41 * This code is derived from software contributed to Berkeley by 42 * the Systems Programming Group of the University of Utah Computer 43 * Science Department, The Mach Operating System project at 44 * Carnegie-Mellon University and Ralph Campbell. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by the University of 57 * California, Berkeley and its contributors. 58 * 4. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 75 */ 76 77 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 78 79 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.71 2010/02/08 19:02:30 joerg Exp $"); 80 81 /* from: Utah Hdr: machdep.c 1.63 91/04/24 */ 82 83 #include "opt_ddb.h" 84 #include "opt_kgdb.h" 85 #include "opt_modular.h" 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/signalvar.h> 90 #include <sys/kernel.h> 91 #include <sys/proc.h> 92 #include <sys/buf.h> 93 #include <sys/reboot.h> 94 #include <sys/conf.h> 95 #include <sys/file.h> 96 #include <sys/callout.h> 97 #include <sys/malloc.h> 98 #include <sys/mbuf.h> 99 #include <sys/msgbuf.h> 100 #include <sys/ioctl.h> 101 #include <sys/device.h> 102 #include <sys/exec.h> 103 #include <sys/mount.h> 104 #include <sys/syscallargs.h> 105 #include <sys/kcore.h> 106 #include <sys/ksyms.h> 107 108 #include <uvm/uvm_extern.h> 109 110 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 111 112 #include <machine/cpu.h> 113 #include <machine/reg.h> 114 #include <machine/psl.h> 115 #include <machine/pte.h> 116 117 #ifdef DDB 118 #include <machine/db_machdep.h> 119 #include <ddb/db_extern.h> 120 #endif 121 122 #include <machine/intr.h> 123 #include <machine/mainboard.h> 124 #include <machine/sysconf.h> 125 #include <machine/autoconf.h> 126 #include <machine/bootinfo.h> 127 #include <machine/prom.h> 128 #include <dev/clock_subr.h> 129 #include <dev/cons.h> 130 131 #include <sys/boot_flag.h> 132 133 #include "fs_mfs.h" 134 #include "opt_execfmt.h" 135 136 #include "zsc.h" /* XXX */ 137 #include "com.h" /* XXX */ 138 #include "ksyms.h" 139 140 /* Our exported CPU info; we can have only one. */ 141 struct cpu_info cpu_info_store; 142 143 /* maps for VM objects */ 144 145 struct vm_map *phys_map = NULL; 146 147 int physmem; /* max supported memory, changes to actual */ 148 char *bootinfo = NULL; /* pointer to bootinfo structure */ 149 150 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 151 int mem_cluster_cnt; 152 153 void to_monitor(int) __attribute__((__noreturn__)); 154 void prom_halt(int) __attribute__((__noreturn__)); 155 156 #ifdef KGDB 157 void zs_kgdb_init(void); 158 void kgdb_connect(int); 159 #endif 160 161 /* 162 * Local functions. 163 */ 164 int initcpu(void); 165 void configure(void); 166 167 void mach_init(int, char *[], char*[], u_int, char *); 168 int memsize_scan(void *); 169 170 #ifdef DEBUG 171 /* stacktrace code violates prototypes to get callee's registers */ 172 extern void stacktrace(void); /*XXX*/ 173 #endif 174 175 /* 176 * safepri is a safe priority for sleep to set for a spin-wait 177 * during autoconfiguration or after a panic. Used as an argument to splx(). 178 * XXX disables interrupt 5 to disable mips3 on-chip clock, which also 179 * disables mips1 FPU interrupts. 180 */ 181 int safepri = MIPS3_PSL_LOWIPL; /* XXX */ 182 183 /* locore callback-vector setup */ 184 extern void mips_vector_init(void); 185 extern void prom_init(void); 186 extern void pizazz_init(void); 187 188 /* platform-specific initialization vector */ 189 static void unimpl_cons_init(void); 190 static void unimpl_iointr(unsigned, unsigned, unsigned, unsigned); 191 static int unimpl_memsize(void *); 192 static void unimpl_intr_establish(int, int (*)(void *), void *); 193 194 struct platform platform = { 195 .iobus = "iobus not set", 196 .cons_init = unimpl_cons_init, 197 .iointr = unimpl_iointr, 198 .memsize = unimpl_memsize, 199 .intr_establish = unimpl_intr_establish, 200 .clkinit = NULL, 201 }; 202 203 struct consdev *cn_tab = NULL; 204 extern struct consdev consdev_prom; 205 extern struct consdev consdev_zs; 206 207 static void null_cnprobe(struct consdev *); 208 static void prom_cninit(struct consdev *); 209 static int prom_cngetc(dev_t); 210 static void prom_cnputc(dev_t, int); 211 static void null_cnpollc(dev_t, int); 212 213 struct consdev consdev_prom = { 214 null_cnprobe, 215 prom_cninit, 216 prom_cngetc, 217 prom_cnputc, 218 null_cnpollc, 219 }; 220 221 222 /* 223 * Do all the stuff that locore normally does before calling main(). 224 * Process arguments passed to us by the prom monitor. 225 * Return the first page address following the system. 226 */ 227 void 228 mach_init(int argc, char *argv[], char *envp[], u_int bim, char *bip) 229 { 230 u_long first, last; 231 char *kernend; 232 char *cp; 233 int i, howto; 234 extern char edata[], end[]; 235 const char *bi_msg; 236 #if NKSYMS || defined(DDB) || defined(MODULAR) 237 int nsym = 0; 238 char *ssym = 0; 239 char *esym = 0; 240 struct btinfo_symtab *bi_syms; 241 #endif 242 243 244 /* Check for valid bootinfo passed from bootstrap */ 245 if (bim == BOOTINFO_MAGIC) { 246 struct btinfo_magic *bi_magic; 247 248 bootinfo = (char *)BOOTINFO_ADDR; /* XXX */ 249 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 250 if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 251 bi_msg = "invalid bootinfo structure.\n"; 252 else 253 bi_msg = NULL; 254 } else 255 bi_msg = "invalid bootinfo (standalone boot?)\n"; 256 257 /* clear the BSS segment */ 258 kernend = (void *)mips_round_page(end); 259 memset(edata, 0, end - edata); 260 261 #if NKSYMS || defined(DDB) || defined(MODULAR) 262 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 263 264 /* Load sysmbol table if present */ 265 if (bi_syms != NULL) { 266 nsym = bi_syms->nsym; 267 ssym = (void *)bi_syms->ssym; 268 esym = (void *)bi_syms->esym; 269 kernend = (void *)mips_round_page(esym); 270 } 271 #endif 272 273 prom_init(); 274 consinit(); 275 276 if (bi_msg != NULL) 277 printf(bi_msg); 278 279 /* 280 * Set the VM page size. 281 */ 282 uvm_setpagesize(); 283 284 /* Find out how much memory is available. */ 285 physmem = memsize_scan(kernend); 286 287 /* 288 * Now that we know how much memory we have, initialize the 289 * mem cluster array. 290 */ 291 mem_clusters[0].start = 0; /* XXX is this correct? */ 292 mem_clusters[0].size = ctob(physmem); 293 mem_cluster_cnt = 1; 294 295 /* 296 * Copy exception-dispatch code down to exception vector. 297 * Initialize locore-function vector. 298 * Clear out the I and D caches. 299 */ 300 mips_vector_init(); 301 302 /* Look at argv[0] and compute bootdev */ 303 makebootdev(argv[0]); 304 305 /* 306 * Look at arguments passed to us and compute boothowto. 307 */ 308 boothowto = RB_AUTOBOOT; 309 for (i = 1; i < argc; i++) { 310 for (cp = argv[i]; *cp; cp++) { 311 /* Ignore superfluous '-', if there is one */ 312 if (*cp == '-') 313 continue; 314 315 howto = 0; 316 BOOT_FLAG(*cp, howto); 317 if (! howto) 318 printf("bootflag '%c' not recognised\n", *cp); 319 else 320 boothowto |= howto; 321 } 322 } 323 324 325 #if NKSYMS || defined(DDB) || defined(MODULAR) 326 /* init symbols if present */ 327 if (esym) 328 ksyms_addsyms_elf(esym - ssym, ssym, esym); 329 #endif 330 #ifdef DDB 331 if (boothowto & RB_KDB) 332 Debugger(); 333 #endif 334 #ifdef KGDB 335 zs_kgdb_init(); /* XXX */ 336 if (boothowto & RB_KDB) 337 kgdb_connect(0); 338 #endif 339 340 #ifdef MFS 341 /* 342 * Check to see if a mini-root was loaded into memory. It resides 343 * at the start of the next page just after the end of BSS. 344 */ 345 if (boothowto & RB_MINIROOT) 346 kernend += round_page(mfs_initminiroot(kernend)); 347 #endif 348 349 /* 350 * Load the rest of the available pages into the VM system. 351 */ 352 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 353 last = mem_clusters[0].start + mem_clusters[0].size; 354 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 355 VM_FREELIST_DEFAULT); 356 357 /* 358 * Initialize error message buffer (at end of core). 359 */ 360 mips_init_msgbuf(); 361 362 /* 363 * Initialize the virtual memory system. 364 */ 365 pmap_bootstrap(); 366 367 /* 368 * Allocate uarea page for lwp0 and set it. 369 */ 370 mips_init_lwp0_uarea(); 371 372 /* 373 * Set up interrupt handling and I/O addresses. 374 */ 375 pizazz_init(); 376 } 377 378 379 380 /* 381 * cpu_startup: allocate memory for variable-sized tables, 382 * initialize CPU, and do autoconfiguration. 383 */ 384 void 385 cpu_startup(void) 386 { 387 vaddr_t minaddr, maxaddr; 388 char pbuf[9]; 389 #ifdef DEBUG 390 extern int pmapdebug; 391 int opmapdebug = pmapdebug; 392 393 pmapdebug = 0; 394 #endif 395 396 /* 397 * Good {morning,afternoon,evening,night}. 398 */ 399 printf("%s%s", copyright, version); 400 printf("%s\n", cpu_model); 401 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 402 printf("total memory = %s\n", pbuf); 403 404 minaddr = 0; 405 /* 406 * Allocate a submap for physio 407 */ 408 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 409 VM_PHYS_SIZE, true, false, NULL); 410 411 /* 412 * No need to allocate an mbuf cluster submap. Mbuf clusters 413 * are allocated via the pool allocator, and we use KSEG to 414 * map those pages. 415 */ 416 417 #ifdef DEBUG 418 pmapdebug = opmapdebug; 419 #endif 420 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 421 printf("avail memory = %s\n", pbuf); 422 } 423 424 /* 425 * Look up information in bootinfo of boot loader. 426 */ 427 void * 428 lookup_bootinfo(int type) 429 { 430 struct btinfo_common *bt; 431 char *help = bootinfo; 432 433 /* Check for a bootinfo record first. */ 434 if (help == NULL) 435 return (NULL); 436 437 do { 438 bt = (struct btinfo_common *)help; 439 if (bt->type == type) 440 return ((void *)help); 441 help += bt->next; 442 } while (bt->next != 0 && 443 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 444 445 return (NULL); 446 } 447 448 int waittime = -1; 449 450 /* 451 * call PROM to halt or reboot. 452 */ 453 void 454 prom_halt(int howto) 455 { 456 if (howto & RB_HALT) 457 MIPS_PROM(reinit)(); 458 MIPS_PROM(reboot)(); 459 /* NOTREACHED */ 460 } 461 462 void 463 cpu_reboot(volatile int howto, char *bootstr) 464 { 465 /* take a snap shot before clobbering any registers */ 466 if (curlwp) 467 savectx(curpcb); 468 469 #ifdef DEBUG 470 if (panicstr) 471 stacktrace(); 472 #endif 473 474 /* If system is cold, just halt. */ 475 if (cold) { 476 howto |= RB_HALT; 477 goto haltsys; 478 } 479 480 /* If "always halt" was specified as a boot flag, obey. */ 481 if ((boothowto & RB_HALT) != 0) 482 howto |= RB_HALT; 483 484 boothowto = howto; 485 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 486 /* 487 * Synchronize the disks.... 488 */ 489 waittime = 0; 490 vfs_shutdown(); 491 492 /* 493 * If we've been adjusting the clock, the todr 494 * will be out of synch; adjust it now. 495 */ 496 resettodr(); 497 } 498 499 /* Disable interrupts. */ 500 splhigh(); 501 502 /* If rebooting and a dump is requested do it. */ 503 #if 0 504 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 505 #else 506 if (howto & RB_DUMP) 507 #endif 508 dumpsys(); 509 510 haltsys: 511 512 /* run any shutdown hooks */ 513 doshutdownhooks(); 514 515 pmf_system_shutdown(boothowto); 516 517 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 518 prom_halt(0x80); /* rom monitor RB_PWOFF */ 519 520 /* Finally, halt/reboot the system. */ 521 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 522 prom_halt(howto & RB_HALT); 523 /*NOTREACHED*/ 524 } 525 526 int 527 initcpu(void) 528 { 529 spl0(); /* safe to turn interrupts on now */ 530 return 0; 531 } 532 533 static void 534 unimpl_cons_init(void) 535 { 536 537 panic("sysconf.init didn't set cons_init"); 538 } 539 540 static void 541 unimpl_iointr(u_int mask, u_int pc, u_int statusreg, u_int causereg) 542 { 543 544 panic("sysconf.init didn't set intr"); 545 } 546 547 static int 548 unimpl_memsize(void *first) 549 { 550 551 panic("sysconf.init didn't set memsize"); 552 } 553 554 void 555 unimpl_intr_establish(int level, int (*func)(void *), void *arg) 556 { 557 panic("sysconf.init didn't init intr_establish"); 558 } 559 560 void 561 delay(int n) 562 { 563 DELAY(n); 564 } 565 566 /* 567 * Find out how much memory is available by testing memory. 568 * Be careful to save and restore the original contents for msgbuf. 569 */ 570 int 571 memsize_scan(void *first) 572 { 573 volatile int *vp, *vp0; 574 int mem, tmp, tmp0; 575 576 #define PATTERN1 0xa5a5a5a5 577 #define PATTERN2 ~PATTERN1 578 579 /* 580 * Non destructive scan of memory to determine the size 581 * Use the first page to test for memory aliases. This 582 * also has the side effect of flushing the bus alignment 583 * buffer 584 */ 585 mem = btoc((paddr_t)first - MIPS_KSEG0_START); 586 vp = (int *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT); 587 vp0 = (int *)MIPS_PHYS_TO_KSEG1(0); /* Start of physical memory */ 588 tmp0 = *vp0; 589 while (vp < (int *)MIPS_MAX_MEM_ADDR) { 590 tmp = *vp; 591 *vp = PATTERN1; 592 *vp0 = PATTERN2; 593 wbflush(); 594 if (*vp != PATTERN1) 595 break; 596 *vp = PATTERN2; 597 *vp0 = PATTERN1; 598 wbflush(); 599 if (*vp != PATTERN2) 600 break; 601 *vp = tmp; 602 vp += PAGE_SIZE/sizeof(int); 603 mem++; 604 } 605 *vp0 = tmp0; 606 return mem; 607 } 608 609 /* 610 * Console initialization: called early on from main, 611 * before vm init or startup. Do enough configuration 612 * to choose and initialize a console. 613 */ 614 615 static void 616 null_cnprobe(struct consdev *cn) 617 { 618 } 619 620 static void 621 prom_cninit(struct consdev *cn) 622 { 623 extern const struct cdevsw cons_cdevsw; 624 625 cn->cn_dev = makedev(cdevsw_lookup_major(&cons_cdevsw), 0); 626 cn->cn_pri = CN_REMOTE; 627 } 628 629 static int 630 prom_cngetc(dev_t dev) 631 { 632 return MIPS_PROM(getchar)(); 633 } 634 635 static void 636 prom_cnputc(dev_t dev, int c) 637 { 638 MIPS_PROM(putchar)(c); 639 } 640 641 static void 642 null_cnpollc(dev_t dev, int on) 643 { 644 } 645 646 void 647 consinit(void) 648 { 649 int zs_unit; 650 651 zs_unit = 0; 652 cn_tab = &consdev_zs; 653 654 (*cn_tab->cn_init)(cn_tab); 655 } 656