machdep.c revision 1.22
1/* $NetBSD: machdep.c,v 1.22 2003/09/26 16:00:28 simonb Exp $ */ 2 3/* 4 * Copyright 2000, 2001 5 * Broadcom Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and copied only 8 * in accordance with the following terms and conditions. Subject to these 9 * conditions, you may download, copy, install, use, modify and distribute 10 * modified or unmodified copies of this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce and 14 * retain this copyright notice and list of conditions as they appear in 15 * the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Broadcom Corporation. The "Broadcom Corporation" name may not be 19 * used to endorse or promote products derived from this software 20 * without the prior written permission of Broadcom Corporation. 21 * 22 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 25 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE 26 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE 27 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35/* 36 * Copyright (c) 2000 Soren S. Jorvang. All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions, and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 */ 59 60#include <sys/cdefs.h> 61__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.22 2003/09/26 16:00:28 simonb Exp $"); 62 63#include "opt_ddb.h" 64#include "opt_execfmt.h" 65 66#include <sys/param.h> 67#include <sys/systm.h> 68#include <sys/kernel.h> 69#include <sys/proc.h> 70#include <sys/buf.h> 71#include <sys/reboot.h> 72#include <sys/conf.h> 73#include <sys/file.h> 74#include <sys/malloc.h> 75#include <sys/mbuf.h> 76#include <sys/msgbuf.h> 77#include <sys/device.h> 78#include <sys/user.h> 79#include <sys/exec.h> 80#include <sys/mount.h> 81#include <sys/sa.h> 82#include <sys/syscallargs.h> 83#include <sys/kcore.h> 84#include <sys/ksyms.h> 85 86#include <uvm/uvm_extern.h> 87 88#include <machine/cpu.h> 89#include <machine/reg.h> 90#include <machine/psl.h> 91#include <machine/pte.h> 92#include <machine/autoconf.h> 93#include <machine/intr.h> 94#include <machine/swarm.h> 95#include <mips/locore.h> 96 97#include <mips/cfe/cfe_api.h> 98 99#if 0 /* XXXCGD */ 100#include <machine/nvram.h> 101#endif /* XXXCGD */ 102#include <machine/leds.h> 103 104#include "ksyms.h" 105 106#if NKSYMS || defined(DDB) || defined(LKM) 107#include <machine/db_machdep.h> 108#include <ddb/db_access.h> 109#include <ddb/db_sym.h> 110#include <ddb/db_extern.h> 111#ifndef DB_ELFSIZE 112#error Must define DB_ELFSIZE! 113#endif 114#define ELFSIZE DB_ELFSIZE 115#include <sys/exec_elf.h> 116#endif 117 118#include <dev/cons.h> 119 120#if NKSYMS || defined(DDB) || defined(LKM) 121/* start and end of kernel symbol table */ 122void *ksym_start, *ksym_end; 123#endif 124 125/* For sysctl_hw. */ 126extern char cpu_model[]; 127 128/* Our exported CPU info. Only one for now */ 129struct cpu_info cpu_info_store; 130 131/* Maps for VM objects. */ 132struct vm_map *exec_map = NULL; 133struct vm_map *mb_map = NULL; 134struct vm_map *phys_map = NULL; 135 136int physmem; /* Total physical memory */ 137 138char bootstring[512]; /* Boot command */ 139int netboot; /* Are we netbooting? */ 140int cfe_present; 141 142struct bootinfo_v1 bootinfo; 143 144phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 145int mem_cluster_cnt; 146 147void configure(void); 148void mach_init(long, long, long, long); 149 150/* 151 * safepri is a safe priority for sleep to set for a spin-wait during 152 * autoconfiguration or after a panic. Used as an argument to splx(). 153 */ 154int safepri = MIPS_INT_MASK | MIPS_SR_INT_IE; 155 156extern caddr_t esym; 157extern struct user *proc0paddr; 158 159/* 160 * Do all the stuff that locore normally does before calling main(). 161 */ 162void 163mach_init(long fwhandle, long magic, long bootdata, long reserved) 164{ 165 caddr_t kernend, v, p0; 166 u_long first, last; 167 vsize_t size; 168 extern char edata[], end[]; 169 int i; 170 uint32_t config; 171 172 /* XXX this code must run on the target cpu */ 173 config = mips3_cp0_config_read(); 174 config &= ~MIPS3_CONFIG_K0_MASK; 175 config |= 0x05; /* XXX. cacheable coherent */ 176 mips3_cp0_config_write(config); 177 178 /* Zero BSS. XXXCGD: uh, is this really necessary still? */ 179 memset(edata, 0, end - edata); 180 181 /* 182 * Copy the bootinfo structure from the boot loader. 183 * this has to be done before mips_vector_init is 184 * called because we may need CFE's TLB handler 185 */ 186 187 if (magic == BOOTINFO_MAGIC) 188 memcpy(&bootinfo, (struct bootinfo_v1 *)bootdata, 189 sizeof bootinfo); 190 else if (reserved == CFE_EPTSEAL) { 191 magic = BOOTINFO_MAGIC; 192 bzero(&bootinfo, sizeof bootinfo); 193 bootinfo.version = BOOTINFO_VERSION; 194 bootinfo.fwhandle = fwhandle; 195 bootinfo.fwentry = bootdata; 196 bootinfo.ssym = (vaddr_t)end; 197 bootinfo.esym = (vaddr_t)end; 198 } 199 200 kernend = (caddr_t)mips_round_page(end); 201#if NKSYMS || defined(DDB) || defined(LKM) 202 if (magic == BOOTINFO_MAGIC) { 203 ksym_start = (void *)bootinfo.ssym; 204 ksym_end = (void *)bootinfo.esym; 205 kernend = (caddr_t)mips_round_page((vaddr_t)ksym_end); 206 } 207#endif 208 209 consinit(); 210 211 uvm_setpagesize(); 212 213 /* 214 * Copy exception-dispatch code down to exception vector. 215 * Initialize locore-function vector. 216 * Clear out the I and D caches. 217 */ 218 mips_vector_init(); 219 220#ifdef DEBUG 221 printf("fwhandle=%08X magic=%08X bootdata=%08X reserved=%08X\n", 222 (u_int)fwhandle, (u_int)magic, (u_int)bootdata, (u_int)reserved); 223#endif 224 225 strcpy(cpu_model, "sb1250"); 226 227 if (magic == BOOTINFO_MAGIC) { 228 int idx; 229 int added; 230 uint64_t start, len, type; 231 232 cfe_init(bootinfo.fwhandle, bootinfo.fwentry); 233 cfe_present = 1; 234 235 idx = 0; 236 physmem = 0; 237 mem_cluster_cnt = 0; 238 while (cfe_enummem(idx, 0, &start, &len, &type) == 0) { 239 added = 0; 240 printf("Memory Block #%d start %08llX len %08llX: %s: ", 241 idx, start, len, (type == CFE_MI_AVAILABLE) ? 242 "Available" : "Reserved"); 243 if ((type == CFE_MI_AVAILABLE) && 244 (mem_cluster_cnt < VM_PHYSSEG_MAX)) { 245 /* 246 * XXX Ignore memory above 256MB for now, it 247 * XXX needs special handling. 248 */ 249 if (start < (256*1024*1024)) { 250 physmem += btoc(((int) len)); 251 mem_clusters[mem_cluster_cnt].start = 252 (long) start; 253 mem_clusters[mem_cluster_cnt].size = 254 (long) len; 255 mem_cluster_cnt++; 256 added = 1; 257 } 258 } 259 if (added) 260 printf("added to map\n"); 261 else 262 printf("not added to map\n"); 263 idx++; 264 } 265 266 } else { 267 /* 268 * Handle the case of not being called from the firmware. 269 */ 270 /* XXX hardwire to 32MB; should be kernel config option */ 271 physmem = 32 * 1024 * 1024 / 4096; 272 mem_clusters[0].start = 0; 273 mem_clusters[0].size = ctob(physmem); 274 mem_cluster_cnt = 1; 275 } 276 277 278 for (i = 0; i < sizeof(bootinfo.boot_flags); i++) { 279 switch (bootinfo.boot_flags[i]) { 280 case '\0': 281 break; 282 case ' ': 283 continue; 284 case '-': 285 while (bootinfo.boot_flags[i] != ' ' && 286 bootinfo.boot_flags[i] != '\0') { 287 switch (bootinfo.boot_flags[i]) { 288 case 'a': 289 boothowto |= RB_ASKNAME; 290 break; 291 case 'd': 292 boothowto |= RB_KDB; 293 break; 294 case 's': 295 boothowto |= RB_SINGLE; 296 break; 297 } 298 i++; 299 } 300 } 301 } 302 303 /* 304 * Load the rest of the available pages into the VM system. 305 * The first chunk is tricky because we have to avoid the 306 * kernel, but the rest are easy. 307 */ 308 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 309 last = mem_clusters[0].start + mem_clusters[0].size; 310 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 311 VM_FREELIST_DEFAULT); 312 313 for (i = 1; i < mem_cluster_cnt; i++) { 314 first = round_page(mem_clusters[i].start); 315 last = mem_clusters[i].start + mem_clusters[i].size; 316 uvm_page_physload(atop(first), atop(last), atop(first), 317 atop(last), VM_FREELIST_DEFAULT); 318 } 319 320 /* 321 * Initialize error message buffer (at end of core). 322 */ 323 mips_init_msgbuf(); 324 325 /* 326 * Allocate space for proc0's USPACE 327 */ 328 p0 = (caddr_t)pmap_steal_memory(USPACE, NULL, NULL); 329 lwp0.l_addr = proc0paddr = (struct user *)p0; 330 lwp0.l_md.md_regs = (struct frame *)(p0 + USPACE) - 1; 331 curpcb = &lwp0.l_addr->u_pcb; 332 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 333 334 /* 335 * Allocate space for system data structures. These data structures 336 * are allocated here instead of cpu_startup() because physical 337 * memory is directly addressable. We don't have to map these into 338 * virtual address space. 339 */ 340 size = (vsize_t)allocsys(NULL, NULL); 341 v = (caddr_t)pmap_steal_memory(size, NULL, NULL); 342 if ((allocsys(v, NULL) - v) != size) 343 panic("mach_init: table size inconsistency"); 344 345 pmap_bootstrap(); 346 347 /* 348 * Initialize debuggers, and break into them, if appropriate. 349 */ 350#if NKSYMS || defined(DDB) || defined(LKM) 351 ksyms_init(((uintptr_t)ksym_end - (uintptr_t)ksym_start), 352 ksym_start, ksym_end); 353#endif 354 355 if (boothowto & RB_KDB) { 356#if defined(DDB) 357 Debugger(); 358#endif 359 } 360} 361 362/* 363 * Allocate memory for variable-sized tables, 364 */ 365void 366cpu_startup(void) 367{ 368 u_int i, base, residual; 369 vaddr_t minaddr, maxaddr; 370 vsize_t size; 371 char pbuf[9]; 372 373 /* 374 * Good {morning,afternoon,evening,night}. 375 */ 376 printf(version); 377 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 378 printf("%s memory", pbuf); 379 380 /* 381 * Allocate virtual address space for file I/O buffers. 382 * Note they are different than the array of headers, 'buf', 383 * and usually occupy more virtual memory than physical. 384 */ 385 size = MAXBSIZE * nbuf; 386 if (uvm_map(kernel_map, (vaddr_t *)(void *)&buffers, round_page(size), 387 NULL, UVM_UNKNOWN_OFFSET, 0, 388 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 389 UVM_ADV_NORMAL, 0)) != 0) 390 panic("startup: cannot allocate VM for buffers"); 391 minaddr = (vaddr_t)buffers; 392 base = bufpages / nbuf; 393 residual = bufpages % nbuf; 394 for (i = 0; i < nbuf; i++) { 395 vsize_t curbufsize; 396 vaddr_t curbuf; 397 struct vm_page *pg; 398 399 /* 400 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 401 * that MAXBSIZE space, we allocate and map (base+1) pages 402 * for the first "residual" buffers, and then we allocate 403 * "base" pages for the rest. 404 */ 405 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 406 curbufsize = PAGE_SIZE * ((i < residual) ? (base + 1) : base); 407 408 while (curbufsize) { 409 pg = uvm_pagealloc(NULL, 0, NULL, 0); 410 if (pg == NULL) 411 panic("cpu_startup: not enough memory for " 412 "buffer cache"); 413 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 414 VM_PROT_READ|VM_PROT_WRITE); 415 curbuf += PAGE_SIZE; 416 curbufsize -= PAGE_SIZE; 417 } 418 } 419 420 /* 421 * Allocate a submap for exec arguments. This map effectively 422 * limits the number of processes exec'ing at any time. 423 */ 424 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS, 425 VM_MAP_PAGEABLE, FALSE, NULL); 426 /* 427 * Allocate a submap for physio. 428 */ 429 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 430 0, FALSE, NULL); 431 432 433 /* 434 * (No need to allocate an mbuf cluster submap. Mbuf clusters 435 * are allocated via the pool allocator, and we use KSEG to 436 * map those pages.) 437 */ 438 439 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 440 printf(", %s free", pbuf); 441 format_bytes(pbuf, sizeof(pbuf), bufpages * PAGE_SIZE); 442 printf(", %s in %u buffers\n", pbuf, nbuf); 443 444 /* 445 * Set up buffers, so they can be used to read disk labels. 446 */ 447 bufinit(); 448} 449 450int waittime = -1; 451 452void 453cpu_reboot(int howto, char *bootstr) 454{ 455 456 /* Take a snapshot before clobbering any registers. */ 457 if (curlwp) 458 savectx((struct user *)curpcb); 459 460 if (cold) { 461 howto |= RB_HALT; 462 goto haltsys; 463 } 464 465 /* If "always halt" was specified as a boot flag, obey. */ 466 if (boothowto & RB_HALT) 467 howto |= RB_HALT; 468 469 boothowto = howto; 470 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 471 waittime = 0; 472 vfs_shutdown(); 473 474 /* 475 * If we've been adjusting the clock, the todr 476 * will be out of synch; adjust it now. 477 */ 478 resettodr(); 479 } 480 481 splhigh(); 482 483 if (howto & RB_DUMP) 484 dumpsys(); 485 486haltsys: 487 doshutdownhooks(); 488 489 if (howto & RB_HALT) { 490 printf("\n"); 491 printf("The operating system has halted.\n"); 492 printf("Please press any key to reboot.\n\n"); 493 cnpollc(1); /* For proper keyboard command handling */ 494 cngetc(); 495 cnpollc(0); 496 } 497 498 printf("rebooting...\n\n"); 499 500 if (cfe_present) { 501 /* 502 * XXX 503 * For some reason we can't return to CFE with 504 * and do a warm start. Need to look into this... 505 */ 506 cfe_exit(0, (howto & RB_DUMP) ? 1 : 0); 507 printf("cfe_exit didn't!\n"); 508 } 509 510 printf("WARNING: reboot failed!\n"); 511 512 for (;;); 513} 514 515static void 516cswarm_setled(u_int index, char c) 517{ 518 volatile u_char *led_ptr = 519 (void *)MIPS_PHYS_TO_KSEG1(SWARM_LEDS_PHYS); 520 521 if (index < 4) 522 led_ptr[0x20 + ((3 - index) << 3)] = c; 523} 524 525void 526cswarm_setleds(const char *str) 527{ 528 int i; 529 530 for (i = 0; i < 4 && str[i]; i++) 531 cswarm_setled(i, str[i]); 532 for (; i < 4; i++) 533 cswarm_setled(' ', str[i]); 534} 535 536int 537sbmips_cca_for_pa(paddr_t pa) 538{ 539 int rv; 540 541 /* Check each DRAM region. */ 542 if ((pa >= 0x0000000000 && pa <= 0x000fffffff) || /* DRAM 0 */ 543 (pa >= 0x0080000000 && pa <= 0x008fffffff) || /* DRAM 1 */ 544 (pa >= 0x0090000000 && pa <= 0x009fffffff) || /* DRAM 2 */ 545 (pa >= 0x00c0000000 && pa <= 0x00cfffffff) || /* DRAM 3 */ 546#ifdef _MIPS_PADDR_T_64BIT 547 (pa >= 0x0100000000 && pa <= 0x07ffffffff) || /* DRAM exp */ 548#endif 549 0) { 550 rv = 5; /* Cacheable coherent. */ 551 goto done; 552 } 553 554 rv = 2; /* Uncached. */ 555done: 556 return (rv); 557} 558