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.redist.c% 9 * 10 * @(#)machdep.c 7.5 (Berkeley) 07/25/91 11 */ 12 13 14 #include "param.h" 15 #include "systm.h" 16 #include "signalvar.h" 17 #include "kernel.h" 18 #include "map.h" 19 #include "proc.h" 20 #include "user.h" 21 #include "buf.h" 22 #include "reboot.h" 23 #include "conf.h" 24 #include "file.h" 25 #include "clist.h" 26 #include "callout.h" 27 #include "malloc.h" 28 #include "mbuf.h" 29 #include "msgbuf.h" 30 #include "net/netisr.h" 31 32 #include "vm/vm.h" 33 #include "vm/vm_kern.h" 34 #include "vm/vm_page.h" 35 36 vm_map_t buffer_map; 37 extern vm_offset_t avail_end; 38 39 #include "machine/cpu.h" 40 #include "machine/reg.h" 41 #include "machine/psl.h" 42 #include "machine/specialreg.h" 43 #include "i386/isa/rtc.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 int msgbufmapped; /* set when safe to use msgbuf */ 60 61 /* 62 * Machine-dependent startup code 63 */ 64 int boothowto = 0, Maxmem = 0; 65 long dumplo; 66 int physmem, maxmem; 67 extern int bootdev; 68 #ifdef SMALL 69 extern int forcemaxmem; 70 #endif 71 int biosmem; 72 73 extern cyloffset; 74 75 cpu_startup(firstaddr) 76 int firstaddr; 77 { 78 register int unixsize; 79 register unsigned i; 80 register struct pte *pte; 81 int mapaddr, j; 82 register caddr_t v; 83 int maxbufs, base, residual; 84 extern long Usrptsize; 85 vm_offset_t minaddr, maxaddr; 86 vm_size_t size; 87 88 /* 89 * Initialize error message buffer (at end of core). 90 */ 91 92 /* avail_end was pre-decremented in pmap_bootstrap to compensate */ 93 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) 94 pmap_enter(pmap_kernel(), msgbufp, avail_end + i * NBPG, 95 VM_PROT_ALL, TRUE); 96 msgbufmapped = 1; 97 98 #ifdef KDB 99 kdb_init(); /* startup kernel debugger */ 100 #endif 101 /* 102 * Good {morning,afternoon,evening,night}. 103 */ 104 printf(version); 105 printf("real mem = %d\n", ctob(physmem)); 106 107 /* 108 * Allocate space for system data structures. 109 * The first available real memory address is in "firstaddr". 110 * The first available kernel virtual address is in "v". 111 * As pages of kernel virtual memory are allocated, "v" is incremented. 112 * As pages of memory are allocated and cleared, 113 * "firstaddr" is incremented. 114 * An index into the kernel page table corresponding to the 115 * virtual memory address maintained in "v" is kept in "mapaddr". 116 */ 117 118 /* 119 * Make two passes. The first pass calculates how much memory is 120 * needed and allocates it. The second pass assigns virtual 121 * addresses to the various data structures. 122 */ 123 firstaddr = 0; 124 again: 125 v = (caddr_t)firstaddr; 126 127 #define valloc(name, type, num) \ 128 (name) = (type *)v; v = (caddr_t)((name)+(num)) 129 #define valloclim(name, type, num, lim) \ 130 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 131 valloc(cfree, struct cblock, nclist); 132 valloc(callout, struct callout, ncallout); 133 valloc(swapmap, struct map, nswapmap = maxproc * 2); 134 #ifdef SYSVSHM 135 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 136 #endif 137 /* 138 * Determine how many buffers to allocate. 139 * Use 10% of memory for the first 2 Meg, 5% of the remaining 140 * memory. Insure a minimum of 16 buffers. 141 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 142 */ 143 if (bufpages == 0) 144 if (physmem < (2 * 1024 * 1024)) 145 bufpages = physmem / 10 / CLSIZE; 146 else 147 bufpages = ((2 * 1024 * 1024 + physmem) / 20) / CLSIZE; 148 if (nbuf == 0) { 149 nbuf = bufpages / 2; 150 if (nbuf < 16) 151 nbuf = 16; 152 } 153 if (nswbuf == 0) { 154 nswbuf = (nbuf / 2) &~ 1; /* force even */ 155 if (nswbuf > 256) 156 nswbuf = 256; /* sanity */ 157 } 158 valloc(swbuf, struct buf, nswbuf); 159 valloc(buf, struct buf, nbuf); 160 161 /* 162 * End of first pass, size has been calculated so allocate memory 163 */ 164 if (firstaddr == 0) { 165 size = (vm_size_t)(v - firstaddr); 166 firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); 167 if (firstaddr == 0) 168 panic("startup: no room for tables"); 169 goto again; 170 } 171 /* 172 * End of second pass, addresses have been assigned 173 */ 174 if ((vm_size_t)(v - firstaddr) != size) 175 panic("startup: table size inconsistency"); 176 /* 177 * Now allocate buffers proper. They are different than the above 178 * in that they usually occupy more virtual memory than physical. 179 */ 180 size = MAXBSIZE * nbuf; 181 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t)&buffers, 182 &maxaddr, size, FALSE); 183 minaddr = (vm_offset_t)buffers; 184 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0, 185 &minaddr, size, FALSE) != KERN_SUCCESS) 186 panic("startup: cannot allocate buffers"); 187 base = bufpages / nbuf; 188 residual = bufpages % nbuf; 189 for (i = 0; i < nbuf; i++) { 190 vm_size_t curbufsize; 191 vm_offset_t curbuf; 192 193 /* 194 * First <residual> buffers get (base+1) physical pages 195 * allocated for them. The rest get (base) physical pages. 196 * 197 * The rest of each buffer occupies virtual space, 198 * but has no physical memory allocated for it. 199 */ 200 curbuf = (vm_offset_t)buffers + i * MAXBSIZE; 201 curbufsize = CLBYTES * (i < residual ? base+1 : base); 202 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); 203 vm_map_simplify(buffer_map, curbuf); 204 } 205 /* 206 * Allocate a submap for exec arguments. This map effectively 207 * limits the number of processes exec'ing at any time. 208 */ 209 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 210 16*NCARGS, TRUE); 211 /* 212 * Allocate a submap for physio 213 */ 214 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 215 VM_PHYS_SIZE, TRUE); 216 217 /* 218 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 219 * we use the more space efficient malloc in place of kmem_alloc. 220 */ 221 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 222 M_MBUF, M_NOWAIT); 223 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 224 mb_map = kmem_suballoc(kernel_map, (vm_offset_t)&mbutl, &maxaddr, 225 VM_MBUF_SIZE, FALSE); 226 /* 227 * Initialize callouts 228 */ 229 callfree = callout; 230 for (i = 1; i < ncallout; i++) 231 callout[i-1].c_next = &callout[i]; 232 233 printf("avail mem = %d\n", ptoa(vm_stat.free_count)); 234 printf("using %d buffers containing %d bytes of memory\n", 235 nbuf, bufpages * CLBYTES); 236 237 /* 238 * Set up CPU-specific registers, cache, etc. 239 */ 240 initcpu(); 241 242 /* 243 * Set up buffers, so they can be used to read disk labels. 244 */ 245 bufinit(); 246 247 /* 248 * Configure the system. 249 */ 250 configure(); 251 } 252 253 #ifdef PGINPROF 254 /* 255 * Return the difference (in microseconds) 256 * between the current time and a previous 257 * time as represented by the arguments. 258 * If there is a pending clock interrupt 259 * which has not been serviced due to high 260 * ipl, return error code. 261 */ 262 /*ARGSUSED*/ 263 vmtime(otime, olbolt, oicr) 264 register int otime, olbolt, oicr; 265 { 266 267 return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); 268 } 269 #endif 270 271 struct sigframe { 272 int sf_signum; 273 int sf_code; 274 struct sigcontext *sf_scp; 275 sig_t sf_handler; 276 int sf_eax; 277 int sf_edx; 278 int sf_ecx; 279 struct sigcontext sf_sc; 280 } ; 281 282 extern int kstack[]; 283 284 /* 285 * Send an interrupt to process. 286 * 287 * Stack is set up to allow sigcode stored 288 * in u. to call routine, followed by kcall 289 * to sigreturn routine below. After sigreturn 290 * resets the signal mask, the stack, and the 291 * frame pointer, it returns to the user 292 * specified pc, psl. 293 */ 294 void 295 sendsig(catcher, sig, mask, code) 296 sig_t catcher; 297 int sig, mask; 298 unsigned code; 299 { 300 register struct proc *p = curproc; 301 register int *regs; 302 register struct sigframe *fp; 303 struct sigacts *ps = p->p_sigacts; 304 int oonstack, frmtrap; 305 306 regs = p->p_regs; 307 oonstack = ps->ps_onstack; 308 frmtrap = curpcb->pcb_flags & FM_TRAP; 309 /* 310 * Allocate and validate space for the signal handler 311 * context. Note that if the stack is in P0 space, the 312 * call to grow() is a nop, and the useracc() check 313 * will fail if the process has not already allocated 314 * the space with a `brk'. 315 */ 316 if (!ps->ps_onstack && (ps->ps_sigonstack & sigmask(sig))) { 317 fp = (struct sigframe *)(ps->ps_sigsp 318 - sizeof(struct sigframe)); 319 ps->ps_onstack = 1; 320 } else { 321 if (frmtrap) 322 fp = (struct sigframe *)(regs[tESP] 323 - sizeof(struct sigframe)); 324 else 325 fp = (struct sigframe *)(regs[sESP] 326 - sizeof(struct sigframe)); 327 } 328 329 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 330 (void)grow((unsigned)fp); 331 332 if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) { 333 /* 334 * Process has trashed its stack; give it an illegal 335 * instruction to halt it in its tracks. 336 */ 337 SIGACTION(p, SIGILL) = SIG_DFL; 338 sig = sigmask(SIGILL); 339 p->p_sigignore &= ~sig; 340 p->p_sigcatch &= ~sig; 341 p->p_sigmask &= ~sig; 342 psignal(p, SIGILL); 343 return; 344 } 345 346 /* 347 * Build the argument list for the signal handler. 348 */ 349 fp->sf_signum = sig; 350 fp->sf_code = code; 351 fp->sf_scp = &fp->sf_sc; 352 fp->sf_handler = catcher; 353 354 /* save scratch registers */ 355 if(frmtrap) { 356 fp->sf_eax = regs[tEAX]; 357 fp->sf_edx = regs[tEDX]; 358 fp->sf_ecx = regs[tECX]; 359 } else { 360 fp->sf_eax = regs[sEAX]; 361 fp->sf_edx = regs[sEDX]; 362 fp->sf_ecx = regs[sECX]; 363 } 364 /* 365 * Build the signal context to be used by sigreturn. 366 */ 367 fp->sf_sc.sc_onstack = oonstack; 368 fp->sf_sc.sc_mask = mask; 369 if(frmtrap) { 370 fp->sf_sc.sc_sp = regs[tESP]; 371 fp->sf_sc.sc_fp = regs[tEBP]; 372 fp->sf_sc.sc_pc = regs[tEIP]; 373 fp->sf_sc.sc_ps = regs[tEFLAGS]; 374 regs[tESP] = (int)fp; 375 regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 376 } else { 377 fp->sf_sc.sc_sp = regs[sESP]; 378 fp->sf_sc.sc_fp = regs[sEBP]; 379 fp->sf_sc.sc_pc = regs[sEIP]; 380 fp->sf_sc.sc_ps = regs[sEFLAGS]; 381 regs[sESP] = (int)fp; 382 regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 383 } 384 } 385 386 /* 387 * System call to cleanup state after a signal 388 * has been taken. Reset signal mask and 389 * stack state from context left by sendsig (above). 390 * Return to previous pc and psl as specified by 391 * context left by sendsig. Check carefully to 392 * make sure that the user has not modified the 393 * psl to gain improper priviledges or to cause 394 * a machine fault. 395 */ 396 sigreturn(p, uap, retval) 397 struct proc *p; 398 struct args { 399 struct sigcontext *sigcntxp; 400 } *uap; 401 int *retval; 402 { 403 register struct sigcontext *scp; 404 register struct sigframe *fp; 405 register int *regs = p->p_regs; 406 407 408 fp = (struct sigframe *) regs[sESP] ; 409 410 if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) 411 return(EINVAL); 412 413 /* restore scratch registers */ 414 regs[sEAX] = fp->sf_eax ; 415 regs[sEDX] = fp->sf_edx ; 416 regs[sECX] = fp->sf_ecx ; 417 418 scp = fp->sf_scp; 419 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) 420 return(EINVAL); 421 #ifdef notyet 422 if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) { 423 return(EINVAL); 424 } 425 #endif 426 p->p_sigacts->ps_onstack = scp->sc_onstack & 01; 427 p->p_sigmask = scp->sc_mask &~ 428 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 429 regs[sEBP] = scp->sc_fp; 430 regs[sESP] = scp->sc_sp; 431 regs[sEIP] = scp->sc_pc; 432 regs[sEFLAGS] = scp->sc_ps; 433 return(EJUSTRETURN); 434 } 435 436 int waittime = -1; 437 438 boot(arghowto) 439 int arghowto; 440 { 441 register long dummy; /* r12 is reserved */ 442 register int howto; /* r11 == how to boot */ 443 register int devtype; /* r10 == major of root dev */ 444 extern char *panicstr; 445 446 howto = arghowto; 447 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 448 register struct buf *bp; 449 int iter, nbusy; 450 451 waittime = 0; 452 (void) splnet(); 453 printf("syncing disks... "); 454 /* 455 * Release inodes held by texts before update. 456 */ 457 if (panicstr == 0) 458 vnode_pager_umount(NULL); 459 sync((struct sigcontext *)0); 460 461 for (iter = 0; iter < 20; iter++) { 462 nbusy = 0; 463 for (bp = &buf[nbuf]; --bp >= buf; ) 464 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 465 nbusy++; 466 if (nbusy == 0) 467 break; 468 printf("%d ", nbusy); 469 DELAY(40000 * iter); 470 } 471 if (nbusy) 472 printf("giving up\n"); 473 else 474 printf("done\n"); 475 DELAY(10000); /* wait for printf to finish */ 476 } 477 splhigh(); 478 devtype = major(rootdev); 479 if (howto&RB_HALT) { 480 printf("halting (in tight loop); hit reset\n\n"); 481 splx(0xfffd); /* all but keyboard XXX */ 482 for (;;) ; 483 } else { 484 if (howto & RB_DUMP) { 485 dumpsys(); 486 /*NOTREACHED*/ 487 } 488 } 489 #ifdef lint 490 dummy = 0; dummy = dummy; 491 printf("howto %d, devtype %d\n", arghowto, devtype); 492 #endif 493 reset_cpu(); 494 for(;;) ; 495 /*NOTREACHED*/ 496 } 497 498 int dumpmag = 0x8fca0101; /* magic number for savecore */ 499 int dumpsize = 0; /* also for savecore */ 500 /* 501 * Doadump comes here after turning off memory management and 502 * getting on the dump stack, either when called above, or by 503 * the auto-restart code. 504 */ 505 dumpsys() 506 { 507 508 if (dumpdev == NODEV) 509 return; 510 if ((minor(dumpdev)&07) != 1) 511 return; 512 dumpsize = physmem; 513 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 514 printf("dump "); 515 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 516 517 case ENXIO: 518 printf("device bad\n"); 519 break; 520 521 case EFAULT: 522 printf("device not ready\n"); 523 break; 524 525 case EINVAL: 526 printf("area improper\n"); 527 break; 528 529 case EIO: 530 printf("i/o error\n"); 531 break; 532 533 default: 534 printf("succeeded\n"); 535 break; 536 } 537 printf("\n\n"); 538 DELAY(1000); 539 } 540 541 microtime(tvp) 542 register struct timeval *tvp; 543 { 544 int s = splhigh(); 545 546 *tvp = time; 547 tvp->tv_usec += tick; 548 while (tvp->tv_usec > 1000000) { 549 tvp->tv_sec++; 550 tvp->tv_usec -= 1000000; 551 } 552 splx(s); 553 } 554 555 physstrat(bp, strat, prio) 556 struct buf *bp; 557 int (*strat)(), prio; 558 { 559 register int s; 560 caddr_t baddr; 561 562 /* 563 * vmapbuf clobbers b_addr so we must remember it so that it 564 * can be restored after vunmapbuf. This is truely rude, we 565 * should really be storing this in a field in the buf struct 566 * but none are available and I didn't want to add one at 567 * this time. Note that b_addr for dirty page pushes is 568 * restored in vunmapbuf. (ugh!) 569 */ 570 baddr = bp->b_un.b_addr; 571 vmapbuf(bp); 572 (*strat)(bp); 573 /* pageout daemon doesn't wait for pushed pages */ 574 if (bp->b_flags & B_DIRTY) 575 return; 576 s = splbio(); 577 while ((bp->b_flags & B_DONE) == 0) 578 sleep((caddr_t)bp, prio); 579 splx(s); 580 vunmapbuf(bp); 581 bp->b_un.b_addr = baddr; 582 } 583 584 initcpu() 585 { 586 } 587 588 /* 589 * Clear registers on exec 590 */ 591 setregs(p, entry) 592 struct proc *p; 593 u_long entry; 594 { 595 596 p->p_regs[sEBP] = 0; /* bottom of the fp chain */ 597 p->p_regs[sEIP] = entry; 598 599 p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ 600 load_cr0(rcr0() | CR0_EM); /* start emulating */ 601 #ifdef NPX 602 npxinit(0x262); 603 #endif 604 } 605 606 /* 607 * Initialize 386 and configure to run kernel 608 */ 609 610 /* 611 * Initialize segments & interrupt table 612 */ 613 614 615 #define GNULL_SEL 0 /* Null Descriptor */ 616 #define GCODE_SEL 1 /* Kernel Code Descriptor */ 617 #define GDATA_SEL 2 /* Kernel Data Descriptor */ 618 #define GLDT_SEL 3 /* LDT - eventually one per process */ 619 #define GTGATE_SEL 4 /* Process task switch gate */ 620 #define GPANIC_SEL 5 /* Task state to consider panic from */ 621 #define GPROC0_SEL 6 /* Task state process slot zero and up */ 622 #define NGDT GPROC0_SEL+1 623 624 union descriptor gdt[GPROC0_SEL+1]; 625 626 /* interrupt descriptor table */ 627 struct gate_descriptor idt[32+16]; 628 629 /* local descriptor table */ 630 union descriptor ldt[5]; 631 #define LSYS5CALLS_SEL 0 /* forced by intel BCS */ 632 #define LSYS5SIGR_SEL 1 633 634 #define L43BSDCALLS_SEL 2 /* notyet */ 635 #define LUCODE_SEL 3 636 #define LUDATA_SEL 4 637 /* seperate stack, es,fs,gs sels ? */ 638 /* #define LPOSIXCALLS_SEL 5 /* notyet */ 639 640 struct i386tss tss, panic_tss; 641 642 extern struct user *proc0paddr; 643 644 /* software prototypes -- in more palitable form */ 645 struct soft_segment_descriptor gdt_segs[] = { 646 /* Null Descriptor */ 647 { 0x0, /* segment base address */ 648 0x0, /* length - all address space */ 649 0, /* segment type */ 650 0, /* segment descriptor priority level */ 651 0, /* segment descriptor present */ 652 0,0, 653 0, /* default 32 vs 16 bit size */ 654 0 /* limit granularity (byte/page units)*/ }, 655 /* Code Descriptor for kernel */ 656 { 0x0, /* segment base address */ 657 0xfffff, /* length - all address space */ 658 SDT_MEMERA, /* segment type */ 659 0, /* segment descriptor priority level */ 660 1, /* segment descriptor present */ 661 0,0, 662 1, /* default 32 vs 16 bit size */ 663 1 /* limit granularity (byte/page units)*/ }, 664 /* Data Descriptor for kernel */ 665 { 0x0, /* segment base address */ 666 0xfffff, /* length - all address space */ 667 SDT_MEMRWA, /* segment type */ 668 0, /* segment descriptor priority level */ 669 1, /* segment descriptor present */ 670 0,0, 671 1, /* default 32 vs 16 bit size */ 672 1 /* limit granularity (byte/page units)*/ }, 673 /* LDT Descriptor */ 674 { (int) ldt, /* segment base address */ 675 sizeof(ldt)-1, /* length - all address space */ 676 SDT_SYSLDT, /* segment type */ 677 0, /* segment descriptor priority level */ 678 1, /* segment descriptor present */ 679 0,0, 680 0, /* unused - default 32 vs 16 bit size */ 681 0 /* limit granularity (byte/page units)*/ }, 682 /* Null Descriptor - Placeholder */ 683 { 0x0, /* segment base address */ 684 0x0, /* length - all address space */ 685 0, /* segment type */ 686 0, /* segment descriptor priority level */ 687 0, /* segment descriptor present */ 688 0,0, 689 0, /* default 32 vs 16 bit size */ 690 0 /* limit granularity (byte/page units)*/ }, 691 /* Panic Tss Descriptor */ 692 { (int) &panic_tss, /* segment base address */ 693 sizeof(tss)-1, /* length - all address space */ 694 SDT_SYS386TSS, /* segment type */ 695 0, /* segment descriptor priority level */ 696 1, /* segment descriptor present */ 697 0,0, 698 0, /* unused - default 32 vs 16 bit size */ 699 0 /* limit granularity (byte/page units)*/ }, 700 /* Proc 0 Tss Descriptor */ 701 { (int) kstack, /* segment base address */ 702 sizeof(tss)-1, /* length - all address space */ 703 SDT_SYS386TSS, /* segment type */ 704 0, /* segment descriptor priority level */ 705 1, /* segment descriptor present */ 706 0,0, 707 0, /* unused - default 32 vs 16 bit size */ 708 0 /* limit granularity (byte/page units)*/ }}; 709 710 struct soft_segment_descriptor ldt_segs[] = { 711 /* Null Descriptor - overwritten by call gate */ 712 { 0x0, /* segment base address */ 713 0x0, /* length - all address space */ 714 0, /* segment type */ 715 0, /* segment descriptor priority level */ 716 0, /* segment descriptor present */ 717 0,0, 718 0, /* default 32 vs 16 bit size */ 719 0 /* limit granularity (byte/page units)*/ }, 720 /* Null Descriptor - overwritten by call gate */ 721 { 0x0, /* segment base address */ 722 0x0, /* length - all address space */ 723 0, /* segment type */ 724 0, /* segment descriptor priority level */ 725 0, /* segment descriptor present */ 726 0,0, 727 0, /* default 32 vs 16 bit size */ 728 0 /* limit granularity (byte/page units)*/ }, 729 /* Null Descriptor - overwritten by call gate */ 730 { 0x0, /* segment base address */ 731 0x0, /* length - all address space */ 732 0, /* segment type */ 733 0, /* segment descriptor priority level */ 734 0, /* segment descriptor present */ 735 0,0, 736 0, /* default 32 vs 16 bit size */ 737 0 /* limit granularity (byte/page units)*/ }, 738 /* Code Descriptor for user */ 739 { 0x0, /* segment base address */ 740 0xfffff, /* length - all address space */ 741 SDT_MEMERA, /* segment type */ 742 SEL_UPL, /* segment descriptor priority level */ 743 1, /* segment descriptor present */ 744 0,0, 745 1, /* default 32 vs 16 bit size */ 746 1 /* limit granularity (byte/page units)*/ }, 747 /* Data Descriptor for user */ 748 { 0x0, /* segment base address */ 749 0xfffff, /* length - all address space */ 750 SDT_MEMRWA, /* segment type */ 751 SEL_UPL, /* segment descriptor priority level */ 752 1, /* segment descriptor present */ 753 0,0, 754 1, /* default 32 vs 16 bit size */ 755 1 /* limit granularity (byte/page units)*/ } }; 756 757 /* table descriptors - used to load tables by microp */ 758 struct region_descriptor r_gdt = { 759 sizeof(gdt)-1,(char *)gdt 760 }; 761 762 struct region_descriptor r_idt = { 763 sizeof(idt)-1,(char *)idt 764 }; 765 766 setidt(idx, func, typ, dpl) char *func; { 767 struct gate_descriptor *ip = idt + idx; 768 769 ip->gd_looffset = (int)func; 770 ip->gd_selector = 8; 771 ip->gd_stkcpy = 0; 772 ip->gd_xx = 0; 773 ip->gd_type = typ; 774 ip->gd_dpl = dpl; 775 ip->gd_p = 1; 776 ip->gd_hioffset = ((int)func)>>16 ; 777 } 778 779 #define IDTVEC(name) __CONCAT(X, name) 780 extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 781 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), 782 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 783 IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), 784 IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), 785 IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), 786 IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), 787 IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall); 788 789 int lcr0(), lcr3(), rcr0(), rcr2(); 790 int _udatasel, _ucodesel, _gsel_tss; 791 792 init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext; 793 int x, *pi; 794 unsigned biosbasemem, biosextmem; 795 struct gate_descriptor *gdp; 796 extern int sigcode,szsigcode; 797 798 proc0.p_addr = proc0paddr; 799 800 /* 801 * Initialize the console before we print anything out. 802 */ 803 804 cninit (KERNBASE+0xa0000); 805 806 /* make gdt memory segments */ 807 gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG); 808 for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x); 809 /* make ldt memory segments */ 810 ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 811 ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 812 /* Note. eventually want private ldts per process */ 813 for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); 814 815 /* exceptions */ 816 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); 817 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); 818 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); 819 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); 820 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL); 821 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); 822 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); 823 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); 824 setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); 825 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); 826 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); 827 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); 828 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); 829 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); 830 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); 831 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); 832 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); 833 setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); 834 setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); 835 setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); 836 setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); 837 setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); 838 setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); 839 setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); 840 setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); 841 setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); 842 setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); 843 setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); 844 setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); 845 setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); 846 setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); 847 setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); 848 849 #include "isa.h" 850 #if NISA >0 851 isa_defaultirq(); 852 #endif 853 854 lgdt(gdt, sizeof(gdt)-1); 855 lidt(idt, sizeof(idt)-1); 856 lldt(GSEL(GLDT_SEL, SEL_KPL)); 857 858 #ifdef notyet 859 /* determine amount of memory present so we can scale kernel PT */ 860 for (i= RAM_BEGIN; i < IOM_BEGIN; i += NBPG) 861 if (probemem(i) == 0) break; 862 if (i == IOM_BEGIN) { 863 if (maxphysmem == 0) maxphysmem = RAM_END; 864 for (i= IOM_END; i < maxphysmem; i += NBPG) 865 if (probemem(i) == 0) break; 866 } 867 maxmem = i / NBPG; 868 #else 869 Maxmem = 8192 *1024 /NBPG; 870 maxmem = Maxmem; 871 #endif 872 873 /* reconcile against BIOS's recorded values in RTC 874 * we trust neither of them, as both can lie! 875 */ 876 biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 877 biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); 878 if (biosbasemem == 0xffff || biosextmem == 0xffff) { 879 if (maxmem > 0xffc) 880 maxmem = 640/4; 881 } else if (biosextmem > 0 && biosbasemem == 640) { 882 int totbios = (biosbasemem + 0x60000 + biosextmem)/4; 883 if (totbios < maxmem) maxmem = totbios; 884 } else maxmem = 640/4; 885 maxmem = maxmem-1; 886 physmem = maxmem - (0x100 -0xa0); 887 888 /* call pmap initialization to make new kernel address space */ 889 pmap_bootstrap (first, 0); 890 /* now running on new page tables, configured,and u/iom is accessible */ 891 892 /* make a initial tss so microp can get interrupt stack on syscall! */ 893 proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; 894 proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 895 _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); 896 ltr(_gsel_tss); 897 898 /* make a call gate to reenter kernel with */ 899 gdp = &ldt[LSYS5CALLS_SEL].gd; 900 901 x = (int) &IDTVEC(syscall); 902 gdp->gd_looffset = x++; 903 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 904 gdp->gd_stkcpy = 0; 905 gdp->gd_type = SDT_SYS386CGT; 906 gdp->gd_dpl = SEL_UPL; 907 gdp->gd_p = 1; 908 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 909 910 /* transfer to user mode */ 911 912 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 913 _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 914 915 /* setup proc 0's pcb */ 916 bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); 917 proc0.p_addr->u_pcb.pcb_flags = 0; 918 proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; 919 } 920 921 extern struct pte *CMAP1, *CMAP2; 922 extern caddr_t CADDR1, CADDR2; 923 /* 924 * zero out physical memory 925 * specified in relocation units (NBPG bytes) 926 */ 927 clearseg(n) { 928 929 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 930 load_cr3(rcr3()); 931 bzero(CADDR2,NBPG); 932 *(int *) CADDR2 = 0; 933 } 934 935 /* 936 * copy a page of physical memory 937 * specified in relocation units (NBPG bytes) 938 */ 939 copyseg(frm, n) { 940 941 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 942 load_cr3(rcr3()); 943 bcopy((void *)frm, (void *)CADDR2, NBPG); 944 } 945 946 /* 947 * copy a page of physical memory 948 * specified in relocation units (NBPG bytes) 949 */ 950 physcopyseg(frm, to) { 951 952 *(int *)CMAP1 = PG_V | PG_KW | ctob(frm); 953 *(int *)CMAP2 = PG_V | PG_KW | ctob(to); 954 load_cr3(rcr3()); 955 bcopy(CADDR1, CADDR2, NBPG); 956 } 957 958 /*aston() { 959 schednetisr(NETISR_AST); 960 }*/ 961 962 setsoftclock() { 963 schednetisr(NETISR_SCLK); 964 } 965 966 /* 967 * insert an element into a queue 968 */ 969 #undef insque 970 _insque(element, head) 971 register struct prochd *element, *head; 972 { 973 element->ph_link = head->ph_link; 974 head->ph_link = (struct proc *)element; 975 element->ph_rlink = (struct proc *)head; 976 ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element; 977 } 978 979 /* 980 * remove an element from a queue 981 */ 982 #undef remque 983 _remque(element) 984 register struct prochd *element; 985 { 986 ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink; 987 ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link; 988 element->ph_rlink = (struct proc *)0; 989 } 990 991 vmunaccess() {} 992 993 /* 994 * Below written in C to allow access to debugging code 995 */ 996 copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 997 void *toaddr, *fromaddr; { 998 u_int c,tally; 999 1000 tally = 0; 1001 while (maxlength--) { 1002 c = fubyte(fromaddr++); 1003 if (c == -1) { 1004 if(lencopied) *lencopied = tally; 1005 return(EFAULT); 1006 } 1007 tally++; 1008 *(char *)toaddr++ = (char) c; 1009 if (c == 0){ 1010 if(lencopied) *lencopied = tally; 1011 return(0); 1012 } 1013 } 1014 if(lencopied) *lencopied = tally; 1015 return(ENAMETOOLONG); 1016 } 1017 1018 copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1019 void *fromaddr, *toaddr; { 1020 int c; 1021 int tally; 1022 1023 tally = 0; 1024 while (maxlength--) { 1025 c = subyte(toaddr++, *(char *)fromaddr); 1026 if (c == -1) return(EFAULT); 1027 tally++; 1028 if (*(char *)fromaddr++ == 0){ 1029 if(lencopied) *lencopied = tally; 1030 return(0); 1031 } 1032 } 1033 if(lencopied) *lencopied = tally; 1034 return(ENAMETOOLONG); 1035 } 1036 1037 copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1038 void *fromaddr, *toaddr; { 1039 u_int tally; 1040 1041 tally = 0; 1042 while (maxlength--) { 1043 *(u_char *)toaddr = *(u_char *)fromaddr++; 1044 tally++; 1045 if (*(u_char *)toaddr++ == 0) { 1046 if(lencopied) *lencopied = tally; 1047 return(0); 1048 } 1049 } 1050 if(lencopied) *lencopied = tally; 1051 return(ENAMETOOLONG); 1052 } 1053