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