1 /* 2 * Copyright (c) 1982,1987,1988 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)machdep.c 7.13 (Berkeley) 06/28/90 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "user.h" 12 #include "kernel.h" 13 #include "map.h" 14 #include "vm.h" 15 #include "proc.h" 16 #include "buf.h" 17 #include "reboot.h" 18 #include "conf.h" 19 #include "file.h" 20 #include "text.h" 21 #include "clist.h" 22 #include "callout.h" 23 #include "cmap.h" 24 #include "malloc.h" 25 #include "mbuf.h" 26 #include "msgbuf.h" 27 #ifdef SYSVSHM 28 #include "shm.h" 29 #endif 30 31 #include "cpu.h" 32 #include "reg.h" 33 #include "pte.h" 34 #include "psl.h" 35 #include "mem.h" 36 #include "mtpr.h" 37 #include "cp.h" 38 39 #include "../tahoevba/vbavar.h" 40 41 /* 42 * Declare these as initialized data so we can patch them. 43 */ 44 int nswbuf = 0; 45 #ifdef NBUF 46 int nbuf = NBUF; 47 #else 48 int nbuf = 0; 49 #endif 50 #ifdef BUFPAGES 51 int bufpages = BUFPAGES; 52 #else 53 int bufpages = 0; 54 #endif 55 #include "yc.h" 56 #if NCY > 0 57 #include "../tahoevba/cyreg.h" 58 #endif 59 int msgbufmapped; /* set when safe to use msgbuf */ 60 int physmem = MAXMEM; /* max supported memory, changes to actual */ 61 62 /* 63 * Machine-dependent startup code 64 */ 65 startup(firstaddr) 66 int firstaddr; 67 { 68 register int unixsize; 69 register unsigned i; 70 register struct pte *pte; 71 int mapaddr, j; 72 register caddr_t v; 73 int maxbufs, base, residual; 74 75 /* 76 * Initialize error message buffer (at end of core). 77 */ 78 maxmem = physmem - btoc(sizeof (struct msgbuf)); 79 pte = msgbufmap; 80 for (i = 1; i < btoc(sizeof (struct msgbuf)) + 1; i++) 81 *(int *)pte++ = PG_V | PG_KW | (physmem - i); 82 mtpr(TBIA, 1); 83 msgbufmapped = 1; 84 #ifdef KADB 85 kdb_init(); /* startup kernel debugger */ 86 (void) cnopen(makedev(0, 1), 0); /* open console XXX */ 87 #endif 88 /* 89 * Good {morning,afternoon,evening,night}. 90 */ 91 printf(version); 92 printf("real mem = %d\n", ctob(physmem)); 93 94 /* 95 * Allocate space for system data structures. 96 * The first available real memory address is in "firstaddr". 97 * The first available kernel virtual address is in "v". 98 * As pages of kernel virtual memory are allocated, "v" is incremented. 99 * As pages of memory are allocated and cleared, 100 * "firstaddr" is incremented. 101 * An index into the kernel page table corresponding to the 102 * virtual memory address maintained in "v" is kept in "mapaddr". 103 */ 104 v = (caddr_t)(0xc0000000 | (firstaddr * NBPG)); 105 #define valloc(name, type, num) \ 106 (name) = (type *)v; v = (caddr_t)((name)+(num)) 107 #define valloclim(name, type, num, lim) \ 108 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 109 #if NCY > 0 110 /* 111 * Allocate raw buffers for tapemaster controllers 112 * first, as they need buffers in the first megabyte. 113 */ 114 valloc(cybuf, char, NCY * CYMAXIO); 115 #endif 116 valloclim(file, struct file, nfile, fileNFILE); 117 valloclim(proc, struct proc, nproc, procNPROC); 118 valloclim(text, struct text, ntext, textNTEXT); 119 valloc(cfree, struct cblock, nclist); 120 valloc(callout, struct callout, ncallout); 121 valloc(swapmap, struct map, nswapmap = nproc * 2); 122 valloc(argmap, struct map, ARGMAPSIZE); 123 valloc(kernelmap, struct map, nproc); 124 valloc(mbmap, struct map, nmbclusters/4); 125 valloc(kmemmap, struct map, ekmempt - kmempt); 126 valloc(kmemusage, struct kmemusage, ekmempt - kmempt); 127 #ifdef SYSVSHM 128 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 129 #endif 130 131 /* 132 * Determine how many buffers to allocate. 133 * Use 10% of memory for the first 2 Meg, 5% of the remaining 134 * memory. Insure a minimum of 16 buffers. 135 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 136 */ 137 if (bufpages == 0) 138 if (physmem < (2 * 1024 * 1024)) 139 bufpages = physmem / 10 / CLSIZE; 140 else 141 bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE; 142 if (nbuf == 0) { 143 nbuf = bufpages / 2; 144 if (nbuf < 16) 145 nbuf = 16; 146 } 147 if (nswbuf == 0) { 148 nswbuf = (nbuf / 2) &~ 1; /* force even */ 149 if (nswbuf > 256) 150 nswbuf = 256; /* sanity */ 151 } 152 valloc(swbuf, struct buf, nswbuf); 153 154 /* 155 * Now the amount of virtual memory remaining for buffers 156 * can be calculated, estimating needs for the cmap. 157 */ 158 ncmap = (maxmem*NBPG - ((int)v &~ 0xc0000000)) / 159 (CLBYTES + sizeof(struct cmap)) + 2; 160 maxbufs = ((SYSPTSIZE * NBPG) - 161 ((int)(v + ncmap * sizeof(struct cmap)) - 0xc0000000)) / 162 (MAXBSIZE + sizeof(struct buf)); 163 if (maxbufs < 16) 164 panic("sys pt too small"); 165 if (nbuf > maxbufs) { 166 printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs); 167 nbuf = maxbufs; 168 } 169 if (bufpages > nbuf * (MAXBSIZE / CLBYTES)) 170 bufpages = nbuf * (MAXBSIZE / CLBYTES); 171 valloc(buf, struct buf, nbuf); 172 173 /* 174 * Allocate space for core map. 175 * Allow space for all of phsical memory minus the amount 176 * dedicated to the system. The amount of physical memory 177 * dedicated to the system is the total virtual memory of 178 * the system thus far, plus core map, buffer pages, 179 * and buffer headers not yet allocated. 180 * Add 2: 1 because the 0th entry is unused, 1 for rounding. 181 */ 182 ncmap = (maxmem*NBPG - ((int)(v + bufpages*CLBYTES) &~ 0xc0000000)) / 183 (CLBYTES + sizeof(struct cmap)) + 2; 184 valloclim(cmap, struct cmap, ncmap, ecmap); 185 186 /* 187 * Clear space allocated thus far, and make r/w entries 188 * for the space in the kernel map. 189 */ 190 unixsize = btoc((int)v &~ 0xc0000000); 191 while (firstaddr < unixsize) { 192 *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | firstaddr; 193 clearseg((unsigned)firstaddr); 194 firstaddr++; 195 } 196 197 /* 198 * Now allocate buffers proper. They are different than the above 199 * in that they usually occupy more virtual memory than physical. 200 */ 201 v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET); 202 valloc(buffers, char, MAXBSIZE * nbuf); 203 base = bufpages / nbuf; 204 residual = bufpages % nbuf; 205 mapaddr = firstaddr; 206 for (i = 0; i < residual; i++) { 207 for (j = 0; j < (base + 1) * CLSIZE; j++) { 208 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; 209 clearseg((unsigned)firstaddr); 210 firstaddr++; 211 } 212 mapaddr += MAXBSIZE / NBPG; 213 } 214 for (i = residual; i < nbuf; i++) { 215 for (j = 0; j < base * CLSIZE; j++) { 216 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; 217 clearseg((unsigned)firstaddr); 218 firstaddr++; 219 } 220 mapaddr += MAXBSIZE / NBPG; 221 } 222 223 unixsize = btoc((int)v &~ 0xc0000000); 224 if (firstaddr >= physmem - 8*UPAGES) 225 panic("no memory"); 226 mtpr(TBIA, 1); /* After we just cleared it all! */ 227 228 /* 229 * Initialize callouts 230 */ 231 callfree = callout; 232 for (i = 1; i < ncallout; i++) 233 callout[i-1].c_next = &callout[i]; 234 235 /* 236 * Initialize memory allocator and swap 237 * and user page table maps. 238 * 239 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' 240 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. 241 */ 242 meminit(firstaddr, maxmem); 243 maxmem = freemem; 244 printf("avail mem = %d\n", ctob(maxmem)); 245 printf("using %d buffers containing %d bytes of memory\n", 246 nbuf, bufpages * CLBYTES); 247 rminit(kernelmap, (long)USRPTSIZE, (long)1, 248 "usrpt", nproc); 249 rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE, 250 "mbclusters", nmbclusters/4); 251 kmeminit(); /* now safe to do malloc/free */ 252 intenable = 1; /* Enable interrupts from now on */ 253 254 /* 255 * Set up CPU-specific registers, cache, etc. 256 */ 257 initcpu(); 258 259 /* 260 * Set up buffers, so they can be used to read disk labels. 261 */ 262 bhinit(); 263 binit(); 264 265 /* 266 * Configure the system. 267 */ 268 configure(); 269 } 270 271 #ifdef PGINPROF 272 /* 273 * Return the difference (in microseconds) 274 * between the current time and a previous 275 * time as represented by the arguments. 276 * If there is a pending clock interrupt 277 * which has not been serviced due to high 278 * ipl, return error code. 279 */ 280 /*ARGSUSED*/ 281 vmtime(otime, olbolt, oicr) 282 register int otime, olbolt, oicr; 283 { 284 285 return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); 286 } 287 #endif 288 289 /* 290 * Send an interrupt to process. 291 * 292 * Stack is set up to allow sigcode stored 293 * in u. to call routine, followed by kcall 294 * to sigreturn routine below. After sigreturn 295 * resets the signal mask, the stack, and the 296 * frame pointer, it returns to the user 297 * specified pc, psl. 298 */ 299 sendsig(catcher, sig, mask, code) 300 sig_t catcher; 301 int sig, mask; 302 unsigned code; 303 { 304 register struct sigcontext *scp; 305 register struct proc *p = u.u_procp; 306 register int *regs; 307 register struct sigframe { 308 int sf_signum; 309 int sf_code; 310 struct sigcontext *sf_scp; 311 sig_t sf_handler; 312 int sf_regs[6]; /* r0-r5 */ 313 struct sigcontext *sf_scpcopy; 314 } *fp; 315 int oonstack; 316 317 regs = u.u_ar0; 318 oonstack = u.u_onstack; 319 /* 320 * Allocate and validate space for the signal handler 321 * context. Note that if the stack is in P0 space, the 322 * call to grow() is a nop, and the useracc() check 323 * will fail if the process has not already allocated 324 * the space with a `brk'. 325 */ 326 if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) { 327 scp = (struct sigcontext *)u.u_sigsp - 1; 328 u.u_onstack = 1; 329 } else 330 scp = (struct sigcontext *)regs[SP] - 1; 331 fp = (struct sigframe *)scp - 1; 332 if ((int)fp <= USRSTACK - ctob(u.u_ssize)) 333 (void) grow((unsigned)fp); 334 if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) { 335 /* 336 * Process has trashed its stack; give it an illegal 337 * instruction to halt it in its tracks. 338 */ 339 SIGACTION(p, SIGILL) = SIG_DFL; 340 sig = sigmask(SIGILL); 341 p->p_sigignore &= ~sig; 342 p->p_sigcatch &= ~sig; 343 p->p_sigmask &= ~sig; 344 psignal(p, SIGILL); 345 return; 346 } 347 /* 348 * Build the argument list for the signal handler. 349 */ 350 fp->sf_signum = sig; 351 fp->sf_code = code; 352 fp->sf_scp = scp; 353 fp->sf_handler = catcher; 354 /* 355 * Build the callf argument frame to be used to call sigreturn. 356 */ 357 fp->sf_scpcopy = scp; 358 /* 359 * Build the signal context to be used by sigreturn. 360 */ 361 scp->sc_onstack = oonstack; 362 scp->sc_mask = mask; 363 scp->sc_sp = regs[SP]; 364 scp->sc_fp = regs[FP]; 365 scp->sc_pc = regs[PC]; 366 scp->sc_ps = regs[PS]; 367 regs[SP] = (int)fp; 368 regs[PC] = (int)u.u_pcb.pcb_sigc; 369 } 370 371 /* 372 * System call to cleanup state after a signal 373 * has been taken. Reset signal mask and 374 * stack state from context left by sendsig (above). 375 * Return to previous pc and psl as specified by 376 * context left by sendsig. Check carefully to 377 * make sure that the user has not modified the 378 * psl to gain improper priviledges or to cause 379 * a machine fault. 380 */ 381 /* ARGSUSED */ 382 sigreturn(p, uap, retval) 383 struct proc *p; 384 struct args { 385 struct sigcontext *sigcntxp; 386 } *uap; 387 int *retval; 388 { 389 register struct sigcontext *scp; 390 register int *regs = u.u_ar0; 391 392 scp = uap->sigcntxp; 393 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) 394 return (EINVAL); 395 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_IS)) != 0 || 396 (scp->sc_ps & (PSL_PRVMOD|PSL_CURMOD)) != (PSL_PRVMOD|PSL_CURMOD)) 397 return (EINVAL); 398 u.u_onstack = scp->sc_onstack & 01; 399 p->p_sigmask = scp->sc_mask &~ sigcantmask; 400 regs[FP] = scp->sc_fp; 401 regs[SP] = scp->sc_sp; 402 regs[PC] = scp->sc_pc; 403 regs[PS] = scp->sc_ps; 404 return (EJUSTRETURN); 405 } 406 407 int waittime = -1; 408 409 boot(arghowto) 410 int arghowto; 411 { 412 register long dummy; /* r12 is reserved */ 413 register int howto; /* r11 == how to boot */ 414 register int devtype; /* r10 == major of root dev */ 415 extern char *panicstr; 416 417 howto = arghowto; 418 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 419 register struct buf *bp; 420 int iter, nbusy; 421 422 waittime = 0; 423 (void) splnet(); 424 printf("syncing disks... "); 425 /* 426 * Release vnodes held by texts before update. 427 */ 428 if (panicstr == 0) 429 xumount(NULL); 430 sync(); 431 432 for (iter = 0; iter < 20; iter++) { 433 nbusy = 0; 434 for (bp = &buf[nbuf]; --bp >= buf; ) 435 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 436 nbusy++; 437 if (nbusy == 0) 438 break; 439 printf("%d ", nbusy); 440 DELAY(40000 * iter); 441 } 442 if (nbusy) 443 printf("giving up\n"); 444 else 445 printf("done\n"); 446 DELAY(10000); /* wait for printf to finish */ 447 } 448 mtpr(IPL, 0x1f); /* extreme priority */ 449 devtype = major(rootdev); 450 *(int *)CPBFLG = howto; 451 if (howto&RB_HALT) { 452 printf("halting (in tight loop); hit ~h\n\n"); 453 mtpr(IPL, 0x1f); 454 for (;;) 455 ; 456 } else { 457 if (howto & RB_DUMP) { 458 doadump(); /* CPBOOT's itsself */ 459 /*NOTREACHED*/ 460 } 461 tocons(CPBOOT); 462 } 463 #ifdef lint 464 dummy = 0; dummy = dummy; 465 printf("howto %d, devtype %d\n", arghowto, devtype); 466 #endif 467 for (;;) 468 asm("halt"); 469 /*NOTREACHED*/ 470 } 471 472 struct cpdcb_o cpcontrol; 473 474 /* 475 * Send the given comand ('c') to the console processor. 476 * Assumed to be one of the last things the OS does before 477 * halting or rebooting. 478 */ 479 tocons(c) 480 { 481 register timeout; 482 483 cpcontrol.cp_hdr.cp_unit = CPUNIT; 484 cpcontrol.cp_hdr.cp_comm = (char)c; 485 if (c != CPBOOT) 486 cpcontrol.cp_hdr.cp_count = 1; /* Just for sanity */ 487 else { 488 cpcontrol.cp_hdr.cp_count = 4; 489 *(int *)cpcontrol.cp_buf = 0; /* r11 value for reboot */ 490 } 491 timeout = 100000; /* Delay loop */ 492 while (timeout-- && (cnlast->cp_unit&CPDONE) == 0) 493 uncache(&cnlast->cp_unit); 494 /* give up, force it to listen */ 495 mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&cpcontrol)); 496 } 497 498 #if CLSIZE != 1 499 /* 500 * Invalidate single all pte's in a cluster 501 */ 502 tbiscl(v) 503 unsigned v; 504 { 505 register caddr_t addr; /* must be first reg var */ 506 register int i; 507 508 addr = ptob(v); 509 for (i = 0; i < CLSIZE; i++) { 510 mtpr(TBIS, addr); 511 addr += NBPG; 512 } 513 } 514 #endif 515 516 int dumpmag = 0x8fca0101; /* magic number for savecore */ 517 int dumpsize = 0; /* also for savecore */ 518 519 dumpconf() 520 { 521 int nblks; 522 523 dumpsize = physmem; 524 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) { 525 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); 526 if (dumpsize > btoc(dbtob(nblks - dumplo))) 527 dumpsize = btoc(dbtob(nblks - dumplo)); 528 else if (dumplo == 0) 529 dumplo = nblks - btodb(ctob(physmem)); 530 } 531 /* 532 * Don't dump on the first CLSIZE pages, 533 * in case the dump device includes a disk label. 534 */ 535 if (dumplo < CLSIZE) 536 dumplo = CLSIZE; 537 } 538 539 /* 540 * Doadump comes here after turning off memory management and 541 * getting on the dump stack, either when called above, or by 542 * the auto-restart code. 543 */ 544 dumpsys() 545 { 546 547 if (dumpdev == NODEV) 548 return; 549 /* 550 * For dumps during autoconfiguration, 551 * if dump device has already configured... 552 */ 553 if (dumpsize == 0) 554 dumpconf(); 555 if (dumplo < 0) 556 return; 557 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 558 printf("dump "); 559 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 560 561 case ENXIO: 562 printf("device bad\n"); 563 break; 564 565 case EFAULT: 566 printf("device not ready\n"); 567 break; 568 569 case EINVAL: 570 printf("area improper\n"); 571 break; 572 573 case EIO: 574 printf("i/o error\n"); 575 break; 576 577 default: 578 printf("succeeded\n"); 579 break; 580 } 581 printf("\n\n"); 582 DELAY(1000); 583 tocons(CPBOOT); 584 } 585 586 /* 587 * Bus error 'recovery' code. 588 * Print out the buss frame and then give up. 589 * (More information from special registers can be printed here.) 590 */ 591 592 /* 593 * Frame for bus error 594 */ 595 struct buserframe { 596 int which_bus; /* primary or secondary */ 597 int memerreg; /* memory error register */ 598 int trp_pc; /* trapped pc */ 599 int trp_psl; /* trapped psl */ 600 }; 601 602 char *mem_errcd[8] = { 603 "Unknown error code 0", 604 "Address parity error", /* APE */ 605 "Data parity error", /* DPE */ 606 "Data check error", /* DCE */ 607 "Versabus timeout", /* VTO */ 608 "Versabus error", /* VBE */ 609 "Non-existent memory", /* NEM */ 610 "Unknown error code 7", 611 }; 612 613 buserror(v) 614 caddr_t v; 615 { 616 register struct buserframe *busef = (struct buserframe *)v; 617 register long reg; 618 619 printf("bus error, address %x, psl %x\n", 620 busef->trp_pc, busef->trp_psl); 621 reg = busef->memerreg; 622 printf("mear %x %s\n", 623 ((reg&MEAR)>>16)&0xffff, mem_errcd[reg & ERRCD]); 624 if (reg&AXE) 625 printf("adapter external error\n"); 626 printf("error master: %s\n", reg&ERM ? "versabus" : "tahoe"); 627 if (reg&IVV) 628 printf("illegal interrupt vector from ipl %d\n", (reg>>2)&7); 629 reg = busef->which_bus; 630 printf("mcbr %x versabus type %x\n", 631 ((reg&MCBR)>>16)&0xffff, reg & 0xffc3); 632 if ((busef->memerreg&IVV) == 0) 633 panic("buserror"); 634 } 635 636 microtime(tvp) 637 register struct timeval *tvp; 638 { 639 int s = splhigh(); 640 641 *tvp = time; 642 tvp->tv_usec += tick; 643 while (tvp->tv_usec > 1000000) { 644 tvp->tv_sec++; 645 tvp->tv_usec -= 1000000; 646 } 647 splx(s); 648 } 649 650 initcpu() 651 { 652 register struct proc *p; 653 654 p = &proc[0]; 655 #define initkey(which, p, index) \ 656 which/**/_cache[index] = 1, which/**/_cnt[index] = 1; \ 657 p->p_/**/which = index; 658 initkey(ckey, p, MAXCKEY); 659 initkey(dkey, p, MAXDKEY); 660 } 661 662 /* 663 * Clear registers on exec 664 */ 665 /* ARGSUSED */ 666 setregs(entry, retval) 667 u_long entry; 668 int *retval; 669 { 670 671 #ifdef notdef 672 /* should pass args to init on the stack */ 673 for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 674 *rp++ = 0; 675 #endif 676 u.u_ar0[FP] = 0; /* bottom of the fp chain */ 677 u.u_ar0[PC] = entry + 2; 678 } 679