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