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