machdep.c revision 1.81
1/* $NetBSD: machdep.c,v 1.81 2005/04/25 15:02:06 lukem 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.81 2005/04/25 15:02:06 lukem Exp $"); 80 81/* from: Utah Hdr: machdep.c 1.63 91/04/24 */ 82 83#include "fs_mfs.h" 84#include "opt_ddb.h" 85#include "opt_execfmt.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/malloc.h> 97#include <sys/mbuf.h> 98#include <sys/msgbuf.h> 99#include <sys/ioctl.h> 100#include <sys/device.h> 101#include <sys/user.h> 102#include <sys/exec.h> 103#include <sys/mount.h> 104#include <sys/sa.h> 105#include <sys/syscallargs.h> 106#include <sys/kcore.h> 107#include <sys/ksyms.h> 108 109#include <uvm/uvm_extern.h> 110 111#include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 112 113#include <machine/cpu.h> 114#include <machine/intr.h> 115#include <machine/reg.h> 116#include <machine/psl.h> 117#include <machine/pte.h> 118#include <machine/autoconf.h> 119#include <machine/bootinfo.h> 120#include <machine/apbus.h> 121#include <machine/apcall.h> 122 123#include <mips/cache.h> 124#include <mips/locore.h> 125 126#define _NEWSMIPS_BUS_DMA_PRIVATE 127#include <machine/bus.h> 128 129#ifdef DDB 130#include <machine/db_machdep.h> 131#include <ddb/db_access.h> 132#include <ddb/db_extern.h> 133#include <ddb/db_sym.h> 134#endif 135 136#include <machine/adrsmap.h> 137#include <machine/machConst.h> 138#include <machine/intr.h> 139#include <newsmips/newsmips/machid.h> 140#include <dev/cons.h> 141 142#include "ksyms.h" 143 144/* the following is used externally (sysctl_hw) */ 145extern char cpu_model[]; 146 147/* Our exported CPU info; we can have only one. */ 148struct cpu_info cpu_info_store; 149 150/* maps for VM objects */ 151 152struct vm_map *exec_map = NULL; 153struct vm_map *mb_map = NULL; 154struct vm_map *phys_map = NULL; 155 156char *bootinfo = NULL; /* pointer to bootinfo structure */ 157int physmem; /* max supported memory, changes to actual */ 158int systype; /* what type of NEWS we are */ 159struct apbus_sysinfo *_sip = NULL; 160 161phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 162int mem_cluster_cnt; 163 164struct idrom idrom; 165void (*readmicrotime)(struct timeval *tvp); 166void (*hardware_intr)(uint32_t, uint32_t, uint32_t, uint32_t); 167void (*enable_intr)(void); 168void (*disable_intr)(void); 169void (*enable_timer)(void); 170 171/* 172 * Local functions. 173 */ 174 175/* initialize bss, etc. from kernel start, before main() is called. */ 176void mach_init(int, int, int, int); 177 178void prom_halt(int) __attribute__((__noreturn__)); 179void to_monitor(int) __attribute__((__noreturn__)); 180 181#ifdef DEBUG 182/* stacktrace code violates prototypes to get callee's registers */ 183extern void stacktrace(void); /*XXX*/ 184#endif 185 186/* 187 * safepri is a safe priority for sleep to set for a spin-wait 188 * during autoconfiguration or after a panic. Used as an argument to splx(). 189 * XXX disables interrupt 5 to disable mips3 on-chip clock, which also 190 * disables mips1 FPU interrupts. 191 */ 192int safepri = MIPS3_PSL_LOWIPL; /* XXX */ 193 194/* 195 * This is a mask of bits to clear in the SR when we go to a 196 * given interrupt priority level. 197 */ 198const uint32_t ipl_sr_bits[_IPL_N] = { 199 0, /* IPL_NONE */ 200 201 MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ 202 203 MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ 204 205 MIPS_SOFT_INT_MASK_0| 206 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ 207 208 MIPS_SOFT_INT_MASK_0| 209 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ 210 211 MIPS_SOFT_INT_MASK_0| 212 MIPS_SOFT_INT_MASK_1| 213 MIPS_INT_MASK_0, /* IPL_BIO */ 214 215 MIPS_SOFT_INT_MASK_0| 216 MIPS_SOFT_INT_MASK_1| 217 MIPS_INT_MASK_0| 218 MIPS_INT_MASK_1, /* IPL_NET */ 219 220 MIPS_SOFT_INT_MASK_0| 221 MIPS_SOFT_INT_MASK_1| 222 MIPS_INT_MASK_0| 223 MIPS_INT_MASK_1, /* IPL_{TTY,SERIAL} */ 224 225 MIPS_SOFT_INT_MASK_0| 226 MIPS_SOFT_INT_MASK_1| 227 MIPS_INT_MASK_0| 228 MIPS_INT_MASK_1| 229 MIPS_INT_MASK_2, /* IPL_{CLOCK,HIGH} */ 230}; 231 232const uint32_t mips_ipl_si_to_sr[_IPL_NSOFT] = { 233 MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ 234 MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ 235 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ 236 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ 237}; 238 239extern struct user *proc0paddr; 240extern u_long bootdev; 241extern char edata[], end[]; 242 243/* 244 * Do all the stuff that locore normally does before calling main(). 245 * Process arguments passed to us by the prom monitor. 246 * Return the first page address following the system. 247 */ 248void 249mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem) 250{ 251 u_long first, last; 252 caddr_t kernend, v; 253 struct btinfo_magic *bi_magic; 254 struct btinfo_bootarg *bi_arg; 255 struct btinfo_systype *bi_systype; 256#if NKSYMS || defined(DDB) || defined(LKM) 257 struct btinfo_symtab *bi_sym; 258 int nsym = 0; 259 char *ssym, *esym; 260 261 ssym = esym = NULL; /* XXX: gcc */ 262#endif 263 bi_arg = NULL; 264 265 /* clear the BSS segment */ 266 memset(edata, 0, end - edata); 267 268 systype = NEWS3400; /* XXX compatibility */ 269 270 bootinfo = (void *)BOOTINFO_ADDR; /* XXX */ 271 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 272 if (bi_magic && bi_magic->magic == BOOTINFO_MAGIC) { 273 bi_arg = lookup_bootinfo(BTINFO_BOOTARG); 274 if (bi_arg) { 275 x_boothowto = bi_arg->howto; 276 x_bootdev = bi_arg->bootdev; 277 x_maxmem = bi_arg->maxmem; 278 } 279#if NKSYMS || defined(DDB) || defined(LKM) 280 bi_sym = lookup_bootinfo(BTINFO_SYMTAB); 281 if (bi_sym) { 282 nsym = bi_sym->nsym; 283 ssym = (void *)bi_sym->ssym; 284 esym = (void *)bi_sym->esym; 285 } 286#endif 287 288 bi_systype = lookup_bootinfo(BTINFO_SYSTYPE); 289 if (bi_systype) 290 systype = bi_systype->type; 291 } 292 293#ifdef news5000 294 if (systype == NEWS5000) { 295 int i; 296 char *bootspec = (char *)x_bootdev; 297 298 if (bi_arg == NULL) 299 panic("news5000 requires BTINFO_BOOTARG to boot"); 300 301 _sip = (void *)bi_arg->sip; 302 x_maxmem = _sip->apbsi_memsize; 303 x_maxmem -= 0x00100000; /* reserve 1MB for ROM monitor */ 304 if (strncmp(bootspec, "scsi", 4) == 0) { 305 x_bootdev = (5 << 28) | 0; /* magic, sd */ 306 bootspec += 4; 307 if (*bootspec != '(' /*)*/) 308 goto bootspec_end; 309 i = strtoul(bootspec + 1, &bootspec, 10); 310 x_bootdev |= (i << 24); /* bus */ 311 if (*bootspec != ',') 312 goto bootspec_end; 313 i = strtoul(bootspec + 1, &bootspec, 10); 314 x_bootdev |= (i / 10) << 20; /* controller */ 315 x_bootdev |= (i % 10) << 16; /* unit */ 316 if (*bootspec != ',') 317 goto bootspec_end; 318 i = strtoul(bootspec + 1, &bootspec, 10); 319 x_bootdev |= (i << 8); /* partition */ 320 } 321 bootspec_end: 322 consinit(); 323 } 324#endif 325 326 /* 327 * Save parameters into kernel work area. 328 */ 329 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_MAXMEMSIZE_ADDR)) = x_maxmem; 330 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTDEV_ADDR)) = x_bootdev; 331 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTSW_ADDR)) = x_boothowto; 332 333 kernend = (caddr_t)mips_round_page(end); 334#if NKSYMS || defined(DDB) || defined(LKM) 335 if (nsym) 336 kernend = (caddr_t)mips_round_page(esym); 337#endif 338 339 /* 340 * Set the VM page size. 341 */ 342 uvm_setpagesize(); 343 344 boothowto = x_boothowto; 345 bootdev = x_bootdev; 346 physmem = btoc(x_maxmem); 347 348 /* 349 * Now that we know how much memory we have, initialize the 350 * mem cluster array. 351 */ 352 mem_clusters[0].start = 0; /* XXX is this correct? */ 353 mem_clusters[0].size = ctob(physmem); 354 mem_cluster_cnt = 1; 355 356 /* 357 * Copy exception-dispatch code down to exception vector. 358 * Initialize locore-function vector. 359 * Clear out the I and D caches. 360 */ 361 mips_vector_init(); 362 363 /* 364 * We know the CPU type now. Initialize our DMA tags (might 365 * need this early). 366 */ 367 newsmips_bus_dma_init(); 368 369#if NKSYMS || defined(DDB) || defined(LKM) 370 if (nsym) 371 ksyms_init(esym - ssym, ssym, esym); 372#endif 373 374#ifdef KADB 375 boothowto |= RB_KDB; 376#endif 377 378#ifdef MFS 379 /* 380 * Check to see if a mini-root was loaded into memory. It resides 381 * at the start of the next page just after the end of BSS. 382 */ 383 if (boothowto & RB_MINIROOT) 384 kernend += round_page(mfs_initminiroot(kernend)); 385#endif 386 387 /* 388 * Load the rest of the available pages into the VM system. 389 */ 390 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 391 last = mem_clusters[0].start + mem_clusters[0].size; 392 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 393 VM_FREELIST_DEFAULT); 394 395 /* 396 * Initialize error message buffer (at end of core). 397 */ 398 mips_init_msgbuf(); 399 400 /* 401 * Initialize the virtual memory system. 402 */ 403 pmap_bootstrap(); 404 405 /* 406 * Allocate space for lwp0's USPACE. 407 */ 408 v = (caddr_t)uvm_pageboot_alloc(USPACE); 409 lwp0.l_addr = proc0paddr = (struct user *)v; 410 lwp0.l_md.md_regs = (struct frame *)(v + USPACE) - 1; 411 curpcb = &lwp0.l_addr->u_pcb; 412 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 413 414 /* 415 * Determine what model of computer we are running on. 416 */ 417 switch (systype) { 418#ifdef news3400 419 case NEWS3400: 420 news3400_init(); 421 strcpy(cpu_model, idrom.id_machine); 422 if (strcmp(cpu_model, "news3400") == 0 || 423 strcmp(cpu_model, "news3200") == 0 || 424 strcmp(cpu_model, "news3700") == 0) { 425 /* 426 * Set up interrupt handling and I/O addresses. 427 */ 428 hardware_intr = news3400_intr; 429 cpuspeed = 10; 430 } else { 431 printf("kernel not configured for machine %s\n", 432 cpu_model); 433 } 434 break; 435#endif 436 437#ifdef news5000 438 case NEWS5000: 439 news5000_init(); 440 strcpy(cpu_model, idrom.id_machine); 441 if (strcmp(cpu_model, "news5000") == 0 || 442 strcmp(cpu_model, "news5900") == 0) { 443 /* 444 * Set up interrupt handling and I/O addresses. 445 */ 446 hardware_intr = news5000_intr; 447 cpuspeed = 50; /* ??? XXX */ 448 } else { 449 printf("kernel not configured for machine %s\n", 450 cpu_model); 451 } 452 break; 453#endif 454 455 default: 456 printf("kernel not configured for systype %d\n", systype); 457 break; 458 } 459} 460 461void 462mips_machdep_cache_config(void) 463{ 464 /* All r4k news boxen have a 1MB L2 cache. */ 465 if (CPUISMIPS3) 466 mips_sdcache_size = 1024 * 1024; 467} 468 469/* 470 * cpu_startup: allocate memory for variable-sized tables, 471 * initialize CPU, and do autoconfiguration. 472 */ 473void 474cpu_startup(void) 475{ 476 vaddr_t minaddr, maxaddr; 477 char pbuf[9]; 478#ifdef DEBUG 479 extern int pmapdebug; 480 int opmapdebug = pmapdebug; 481 482 pmapdebug = 0; 483#endif 484 485 /* 486 * Good {morning,afternoon,evening,night}. 487 */ 488 printf("%s%s", copyright, version); 489 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 490 printf("total memory = %s\n", pbuf); 491 492 minaddr = 0; 493 /* 494 * Allocate a submap for exec arguments. This map effectively 495 * limits the number of processes exec'ing at any time. 496 */ 497 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 498 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 499 /* 500 * Allocate a submap for physio 501 */ 502 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 503 VM_PHYS_SIZE, 0, FALSE, NULL); 504 505 /* 506 * No need to allocate an mbuf cluster submap. Mbuf clusters 507 * are allocated via the pool allocator, and we use KSEG to 508 * map those pages. 509 */ 510 511#ifdef DEBUG 512 pmapdebug = opmapdebug; 513#endif 514 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 515 printf("avail memory = %s\n", pbuf); 516} 517 518/* 519 * lookup_bootinfo: 520 * Look up information in bootinfo of boot loader. 521 */ 522void * 523lookup_bootinfo(int type) 524{ 525 struct btinfo_common *bt; 526 char *help = bootinfo; 527 528 /* Check for a bootinfo record first. */ 529 if (help == NULL) 530 return NULL; 531 532 do { 533 bt = (struct btinfo_common *)help; 534 if (bt->type == type) 535 return (void *)help; 536 help += bt->next; 537 } while (bt->next != 0 && 538 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 539 540 return NULL; 541} 542 543/* 544 * call PROM to halt or reboot. 545 */ 546void 547prom_halt(int howto) 548 549{ 550#ifdef news5000 551 if (systype == NEWS5000) 552 apcall_exit(howto); 553#endif 554#ifdef news3400 555 if (systype == NEWS3400) 556 to_monitor(howto); 557#endif 558 for (;;); 559} 560 561int waittime = -1; 562 563void 564cpu_reboot(volatile int howto, char *bootstr) 565{ 566 567 /* take a snap shot before clobbering any registers */ 568 if (curlwp) 569 savectx((struct user *)curpcb); 570 571#ifdef DEBUG 572 if (panicstr) 573 stacktrace(); 574#endif 575 576 /* If system is cold, just halt. */ 577 if (cold) { 578 howto |= RB_HALT; 579 goto haltsys; 580 } 581 582 /* If "always halt" was specified as a boot flag, obey. */ 583 if ((boothowto & RB_HALT) != 0) 584 howto |= RB_HALT; 585 586 boothowto = howto; 587 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 588 /* 589 * Synchronize the disks.... 590 */ 591 waittime = 0; 592 vfs_shutdown(); 593 594 /* 595 * If we've been adjusting the clock, the todr 596 * will be out of synch; adjust it now. 597 */ 598 resettodr(); 599 } 600 601 /* Disable interrupts. */ 602 disable_intr(); 603 604 splhigh(); 605 606 /* If rebooting and a dump is requested do it. */ 607#if 0 608 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 609#else 610 if (howto & RB_DUMP) 611#endif 612 dumpsys(); 613 614haltsys: 615 616 /* run any shutdown hooks */ 617 doshutdownhooks(); 618 619 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 620 prom_halt(0x80); /* rom monitor RB_PWOFF */ 621 622 /* Finally, halt/reboot the system. */ 623 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 624 prom_halt(howto & RB_HALT); 625 /*NOTREACHED*/ 626} 627 628/* 629 * Return the best possible estimate of the time in the timeval 630 * to which tvp points. Unfortunately, we can't read the hardware registers. 631 * We guarantee that the time will be greater than the value obtained by a 632 * previous call. 633 */ 634void 635microtime(struct timeval *tvp) 636{ 637 int s = splclock(); 638 static struct timeval lasttime; 639 640 if (readmicrotime) 641 readmicrotime(tvp); 642 else 643 *tvp = time; 644 645 if (tvp->tv_sec == lasttime.tv_sec && 646 tvp->tv_usec <= lasttime.tv_usec && 647 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 648 tvp->tv_sec++; 649 tvp->tv_usec -= 1000000; 650 } 651 lasttime = *tvp; 652 splx(s); 653} 654 655void 656delay(int n) 657{ 658 659 DELAY(n); 660} 661 662void 663cpu_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 664{ 665 666 uvmexp.intrs++; 667 668 /* device interrupts */ 669 (*hardware_intr)(status, cause, pc, ipending); 670 671 /* software interrupts */ 672 ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0); 673 if (ipending == 0) 674 return; 675 676 _clrsoftintr(ipending); 677 678 softintr_dispatch(ipending); 679} 680