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