machdep.c revision 1.62
1/* $NetBSD: machdep.c,v 1.62 2006/04/21 16:52:15 tsutsui Exp $ */ 2 3/* 4 * Copyright (c) 2000 Soren S. Jorvang. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.62 2006/04/21 16:52:15 tsutsui Exp $"); 30 31#include "opt_ddb.h" 32#include "opt_kgdb.h" 33#include "opt_execfmt.h" 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/proc.h> 39#include <sys/buf.h> 40#include <sys/reboot.h> 41#include <sys/conf.h> 42#include <sys/file.h> 43#include <sys/malloc.h> 44#include <sys/mbuf.h> 45#include <sys/msgbuf.h> 46#include <sys/device.h> 47#include <sys/user.h> 48#include <sys/exec.h> 49#include <uvm/uvm_extern.h> 50#include <sys/sysctl.h> 51#include <sys/mount.h> 52#include <sys/sa.h> 53#include <sys/syscallargs.h> 54#include <sys/kcore.h> 55#include <sys/boot_flag.h> 56#include <sys/ksyms.h> 57 58#include <machine/cpu.h> 59#include <machine/reg.h> 60#include <machine/psl.h> 61#include <machine/pte.h> 62#include <machine/autoconf.h> 63#include <machine/bootinfo.h> 64#include <machine/intr.h> 65#include <mips/locore.h> 66 67#include <machine/nvram.h> 68#include <machine/leds.h> 69 70#include <dev/cons.h> 71 72#include <arch/cobalt/dev/gtreg.h> 73#define GT_BASE 0x14000000 /* XXX */ 74 75#ifdef KGDB 76#include <sys/kgdb.h> 77#endif 78 79#include "ksyms.h" 80 81#if NKSYMS || defined(DDB) || defined(LKM) 82#include <machine/db_machdep.h> 83#include <ddb/db_extern.h> 84#define ELFSIZE DB_ELFSIZE 85#include <sys/exec_elf.h> 86#endif 87 88/* Our exported CPU info; we can have only one. */ 89struct cpu_info cpu_info_store; 90 91/* Maps for VM objects. */ 92struct vm_map *exec_map = NULL; 93struct vm_map *mb_map = NULL; 94struct vm_map *phys_map = NULL; 95 96int physmem; /* Total physical memory */ 97char *bootinfo = NULL; /* pointer to bootinfo structure */ 98 99char bootstring[512]; /* Boot command */ 100int netboot; /* Are we netbooting? */ 101 102char * nfsroot_bstr = NULL; 103char * root_bstr = NULL; 104int bootunit = -1; 105int bootpart = -1; 106 107int cpuspeed; 108 109u_int cobalt_id; 110static const char * const cobalt_model[] = 111{ 112 NULL, 113 NULL, 114 NULL, 115 "Cobalt Qube 2700", 116 "Cobalt RaQ", 117 "Cobalt Qube 2", 118 "Cobalt RaQ 2" 119}; 120#define COBALT_MODELS __arraycount(cobalt_model) 121 122phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 123int mem_cluster_cnt; 124 125void mach_init(unsigned int, u_int, char*); 126void decode_bootstring(void); 127static char * strtok_light(char *, const char); 128static u_int read_board_id(void); 129 130/* 131 * safepri is a safe priority for sleep to set for a spin-wait during 132 * autoconfiguration or after a panic. Used as an argument to splx(). 133 */ 134int safepri = MIPS1_PSL_LOWIPL; 135 136extern caddr_t esym; 137extern struct user *proc0paddr; 138 139 140 141/* 142 * Do all the stuff that locore normally does before calling main(). 143 */ 144void 145mach_init(unsigned int memsize, u_int bim, char *bip) 146{ 147 caddr_t kernend, v; 148 u_long first, last; 149 extern char edata[], end[]; 150 const char *bi_msg; 151#if NKSYMS || defined(DDB) || defined(LKM) 152 int nsym = 0; 153 caddr_t ssym = 0; 154 struct btinfo_symtab *bi_syms; 155#endif 156 157 /* 158 * Clear the BSS segment. 159 */ 160#if NKSYMS || defined(DDB) || defined(LKM) 161 if (memcmp(((Elf_Ehdr *)end)->e_ident, ELFMAG, SELFMAG) == 0 && 162 ((Elf_Ehdr *)end)->e_ident[EI_CLASS] == ELFCLASS) { 163 esym = end; 164 esym += ((Elf_Ehdr *)end)->e_entry; 165 kernend = (caddr_t)mips_round_page(esym); 166 memset(edata, 0, end - edata); 167 } else 168#endif 169 { 170 kernend = (caddr_t)mips_round_page(end); 171 memset(edata, 0, kernend - edata); 172 } 173 174 /* Check for valid bootinfo passed from bootstrap */ 175 if (bim == BOOTINFO_MAGIC) { 176 struct btinfo_magic *bi_magic; 177 178 bootinfo = bip; 179 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 180 if (bi_magic == NULL || bi_magic->magic != BOOTINFO_MAGIC) 181 bi_msg = "invalid bootinfo structure.\n"; 182 else 183 bi_msg = NULL; 184 } else 185 bi_msg = "invalid bootinfo (standalone boot?)\n"; 186 187#if NKSYMS || defined(DDB) || defined(LKM) 188 bi_syms = lookup_bootinfo(BTINFO_SYMTAB); 189 190 /* Load symbol table if present */ 191 if (bi_syms != NULL) { 192 nsym = bi_syms->nsym; 193 ssym = (caddr_t)bi_syms->ssym; 194 esym = (caddr_t)bi_syms->esym; 195 kernend = (caddr_t)mips_round_page(esym); 196 } 197#endif 198 199 cobalt_id = read_board_id(); 200 if (cobalt_id >= COBALT_MODELS || cobalt_model[cobalt_id] == NULL) 201 sprintf(cpu_model, "Cobalt unknown model (board ID %u)", 202 cobalt_id); 203 else 204 strcpy(cpu_model, cobalt_model[cobalt_id]); 205 206 switch (cobalt_id) { 207 case COBALT_ID_QUBE2700: 208 case COBALT_ID_RAQ: 209 cpuspeed = 150; /* MHz */ 210 break; 211 case COBALT_ID_QUBE2: 212 case COBALT_ID_RAQ2: 213 cpuspeed = 250; /* MHz */ 214 break; 215 default: 216 /* assume the fastest, so that delay(9) works */ 217 cpuspeed = 250; 218 break; 219 } 220 curcpu()->ci_cpu_freq = cpuspeed * 1000 * 1000; 221 curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz; 222 curcpu()->ci_divisor_delay = 223 ((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000); 224 /* all models have Rm5200, which is CPU_MIPS_DOUBLE_COUNT */ 225 curcpu()->ci_cycles_per_hz /= 2; 226 curcpu()->ci_divisor_delay /= 2; 227 MIPS_SET_CI_RECIPRICAL(curcpu()); 228 229 physmem = btoc(memsize - MIPS_KSEG0_START); 230 231 consinit(); 232 233 if (bi_msg != NULL) 234 printf(bi_msg); 235 236 uvm_setpagesize(); 237 238 /* 239 * Copy exception-dispatch code down to exception vector. 240 * Initialize locore-function vector. 241 * Clear out the I and D caches. 242 */ 243 mips_vector_init(); 244 245 /* 246 * The boot command is passed in the top 512 bytes, 247 * so don't clobber that. 248 */ 249 mem_clusters[0].start = 0; 250 mem_clusters[0].size = ctob(physmem) - 512; 251 mem_cluster_cnt = 1; 252 253 memcpy(bootstring, (char *)(memsize - 512), 512); 254 memset((char *)(memsize - 512), 0, 512); 255 bootstring[511] = '\0'; 256 257 decode_bootstring(); 258 259#if NKSYMS || defined(DDB) || defined(LKM) 260 /* init symbols if present */ 261 if ((bi_syms != NULL) && (esym != NULL)) 262 ksyms_init(esym - ssym, ssym, esym); 263 else 264 ksyms_init(0, NULL, NULL); 265#endif 266#ifdef DDB 267 if (boothowto & RB_KDB) 268 Debugger(); 269#endif 270#ifdef KGDB 271 if (boothowto & RB_KDB) 272 kgdb_connect(0); 273#endif 274 275 /* 276 * Load the rest of the available pages into the VM system. 277 */ 278 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 279 last = mem_clusters[0].start + mem_clusters[0].size; 280 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 281 VM_FREELIST_DEFAULT); 282 283 /* 284 * Initialize error message buffer (at end of core). 285 */ 286 mips_init_msgbuf(); 287 288 pmap_bootstrap(); 289 290 /* 291 * Allocate space for proc0's USPACE. 292 */ 293 v = (caddr_t)uvm_pageboot_alloc(USPACE); 294 lwp0.l_addr = proc0paddr = (struct user *)v; 295 lwp0.l_md.md_regs = (struct frame *)(v + USPACE) - 1; 296 curpcb = &lwp0.l_addr->u_pcb; 297 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 298} 299 300/* 301 * Allocate memory for variable-sized tables, 302 */ 303void 304cpu_startup(void) 305{ 306 vaddr_t minaddr, maxaddr; 307 char pbuf[9]; 308 309 /* 310 * Good {morning,afternoon,evening,night}. 311 */ 312 printf("%s%s", copyright, version); 313 printf("%s\n", cpu_model); 314 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 315 printf("total memory = %s\n", pbuf); 316 317 minaddr = 0; 318 /* 319 * Allocate a submap for exec arguments. This map effectively 320 * limits the number of processes exec'ing at any time. 321 */ 322 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 323 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 324 /* 325 * Allocate a submap for physio. 326 */ 327 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 328 VM_PHYS_SIZE, 0, FALSE, NULL); 329 330 /* 331 * (No need to allocate an mbuf cluster submap. Mbuf clusters 332 * are allocated via the pool allocator, and we use KSEG to 333 * map those pages.) 334 */ 335 336 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 337 printf("avail memory = %s\n", pbuf); 338} 339 340int waittime = -1; 341 342void 343cpu_reboot(int howto, char *bootstr) 344{ 345 346 /* Take a snapshot before clobbering any registers. */ 347 if (curlwp) 348 savectx((struct user *)curpcb); 349 350 if (cold) { 351 howto |= RB_HALT; 352 goto haltsys; 353 } 354 355 /* If "always halt" was specified as a boot flag, obey. */ 356 if (boothowto & RB_HALT) 357 howto |= RB_HALT; 358 359 boothowto = howto; 360 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 361 waittime = 0; 362 vfs_shutdown(); 363 364 /* 365 * If we've been adjusting the clock, the todr 366 * will be out of synch; adjust it now. 367 */ 368 resettodr(); 369 } 370 371 splhigh(); 372 373 if (howto & RB_DUMP) 374 dumpsys(); 375 376 haltsys: 377 doshutdownhooks(); 378 379 if (howto & RB_HALT) { 380 printf("\n"); 381 printf("The operating system has halted.\n"); 382 printf("Please press any key to reboot.\n\n"); 383 cnpollc(1); /* For proper keyboard command handling */ 384 cngetc(); 385 cnpollc(0); 386 } 387 388 printf("rebooting...\n\n"); 389 delay(500000); 390 391 *(volatile char *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET; 392 printf("WARNING: reboot failed!\n"); 393 394 for (;;) 395 ; 396} 397 398#define NINTR 6 399 400static struct cobalt_intrhand intrtab[NINTR]; 401 402const uint32_t mips_ipl_si_to_sr[_IPL_NSOFT] = { 403 MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */ 404 MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */ 405 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTNET */ 406 MIPS_SOFT_INT_MASK_1, /* IPL_SOFTSERIAL */ 407}; 408 409void * 410cpu_intr_establish(int level, int ipl, int (*func)(void *), void *arg) 411{ 412 struct cobalt_intrhand *ih; 413 414 if (level < 0 || level >= NINTR) 415 panic("invalid interrupt level"); 416 417 ih = &intrtab[level]; 418 419 if (ih->ih_func != NULL) 420 panic("cannot share CPU interrupts"); 421 422 ih->ih_cookie_type = COBALT_COOKIE_TYPE_CPU; 423 ih->ih_func = func; 424 ih->ih_arg = arg; 425 426 return ih; 427} 428 429void 430cpu_intr_disestablish(void *cookie) 431{ 432 struct cobalt_intrhand *ih = cookie; 433 434 if (ih->ih_cookie_type == COBALT_COOKIE_TYPE_CPU) { 435 ih->ih_func = NULL; 436 ih->ih_arg = NULL; 437 ih->ih_cookie_type = 0; 438 } 439} 440 441void 442cpu_intr(uint32_t status, uint32_t cause, uint32_t pc, uint32_t ipending) 443{ 444 struct clockframe cf; 445 static uint32_t cycles; 446 int i; 447 448 uvmexp.intrs++; 449 450 if (ipending & MIPS_INT_MASK_0) { 451 volatile uint32_t *irq_src = 452 (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_INTR_CAUSE); 453 454 if ((*irq_src & T0EXP) != 0) { 455 *irq_src = 0; 456 457 cf.pc = pc; 458 cf.sr = status; 459 460 hardclock(&cf); 461 } 462 cause &= ~MIPS_INT_MASK_0; 463 } 464 465 for (i = 0; i < 5; i++) { 466 if (ipending & (MIPS_INT_MASK_0 << i)) 467 if (intrtab[i].ih_func != NULL) 468 if ((*intrtab[i].ih_func)(intrtab[i].ih_arg)) 469 cause &= ~(MIPS_INT_MASK_0 << i); 470 } 471 472 if (ipending & MIPS_INT_MASK_5) { 473 cycles = mips3_cp0_count_read(); 474 mips3_cp0_compare_write(cycles + 1250000); /* XXX */ 475 476#if 0 477 cf.pc = pc; 478 cf.sr = status; 479 480 statclock(&cf); 481#endif 482 cause &= ~MIPS_INT_MASK_5; 483 } 484 485 _splset((status & ~cause & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 486 487 /* software interrupt */ 488 ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0); 489 if (ipending == 0) 490 return; 491 492 _clrsoftintr(ipending); 493 494 softintr_dispatch(ipending); 495} 496 497 498void 499decode_bootstring(void) 500{ 501 char *work; 502 char *equ; 503 int i; 504 505 /* break apart bootstring on ' ' boundries and itterate*/ 506 work = strtok_light(bootstring, ' '); 507 while (work != '\0') { 508 /* if starts with '-', we got options, walk its decode */ 509 if (work[0] == '-') { 510 i = 1; 511 while (work[i] != ' ' && work[i] != '\0') { 512 BOOT_FLAG(work[i], boothowto); 513 i++; 514 } 515 } else 516 517 /* if it has a '=' its an assignment, switch and set */ 518 if ((equ = strchr(work,'=')) != '\0') { 519 if(0 == memcmp("nfsroot=", work, 8)) { 520 nfsroot_bstr = (equ +1); 521 } else 522 if(0 == memcmp("root=", work, 5)) { 523 root_bstr = (equ +1); 524 } 525 } else 526 527 /* else it a single value, switch and process */ 528 if (memcmp("single", work, 5) == 0) { 529 boothowto |= RB_SINGLE; 530 } else 531 if (memcmp("ro", work, 2) == 0) { 532 /* this is also inserted by the firmware */ 533 } 534 535 /* grab next token */ 536 work = strtok_light(NULL, ' '); 537 } 538 539 if (root_bstr != NULL) { 540 /* this should be of the form "/dev/hda1" */ 541 /* [abcd][1234] drive partition linux probe order */ 542 if ((memcmp("/dev/hd",root_bstr,7) == 0) && 543 (strlen(root_bstr) == 9) ){ 544 bootunit = root_bstr[7] - 'a'; 545 bootpart = root_bstr[8] - '1'; 546 } 547 } 548} 549 550 551static char * 552strtok_light(char *str, const char sep) 553{ 554 static char *proc; 555 char *head; 556 char *work; 557 558 if (str != NULL) 559 proc = str; 560 if (proc == NULL) /* end of string return NULL */ 561 return proc; 562 563 head = proc; 564 565 work = strchr (proc, sep); 566 if (work == NULL) { /* we hit the end */ 567 proc = work; 568 } else { 569 proc = (work +1 ); 570 *work = '\0'; 571 } 572 573 return head; 574} 575 576/* 577 * Look up information in bootinfo of boot loader. 578 */ 579void * 580lookup_bootinfo(int type) 581{ 582 struct btinfo_common *bt; 583 char *help = bootinfo; 584 585 /* Check for a bootinfo record first. */ 586 if (help == NULL) { 587 printf("##### help == NULL\n"); 588 return NULL; 589 } 590 591 do { 592 bt = (struct btinfo_common *)help; 593 printf("Type %d @0x%x\n", bt->type, (u_int)bt); 594 if (bt->type == type) 595 return (void *)help; 596 help += bt->next; 597 } while (bt->next != 0 && 598 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 599 600 return NULL; 601} 602 603/* 604 * Get board ID of cobalt models. 605 * 606 * The board ID info is stored at the PCI config register 607 * on the PCI-ISA bridge part of the VIA VT82C586 chipset. 608 * We can't use pci_conf_read(9) yet here, so read it directly. 609 */ 610static u_int 611read_board_id(void) 612{ 613 volatile uint32_t *pcicfg_addr, *pcicfg_data; 614 uint32_t reg; 615 616#define PCIB_PCI_BUS 0 617#define PCIB_PCI_DEV 9 618#define PCIB_PCI_FUNC 0 619#define PCIB_BOARD_ID_REG 0x94 620#define COBALT_BOARD_ID(reg) ((reg & 0x000000f0) >> 4) 621 622 pcicfg_addr = (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_PCICFG_ADDR); 623 pcicfg_data = (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_PCICFG_DATA); 624 625 *pcicfg_addr = PCICFG_ENABLE | 626 (PCIB_PCI_BUS << 16) | (PCIB_PCI_DEV << 11) | (PCIB_PCI_FUNC << 8) | 627 PCIB_BOARD_ID_REG; 628 reg = *pcicfg_data; 629 *pcicfg_addr = 0; 630 631 return COBALT_BOARD_ID(reg); 632} 633