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