1 /*- 2 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * %sccs.include.386.c% 9 * 10 * @(#)machdep.c 5.5 (Berkeley) 11/25/90 11 */ 12 13 #include "param.h" 14 #include "systm.h" 15 #include "dir.h" 16 #include "user.h" 17 #include "kernel.h" 18 #include "malloc.h" 19 #include "map.h" 20 #include "vm.h" 21 #include "proc.h" 22 #include "buf.h" 23 #include "reboot.h" 24 #include "conf.h" 25 #include "inode.h" 26 #include "file.h" 27 #include "text.h" 28 #include "clist.h" 29 #include "callout.h" 30 #include "cmap.h" 31 #include "mbuf.h" 32 #include "msgbuf.h" 33 #include "quota.h" 34 #include "../net/netisr.h" 35 36 #include "../i386/frame.h" 37 #include "../i386/reg.h" 38 #include "../i386/segments.h" 39 #include "../i386/pte.h" 40 #include "../i386/psl.h" 41 #include "../i386/isa/rtc.h" 42 43 /* 44 * Declare these as initialized data so we can patch them. 45 */ 46 int nswbuf = 0; 47 #ifdef NBUF 48 int nbuf = NBUF; 49 #else 50 int nbuf = 0; 51 #endif 52 #ifdef BUFPAGES 53 int bufpages = BUFPAGES; 54 #else 55 int bufpages = 0; 56 #endif 57 int kernmem; 58 59 /* 60 * Machine-dependent startup code 61 */ 62 /*extern char Sysbase; 63 caddr_t sbase = { &Sysbase };*/ 64 extern char Sysbase[]; 65 /* extern struct pte EMCmap[]; 66 extern char EMCbase[]; */ 67 int boothowto = 0, Maxmem = 0; 68 extern int bootdev; 69 #ifdef SMALL 70 extern int forcemaxmem; 71 #endif 72 int biosmem; 73 74 extern cyloffset; 75 76 caddr_t bypasshole(b,t) caddr_t b,t; { 77 78 if (b <= Sysbase + 0xa0000 && t > Sysbase + 0xa0000) 79 return(Sysbase + 0x100000); 80 return(b); 81 } 82 83 startup(firstaddr) 84 int firstaddr; 85 { 86 register int unixsize; 87 register unsigned i; 88 register struct pte *pte; 89 int mapaddr, j; 90 register caddr_t v; 91 int maxbufs, base, residual; 92 extern struct map *useriomap; 93 94 /* 95 * Initialize the console before we print anything out. 96 */ 97 /*cninit();*/ 98 99 /* 100 * Bounds check memory size information against bios values 101 * use the lesser of the two 102 */ 103 biosmem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 104 printf("Maxmem %x howto %x bootdev %x cyloff %x firstaddr %x bios %d %d\n", 105 Maxmem, boothowto, bootdev, cyloffset, firstaddr, 106 biosmem, 107 rtcin(RTC_EXTLO) + (rtcin(RTC_EXTHI)<<8) 108 ); 109 maxmem = Maxmem-1; 110 111 if(biosmem != 640) 112 panic("does not have 640K of base memory"); 113 114 biosmem = 1024; 115 biosmem += rtcin(RTC_EXTLO) + (rtcin(RTC_EXTHI)<<8); 116 biosmem = biosmem/4 - 1 ; 117 if (biosmem < maxmem) maxmem=biosmem; 118 119 #ifdef SMALL 120 if(forcemaxmem && maxmem > forcemaxmem) 121 maxmem = forcemaxmem-1; 122 #endif 123 /* 124 maxmem = 0xA00;*/ 125 126 /* 127 * Initialize error message buffer (at end of core). 128 */ 129 /* Problem to resolve. AT's have memory that is not contigous, as 130 I/O address space for video adapters and network cards fall into 131 a range of 0xa0000 - 0x100000 . Note that the cmap really expects 132 contigous memory. For the moment, use the bottom of memory for 133 kernel and run-time configured storage (e.g. valloc), using memory 134 above 0x100000 for the cmap, and wasting the stuff left over after 135 valloc-end up to 0xa0000 (640K). Will have to fix this before beta, 136 and will have to somehow move this out into per bus adapter directory 137 (e.g. configurable). For now, punt 138 139 How about starting cmap normally following valloc space, and then 140 write a routine than allocs only phys pages in the 0xa0000-0x100000 141 hole? 142 143 Temporary fix for beta, if we only have 640K, then cmap follows valloc 144 up to 640K. 145 */ 146 maxmem -= btoc(sizeof (struct msgbuf)); 147 pte = msgbufmap; 148 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) 149 *(int *)pte++ = PG_V | PG_KW | ctob(maxmem + i); 150 151 #ifdef notdef 152 /* XXX EMC */ 153 pte = EMCmap; 154 *(int *)pte = PG_V | PG_UW | 0xc0000000; 155 printf("EMC at %x\n", EMCbase); 156 #endif 157 158 freemem = physmem = maxmem; 159 160 load_cr3(_cr3()); 161 162 #ifdef KDB 163 kdb_init(); /* startup kernel debugger */ 164 #endif 165 /* 166 * Good {morning,afternoon,evening,night}. 167 */ 168 printf(version); 169 printf("real mem = %d\n", ctob(physmem)); 170 171 /* 172 * Allocate space for system data structures. 173 * The first available real memory address is in "firstaddr". 174 * The first available kernel virtual address is in "v". 175 * As pages of kernel virtual memory are allocated, "v" is incremented. 176 * As pages of memory are allocated and cleared, 177 * "firstaddr" is incremented. 178 * An index into the kernel page table corresponding to the 179 * virtual memory address maintained in "v" is kept in "mapaddr". 180 */ 181 v = (caddr_t)(Sysbase + (firstaddr * NBPG)); 182 /*v = sbase + (firstaddr * NBPG);*/ 183 #define valloc(name, type, num) \ 184 v = bypasshole (v, v + (int) ((name)+(num))) ; \ 185 (name) = (type *)v; v = (caddr_t)((name)+(num)) 186 #define valloclim(name, type, num, lim) \ 187 v = bypasshole (v, v + (int) ((name)+(num))) ; \ 188 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 189 valloclim(inode, struct inode, ninode, inodeNINODE); 190 valloclim(file, struct file, nfile, fileNFILE); 191 valloclim(proc, struct proc, nproc, procNPROC); 192 valloclim(text, struct text, ntext, textNTEXT); 193 valloc(cfree, struct cblock, nclist); 194 valloc(callout, struct callout, ncallout); 195 valloc(swapmap, struct map, nswapmap = nproc * 2); 196 valloc(argmap, struct map, ARGMAPSIZE); 197 valloc(kernelmap, struct map, nproc); 198 valloc(useriomap, struct map, nproc); 199 valloc(mbmap, struct map, nmbclusters/4); 200 valloc(namecache, struct namecache, nchsize); 201 202 valloc(kmemmap, struct map, ekmempt - kmempt); 203 valloc(kmemusage, struct kmemusage, ekmempt - kmempt); 204 #ifdef QUOTA 205 valloclim(quota, struct quota, nquota, quotaNQUOTA); 206 valloclim(dquot, struct dquot, ndquot, dquotNDQUOT); 207 #endif 208 209 /* 210 * Determine how many buffers to allocate. 211 * Use 10% of memory for the first 2 Meg, 5% of the remaining 212 * memory. Insure a minimum of 16 buffers. 213 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 214 */ 215 if (bufpages == 0) 216 if (physmem < (2 * 1024 * 1024)) 217 bufpages = physmem / 10 / CLSIZE; 218 else 219 bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE; 220 if (nbuf == 0) { 221 nbuf = bufpages / 2; 222 if (nbuf < 16) 223 nbuf = 16; 224 } 225 if (nswbuf == 0) { 226 nswbuf = (nbuf / 2) &~ 1; /* force even */ 227 if (nswbuf > 256) 228 nswbuf = 256; /* sanity */ 229 } 230 valloc(swbuf, struct buf, nswbuf); 231 232 /* 233 * Now the amount of virtual memory remaining for buffers 234 * can be calculated, estimating needs for the cmap. 235 */ 236 ncmap = (maxmem*NBPG - ((int)(v - Sysbase))) / 237 (CLBYTES + sizeof(struct cmap)) + 2; 238 maxbufs = ((SYSPTSIZE * NBPG) - 239 ((int)(v - Sysbase + ncmap * sizeof(struct cmap)))) / 240 (MAXBSIZE + sizeof(struct buf)); 241 if (maxbufs < 16) 242 panic("sys pt too small"); 243 if (nbuf > maxbufs) { 244 printf("SYSPTSIZE limits number of buffers to %d\n", maxbufs); 245 nbuf = maxbufs; 246 } 247 if (bufpages > nbuf * (MAXBSIZE / CLBYTES)) 248 bufpages = nbuf * (MAXBSIZE / CLBYTES); 249 valloc(buf, struct buf, nbuf); 250 251 /* 252 * Allocate space for core map. 253 * Allow space for all of physical memory minus the amount 254 * dedicated to the system. The amount of physical memory 255 * dedicated to the system is the total virtual memory of 256 * the system thus far, plus core map, buffer pages, 257 * and buffer headers not yet allocated. 258 * Add 2: 1 because the 0th entry is unused, 1 for rounding. 259 */ 260 /*ncmap = (maxmem*NBPG - ((int)((v - sbase) + bufpages*CLBYTES))) /*/ 261 ncmap = (maxmem*NBPG - ((int)((v - Sysbase) + bufpages*CLBYTES))) / 262 (CLBYTES + sizeof(struct cmap)) + 2; 263 valloclim(cmap, struct cmap, ncmap, ecmap); 264 265 /* 266 * Clear space allocated thus far, and make r/w entries 267 * for the space in the kernel map. 268 */ 269 unixsize = btoc((int)(v - Sysbase)); 270 while (firstaddr < unixsize) { 271 *(int *)(&Sysmap[firstaddr]) = PG_V | PG_KW | ctob(firstaddr); 272 clearseg((unsigned)firstaddr); 273 firstaddr++; 274 } 275 276 /* 277 * Now allocate buffers proper. They are different than the above 278 * in that they usually occupy more virtual memory than physical. 279 */ 280 v = bypasshole (v, (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET + 281 MAXBSIZE*nbuf)); 282 v = (caddr_t) ((int)(v + PGOFSET) &~ PGOFSET); 283 valloc(buffers, char, MAXBSIZE * nbuf); 284 base = bufpages / nbuf; 285 residual = bufpages % nbuf; 286 mapaddr = firstaddr = btoc((unsigned) buffers - (unsigned)Sysbase); 287 for (i = 0; i < residual; i++) { 288 for (j = 0; j < (base + 1) * CLSIZE; j++) { 289 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | ctob(firstaddr); 290 clearseg((unsigned)firstaddr); 291 firstaddr++; 292 } 293 mapaddr += MAXBSIZE / NBPG; 294 } 295 for (i = residual; i < nbuf; i++) { 296 for (j = 0; j < base * CLSIZE; j++) { 297 *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | ctob(firstaddr); 298 clearseg((unsigned)firstaddr); 299 firstaddr++; 300 } 301 mapaddr += MAXBSIZE / NBPG; 302 } 303 304 unixsize = btoc((int)(v - Sysbase)); 305 if (firstaddr >= physmem - 8*UPAGES) 306 panic("no memory"); 307 308 /* 309 * Initialize callouts 310 */ 311 callfree = callout; 312 for (i = 1; i < ncallout; i++) 313 callout[i-1].c_next = &callout[i]; 314 315 /* 316 * Initialize memory allocator and swap 317 * and user page table maps. 318 * 319 * THE USER PAGE TABLE MAP IS CALLED ``kernelmap'' 320 * WHICH IS A VERY UNDESCRIPTIVE AND INCONSISTENT NAME. 321 */ 322 323 /* 324 * cmap must not allocate the hole, so toss memory 325 */ 326 if(firstaddr < 640/4 && maxmem > 1024/4){ 327 printf("[not using %dK due to hole]\n", 4*(640/4 - firstaddr)); 328 firstaddr = 0x100; 329 } 330 if(maxmem < 2048/4-10) 331 printf("WARNING: NOT ENOUGH RAM MEMORY - RUNNING IN DEGRADED MODE\n"); 332 333 meminit(firstaddr, maxmem); 334 maxmem = freemem; 335 printf("avail mem = %d\n", ctob(maxmem)); 336 printf("using %d buffers containing %d bytes of memory\n", 337 nbuf, bufpages * CLBYTES); 338 rminit(kernelmap, (long)USRPTSIZE, (long)1, 339 "usrpt", nproc); 340 /* 341 * PTEs for mapping user space into kernel for phyio operations. 342 * One page is enough to handle 4Mb of simultaneous raw IO operations. 343 */ 344 rminit(useriomap, (long)USRIOSIZE, (long)1, "usrio", nproc); 345 rminit(mbmap, (long)(nmbclusters * CLSIZE), (long)CLSIZE, 346 "mbclusters", nmbclusters/4); 347 kmeminit(); /* now safe to do malloc/free */ 348 /*intenable = 1; /* Enable interrupts from now on */ 349 350 /* 351 * Set up CPU-specific registers, cache, etc. 352 */ 353 initcpu(); 354 355 /* 356 * Set up buffers, so they can be used to read disk labels. 357 */ 358 bhinit(); 359 binit(); 360 361 /* 362 * Configure the system. 363 */ 364 configure(); 365 } 366 367 #ifdef PGINPROF 368 /* 369 * Return the difference (in microseconds) 370 * between the current time and a previous 371 * time as represented by the arguments. 372 * If there is a pending clock interrupt 373 * which has not been serviced due to high 374 * ipl, return error code. 375 */ 376 /*ARGSUSED*/ 377 vmtime(otime, olbolt, oicr) 378 register int otime, olbolt, oicr; 379 { 380 381 return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); 382 } 383 #endif 384 385 struct sigframe { 386 int sf_signum; 387 int sf_code; 388 struct sigcontext *sf_scp; 389 int (*sf_handler)(); 390 int sf_eax; 391 int sf_edx; 392 int sf_ecx; 393 struct save87 sf_fsave; /* fpu coproc */ 394 } ; 395 396 /* 397 * Send an interrupt to process. 398 * 399 * Stack is set up to allow sigcode stored 400 * in u. to call routine, followed by kcall 401 * to sigreturn routine below. After sigreturn 402 * resets the signal mask, the stack, and the 403 * frame pointer, it returns to the user 404 * specified pc, psl. 405 */ 406 sendsig(p, sig, mask, frmtrp) 407 int (*p)(), sig, mask; 408 { 409 register struct sigcontext *scp; 410 register int *regs; 411 register struct sigframe *fp; 412 int oonstack; 413 414 #include "dbg.h" 415 dprintf(DSIGNAL,"sendsig %d code %d to pid %d frmtrp %d to locn %x\n", 416 sig, u.u_code, u.u_procp->p_pid, frmtrp, p); 417 regs = u.u_ar0; 418 oonstack = u.u_onstack; 419 /* 420 * Allocate and validate space for the signal handler 421 * context. Note that if the stack is in P0 space, the 422 * call to grow() is a nop, and the useracc() check 423 * will fail if the process has not already allocated 424 * the space with a `brk'. 425 */ 426 if (!u.u_onstack && (u.u_sigonstack & sigmask(sig))) { 427 scp = (struct sigcontext *)u.u_sigsp - 1; 428 u.u_onstack = 1; 429 } else { 430 if (frmtrp) 431 scp = (struct sigcontext *)regs[tESP] - 1; 432 else 433 scp = (struct sigcontext *)regs[sESP] - 1; 434 } 435 fp = (struct sigframe *)scp - 1; 436 if ((int)fp <= USRSTACK - ctob(u.u_ssize)) 437 (void) grow((unsigned)fp); 438 if (useracc((caddr_t)fp, sizeof (*fp) + sizeof (*scp), B_WRITE) == 0) { 439 /* 440 * Process has trashed its stack; give it an illegal 441 * instruction to halt it in its tracks. 442 */ 443 printf("sendsig: failed to grow stack down to %x\n", fp); 444 u.u_signal[SIGILL] = SIG_DFL; 445 sig = sigmask(SIGILL); 446 u.u_procp->p_sigignore &= ~sig; 447 u.u_procp->p_sigcatch &= ~sig; 448 u.u_procp->p_sigmask &= ~sig; 449 psignal(u.u_procp, SIGILL); 450 return; 451 } 452 453 /* 454 * Build the argument list for the signal handler. 455 */ 456 fp->sf_signum = sig; 457 if (sig == SIGILL || sig == SIGFPE) { 458 fp->sf_code = u.u_code; 459 u.u_code = 0; 460 } else 461 fp->sf_code = 0; 462 /* indicate trap occured from system call */ 463 if(!frmtrp) fp->sf_code |= 0x80; 464 465 fp->sf_scp = scp; 466 fp->sf_handler = p; 467 468 /* save scratch registers */ 469 if(frmtrp) { 470 fp->sf_eax = regs[tEAX]; 471 fp->sf_edx = regs[tEDX]; 472 fp->sf_ecx = regs[tECX]; 473 } else { 474 fp->sf_eax = regs[sEAX]; 475 fp->sf_edx = regs[sEDX]; 476 fp->sf_ecx = regs[sECX]; 477 } 478 #ifdef notyet 479 /* XXX FPU state? */ 480 #endif 481 /* 482 * Build the signal context to be used by sigreturn. 483 */ 484 scp->sc_onstack = oonstack; 485 scp->sc_mask = mask; 486 if(frmtrp) { 487 scp->sc_sp = regs[tESP]; 488 scp->sc_fp = regs[tEBP]; 489 scp->sc_pc = regs[tEIP]; 490 scp->sc_ps = regs[tEFLAGS]; 491 regs[tESP] = (int)fp; 492 regs[tEIP] = (int)u.u_pcb.pcb_sigc; 493 } else { 494 scp->sc_sp = regs[sESP]; 495 scp->sc_fp = regs[sEBP]; 496 scp->sc_pc = regs[sEIP]; 497 scp->sc_ps = regs[sEFLAGS]; 498 regs[sESP] = (int)fp; 499 regs[sEIP] = (int)u.u_pcb.pcb_sigc; 500 } 501 } 502 503 /* 504 * System call to cleanup state after a signal 505 * has been taken. Reset signal mask and 506 * stack state from context left by sendsig (above). 507 * Return to previous pc and psl as specified by 508 * context left by sendsig. Check carefully to 509 * make sure that the user has not modified the 510 * psl to gain improper priviledges or to cause 511 * a machine fault. 512 */ 513 sigreturn() 514 { 515 register struct sigframe *fp; 516 register struct sigcontext *scp; 517 register int *regs = u.u_ar0; 518 519 fp = (struct sigframe *) regs[sESP] ; 520 if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) { 521 u.u_error = EINVAL; 522 return; 523 } 524 525 /* restore scratch registers */ 526 regs[sEAX] = fp->sf_eax ; 527 regs[sEDX] = fp->sf_edx ; 528 regs[sECX] = fp->sf_ecx ; 529 #ifdef notyet 530 /* XXX FPU state? */ 531 #endif 532 533 scp = fp->sf_scp; 534 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) { 535 u.u_error = EINVAL; 536 return; 537 } 538 #ifdef notyet 539 if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) { 540 u.u_error = EINVAL; 541 return; 542 } 543 #endif 544 u.u_eosys = JUSTRETURN; 545 u.u_onstack = scp->sc_onstack & 01; 546 u.u_procp->p_sigmask = scp->sc_mask &~ 547 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 548 regs[sEBP] = scp->sc_fp; 549 regs[sESP] = scp->sc_sp; 550 regs[sEIP] = scp->sc_pc; 551 regs[sEFLAGS] = scp->sc_ps; 552 } 553 554 int waittime = -1; 555 556 boot(arghowto) 557 int arghowto; 558 { 559 register long dummy; /* r12 is reserved */ 560 register int howto; /* r11 == how to boot */ 561 register int devtype; /* r10 == major of root dev */ 562 extern char *panicstr; 563 564 howto = arghowto; 565 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 566 register struct buf *bp; 567 int iter, nbusy; 568 569 waittime = 0; 570 (void) splnet(); 571 printf("syncing disks... "); 572 /* 573 * Release inodes held by texts before update. 574 */ 575 if (panicstr == 0) 576 xumount(NODEV); 577 update(); 578 579 for (iter = 0; iter < 20; iter++) { 580 nbusy = 0; 581 for (bp = &buf[nbuf]; --bp >= buf; ) 582 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 583 nbusy++; 584 if (nbusy == 0) 585 break; 586 printf("%d ", nbusy); 587 DELAY(40000 * iter); 588 } 589 if (nbusy) 590 printf("giving up\n"); 591 else 592 printf("done\n"); 593 DELAY(10000); /* wait for printf to finish */ 594 } 595 splhigh(); 596 devtype = major(rootdev); 597 if (howto&RB_HALT) { 598 printf("halting (in tight loop); hit reset\n\n"); 599 reset_cpu(); 600 for (;;) ; 601 } else { 602 if (howto & RB_DUMP) { 603 doadump(); /* CPBOOT's itsself */ 604 /*NOTREACHED*/ 605 } 606 } 607 #ifdef lint 608 dummy = 0; dummy = dummy; 609 printf("howto %d, devtype %d\n", arghowto, devtype); 610 #endif 611 reset_cpu(); 612 for(;;) ; 613 /*NOTREACHED*/ 614 } 615 616 int dumpmag = 0x8fca0101; /* magic number for savecore */ 617 int dumpsize = 0; /* also for savecore */ 618 /* 619 * Doadump comes here after turning off memory management and 620 * getting on the dump stack, either when called above, or by 621 * the auto-restart code. 622 */ 623 dumpsys() 624 { 625 626 if (dumpdev == NODEV) 627 return; 628 #ifdef notdef 629 if ((minor(dumpdev)&07) != 1) 630 return; 631 #endif 632 dumpsize = physmem; 633 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 634 printf("dump "); 635 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 636 637 case ENXIO: 638 printf("device bad\n"); 639 break; 640 641 case EFAULT: 642 printf("device not ready\n"); 643 break; 644 645 case EINVAL: 646 printf("area improper\n"); 647 break; 648 649 case EIO: 650 printf("i/o error\n"); 651 break; 652 653 default: 654 printf("succeeded\n"); 655 break; 656 } 657 printf("\n\n"); 658 DELAY(1000); 659 } 660 661 microtime(tvp) 662 register struct timeval *tvp; 663 { 664 int s = splhigh(); 665 666 *tvp = time; 667 tvp->tv_usec += tick; 668 while (tvp->tv_usec > 1000000) { 669 tvp->tv_sec++; 670 tvp->tv_usec -= 1000000; 671 } 672 splx(s); 673 } 674 675 physstrat(bp, strat, prio) 676 struct buf *bp; 677 int (*strat)(), prio; 678 { 679 register int s; 680 caddr_t baddr; 681 682 /* 683 * vmapbuf clobbers b_addr so we must remember it so that it 684 * can be restored after vunmapbuf. This is truely rude, we 685 * should really be storing this in a field in the buf struct 686 * but none are available and I didn't want to add one at 687 * this time. Note that b_addr for dirty page pushes is 688 * restored in vunmapbuf. (ugh!) 689 */ 690 baddr = bp->b_un.b_addr; 691 vmapbuf(bp); 692 (*strat)(bp); 693 /* pageout daemon doesn't wait for pushed pages */ 694 if (bp->b_flags & B_DIRTY) 695 return; 696 s = splbio(); 697 while ((bp->b_flags & B_DONE) == 0) 698 sleep((caddr_t)bp, prio); 699 splx(s); 700 vunmapbuf(bp); 701 bp->b_un.b_addr = baddr; 702 } 703 704 initcpu() 705 { 706 register struct proc *p; 707 708 p = &proc[0]; 709 } 710 711 /* 712 * Clear registers on exec 713 */ 714 setregs(entry) 715 u_long entry; 716 { 717 718 #ifdef notdef 719 /* should pass args to init on the stack */ 720 for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) 721 *rp++ = 0; 722 #endif 723 u.u_ar0[sEBP] = 0; /* bottom of the fp chain */ 724 u.u_ar0[sEIP] = entry; 725 } 726 727 /* 728 * Initialize 386 and configure to run kernel 729 */ 730 731 /* 732 * Initialize segments & interrupt table 733 */ 734 735 736 #define GNULL_SEL 0 /* Null Descriptor */ 737 #define GCODE_SEL 1 /* Kernel Code Descriptor */ 738 #define GDATA_SEL 2 /* Kernel Data Descriptor */ 739 #define GLDT_SEL 3 /* LDT - eventually one per process */ 740 #define GTGATE_SEL 4 /* Process task switch gate */ 741 #define GPANIC_SEL 5 /* Task state to consider panic from */ 742 #define GPROC0_SEL 6 /* Task state process slot zero and up */ 743 744 union descriptor gdt[GPROC0_SEL]; 745 746 /* interrupt descriptor table */ 747 struct gate_descriptor idt[32+16]; 748 749 /* local descriptor table */ 750 union descriptor ldt[5]; 751 #define LSYS5CALLS_SEL 0 /* forced by intel BCS */ 752 #define LSYS5SIGR_SEL 1 753 754 #define L43BSDCALLS_SEL 2 /* notyet */ 755 #define LUCODE_SEL 3 756 #define LUDATA_SEL 4 757 /* seperate stack, es,fs,gs sels ? */ 758 /* #define LPOSIXCALLS_SEL 5 /* notyet */ 759 760 struct i386tss tss; 761 762 /* software prototypes -- in more palitable form */ 763 struct soft_segment_descriptor gdt_segs[] = { 764 /* Null Descriptor */ 765 { 0x0, /* segment base address */ 766 0x0, /* length - all address space */ 767 0, /* segment type */ 768 0, /* segment descriptor priority level */ 769 0, /* segment descriptor present */ 770 0,0, 771 0, /* default 32 vs 16 bit size */ 772 0 /* limit granularity (byte/page units)*/ }, 773 /* Code Descriptor for kernel */ 774 { 0x0, /* segment base address */ 775 0xfffff, /* length - all address space */ 776 SDT_MEMERA, /* segment type */ 777 0, /* segment descriptor priority level */ 778 1, /* segment descriptor present */ 779 0,0, 780 1, /* default 32 vs 16 bit size */ 781 1 /* limit granularity (byte/page units)*/ }, 782 /* Data Descriptor for kernel */ 783 { 0x0, /* segment base address */ 784 0xfffff, /* length - all address space */ 785 SDT_MEMRWA, /* segment type */ 786 0, /* segment descriptor priority level */ 787 1, /* segment descriptor present */ 788 0,0, 789 1, /* default 32 vs 16 bit size */ 790 1 /* limit granularity (byte/page units)*/ }, 791 /* LDT Descriptor */ 792 { (int) ldt, /* segment base address */ 793 sizeof(ldt)-1, /* length - all address space */ 794 SDT_SYSLDT, /* segment type */ 795 0, /* segment descriptor priority level */ 796 1, /* segment descriptor present */ 797 0,0, 798 0, /* unused - default 32 vs 16 bit size */ 799 0 /* limit granularity (byte/page units)*/ }, 800 /* Null Descriptor - Placeholder */ 801 { 0x0, /* segment base address */ 802 0x0, /* length - all address space */ 803 0, /* segment type */ 804 0, /* segment descriptor priority level */ 805 0, /* segment descriptor present */ 806 0,0, 807 0, /* default 32 vs 16 bit size */ 808 0 /* limit granularity (byte/page units)*/ }, 809 /* Panic Tss Descriptor */ 810 { (int) &u, /* segment base address */ 811 sizeof(tss)-1, /* length - all address space */ 812 SDT_SYS386TSS, /* segment type */ 813 0, /* segment descriptor priority level */ 814 1, /* segment descriptor present */ 815 0,0, 816 0, /* unused - default 32 vs 16 bit size */ 817 0 /* limit granularity (byte/page units)*/ }}; 818 819 struct soft_segment_descriptor ldt_segs[] = { 820 /* Null Descriptor - overwritten by call gate */ 821 { 0x0, /* segment base address */ 822 0x0, /* length - all address space */ 823 0, /* segment type */ 824 0, /* segment descriptor priority level */ 825 0, /* segment descriptor present */ 826 0,0, 827 0, /* default 32 vs 16 bit size */ 828 0 /* limit granularity (byte/page units)*/ }, 829 /* Null Descriptor - overwritten by call gate */ 830 { 0x0, /* segment base address */ 831 0x0, /* length - all address space */ 832 0, /* segment type */ 833 0, /* segment descriptor priority level */ 834 0, /* segment descriptor present */ 835 0,0, 836 0, /* default 32 vs 16 bit size */ 837 0 /* limit granularity (byte/page units)*/ }, 838 /* Null Descriptor - overwritten by call gate */ 839 { 0x0, /* segment base address */ 840 0x0, /* length - all address space */ 841 0, /* segment type */ 842 0, /* segment descriptor priority level */ 843 0, /* segment descriptor present */ 844 0,0, 845 0, /* default 32 vs 16 bit size */ 846 0 /* limit granularity (byte/page units)*/ }, 847 /* Code Descriptor for user */ 848 { 0x0, /* segment base address */ 849 0xfffff, /* length - all address space */ 850 SDT_MEMERA, /* segment type */ 851 SEL_UPL, /* segment descriptor priority level */ 852 1, /* segment descriptor present */ 853 0,0, 854 1, /* default 32 vs 16 bit size */ 855 1 /* limit granularity (byte/page units)*/ }, 856 /* Data Descriptor for user */ 857 { 0x0, /* segment base address */ 858 0xfffff, /* length - all address space */ 859 SDT_MEMRWA, /* segment type */ 860 SEL_UPL, /* segment descriptor priority level */ 861 1, /* segment descriptor present */ 862 0,0, 863 1, /* default 32 vs 16 bit size */ 864 1 /* limit granularity (byte/page units)*/ } }; 865 866 /* table descriptors - used to load tables by microp */ 867 struct region_descriptor r_gdt = { 868 sizeof(gdt)-1,(char *)gdt 869 }; 870 871 struct region_descriptor r_idt = { 872 sizeof(idt)-1,(char *)idt 873 }; 874 875 setidt(idx, func, typ, dpl) char *func; { 876 struct gate_descriptor *ip = idt + idx; 877 878 ip->gd_looffset = (int)func; 879 ip->gd_selector = 8; 880 ip->gd_stkcpy = 0; 881 ip->gd_xx = 0; 882 ip->gd_type = typ; 883 ip->gd_dpl = dpl; 884 ip->gd_p = 1; 885 ip->gd_hioffset = ((int)func)>>16 ; 886 } 887 888 #define IDTVEC(name) X/**/name 889 extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 890 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), 891 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 892 IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), 893 IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), 894 IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), 895 IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), 896 IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall); 897 898 int lcr0(), lcr3(), rcr0(), rcr2(); 899 int _udatasel, _ucodesel, _gsel_tss; 900 901 init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext; 902 int x, *pi; 903 struct gate_descriptor *gdp; 904 905 /* make gdt memory segments */ 906 gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG); 907 for (x=0; x < 6; x++) ssdtosd(gdt_segs+x, gdt+x); 908 /* make ldt memory segments */ 909 ldt_segs[LUCODE_SEL].ssd_limit = btoc((int) Sysbase); 910 /*ldt_segs[LUDATA_SEL].ssd_limit = btoc((int) Sysbase); */ 911 ldt_segs[LUDATA_SEL].ssd_limit = btoc(0xfffff000); 912 /* Note. eventually want private ldts per process */ 913 for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); 914 915 /* exceptions */ 916 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); 917 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); 918 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); 919 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); 920 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL); 921 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); 922 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); 923 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); 924 setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); 925 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); 926 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); 927 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); 928 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); 929 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); 930 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); 931 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); 932 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); 933 setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); 934 setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); 935 setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); 936 setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); 937 setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); 938 setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); 939 setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); 940 setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); 941 setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); 942 setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); 943 setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); 944 setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); 945 setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); 946 setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); 947 setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); 948 949 #include "isa.h" 950 #if NISA >0 951 isa_defaultirq(); 952 #endif 953 954 lgdt(gdt, sizeof(gdt)-1); 955 lidt(idt, sizeof(idt)-1); 956 lldt(GSEL(GLDT_SEL, SEL_KPL)); 957 958 959 /* make a initial tss so microp can get interrupt stack on syscall! */ 960 u.u_pcb.pcbtss.tss_esp0 = (int) &u + UPAGES*NBPG; 961 u.u_pcb.pcbtss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 962 _gsel_tss = GSEL(GPANIC_SEL, SEL_KPL); 963 ltr(_gsel_tss); 964 965 /* make a call gate to reenter kernel with */ 966 gdp = &ldt[LSYS5CALLS_SEL].gd; 967 968 x = (int) &IDTVEC(syscall); 969 gdp->gd_looffset = x++; 970 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 971 gdp->gd_stkcpy = 0; 972 gdp->gd_type = SDT_SYS386CGT; 973 gdp->gd_dpl = SEL_UPL; 974 gdp->gd_p = 1; 975 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 976 977 /* transfer to user mode */ 978 979 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 980 _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 981 } 982 983 /* 984 * zero out physical memory 985 * specified in relocation units (NBPG bytes) 986 */ 987 clearseg(n) { 988 extern CMAP1, CADDR1; 989 990 CMAP1 = PG_V | PG_KW | ctob(n); 991 load_cr3(_cr3()); 992 bzero(&CADDR1,NBPG); 993 } 994 995 /* 996 * copy a page of physical memory 997 * specified in relocation units (NBPG bytes) 998 */ 999 copyseg(frm, n) { 1000 extern CMAP2, CADDR2; 1001 1002 CMAP2 = PG_V | PG_KW | ctob(n); 1003 load_cr3(_cr3()); 1004 bcopy(frm, &CADDR2,NBPG); 1005 } 1006 1007 aston() { 1008 schednetisr(NETISR_AST); 1009 } 1010 1011 /* 1012 * insert an element into a queue 1013 */ 1014 #undef insque 1015 _insque(element, head) 1016 register struct prochd *element, *head; 1017 { 1018 element->ph_link = head->ph_link; 1019 head->ph_link = (struct proc *)element; 1020 element->ph_rlink = (struct proc *)head; 1021 ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element; 1022 } 1023 1024 /* 1025 * remove an element from a queue 1026 */ 1027 #undef remque 1028 _remque(element) 1029 register struct prochd *element; 1030 { 1031 ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink; 1032 ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link; 1033 element->ph_rlink = (struct proc *)0; 1034 } 1035 1036 vmunaccess() {} 1037 1038 /* 1039 * Below written in C to allow access to debugging code 1040 */ 1041 copyinstr(fromaddr, toaddr, maxlength, lencopied) int *lencopied; 1042 char *toaddr; { 1043 int c,tally; 1044 1045 tally = 0; 1046 while (maxlength--) { 1047 c = fubyte(fromaddr++); 1048 if (c == -1) { 1049 if(lencopied) *lencopied = tally; 1050 return(EFAULT); 1051 } 1052 tally++; 1053 *toaddr++ = (char) c; 1054 if (c == 0){ 1055 if(lencopied) *lencopied = tally; 1056 return(0); 1057 } 1058 } 1059 if(lencopied) *lencopied = tally; 1060 return(ENOENT); 1061 } 1062 1063 copyoutstr(fromaddr, toaddr, maxlength, lencopied) int *lencopied; 1064 u_char *fromaddr; { 1065 int c; 1066 int tally; 1067 1068 tally = 0; 1069 while (maxlength--) { 1070 c = subyte(toaddr++,*fromaddr); 1071 if (c == -1) return(EFAULT); 1072 tally++; 1073 if (*fromaddr++ == 0){ 1074 if(lencopied) *lencopied = tally; 1075 return(0); 1076 } 1077 } 1078 if(lencopied) *lencopied = tally; 1079 return(ENOENT); 1080 } 1081 1082 copystr(fromaddr, toaddr, maxlength, lencopied) int *lencopied; 1083 u_char *fromaddr, *toaddr; { 1084 int tally; 1085 1086 tally = 0; 1087 while (maxlength--) { 1088 *toaddr = *fromaddr++; 1089 tally++; 1090 if (*toaddr++ == 0) { 1091 if(lencopied) *lencopied = tally; 1092 return(0); 1093 } 1094 } 1095 if(lencopied) *lencopied = tally; 1096 return(ENOENT); 1097 } 1098 1099 /* 1100 * ovbcopy - like bcopy, but recognizes overlapping ranges and handles 1101 * them correctly. 1102 */ 1103 ovbcopy(from, to, bytes) 1104 char *from, *to; 1105 int bytes; /* num bytes to copy */ 1106 { 1107 /* Assume that bcopy copies left-to-right (low addr first). */ 1108 if (from + bytes <= to || to + bytes <= from || to == from) 1109 bcopy(from, to, bytes); /* non-overlapping or no-op*/ 1110 else if (from > to) 1111 bcopy(from, to, bytes); /* overlapping but OK */ 1112 else { 1113 /* to > from: overlapping, and must copy right-to-left. */ 1114 from += bytes - 1; 1115 to += bytes - 1; 1116 while (bytes-- > 0) 1117 *to-- = *from--; 1118 } 1119 } 1120