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