machdep.c revision 1.39
1/* $NetBSD: machdep.c,v 1.39 2008/11/11 06:46:43 dyoung 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.39 2008/11/11 06:46:43 dyoung 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/syscallargs.h> 82#include <sys/kcore.h> 83#include <sys/ksyms.h> 84 85#include <uvm/uvm_extern.h> 86 87#include <machine/cpu.h> 88#include <machine/reg.h> 89#include <machine/psl.h> 90#include <machine/pte.h> 91#include <machine/autoconf.h> 92#include <machine/intr.h> 93#include <machine/swarm.h> 94#include <mips/locore.h> 95 96#include <mips/cfe/cfe_api.h> 97 98#if 0 /* XXXCGD */ 99#include <machine/nvram.h> 100#endif /* XXXCGD */ 101#include <machine/leds.h> 102 103#include "ksyms.h" 104 105#if NKSYMS || defined(DDB) || defined(LKM) 106#include <machine/db_machdep.h> 107#include <ddb/db_access.h> 108#include <ddb/db_sym.h> 109#include <ddb/db_extern.h> 110#ifndef DB_ELFSIZE 111#error Must define DB_ELFSIZE! 112#endif 113#define ELFSIZE DB_ELFSIZE 114#include <sys/exec_elf.h> 115#endif 116 117#include <dev/cons.h> 118 119#if NKSYMS || defined(DDB) || defined(LKM) 120/* start and end of kernel symbol table */ 121void *ksym_start, *ksym_end; 122#endif 123 124/* Our exported CPU info. Only one for now */ 125struct cpu_info cpu_info_store; 126 127/* Maps for VM objects. */ 128struct vm_map *mb_map = NULL; 129struct vm_map *phys_map = NULL; 130 131int physmem; /* Total physical memory */ 132 133char bootstring[512]; /* Boot command */ 134int netboot; /* Are we netbooting? */ 135int cfe_present; 136 137struct bootinfo_v1 bootinfo; 138 139phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 140int mem_cluster_cnt; 141 142void configure(void); 143void mach_init(long, long, long, long); 144 145/* 146 * safepri is a safe priority for sleep to set for a spin-wait during 147 * autoconfiguration or after a panic. Used as an argument to splx(). 148 */ 149int safepri = MIPS_INT_MASK | MIPS_SR_INT_IE; 150 151extern void *esym; 152extern struct user *proc0paddr; 153 154/* 155 * Do all the stuff that locore normally does before calling main(). 156 */ 157void 158mach_init(long fwhandle, long magic, long bootdata, long reserved) 159{ 160 void *kernend, *p0; 161 u_long first, last; 162 extern char edata[], end[]; 163 int i; 164 uint32_t config; 165 166 /* XXX this code must run on the target CPU */ 167 config = mips3_cp0_config_read(); 168 config &= ~MIPS3_CONFIG_K0_MASK; 169 config |= 0x05; /* XXX. cacheable coherent */ 170 mips3_cp0_config_write(config); 171 172 /* Zero BSS. XXXCGD: uh, is this really necessary still? */ 173 memset(edata, 0, end - edata); 174 175 /* 176 * Copy the bootinfo structure from the boot loader. 177 * this has to be done before mips_vector_init is 178 * called because we may need CFE's TLB handler 179 */ 180 181 if (magic == BOOTINFO_MAGIC) 182 memcpy(&bootinfo, (struct bootinfo_v1 *)bootdata, 183 sizeof bootinfo); 184 else if (reserved == CFE_EPTSEAL) { 185 magic = BOOTINFO_MAGIC; 186 bzero(&bootinfo, sizeof bootinfo); 187 bootinfo.version = BOOTINFO_VERSION; 188 bootinfo.fwhandle = fwhandle; 189 bootinfo.fwentry = bootdata; 190 bootinfo.ssym = (vaddr_t)end; 191 bootinfo.esym = (vaddr_t)end; 192 } 193 194 kernend = (void *)mips_round_page(end); 195#if NKSYMS || defined(DDB) || defined(LKM) 196 if (magic == BOOTINFO_MAGIC) { 197 ksym_start = (void *)bootinfo.ssym; 198 ksym_end = (void *)bootinfo.esym; 199 kernend = (void *)mips_round_page((vaddr_t)ksym_end); 200 } 201#endif 202 203 consinit(); 204 205 uvm_setpagesize(); 206 207 /* 208 * Copy exception-dispatch code down to exception vector. 209 * Initialize locore-function vector. 210 * Clear out the I and D caches. 211 */ 212 mips_vector_init(); 213 214#ifdef DEBUG 215 printf("fwhandle=%08X magic=%08X bootdata=%08X reserved=%08X\n", 216 (u_int)fwhandle, (u_int)magic, (u_int)bootdata, (u_int)reserved); 217#endif 218 219 strcpy(cpu_model, "sb1250"); 220 221 if (magic == BOOTINFO_MAGIC) { 222 int idx; 223 int added; 224 uint64_t start, len, type; 225 226 cfe_init(bootinfo.fwhandle, bootinfo.fwentry); 227 cfe_present = 1; 228 229 idx = 0; 230 physmem = 0; 231 mem_cluster_cnt = 0; 232 while (cfe_enummem(idx, 0, &start, &len, &type) == 0) { 233 added = 0; 234 printf("Memory Block #%d start %08"PRIx64"X len %08"PRIx64"X: %s: ", 235 idx, start, len, (type == CFE_MI_AVAILABLE) ? 236 "Available" : "Reserved"); 237 if ((type == CFE_MI_AVAILABLE) && 238 (mem_cluster_cnt < VM_PHYSSEG_MAX)) { 239 /* 240 * XXX Ignore memory above 256MB for now, it 241 * XXX needs special handling. 242 */ 243 if (start < (256*1024*1024)) { 244 physmem += btoc(((int) len)); 245 mem_clusters[mem_cluster_cnt].start = 246 (long) start; 247 mem_clusters[mem_cluster_cnt].size = 248 (long) len; 249 mem_cluster_cnt++; 250 added = 1; 251 } 252 } 253 if (added) 254 printf("added to map\n"); 255 else 256 printf("not added to map\n"); 257 idx++; 258 } 259 260 } else { 261 /* 262 * Handle the case of not being called from the firmware. 263 */ 264 /* XXX hardwire to 32MB; should be kernel config option */ 265 physmem = 32 * 1024 * 1024 / 4096; 266 mem_clusters[0].start = 0; 267 mem_clusters[0].size = ctob(physmem); 268 mem_cluster_cnt = 1; 269 } 270 271 272 for (i = 0; i < sizeof(bootinfo.boot_flags); i++) { 273 switch (bootinfo.boot_flags[i]) { 274 case '\0': 275 break; 276 case ' ': 277 continue; 278 case '-': 279 while (bootinfo.boot_flags[i] != ' ' && 280 bootinfo.boot_flags[i] != '\0') { 281 switch (bootinfo.boot_flags[i]) { 282 case 'a': 283 boothowto |= RB_ASKNAME; 284 break; 285 case 'd': 286 boothowto |= RB_KDB; 287 break; 288 case 's': 289 boothowto |= RB_SINGLE; 290 break; 291 } 292 i++; 293 } 294 } 295 } 296 297 /* 298 * Load the rest of the available pages into the VM system. 299 * The first chunk is tricky because we have to avoid the 300 * kernel, but the rest are easy. 301 */ 302 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 303 last = mem_clusters[0].start + mem_clusters[0].size; 304 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 305 VM_FREELIST_DEFAULT); 306 307 for (i = 1; i < mem_cluster_cnt; i++) { 308 first = round_page(mem_clusters[i].start); 309 last = mem_clusters[i].start + mem_clusters[i].size; 310 uvm_page_physload(atop(first), atop(last), atop(first), 311 atop(last), VM_FREELIST_DEFAULT); 312 } 313 314 /* 315 * Initialize error message buffer (at end of core). 316 */ 317 mips_init_msgbuf(); 318 319 /* 320 * Allocate space for proc0's USPACE 321 */ 322 p0 = (void *)pmap_steal_memory(USPACE, NULL, NULL); 323 lwp0.l_addr = proc0paddr = (struct user *)p0; 324 lwp0.l_md.md_regs = (struct frame *)((char *)p0 + USPACE) - 1; 325 proc0paddr->u_pcb.pcb_context[11] = 326 MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 327 328 pmap_bootstrap(); 329 330 /* 331 * Initialize debuggers, and break into them, if appropriate. 332 */ 333#if NKSYMS || defined(DDB) || defined(LKM) 334 ksyms_init(((uintptr_t)ksym_end - (uintptr_t)ksym_start), 335 ksym_start, ksym_end); 336#endif 337 338 if (boothowto & RB_KDB) { 339#if defined(DDB) 340 Debugger(); 341#endif 342 } 343} 344 345/* 346 * Allocate memory for variable-sized tables, 347 */ 348void 349cpu_startup(void) 350{ 351 vaddr_t minaddr, maxaddr; 352 char pbuf[9]; 353 354 /* 355 * Good {morning,afternoon,evening,night}. 356 */ 357 printf("%s%s", copyright, version); 358 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 359 printf("total memory = %s\n", pbuf); 360 361 minaddr = 0; 362 /* 363 * Allocate a submap for physio. 364 */ 365 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 366 0, false, NULL); 367 368 369 /* 370 * (No need to allocate an mbuf cluster submap. Mbuf clusters 371 * are allocated via the pool allocator, and we use KSEG to 372 * map those pages.) 373 */ 374 375 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 376 printf("avail memory = %s\n", pbuf); 377} 378 379int waittime = -1; 380 381void 382cpu_reboot(int howto, char *bootstr) 383{ 384 385 /* Take a snapshot before clobbering any registers. */ 386 if (curlwp) 387 savectx((struct user *)curpcb); 388 389 if (cold) { 390 howto |= RB_HALT; 391 goto haltsys; 392 } 393 394 /* If "always halt" was specified as a boot flag, obey. */ 395 if (boothowto & RB_HALT) 396 howto |= RB_HALT; 397 398 boothowto = howto; 399 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 400 waittime = 0; 401 vfs_shutdown(); 402 403 /* 404 * If we've been adjusting the clock, the todr 405 * will be out of synch; adjust it now. 406 */ 407 resettodr(); 408 } 409 410 splhigh(); 411 412 if (howto & RB_DUMP) 413 dumpsys(); 414 415haltsys: 416 doshutdownhooks(); 417 418 pmf_system_shutdown(boothowto); 419 420 if (howto & RB_HALT) { 421 printf("\n"); 422 printf("The operating system has halted.\n"); 423 printf("Please press any key to reboot.\n\n"); 424 cnpollc(1); /* For proper keyboard command handling */ 425 cngetc(); 426 cnpollc(0); 427 } 428 429 printf("rebooting...\n\n"); 430 431 if (cfe_present) { 432 /* 433 * XXX 434 * For some reason we can't return to CFE with 435 * and do a warm start. Need to look into this... 436 */ 437 cfe_exit(0, (howto & RB_DUMP) ? 1 : 0); 438 printf("cfe_exit didn't!\n"); 439 } 440 441 printf("WARNING: reboot failed!\n"); 442 443 for (;;); 444} 445 446static void 447cswarm_setled(u_int index, char c) 448{ 449 volatile u_char *led_ptr = 450 (void *)MIPS_PHYS_TO_KSEG1(SWARM_LEDS_PHYS); 451 452 if (index < 4) 453 led_ptr[0x20 + ((3 - index) << 3)] = c; 454} 455 456void 457cswarm_setleds(const char *str) 458{ 459 int i; 460 461 for (i = 0; i < 4 && str[i]; i++) 462 cswarm_setled(i, str[i]); 463 for (; i < 4; i++) 464 cswarm_setled(' ', str[i]); 465} 466 467int 468sbmips_cca_for_pa(paddr_t pa) 469{ 470 int rv; 471 472 /* Check each DRAM region. */ 473 if ((pa >= 0x0000000000 && pa <= 0x000fffffff) || /* DRAM 0 */ 474 (pa >= 0x0080000000 && pa <= 0x008fffffff) || /* DRAM 1 */ 475 (pa >= 0x0090000000 && pa <= 0x009fffffff) || /* DRAM 2 */ 476 (pa >= 0x00c0000000 && pa <= 0x00cfffffff) || /* DRAM 3 */ 477#ifdef _MIPS_PADDR_T_64BIT 478 (pa >= 0x0100000000LL && pa <= 0x07ffffffffLL) || /* DRAM exp */ 479#endif 480 0) { 481 rv = 5; /* Cacheable coherent. */ 482 goto done; 483 } 484 485 rv = 2; /* Uncached. */ 486done: 487 return (rv); 488} 489