machdep.c revision 1.119
1/* $NetBSD: machdep.c,v 1.119 2016/12/22 14:47:58 cherry Exp $ */ 2 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department, The Mach Operating System project at 11 * Carnegie-Mellon University and Ralph Campbell. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 38 */ 39 40#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 41 42__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.119 2016/12/22 14:47:58 cherry Exp $"); 43 44/* from: Utah Hdr: machdep.c 1.63 91/04/24 */ 45 46#include "opt_ddb.h" 47#include "opt_execfmt.h" 48#include "opt_modular.h" 49 50#define __INTR_PRIVATE 51 52#include <sys/param.h> 53#include <sys/systm.h> 54#include <sys/signalvar.h> 55#include <sys/kernel.h> 56#include <sys/proc.h> 57#include <sys/buf.h> 58#include <sys/reboot.h> 59#include <sys/conf.h> 60#include <sys/file.h> 61#include <sys/malloc.h> 62#include <sys/mbuf.h> 63#include <sys/msgbuf.h> 64#include <sys/ioctl.h> 65#include <sys/device.h> 66#include <sys/exec.h> 67#include <sys/mount.h> 68#include <sys/syscallargs.h> 69#include <sys/kcore.h> 70#include <sys/ksyms.h> 71#include <sys/cpu.h> 72#include <sys/intr.h> 73 74#include <uvm/uvm_extern.h> 75 76#include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 77 78#include <mips/cache.h> 79#include <mips/locore.h> 80 81#include <machine/reg.h> 82#include <machine/psl.h> 83#include <machine/pte.h> 84#include <machine/autoconf.h> 85#include <machine/bootinfo.h> 86#include <machine/apbus.h> 87#include <machine/apcall.h> 88 89 90#define _NEWSMIPS_BUS_DMA_PRIVATE 91#include <machine/bus.h> 92 93#ifdef DDB 94#include <machine/db_machdep.h> 95#include <ddb/db_access.h> 96#include <ddb/db_extern.h> 97#include <ddb/db_sym.h> 98#endif 99 100#include <machine/adrsmap.h> 101#include <machine/machConst.h> 102#include <newsmips/newsmips/machid.h> 103#include <dev/cons.h> 104 105#include "ksyms.h" 106 107/* maps for VM objects */ 108 109struct vm_map *phys_map = NULL; 110 111char *bootinfo = NULL; /* pointer to bootinfo structure */ 112int systype; /* what type of NEWS we are */ 113struct apbus_sysinfo *_sip = NULL; 114 115phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 116int mem_cluster_cnt; 117 118struct idrom idrom; 119void (*hardware_intr)(int, vaddr_t, uint32_t); 120void (*enable_intr)(void); 121void (*disable_intr)(void); 122void (*enable_timer)(void); 123 124/* 125 * Local functions. 126 */ 127 128/* initialize bss, etc. from kernel start, before main() is called. */ 129void mach_init(int, int, int, int); 130 131void prom_halt(int) __attribute__((__noreturn__)); 132void to_monitor(int) __attribute__((__noreturn__)); 133 134#ifdef DEBUG 135/* stacktrace code violates prototypes to get callee's registers */ 136extern void stacktrace(void); /*XXX*/ 137#endif 138 139extern u_long bootdev; 140extern char edata[], end[]; 141 142/* 143 * Do all the stuff that locore normally does before calling main(). 144 * Process arguments passed to us by the prom monitor. 145 * Return the first page address following the system. 146 */ 147void 148mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem) 149{ 150 u_long first, last; 151 char *kernend; 152 const char *model; 153 struct btinfo_magic *bi_magic; 154 struct btinfo_bootarg *bi_arg; 155 struct btinfo_systype *bi_systype; 156#if NKSYMS || defined(DDB) || defined(MODULAR) 157 struct btinfo_symtab *bi_sym; 158 int nsym = 0; 159 char *ssym, *esym; 160 161 ssym = esym = NULL; /* XXX: gcc */ 162#endif 163 bi_arg = NULL; 164 165 bootinfo = (void *)BOOTINFO_ADDR; /* XXX */ 166 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 167 if (bi_magic && bi_magic->magic == BOOTINFO_MAGIC) { 168 bi_arg = lookup_bootinfo(BTINFO_BOOTARG); 169 if (bi_arg) { 170 x_boothowto = bi_arg->howto; 171 x_bootdev = bi_arg->bootdev; 172 x_maxmem = bi_arg->maxmem; 173 } 174#if NKSYMS || defined(DDB) || defined(MODULAR) 175 bi_sym = lookup_bootinfo(BTINFO_SYMTAB); 176 if (bi_sym) { 177 nsym = bi_sym->nsym; 178 ssym = (void *)bi_sym->ssym; 179 esym = (void *)bi_sym->esym; 180 } 181#endif 182 183 bi_systype = lookup_bootinfo(BTINFO_SYSTYPE); 184 if (bi_systype) 185 systype = bi_systype->type; 186 } else { 187 /* 188 * Running kernel is loaded by non-native loader; 189 * clear the BSS segment here. 190 */ 191 memset(edata, 0, end - edata); 192 } 193 194 if (systype == 0) 195 systype = NEWS3400; /* XXX compatibility for old boot */ 196 197#ifdef news5000 198 if (systype == NEWS5000) { 199 int i; 200 char *bspec = (char *)x_bootdev; 201 202 if (bi_arg == NULL) 203 panic("news5000 requires BTINFO_BOOTARG to boot"); 204 205 _sip = (void *)bi_arg->sip; 206 x_maxmem = _sip->apbsi_memsize; 207 x_maxmem -= 0x00100000; /* reserve 1MB for ROM monitor */ 208 if (strncmp(bspec, "scsi", 4) == 0) { 209 x_bootdev = (5 << 28) | 0; /* magic, sd */ 210 bspec += 4; 211 if (*bspec != '(' /*)*/) 212 goto bootspec_end; 213 i = strtoul(bspec + 1, &bspec, 10); 214 x_bootdev |= (i << 24); /* bus */ 215 if (*bspec != ',') 216 goto bootspec_end; 217 i = strtoul(bspec + 1, &bspec, 10); 218 x_bootdev |= (i / 10) << 20; /* controller */ 219 x_bootdev |= (i % 10) << 16; /* unit */ 220 if (*bspec != ',') 221 goto bootspec_end; 222 i = strtoul(bspec + 1, &bspec, 10); 223 x_bootdev |= (i << 8); /* partition */ 224 } 225 bootspec_end: 226 consinit(); 227 } 228#endif 229 230 /* 231 * Save parameters into kernel work area. 232 */ 233 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_MAXMEMSIZE_ADDR)) = x_maxmem; 234 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTDEV_ADDR)) = x_bootdev; 235 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTSW_ADDR)) = x_boothowto; 236 237 kernend = (char *)mips_round_page(end); 238#if NKSYMS || defined(DDB) || defined(MODULAR) 239 if (nsym) 240 kernend = (char *)mips_round_page(esym); 241#endif 242 243 uvm_md_init(); 244 245 boothowto = x_boothowto; 246 bootdev = x_bootdev; 247 physmem = btoc(x_maxmem); 248 249 /* 250 * Now that we know how much memory we have, initialize the 251 * mem cluster array. 252 */ 253 mem_clusters[0].start = 0; /* XXX is this correct? */ 254 mem_clusters[0].size = ctob(physmem); 255 mem_cluster_cnt = 1; 256 257 /* 258 * Copy exception-dispatch code down to exception vector. 259 * Initialize locore-function vector. 260 * Clear out the I and D caches. 261 */ 262 mips_vector_init(NULL, false); 263 264 /* 265 * We know the CPU type now. Initialize our DMA tags (might 266 * need this early). 267 */ 268 newsmips_bus_dma_init(); 269 270#if NKSYMS || defined(DDB) || defined(MODULAR) 271 if (nsym) 272 ksyms_addsyms_elf(esym - ssym, ssym, esym); 273#endif 274 275#ifdef KADB 276 boothowto |= RB_KDB; 277#endif 278 279 /* 280 * Check to see if a mini-root was loaded into memory. It resides 281 * at the start of the next page just after the end of BSS. 282 */ 283 if (boothowto & RB_MINIROOT) 284 kernend += round_page(mfs_initminiroot(kernend)); 285 286 /* 287 * Load the rest of the available pages into the VM system. 288 */ 289 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 290 last = mem_clusters[0].start + mem_clusters[0].size; 291 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 292 VM_FREELIST_DEFAULT); 293 294 /* 295 * Initialize error message buffer (at end of core). 296 */ 297 mips_init_msgbuf(); 298 299 /* 300 * Initialize the virtual memory system. 301 */ 302 pmap_bootstrap(); 303 304 /* 305 * Allocate uarea page for lwp0 and set it. 306 */ 307 mips_init_lwp0_uarea(); 308 309 /* 310 * Determine what model of computer we are running on. 311 */ 312 switch (systype) { 313#ifdef news3400 314 case NEWS3400: 315 news3400_init(); 316 cpu_setmodel("%s", idrom.id_machine); 317 model = cpu_getmodel(); 318 if (strcmp(model, "news3400") == 0 || 319 strcmp(model, "news3200") == 0 || 320 strcmp(model, "news3700") == 0) { 321 /* 322 * Set up interrupt handling and I/O addresses. 323 */ 324 hardware_intr = news3400_intr; 325 cpuspeed = 10; 326 } else { 327 printf("kernel not configured for machine %s\n", model); 328 } 329 break; 330#endif 331 332#ifdef news5000 333 case NEWS5000: 334 news5000_init(); 335 cpu_setmodel("%s", idrom.id_machine); 336 model = cpu_getmodel(); 337 if (strcmp(model, "news5000") == 0 || 338 strcmp(model, "news5900") == 0) { 339 /* 340 * Set up interrupt handling and I/O addresses. 341 */ 342 hardware_intr = news5000_intr; 343 cpuspeed = 50; /* ??? XXX */ 344 } else { 345 printf("kernel not configured for machine %s\n", model); 346 } 347 break; 348#endif 349 350 default: 351 printf("kernel not configured for systype %d\n", systype); 352 break; 353 } 354} 355 356void 357mips_machdep_cache_config(void) 358{ 359 /* All r4k news boxen have a 1MB L2 cache. */ 360 if (CPUISMIPS3) 361 mips_cache_info.mci_sdcache_size = 1024 * 1024; 362} 363 364/* 365 * cpu_startup: allocate memory for variable-sized tables, 366 * initialize CPU, and do autoconfiguration. 367 */ 368void 369cpu_startup(void) 370{ 371 printf("SONY NET WORK STATION, Model %s, ", idrom.id_model); 372 printf("Machine ID #%d\n", idrom.id_serial); 373 374 cpu_startup_common(); 375} 376 377/* 378 * lookup_bootinfo: 379 * Look up information in bootinfo of boot loader. 380 */ 381void * 382lookup_bootinfo(int type) 383{ 384 struct btinfo_common *bt; 385 char *help = bootinfo; 386 387 /* Check for a bootinfo record first. */ 388 if (help == NULL) 389 return NULL; 390 391 do { 392 bt = (struct btinfo_common *)help; 393 if (bt->type == type) 394 return (void *)help; 395 help += bt->next; 396 } while (bt->next != 0 && 397 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 398 399 return NULL; 400} 401 402/* 403 * call PROM to halt or reboot. 404 */ 405void 406prom_halt(int howto) 407 408{ 409#ifdef news5000 410 if (systype == NEWS5000) 411 apcall_exit(howto); 412#endif 413#ifdef news3400 414 if (systype == NEWS3400) 415 to_monitor(howto); 416#endif 417 for (;;); 418} 419 420int waittime = -1; 421 422void 423cpu_reboot(volatile int howto, char *bootstr) 424{ 425 426 /* take a snap shot before clobbering any registers */ 427 savectx(curpcb); 428 429#ifdef DEBUG 430 if (panicstr) 431 stacktrace(); 432#endif 433 434 /* If system is cold, just halt. */ 435 if (cold) { 436 howto |= RB_HALT; 437 goto haltsys; 438 } 439 440 /* If "always halt" was specified as a boot flag, obey. */ 441 if ((boothowto & RB_HALT) != 0) 442 howto |= RB_HALT; 443 444 boothowto = howto; 445 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 446 /* 447 * Synchronize the disks.... 448 */ 449 waittime = 0; 450 vfs_shutdown(); 451 452 /* 453 * If we've been adjusting the clock, the todr 454 * will be out of synch; adjust it now. 455 */ 456 resettodr(); 457 } 458 459 /* Disable interrupts. */ 460 disable_intr(); 461 462 splhigh(); 463 464 /* If rebooting and a dump is requested do it. */ 465#if 0 466 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 467#else 468 if (howto & RB_DUMP) 469#endif 470 dumpsys(); 471 472haltsys: 473 474 /* run any shutdown hooks */ 475 doshutdownhooks(); 476 477 pmf_system_shutdown(boothowto); 478 479 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 480 prom_halt(0x80); /* rom monitor RB_PWOFF */ 481 482 /* Finally, halt/reboot the system. */ 483 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 484 prom_halt(howto & RB_HALT); 485 /*NOTREACHED*/ 486} 487 488void 489delay(int n) 490{ 491 492 DELAY(n); 493} 494 495void 496cpu_intr(int ppl, vaddr_t pc, uint32_t status) 497{ 498 curcpu()->ci_data.cpu_nintr++; 499 500 /* device interrupts */ 501 (*hardware_intr)(ppl, pc, status); 502} 503