1 /* $NetBSD: machdep.c,v 1.40 2002/09/25 22:21:07 thorpej 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 "opt_ddb.h" 29 #include "opt_kgdb.h" 30 #include "opt_execfmt.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/proc.h> 36 #include <sys/buf.h> 37 #include <sys/reboot.h> 38 #include <sys/conf.h> 39 #include <sys/file.h> 40 #include <sys/malloc.h> 41 #include <sys/mbuf.h> 42 #include <sys/msgbuf.h> 43 #include <sys/device.h> 44 #include <sys/user.h> 45 #include <sys/exec.h> 46 #include <uvm/uvm_extern.h> 47 #include <sys/sysctl.h> 48 #include <sys/mount.h> 49 #include <sys/syscallargs.h> 50 #include <sys/kcore.h> 51 #include <sys/boot_flag.h> 52 53 #include <machine/cpu.h> 54 #include <machine/reg.h> 55 #include <machine/psl.h> 56 #include <machine/pte.h> 57 #include <machine/autoconf.h> 58 #include <machine/intr.h> 59 #include <machine/intr_machdep.h> 60 #include <mips/locore.h> 61 62 #include <machine/nvram.h> 63 #include <machine/leds.h> 64 65 #include <dev/cons.h> 66 67 #ifdef KGDB 68 #include <sys/kgdb.h> 69 #endif 70 71 #ifdef DDB 72 #include <machine/db_machdep.h> 73 #include <ddb/db_extern.h> 74 #define ELFSIZE DB_ELFSIZE 75 #include <sys/exec_elf.h> 76 #endif 77 78 /* For sysctl. */ 79 extern char cpu_model[]; 80 81 /* Our exported CPU info; we can have only one. */ 82 struct cpu_info cpu_info_store; 83 84 /* Maps for VM objects. */ 85 struct vm_map *exec_map = NULL; 86 struct vm_map *mb_map = NULL; 87 struct vm_map *phys_map = NULL; 88 89 int physmem; /* Total physical memory */ 90 91 char bootstring[512]; /* Boot command */ 92 int netboot; /* Are we netbooting? */ 93 94 char * nfsroot_bstr = NULL; 95 char * root_bstr = NULL; 96 int bootunit = -1; 97 int bootpart = -1; 98 99 100 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 101 int mem_cluster_cnt; 102 103 void configure(void); 104 void mach_init(unsigned int); 105 void decode_bootstring(void); 106 static char * strtok_light(char *, const char); 107 108 /* 109 * safepri is a safe priority for sleep to set for a spin-wait during 110 * autoconfiguration or after a panic. Used as an argument to splx(). 111 */ 112 int safepri = MIPS1_PSL_LOWIPL; 113 114 extern caddr_t esym; 115 extern struct user *proc0paddr; 116 117 118 119 /* 120 * Do all the stuff that locore normally does before calling main(). 121 */ 122 void 123 mach_init(memsize) 124 unsigned int memsize; 125 { 126 caddr_t kernend, v; 127 u_long first, last; 128 vsize_t size; 129 extern char edata[], end[]; 130 131 /* 132 * Clear the BSS segment. 133 */ 134 #ifdef DDB 135 if (memcmp(((Elf_Ehdr *)end)->e_ident, ELFMAG, SELFMAG) == 0 && 136 ((Elf_Ehdr *)end)->e_ident[EI_CLASS] == ELFCLASS) { 137 esym = end; 138 esym += ((Elf_Ehdr *)end)->e_entry; 139 kernend = (caddr_t)mips_round_page(esym); 140 memset(edata, 0, end - edata); 141 } else 142 #endif 143 { 144 kernend = (caddr_t)mips_round_page(end); 145 memset(edata, 0, kernend - edata); 146 } 147 148 physmem = btoc(memsize - MIPS_KSEG0_START); 149 150 consinit(); 151 152 uvm_setpagesize(); 153 154 /* 155 * Copy exception-dispatch code down to exception vector. 156 * Initialize locore-function vector. 157 * Clear out the I and D caches. 158 */ 159 mips_vector_init(); 160 161 /* 162 * The boot command is passed in the top 512 bytes, 163 * so don't clobber that. 164 */ 165 mem_clusters[0].start = 0; 166 mem_clusters[0].size = ctob(physmem) - 512; 167 mem_cluster_cnt = 1; 168 169 memcpy(bootstring, (char *)(memsize - 512), 512); 170 memset((char *)(memsize - 512), 0, 512); 171 bootstring[511] = '\0'; 172 173 decode_bootstring(); 174 175 #ifdef DDB 176 ddb_init(0, NULL, NULL); 177 if (boothowto & RB_KDB) 178 Debugger(); 179 #endif 180 #ifdef KGDB 181 if (boothowto & RB_KDB) 182 kgdb_connect(0); 183 #endif 184 185 strcpy(cpu_model, "Cobalt Microserver"); 186 187 /* 188 * Load the rest of the available pages into the VM system. 189 */ 190 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 191 last = mem_clusters[0].start + mem_clusters[0].size; 192 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 193 VM_FREELIST_DEFAULT); 194 195 /* 196 * Initialize error message buffer (at end of core). 197 */ 198 mips_init_msgbuf(); 199 200 /* 201 * Compute the size of system data structures. pmap_bootstrap() 202 * needs some of this information. 203 */ 204 size = (vsize_t)allocsys(NULL, NULL); 205 206 pmap_bootstrap(); 207 208 /* 209 * Allocate space for proc0's USPACE. 210 */ 211 v = (caddr_t)uvm_pageboot_alloc(USPACE); 212 proc0.p_addr = proc0paddr = (struct user *)v; 213 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 214 curpcb = &proc0.p_addr->u_pcb; 215 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 216 217 /* 218 * Allocate space for system data structures. These data structures 219 * are allocated here instead of cpu_startup() because physical 220 * memory is directly addressable. We don't have to map these into 221 * virtual address space. 222 */ 223 v = (caddr_t)uvm_pageboot_alloc(size); 224 if ((allocsys(v, NULL) - v) != size) 225 panic("mach_init: table size inconsistency"); 226 } 227 228 /* 229 * Allocate memory for variable-sized tables, 230 */ 231 void 232 cpu_startup() 233 { 234 int i, base, residual; 235 vaddr_t minaddr, maxaddr; 236 vsize_t size; 237 char pbuf[9]; 238 239 /* 240 * Good {morning,afternoon,evening,night}. 241 */ 242 printf(version); 243 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 244 printf("%s memory", pbuf); 245 246 /* 247 * Allocate virtual address space for file I/O buffers. 248 * Note they are different than the array of headers, 'buf', 249 * and usually occupy more virtual memory than physical. 250 */ 251 size = MAXBSIZE * nbuf; 252 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 253 NULL, UVM_UNKNOWN_OFFSET, 0, 254 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 255 UVM_ADV_NORMAL, 0)) != 0) 256 panic("startup: cannot allocate VM for buffers"); 257 minaddr = (vaddr_t)buffers; 258 base = bufpages / nbuf; 259 residual = bufpages % nbuf; 260 for (i = 0; i < nbuf; i++) { 261 vsize_t curbufsize; 262 vaddr_t curbuf; 263 struct vm_page *pg; 264 265 /* 266 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 267 * that MAXBSIZE space, we allocate and map (base+1) pages 268 * for the first "residual" buffers, and then we allocate 269 * "base" pages for the rest. 270 */ 271 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 272 curbufsize = NBPG * ((i < residual) ? (base + 1) : base); 273 274 while (curbufsize) { 275 pg = uvm_pagealloc(NULL, 0, NULL, 0); 276 if (pg == NULL) 277 panic("cpu_startup: not enough memory for " 278 "buffer cache"); 279 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 280 VM_PROT_READ|VM_PROT_WRITE); 281 curbuf += PAGE_SIZE; 282 curbufsize -= PAGE_SIZE; 283 } 284 } 285 pmap_update(pmap_kernel()); 286 287 /* 288 * Allocate a submap for exec arguments. This map effectively 289 * limits the number of processes exec'ing at any time. 290 */ 291 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 292 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 293 /* 294 * Allocate a submap for physio. 295 */ 296 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 297 VM_PHYS_SIZE, 0, FALSE, NULL); 298 299 /* 300 * (No need to allocate an mbuf cluster submap. Mbuf clusters 301 * are allocated via the pool allocator, and we use KSEG to 302 * map those pages.) 303 */ 304 305 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 306 printf(", %s free", pbuf); 307 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 308 printf(", %s in %u buffers\n", pbuf, nbuf); 309 310 /* 311 * Set up buffers, so they can be used to read disk labels. 312 */ 313 bufinit(); 314 } 315 316 int waittime = -1; 317 318 void 319 cpu_reboot(howto, bootstr) 320 int howto; 321 char *bootstr; 322 { 323 /* Take a snapshot before clobbering any registers. */ 324 if (curproc) 325 savectx((struct user *)curpcb); 326 327 if (cold) { 328 howto |= RB_HALT; 329 goto haltsys; 330 } 331 332 /* If "always halt" was specified as a boot flag, obey. */ 333 if (boothowto & RB_HALT) 334 howto |= RB_HALT; 335 336 boothowto = howto; 337 if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) { 338 waittime = 0; 339 vfs_shutdown(); 340 341 /* 342 * If we've been adjusting the clock, the todr 343 * will be out of synch; adjust it now. 344 */ 345 resettodr(); 346 } 347 348 splhigh(); 349 350 if (howto & RB_DUMP) 351 dumpsys(); 352 353 haltsys: 354 doshutdownhooks(); 355 356 if (howto & RB_HALT) { 357 printf("\n"); 358 printf("The operating system has halted.\n"); 359 printf("Please press any key to reboot.\n\n"); 360 cnpollc(1); /* For proper keyboard command handling */ 361 cngetc(); 362 cnpollc(0); 363 } 364 365 printf("rebooting...\n\n"); 366 delay(500000); 367 368 *(volatile char *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET; 369 printf("WARNING: reboot failed!\n"); 370 371 for (;;); 372 } 373 374 void 375 microtime(tvp) 376 struct timeval *tvp; 377 { 378 int s = splclock(); 379 static struct timeval lasttime; 380 u_int32_t counter0; 381 382 *tvp = time; 383 384 counter0 = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x14000850); 385 386 /* 387 * XXX 388 */ 389 390 counter0 /= 50; 391 counter0 %= 10000; 392 393 if (counter0 > 9999) { 394 counter0 = 9999; 395 } 396 397 tvp->tv_usec -= tvp->tv_usec % 10000; 398 tvp->tv_usec += 10000 - counter0; 399 400 lasttime = *tvp; 401 splx(s); 402 } 403 404 unsigned long cpuspeed; 405 406 __inline void 407 delay(n) 408 unsigned long n; 409 { 410 volatile register long N = cpuspeed * n; 411 412 while (--N > 0); 413 } 414 415 #define NINTR 6 416 417 static struct cobalt_intr intrtab[NINTR]; 418 419 void * 420 cpu_intr_establish(level, ipl, func, arg) 421 int level; 422 int ipl; 423 int (*func)(void *); 424 void *arg; 425 { 426 if (level < 0 || level >= NINTR) 427 panic("invalid interrupt level"); 428 429 if (intrtab[level].func != NULL) 430 panic("cannot share CPU interrupts"); 431 432 intrtab[level].cookie_type = COBALT_COOKIE_TYPE_CPU; 433 intrtab[level].func = func; 434 intrtab[level].arg = arg; 435 436 return &intrtab[level]; 437 } 438 439 void 440 cpu_intr_disestablish(cookie) 441 void *cookie; 442 { 443 struct cobalt_intr *p = cookie; 444 445 if (p->cookie_type == COBALT_COOKIE_TYPE_CPU) { 446 p->func = NULL; 447 p->arg = NULL; 448 } 449 } 450 451 void 452 cpu_intr(status, cause, pc, ipending) 453 u_int32_t status; 454 u_int32_t cause; 455 u_int32_t pc; 456 u_int32_t ipending; 457 { 458 struct clockframe cf; 459 static u_int32_t cycles; 460 int i; 461 462 uvmexp.intrs++; 463 464 if (ipending & MIPS_INT_MASK_0) { 465 volatile u_int32_t *irq_src = 466 (u_int32_t *)MIPS_PHYS_TO_KSEG1(0x14000c18); 467 468 if (*irq_src & 0x00000100) { 469 *irq_src = 0; 470 471 cf.pc = pc; 472 cf.sr = status; 473 474 hardclock(&cf); 475 } 476 cause &= ~MIPS_INT_MASK_0; 477 } 478 479 for (i = 0; i < 5; i++) { 480 if (ipending & (MIPS_INT_MASK_0 << i)) 481 if (intrtab[i].func != NULL) 482 if ((*intrtab[i].func)(intrtab[i].arg)) 483 cause &= ~(MIPS_INT_MASK_0 << i); 484 } 485 486 if (ipending & MIPS_INT_MASK_5) { 487 cycles = mips3_cp0_count_read(); 488 mips3_cp0_compare_write(cycles + 1250000); /* XXX */ 489 490 #if 0 491 cf.pc = pc; 492 cf.sr = status; 493 494 statclock(&cf); 495 #endif 496 cause &= ~MIPS_INT_MASK_5; 497 } 498 499 _splset((status & ~cause & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 500 501 /* 'softnet' interrupt */ 502 if (ipending & MIPS_SOFT_INT_MASK_1) { 503 clearsoftnet(); 504 uvmexp.softs++; 505 netintr(); 506 } 507 508 /* 'softclock' interrupt */ 509 if (ipending & MIPS_SOFT_INT_MASK_0) { 510 clearsoftclock(); 511 uvmexp.softs++; 512 intrcnt[SOFTCLOCK_INTR]++; 513 softclock(NULL); 514 } 515 } 516 517 518 void 519 decode_bootstring(void) 520 { 521 char * work; 522 char * equ; 523 int i; 524 525 /* break apart bootstring on ' ' boundries and itterate*/ 526 work = strtok_light(bootstring, ' '); 527 while (work != '\0') { 528 /* if starts with '-', we got options, walk its decode */ 529 if (work[0] == '-') { 530 i = 1; 531 while (work[i] != ' ' && work[i] != '\0') { 532 BOOT_FLAG(work[i], boothowto); 533 i++; 534 } 535 } else 536 537 /* if it has a '=' its an assignment, switch and set */ 538 if ((equ = strchr(work,'=')) != '\0') { 539 if(0 == memcmp("nfsroot=", work, 8)) { 540 nfsroot_bstr = (equ +1); 541 } else 542 if(0 == memcmp("root=", work, 5)) { 543 root_bstr = (equ +1); 544 } 545 } else 546 547 /* else it a single value, switch and process */ 548 if (memcmp("single", work, 5) == 0) { 549 boothowto |= RB_SINGLE; 550 } else 551 if (memcmp("ro", work, 2) == 0) { 552 /* this is also inserted by the firmware */ 553 } 554 555 /* grab next token */ 556 work = strtok_light(NULL, ' '); 557 } 558 559 if (root_bstr != NULL) { 560 /* this should be of the form "/dev/hda1" */ 561 /* [abcd][1234] drive partition linux probe order */ 562 if ((memcmp("/dev/hd",root_bstr,7) == 0) && 563 (strlen(root_bstr) == 9) ){ 564 bootunit = root_bstr[7] - 'a'; 565 bootpart = root_bstr[8] - '1'; 566 } 567 } 568 } 569 570 571 static char * 572 strtok_light(str, sep) 573 char * str; 574 const char sep; 575 { 576 static char * proc; 577 char * head; 578 char * work; 579 580 if (str != NULL) 581 proc = str; 582 if (proc == NULL) /* end of string return NULL */ 583 return proc; 584 585 head = proc; 586 587 work = strchr (proc, sep); 588 if (work == NULL) { /* we hit the end */ 589 proc = work; 590 } else { 591 proc = (work +1 ); 592 *work = '\0'; 593 } 594 595 return head; 596 } 597 598