machdep.c revision 1.118
1/* $NetBSD: machdep.c,v 1.118 2016/07/21 19:49:59 christos 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.118 2016/07/21 19:49:59 christos 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 /* 244 * Set the VM page size. 245 */ 246 uvm_setpagesize(); 247 248 boothowto = x_boothowto; 249 bootdev = x_bootdev; 250 physmem = btoc(x_maxmem); 251 252 /* 253 * Now that we know how much memory we have, initialize the 254 * mem cluster array. 255 */ 256 mem_clusters[0].start = 0; /* XXX is this correct? */ 257 mem_clusters[0].size = ctob(physmem); 258 mem_cluster_cnt = 1; 259 260 /* 261 * Copy exception-dispatch code down to exception vector. 262 * Initialize locore-function vector. 263 * Clear out the I and D caches. 264 */ 265 mips_vector_init(NULL, false); 266 267 /* 268 * We know the CPU type now. Initialize our DMA tags (might 269 * need this early). 270 */ 271 newsmips_bus_dma_init(); 272 273#if NKSYMS || defined(DDB) || defined(MODULAR) 274 if (nsym) 275 ksyms_addsyms_elf(esym - ssym, ssym, esym); 276#endif 277 278#ifdef KADB 279 boothowto |= RB_KDB; 280#endif 281 282 /* 283 * Check to see if a mini-root was loaded into memory. It resides 284 * at the start of the next page just after the end of BSS. 285 */ 286 if (boothowto & RB_MINIROOT) 287 kernend += round_page(mfs_initminiroot(kernend)); 288 289 /* 290 * Load the rest of the available pages into the VM system. 291 */ 292 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 293 last = mem_clusters[0].start + mem_clusters[0].size; 294 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 295 VM_FREELIST_DEFAULT); 296 297 /* 298 * Initialize error message buffer (at end of core). 299 */ 300 mips_init_msgbuf(); 301 302 /* 303 * Initialize the virtual memory system. 304 */ 305 pmap_bootstrap(); 306 307 /* 308 * Allocate uarea page for lwp0 and set it. 309 */ 310 mips_init_lwp0_uarea(); 311 312 /* 313 * Determine what model of computer we are running on. 314 */ 315 switch (systype) { 316#ifdef news3400 317 case NEWS3400: 318 news3400_init(); 319 cpu_setmodel("%s", idrom.id_machine); 320 model = cpu_getmodel(); 321 if (strcmp(model, "news3400") == 0 || 322 strcmp(model, "news3200") == 0 || 323 strcmp(model, "news3700") == 0) { 324 /* 325 * Set up interrupt handling and I/O addresses. 326 */ 327 hardware_intr = news3400_intr; 328 cpuspeed = 10; 329 } else { 330 printf("kernel not configured for machine %s\n", model); 331 } 332 break; 333#endif 334 335#ifdef news5000 336 case NEWS5000: 337 news5000_init(); 338 cpu_setmodel("%s", idrom.id_machine); 339 model = cpu_getmodel(); 340 if (strcmp(model, "news5000") == 0 || 341 strcmp(model, "news5900") == 0) { 342 /* 343 * Set up interrupt handling and I/O addresses. 344 */ 345 hardware_intr = news5000_intr; 346 cpuspeed = 50; /* ??? XXX */ 347 } else { 348 printf("kernel not configured for machine %s\n", model); 349 } 350 break; 351#endif 352 353 default: 354 printf("kernel not configured for systype %d\n", systype); 355 break; 356 } 357} 358 359void 360mips_machdep_cache_config(void) 361{ 362 /* All r4k news boxen have a 1MB L2 cache. */ 363 if (CPUISMIPS3) 364 mips_cache_info.mci_sdcache_size = 1024 * 1024; 365} 366 367/* 368 * cpu_startup: allocate memory for variable-sized tables, 369 * initialize CPU, and do autoconfiguration. 370 */ 371void 372cpu_startup(void) 373{ 374 printf("SONY NET WORK STATION, Model %s, ", idrom.id_model); 375 printf("Machine ID #%d\n", idrom.id_serial); 376 377 cpu_startup_common(); 378} 379 380/* 381 * lookup_bootinfo: 382 * Look up information in bootinfo of boot loader. 383 */ 384void * 385lookup_bootinfo(int type) 386{ 387 struct btinfo_common *bt; 388 char *help = bootinfo; 389 390 /* Check for a bootinfo record first. */ 391 if (help == NULL) 392 return NULL; 393 394 do { 395 bt = (struct btinfo_common *)help; 396 if (bt->type == type) 397 return (void *)help; 398 help += bt->next; 399 } while (bt->next != 0 && 400 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 401 402 return NULL; 403} 404 405/* 406 * call PROM to halt or reboot. 407 */ 408void 409prom_halt(int howto) 410 411{ 412#ifdef news5000 413 if (systype == NEWS5000) 414 apcall_exit(howto); 415#endif 416#ifdef news3400 417 if (systype == NEWS3400) 418 to_monitor(howto); 419#endif 420 for (;;); 421} 422 423int waittime = -1; 424 425void 426cpu_reboot(volatile int howto, char *bootstr) 427{ 428 429 /* take a snap shot before clobbering any registers */ 430 savectx(curpcb); 431 432#ifdef DEBUG 433 if (panicstr) 434 stacktrace(); 435#endif 436 437 /* If system is cold, just halt. */ 438 if (cold) { 439 howto |= RB_HALT; 440 goto haltsys; 441 } 442 443 /* If "always halt" was specified as a boot flag, obey. */ 444 if ((boothowto & RB_HALT) != 0) 445 howto |= RB_HALT; 446 447 boothowto = howto; 448 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 449 /* 450 * Synchronize the disks.... 451 */ 452 waittime = 0; 453 vfs_shutdown(); 454 455 /* 456 * If we've been adjusting the clock, the todr 457 * will be out of synch; adjust it now. 458 */ 459 resettodr(); 460 } 461 462 /* Disable interrupts. */ 463 disable_intr(); 464 465 splhigh(); 466 467 /* If rebooting and a dump is requested do it. */ 468#if 0 469 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 470#else 471 if (howto & RB_DUMP) 472#endif 473 dumpsys(); 474 475haltsys: 476 477 /* run any shutdown hooks */ 478 doshutdownhooks(); 479 480 pmf_system_shutdown(boothowto); 481 482 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 483 prom_halt(0x80); /* rom monitor RB_PWOFF */ 484 485 /* Finally, halt/reboot the system. */ 486 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 487 prom_halt(howto & RB_HALT); 488 /*NOTREACHED*/ 489} 490 491void 492delay(int n) 493{ 494 495 DELAY(n); 496} 497 498void 499cpu_intr(int ppl, vaddr_t pc, uint32_t status) 500{ 501 curcpu()->ci_data.cpu_nintr++; 502 503 /* device interrupts */ 504 (*hardware_intr)(ppl, pc, status); 505} 506