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