machdep.c revision 1.2
1/* $NetBSD: machdep.c,v 1.2 2002/03/17 06:28:57 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/map.h> 68#include <sys/proc.h> 69#include <sys/buf.h> 70#include <sys/reboot.h> 71#include <sys/conf.h> 72#include <sys/file.h> 73#include <sys/malloc.h> 74#include <sys/mbuf.h> 75#include <sys/msgbuf.h> 76#include <sys/device.h> 77#include <sys/user.h> 78#include <sys/exec.h> 79#include <sys/sysctl.h> 80#include <sys/mount.h> 81#include <sys/syscallargs.h> 82#include <sys/kcore.h> 83 84#include <uvm/uvm_extern.h> 85 86#include <machine/cpu.h> 87#include <machine/reg.h> 88#include <machine/psl.h> 89#include <machine/pte.h> 90#include <machine/autoconf.h> 91#include <machine/intr.h> 92#include <mips/locore.h> 93 94#include <mips/cfe/cfe_xiocb.h> 95#include <mips/cfe/cfe_api.h> 96 97#if 0 /* XXXCGD */ 98#include <machine/nvram.h> 99#endif /* XXXCGD */ 100#include <machine/leds.h> 101 102#ifdef DDB 103#include <machine/db_machdep.h> 104#include <ddb/db_access.h> 105#include <ddb/db_sym.h> 106#include <ddb/db_extern.h> 107#ifndef DB_ELFSIZE 108#error Must define DB_ELFSIZE! 109#endif 110#define ELFSIZE DB_ELFSIZE 111#include <sys/exec_elf.h> 112#endif 113 114#include <dev/cons.h> 115 116#ifdef IKOS 117#include <sbmips/ikos/ikosvar.h> 118#endif 119 120/* For sysctl. */ 121char machine[] = MACHINE; 122char machine_arch[] = MACHINE_ARCH; 123char cpu_model[] = "sb1250"; 124 125/* Our exported CPU info. Only one for now */ 126struct cpu_info cpu_info_store; 127 128/* Maps for VM objects. */ 129struct vm_map *exec_map = NULL; 130struct vm_map *mb_map = NULL; 131struct vm_map *phys_map = NULL; 132 133int physmem; /* Total physical memory */ 134 135char bootstring[512]; /* Boot command */ 136int netboot; /* Are we netbooting? */ 137int cfe_present; 138 139struct bootinfo_v1 bootinfo; 140 141phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 142int mem_cluster_cnt; 143 144void configure(void); 145void mach_init(long,long,long,long); 146 147/* 148 * safepri is a safe priority for sleep to set for a spin-wait during 149 * autoconfiguration or after a panic. Used as an argument to splx(). 150 */ 151int safepri = MIPS_INT_MASK | MIPS_SR_INT_IE; 152 153extern caddr_t esym; 154extern struct user *proc0paddr; 155 156/* 157 * Do all the stuff that locore normally does before calling main(). 158 */ 159void 160mach_init(fwhandle,magic,bootdata,reserved) 161 long fwhandle; 162 long magic; 163 long bootdata; 164 long reserved; 165{ 166 caddr_t kernend, v, p0; 167 u_long first, last; 168 vsize_t size; 169 extern char edata[], end[]; 170 int i; 171 u_int memsize; 172 uint32_t config; 173 174 /* XXX this code must run on the target cpu */ 175 config = mips3_cp0_config_read(); 176 config &= ~MIPS3_CONFIG_K0_MASK; 177 config |= 0x05; /* XXX. cacheable coherent */ 178 mips3_cp0_config_write(config); 179 180 /* XXXCGD */ 181#ifdef SBMIPS_MEM_SIZE 182 memsize = SBMIPS_MEM_SIZE; 183#else 184 memsize = 32 * 1024 * 1024; 185#endif 186 memsize += MIPS_KSEG0_START; 187 188 /* 189 * Clear the BSS segment. 190 */ 191#ifdef DDB 192 if (memcmp(((Elf_Ehdr *)end)->e_ident, ELFMAG, SELFMAG) == 0 && 193 ((Elf_Ehdr *)end)->e_ident[EI_CLASS] == ELFCLASS) { 194 esym = end; 195 esym += ((Elf_Ehdr *)end)->e_entry; 196 kernend = (caddr_t)mips_round_page(esym); 197 bzero(edata, end - edata); 198 } else 199#endif 200 { 201 kernend = (caddr_t)mips_round_page(end); 202 memset(edata, 0, kernend - edata); 203 } 204 205 /* 206 * Copy the bootinfo structure from the boot loader. 207 * this has to be done before mips_vector_init is 208 * called because we may need CFE's TLB handler 209 */ 210 211 cfe_present = 0; 212 if (magic == BOOTINFO_MAGIC) 213 bcopy((struct bootinfo_v1 *)bootdata, &bootinfo, 214 sizeof bootinfo); 215 else if (reserved == CFE_EPTSEAL) { 216 magic = BOOTINFO_MAGIC; 217 bzero(&bootinfo, sizeof bootinfo); 218 bootinfo.version = BOOTINFO_VERSION; 219 bootinfo.fwhandle = fwhandle; 220 bootinfo.fwentry = bootdata; 221 } 222 223#ifdef IKOS 224 ikoscons_output_bufsize = IKOSCONS_OUTPUT_BUFSIZE; 225 memsize -= ikoscons_output_bufsize; 226 ikoscons_output_buf = 227 (void *)MIPS_PHYS_TO_KSEG1(MIPS_KSEG0_TO_PHYS(memsize)); 228 memset(ikoscons_output_buf, 0, ikoscons_output_bufsize); 229#endif 230 231 /* 232 * physmem is measured in pages 233 * XXX does this need to be set for 'consinit', 'uvm_setpagesize', 234 * XXX or 'mips_vector_init'? not that I can tell right now... 235 * XXX if CFE is present, this will be recalculated. 236 * XXX 237 * XXX Does 'physmem' want to be the total amount of RAM in the 238 * XXX system, or the amount that is available to us? 239 */ 240 physmem = btoc(memsize - MIPS_KSEG0_START); 241 242 consinit(); 243 244 uvm_setpagesize(); 245 246 /* 247 * Copy exception-dispatch code down to exception vector. 248 * Initialize locore-function vector. 249 * Clear out the I and D caches. 250 */ 251 mips_vector_init(); 252 253#if 0 254*(unsigned long long *)0xb0020440 = 3; 255#endif 256 257 printf("fwhandle=%08X magic=%08X bootdata=%08X reserved=%08X\n", 258 (u_int) fwhandle,(u_int) magic,(u_int) bootdata,(u_int) reserved); 259 260 if (magic == BOOTINFO_MAGIC) { 261 int idx; 262 int added; 263 cfe_xuint_t start,len,type; 264 265 cfe_init(fwhandle); 266 cfe_present = 1; 267 268 idx = 0; 269 physmem = 0; 270 mem_cluster_cnt = 0; 271 while (cfe_getmeminfo(idx,&start,&len,&type) == 0) { 272 added = 0; 273 printf("Memory Block #%d start %08llX len %08llX: %s: ", 274 idx, start, len, (type == CFE_MI_AVAILABLE) ? 275 "Available" : "Reserved"); 276 if ((type == CFE_MI_AVAILABLE) && 277 (mem_cluster_cnt < VM_PHYSSEG_MAX)) { 278 /* 279 * XXX Ignore memory above 256MB for now, it 280 * XXX needs special handling. 281 */ 282 if (start < (256*1024*1024)) { 283 physmem += btoc(((int) len)); 284 mem_clusters[mem_cluster_cnt].start = 285 (long) start; 286 mem_clusters[mem_cluster_cnt].size = 287 (long) len; 288 mem_cluster_cnt++; 289 added = 1; 290 } 291 } 292 if (added) 293 printf("added to map\n"); 294 else 295 printf("not added to map\n"); 296 idx++; 297 } 298 299 } else { 300 /* 301 * Handle the case of not being called from the firmware. 302 */ 303 mem_clusters[0].start = 0; 304 mem_clusters[0].size = ctob(physmem); 305 mem_cluster_cnt = 1; 306 } 307 308 309 for (i = 0; i < sizeof(bootinfo.boot_flags); i++) { 310 switch (bootinfo.boot_flags[i]) { 311 case '\0': 312 break; 313 case ' ': 314 continue; 315 case '-': 316 while (bootinfo.boot_flags[i] != ' ' && 317 bootinfo.boot_flags[i] != '\0') { 318 switch (bootinfo.boot_flags[i]) { 319 case 'a': 320 boothowto |= RB_ASKNAME; 321 break; 322 case 'd': 323 boothowto |= RB_KDB; 324 break; 325 case 's': 326 boothowto |= RB_SINGLE; 327 break; 328 } 329 i++; 330 } 331 } 332 if (memcmp("single", &bootinfo.boot_flags[i], 5) == 0) 333 boothowto |= RB_SINGLE; 334 if (memcmp("nfsroot=", &bootinfo.boot_flags[i], 8) == 0) 335 netboot = 1; 336 /* 337 * XXX Select root device from 'root=/dev/hd[abcd][1234]' too. 338 */ 339 } 340 341 /* 342 * Load the rest of the available pages into the VM system. 343 * The first chunk is tricky because we have to avoid the 344 * kernel, but the rest are easy. 345 */ 346 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 347 last = mem_clusters[0].start + mem_clusters[0].size; 348 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 349 VM_FREELIST_DEFAULT); 350 351 for (i = 1; i < mem_cluster_cnt; i++) { 352 first = round_page(mem_clusters[i].start); 353 last = mem_clusters[i].start + mem_clusters[i].size; 354 uvm_page_physload(atop(first), atop(last), atop(first), 355 atop(last), VM_FREELIST_DEFAULT); 356 } 357 358 /* 359 * Initialize error message buffer (at end of core). 360 */ 361 mips_init_msgbuf(); 362 363 /* 364 * Allocate space for proc0's USPACE 365 */ 366 p0 = (caddr_t)pmap_steal_memory(USPACE, NULL, NULL); 367 proc0.p_addr = proc0paddr = (struct user *)p0; 368 proc0.p_md.md_regs = (struct frame *)(p0 + USPACE) - 1; 369 curpcb = &proc0.p_addr->u_pcb; 370 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 371 372 /* 373 * Allocate space for system data structures. These data structures 374 * are allocated here instead of cpu_startup() because physical 375 * memory is directly addressable. We don't have to map these into 376 * virtual address space. 377 */ 378 size = (vsize_t)allocsys(NULL, NULL); 379 v = (caddr_t)pmap_steal_memory(size, NULL, NULL); 380 if ((allocsys(v, NULL) - v) != size) 381 panic("mach_init: table size inconsistency"); 382 383 pmap_bootstrap(); 384 385 /* 386 * Initialize debuggers, and break into them, if appropriate. 387 */ 388#if defined(DDB) 389 ddb_init(0, 0, 0); 390#endif 391 392 if (boothowto & RB_KDB) { 393#if defined(DDB) 394 Debugger(); 395#endif 396 } 397} 398 399/* 400 * Allocate memory for variable-sized tables, 401 */ 402void 403cpu_startup() 404{ 405 unsigned i; 406 int base, residual; 407 vaddr_t minaddr, maxaddr; 408 vsize_t size; 409 char pbuf[9]; 410 411 /* 412 * Good {morning,afternoon,evening,night}. 413 */ 414 printf(version); 415 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 416 printf("%s memory", pbuf); 417 418 /* 419 * Allocate virtual address space for file I/O buffers. 420 * Note they are different than the array of headers, 'buf', 421 * and usually occupy more virtual memory than physical. 422 */ 423 size = MAXBSIZE * nbuf; 424 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 425 NULL, UVM_UNKNOWN_OFFSET, 0, 426 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 427 UVM_ADV_NORMAL, 0)) != 0) 428 panic("startup: cannot allocate VM for buffers"); 429 minaddr = (vaddr_t)buffers; 430 base = bufpages / nbuf; 431 residual = bufpages % nbuf; 432 for (i = 0; i < nbuf; i++) { 433 vsize_t curbufsize; 434 vaddr_t curbuf; 435 struct vm_page *pg; 436 437 /* 438 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 439 * that MAXBSIZE space, we allocate and map (base+1) pages 440 * for the first "residual" buffers, and then we allocate 441 * "base" pages for the rest. 442 */ 443 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 444 curbufsize = NBPG * ((i < residual) ? (base + 1) : base); 445 446 while (curbufsize) { 447 pg = uvm_pagealloc(NULL, 0, NULL, 0); 448 if (pg == NULL) 449 panic("cpu_startup: not enough memory for " 450 "buffer cache"); 451 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 452 VM_PROT_READ|VM_PROT_WRITE); 453 curbuf += PAGE_SIZE; 454 curbufsize -= PAGE_SIZE; 455 } 456 } 457 458 /* 459 * Allocate a submap for exec arguments. This map effectively 460 * limits the number of processes exec'ing at any time. 461 */ 462 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS, 463 VM_MAP_PAGEABLE, FALSE, NULL); 464 /* 465 * Allocate a submap for physio. 466 */ 467 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, VM_PHYS_SIZE, 468 0, FALSE, NULL); 469 470 471 /* 472 * (No need to allocate an mbuf cluster submap. Mbuf clusters 473 * are allocated via the pool allocator, and we use KSEG to 474 * map those pages.) 475 */ 476 477 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 478 printf(", %s free", pbuf); 479 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 480 printf(", %s in %d buffers\n", pbuf, nbuf); 481 482 /* 483 * Set up buffers, so they can be used to read disk labels. 484 */ 485 bufinit(); 486} 487 488int 489cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 490 int *name; 491 u_int namelen; 492 void *oldp; 493 size_t *oldlenp; 494 void *newp; 495 size_t newlen; 496 struct proc *p; 497{ 498 /* All sysctl names at this level are terminal. */ 499 if (namelen != 1) 500 return ENOTDIR; 501 502 switch (name[0]) { 503 default: 504 return EOPNOTSUPP; 505 } 506} 507 508int waittime = -1; 509 510void 511cpu_reboot(howto, bootstr) 512 int howto; 513 char *bootstr; 514{ 515 /* Take a snapshot before clobbering any registers. */ 516 if (curproc) 517 savectx((struct user *)curpcb); 518 519 if (cold) { 520 howto |= RB_HALT; 521 goto haltsys; 522 } 523 524 /* If "always halt" was specified as a boot flag, obey. */ 525 if (boothowto & RB_HALT) 526 howto |= RB_HALT; 527 528 boothowto = howto; 529 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 530 waittime = 0; 531 vfs_shutdown(); 532 533 /* 534 * If we've been adjusting the clock, the todr 535 * will be out of synch; adjust it now. 536 */ 537 resettodr(); 538 } 539 540 splhigh(); 541 542 if (howto & RB_DUMP) 543 dumpsys(); 544 545haltsys: 546 doshutdownhooks(); 547 548 if (howto & RB_HALT) { 549 printf("\n"); 550 printf("The operating system has halted.\n"); 551 printf("Please press any key to reboot.\n\n"); 552 cnpollc(1); /* For proper keyboard command handling */ 553 cngetc(); 554 cnpollc(0); 555 } 556 557 printf("rebooting...\n\n"); 558 559 if (cfe_present) { 560 cfe_exit(1, (howto & RB_DUMP) ? 1 : 0); 561 printf("cfe_exit didn't!\n"); 562 } 563 564 delay(500000); 565 566#if defined(IKOS) && defined(REALLY_IKOS) 567 *(volatile char *)MIPS_PHYS_TO_KSEG1(0x408000) = 0; 568#else 569 { 570 static int broken; 571 572 if (!broken) { 573 broken = 1; 574 __asm__ ( "move $4, %0 ; break 0x3ff" : : "r"(howto) ); 575 } 576 } 577#endif 578 579 printf("WARNING: reboot failed!\n"); 580 581 for (;;); 582} 583 584static void 585cswarm_setled(u_int index, char c) 586{ 587 volatile u_char *led_ptr = 588 (void *)MIPS_PHYS_TO_KSEG1(0x100a0000); /* XXX */ 589 590 if (index < 4) 591 led_ptr[0x20 + ((3 - index) << 3)] = c; 592} 593 594void 595cswarm_setleds(const char *str) 596{ 597 int i; 598 599 for (i = 0; i < 4 && str[i]; i++) 600 cswarm_setled(i, str[i]); 601 for (; i < 4; i++) 602 cswarm_setled(' ', str[i]); 603} 604 605int 606sbmips_cca_for_pa(paddr_t pa) 607{ 608 int rv; 609 610 /* Check each DRAM region. */ 611 if ((pa >= 0x0000000000 && pa <= 0x000fffffff) || /* DRAM 0 */ 612 (pa >= 0x0080000000 && pa <= 0x008fffffff) || /* DRAM 1 */ 613 (pa >= 0x0090000000 && pa <= 0x009fffffff) || /* DRAM 2 */ 614 (pa >= 0x00c0000000 && pa <= 0x00cfffffff) || /* DRAM 3 */ 615#ifdef _MIPS_PADDR_T_64BIT 616 (pa >= 0x0100000000 && pa <= 0x07ffffffff) || /* DRAM exp */ 617#endif 618 0) { 619 rv = 5; /* Cacheable coherent. */ 620 goto done; 621 } 622 623 rv = 2; /* Uncached. */ 624done: 625 return (rv); 626} 627