1 /* $NetBSD: machdep.c,v 1.58 2008/07/02 17:28:56 ad 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.58 2008/07/02 17:28:56 ad 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 86 #include <sys/param.h> 87 #include <sys/signalvar.h> 88 #include <sys/kernel.h> 89 #include <sys/proc.h> 90 #include <sys/buf.h> 91 #include <sys/reboot.h> 92 #include <sys/conf.h> 93 #include <sys/file.h> 94 #include <sys/callout.h> 95 #include <sys/malloc.h> 96 #include <sys/mbuf.h> 97 #include <sys/msgbuf.h> 98 #include <sys/ioctl.h> 99 #include <sys/device.h> 100 #include <sys/user.h> 101 #include <sys/exec.h> 102 #include <sys/mount.h> 103 #include <sys/syscallargs.h> 104 #include <sys/kcore.h> 105 #include <sys/ksyms.h> 106 107 #include <uvm/uvm_extern.h> 108 109 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 110 111 #include <machine/cpu.h> 112 #include <machine/reg.h> 113 #include <machine/psl.h> 114 #include <machine/pte.h> 115 116 #ifdef DDB 117 #include <machine/db_machdep.h> 118 #include <ddb/db_extern.h> 119 #endif 120 121 #include <machine/intr.h> 122 #include <machine/mainboard.h> 123 #include <machine/sysconf.h> 124 #include <machine/autoconf.h> 125 #include <machine/bootinfo.h> 126 #include <machine/prom.h> 127 #include <dev/clock_subr.h> 128 #include <dev/cons.h> 129 130 #include <sys/boot_flag.h> 131 132 #include "fs_mfs.h" 133 #include "opt_execfmt.h" 134 135 #include "zsc.h" /* XXX */ 136 #include "com.h" /* XXX */ 137 #include "ksyms.h" 138 139 /* Our exported CPU info; we can have only one. */ 140 struct cpu_info cpu_info_store; 141 142 /* maps for VM objects */ 143 144 struct vm_map *mb_map = NULL; 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 __P((int)) __attribute__((__noreturn__)); 154 void prom_halt __P((int)) __attribute__((__noreturn__)); 155 156 #ifdef KGDB 157 void zs_kgdb_init __P((void)); 158 void kgdb_connect __P((int)); 159 #endif 160 161 /* 162 * Local functions. 163 */ 164 int initcpu __P((void)); 165 void configure __P((void)); 166 167 void mach_init __P((int, char *[], char*[], u_int, char *)); 168 int memsize_scan __P((void *)); 169 170 #ifdef DEBUG 171 /* stacktrace code violates prototypes to get callee's registers */ 172 extern void stacktrace __P((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 extern struct user *proc0paddr; 183 184 /* locore callback-vector setup */ 185 extern void mips_vector_init __P((void)); 186 extern void prom_init __P((void)); 187 extern void pizazz_init __P((void)); 188 189 /* platform-specific initialization vector */ 190 static void unimpl_cons_init __P((void)); 191 static void unimpl_iointr __P((unsigned, unsigned, unsigned, unsigned)); 192 static int unimpl_memsize __P((void *)); 193 static void unimpl_intr_establish __P((int, int (*)__P((void *)), void *)); 194 195 struct platform platform = { 196 .iobus = "iobus not set", 197 .cons_init = unimpl_cons_init, 198 .iointr = unimpl_iointr, 199 .memsize = unimpl_memsize, 200 .intr_establish = unimpl_intr_establish, 201 .clkinit = NULL, 202 }; 203 204 struct consdev *cn_tab = NULL; 205 extern struct consdev consdev_prom; 206 extern struct consdev consdev_zs; 207 208 static void null_cnprobe __P((struct consdev *)); 209 static void prom_cninit __P((struct consdev *)); 210 static int prom_cngetc __P((dev_t)); 211 static void prom_cnputc __P((dev_t, int)); 212 static void null_cnpollc __P((dev_t, int)); 213 214 struct consdev consdev_prom = { 215 null_cnprobe, 216 prom_cninit, 217 prom_cngetc, 218 prom_cnputc, 219 null_cnpollc, 220 }; 221 222 223 /* 224 * Do all the stuff that locore normally does before calling main(). 225 * Process arguments passed to us by the prom monitor. 226 * Return the first page address following the system. 227 */ 228 void 229 mach_init(argc, argv, envp, bim, bip) 230 int argc; 231 char *argv[]; 232 char *envp[]; 233 u_int bim; 234 char *bip; 235 { 236 u_long first, last; 237 char *kernend, *v; 238 char *cp; 239 int i, howto; 240 extern char edata[], end[]; 241 const char *bi_msg; 242 #if NKSYMS || defined(DDB) || defined(LKM) 243 int nsym = 0; 244 char *ssym = 0; 245 char *esym = 0; 246 struct btinfo_symtab *bi_syms; 247 #endif 248 249 250 /* Check for valid bootinfo passed from bootstrap */ 251 if (bim == BOOTINFO_MAGIC) { 252 struct btinfo_magic *bi_magic; 253 254 bootinfo = (char *)BOOTINFO_ADDR; /* XXX */ 255 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 256 if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 257 bi_msg = "invalid bootinfo structure.\n"; 258 else 259 bi_msg = NULL; 260 } else 261 bi_msg = "invalid bootinfo (standalone boot?)\n"; 262 263 /* clear the BSS segment */ 264 kernend = (void *)mips_round_page(end); 265 memset(edata, 0, end - edata); 266 267 #if NKSYMS || defined(DDB) || defined(LKM) 268 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 269 270 /* Load sysmbol table if present */ 271 if (bi_syms != NULL) { 272 nsym = bi_syms->nsym; 273 ssym = (void *)bi_syms->ssym; 274 esym = (void *)bi_syms->esym; 275 kernend = (void *)mips_round_page(esym); 276 } 277 #endif 278 279 prom_init(); 280 consinit(); 281 282 if (bi_msg != NULL) 283 printf(bi_msg); 284 285 /* 286 * Set the VM page size. 287 */ 288 uvm_setpagesize(); 289 290 /* Find out how much memory is available. */ 291 physmem = memsize_scan(kernend); 292 293 /* 294 * Now that we know how much memory we have, initialize the 295 * mem cluster array. 296 */ 297 mem_clusters[0].start = 0; /* XXX is this correct? */ 298 mem_clusters[0].size = ctob(physmem); 299 mem_cluster_cnt = 1; 300 301 /* 302 * Copy exception-dispatch code down to exception vector. 303 * Initialize locore-function vector. 304 * Clear out the I and D caches. 305 */ 306 mips_vector_init(); 307 308 /* Look at argv[0] and compute bootdev */ 309 makebootdev(argv[0]); 310 311 /* 312 * Look at arguments passed to us and compute boothowto. 313 */ 314 boothowto = RB_AUTOBOOT; 315 for (i = 1; i < argc; i++) { 316 for (cp = argv[i]; *cp; cp++) { 317 /* Ignore superfluous '-', if there is one */ 318 if (*cp == '-') 319 continue; 320 321 howto = 0; 322 BOOT_FLAG(*cp, howto); 323 if (! howto) 324 printf("bootflag '%c' not recognised\n", *cp); 325 else 326 boothowto |= howto; 327 } 328 } 329 330 331 #if NKSYMS || defined(DDB) || defined(LKM) 332 /* init symbols if present */ 333 if (esym) 334 ksyms_init(esym - ssym, ssym, esym); 335 #endif 336 #ifdef DDB 337 if (boothowto & RB_KDB) 338 Debugger(); 339 #endif 340 #ifdef KGDB 341 zs_kgdb_init(); /* XXX */ 342 if (boothowto & RB_KDB) 343 kgdb_connect(0); 344 #endif 345 346 #ifdef MFS 347 /* 348 * Check to see if a mini-root was loaded into memory. It resides 349 * at the start of the next page just after the end of BSS. 350 */ 351 if (boothowto & RB_MINIROOT) 352 kernend += round_page(mfs_initminiroot(kernend)); 353 #endif 354 355 /* 356 * Load the rest of the available pages into the VM system. 357 */ 358 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 359 last = mem_clusters[0].start + mem_clusters[0].size; 360 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 361 VM_FREELIST_DEFAULT); 362 363 /* 364 * Initialize error message buffer (at end of core). 365 */ 366 mips_init_msgbuf(); 367 368 /* 369 * Initialize the virtual memory system. 370 */ 371 pmap_bootstrap(); 372 373 /* 374 * Allocate space for proc0's USPACE. 375 */ 376 v = (void *)uvm_pageboot_alloc(USPACE); 377 lwp0.l_addr = proc0paddr = (struct user *)v; 378 lwp0.l_md.md_regs = (struct frame *)(v + USPACE) - 1; 379 proc0paddr->u_pcb.pcb_context[11] = 380 MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 381 382 /* 383 * Set up interrupt handling and I/O addresses. 384 */ 385 pizazz_init(); 386 } 387 388 389 390 /* 391 * cpu_startup: allocate memory for variable-sized tables, 392 * initialize CPU, and do autoconfiguration. 393 */ 394 void 395 cpu_startup() 396 { 397 vaddr_t minaddr, maxaddr; 398 char pbuf[9]; 399 #ifdef DEBUG 400 extern int pmapdebug; 401 int opmapdebug = pmapdebug; 402 403 pmapdebug = 0; 404 #endif 405 406 /* 407 * Good {morning,afternoon,evening,night}. 408 */ 409 printf("%s%s", copyright, version); 410 printf("%s\n", cpu_model); 411 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 412 printf("total memory = %s\n", pbuf); 413 414 minaddr = 0; 415 /* 416 * Allocate a submap for physio 417 */ 418 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 419 VM_PHYS_SIZE, true, false, NULL); 420 421 /* 422 * No need to allocate an mbuf cluster submap. Mbuf clusters 423 * are allocated via the pool allocator, and we use KSEG to 424 * map those pages. 425 */ 426 427 #ifdef DEBUG 428 pmapdebug = opmapdebug; 429 #endif 430 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 431 printf("avail memory = %s\n", pbuf); 432 } 433 434 /* 435 * Look up information in bootinfo of boot loader. 436 */ 437 void * 438 lookup_bootinfo(type) 439 int type; 440 { 441 struct btinfo_common *bt; 442 char *help = bootinfo; 443 444 /* Check for a bootinfo record first. */ 445 if (help == NULL) 446 return (NULL); 447 448 do { 449 bt = (struct btinfo_common *)help; 450 if (bt->type == type) 451 return ((void *)help); 452 help += bt->next; 453 } while (bt->next != 0 && 454 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 455 456 return (NULL); 457 } 458 459 int waittime = -1; 460 461 /* 462 * call PROM to halt or reboot. 463 */ 464 void 465 prom_halt(howto) 466 int howto; 467 { 468 if (howto & RB_HALT) 469 MIPS_PROM(reinit)(); 470 MIPS_PROM(reboot)(); 471 /* NOTREACHED */ 472 } 473 474 void 475 cpu_reboot(howto, bootstr) 476 volatile int howto; 477 char *bootstr; 478 { 479 /* take a snap shot before clobbering any registers */ 480 if (curlwp) 481 savectx((struct user *)curpcb); 482 483 #ifdef DEBUG 484 if (panicstr) 485 stacktrace(); 486 #endif 487 488 /* If system is cold, just halt. */ 489 if (cold) { 490 howto |= RB_HALT; 491 goto haltsys; 492 } 493 494 /* If "always halt" was specified as a boot flag, obey. */ 495 if ((boothowto & RB_HALT) != 0) 496 howto |= RB_HALT; 497 498 boothowto = howto; 499 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 500 /* 501 * Synchronize the disks.... 502 */ 503 waittime = 0; 504 vfs_shutdown(); 505 506 /* 507 * If we've been adjusting the clock, the todr 508 * will be out of synch; adjust it now. 509 */ 510 resettodr(); 511 } 512 513 /* Disable interrupts. */ 514 splhigh(); 515 516 /* If rebooting and a dump is requested do it. */ 517 #if 0 518 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 519 #else 520 if (howto & RB_DUMP) 521 #endif 522 dumpsys(); 523 524 haltsys: 525 526 /* run any shutdown hooks */ 527 doshutdownhooks(); 528 529 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 530 prom_halt(0x80); /* rom monitor RB_PWOFF */ 531 532 /* Finally, halt/reboot the system. */ 533 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 534 prom_halt(howto & RB_HALT); 535 /*NOTREACHED*/ 536 } 537 538 int 539 initcpu() 540 { 541 spl0(); /* safe to turn interrupts on now */ 542 return 0; 543 } 544 545 static void 546 unimpl_cons_init() 547 { 548 549 panic("sysconf.init didn't set cons_init"); 550 } 551 552 static void 553 unimpl_iointr(mask, pc, statusreg, causereg) 554 u_int mask; 555 u_int pc; 556 u_int statusreg; 557 u_int causereg; 558 { 559 560 panic("sysconf.init didn't set intr"); 561 } 562 563 static int 564 unimpl_memsize(first) 565 void *first; 566 { 567 568 panic("sysconf.init didn't set memsize"); 569 } 570 571 void 572 unimpl_intr_establish(level, func, arg) 573 int level; 574 int (*func) __P((void *)); 575 void *arg; 576 { 577 panic("sysconf.init didn't init intr_establish"); 578 } 579 580 void 581 delay(n) 582 int n; 583 { 584 DELAY(n); 585 } 586 587 /* 588 * Find out how much memory is available by testing memory. 589 * Be careful to save and restore the original contents for msgbuf. 590 */ 591 int 592 memsize_scan(first) 593 void *first; 594 { 595 volatile int *vp, *vp0; 596 int mem, tmp, tmp0; 597 598 #define PATTERN1 0xa5a5a5a5 599 #define PATTERN2 ~PATTERN1 600 601 /* 602 * Non destructive scan of memory to determine the size 603 * Use the first page to test for memory aliases. This 604 * also has the side effect of flushing the bus alignment 605 * buffer 606 */ 607 mem = btoc((paddr_t)first - MIPS_KSEG0_START); 608 vp = (int *)MIPS_PHYS_TO_KSEG1(mem << PGSHIFT); 609 vp0 = (int *)MIPS_PHYS_TO_KSEG1(0); /* Start of physical memory */ 610 tmp0 = *vp0; 611 while (vp < (int *)MIPS_MAX_MEM_ADDR) { 612 tmp = *vp; 613 *vp = PATTERN1; 614 *vp0 = PATTERN2; 615 wbflush(); 616 if (*vp != PATTERN1) 617 break; 618 *vp = PATTERN2; 619 *vp0 = PATTERN1; 620 wbflush(); 621 if (*vp != PATTERN2) 622 break; 623 *vp = tmp; 624 vp += PAGE_SIZE/sizeof(int); 625 mem++; 626 } 627 *vp0 = tmp0; 628 return mem; 629 } 630 631 /* 632 * Console initialization: called early on from main, 633 * before vm init or startup. Do enough configuration 634 * to choose and initialize a console. 635 */ 636 637 static void 638 null_cnprobe(cn) 639 struct consdev *cn; 640 { 641 } 642 643 static void 644 prom_cninit(cn) 645 struct consdev *cn; 646 { 647 extern const struct cdevsw cons_cdevsw; 648 649 cn->cn_dev = makedev(cdevsw_lookup_major(&cons_cdevsw), 0); 650 cn->cn_pri = CN_REMOTE; 651 } 652 653 static int 654 prom_cngetc(dev) 655 dev_t dev; 656 { 657 return MIPS_PROM(getchar)(); 658 } 659 660 static void 661 prom_cnputc(dev, c) 662 dev_t dev; 663 int c; 664 { 665 MIPS_PROM(putchar)(c); 666 } 667 668 static void 669 null_cnpollc(dev, on) 670 dev_t dev; 671 int on; 672 { 673 } 674 675 void 676 consinit() 677 { 678 int zs_unit; 679 680 zs_unit = 0; 681 cn_tab = &consdev_zs; 682 683 (*cn_tab->cn_init)(cn_tab); 684 } 685