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.15 (Berkeley) 10/11/92 11 */ 12 13 #include <sys/param.h> 14 #include <sys/systm.h> 15 #include <sys/signalvar.h> 16 #include <sys/kernel.h> 17 #include <sys/map.h> 18 #include <sys/proc.h> 19 #include <sys/user.h> 20 #include <sys/buf.h> 21 #include <sys/reboot.h> 22 #include <sys/conf.h> 23 #include <sys/file.h> 24 #include <sys/clist.h> 25 #include <sys/callout.h> 26 #include <sys/malloc.h> 27 #include <sys/mbuf.h> 28 #include <sys/msgbuf.h> 29 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(kernel_pmap, 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 callout[i-1].c_next = NULL; 233 234 /*printf("avail mem = %d\n", ptoa(vm_page_free_count));*/ 235 printf("using %d buffers containing %d bytes of memory\n", 236 nbuf, bufpages * CLBYTES); 237 238 /* 239 * Set up CPU-specific registers, cache, etc. 240 */ 241 initcpu(); 242 243 /* 244 * Set up buffers, so they can be used to read disk labels. 245 */ 246 bufinit(); 247 248 /* 249 * Configure the system. 250 */ 251 configure(); 252 } 253 254 #ifdef PGINPROF 255 /* 256 * Return the difference (in microseconds) 257 * between the current time and a previous 258 * time as represented by the arguments. 259 * If there is a pending clock interrupt 260 * which has not been serviced due to high 261 * ipl, return error code. 262 */ 263 /*ARGSUSED*/ 264 vmtime(otime, olbolt, oicr) 265 register int otime, olbolt, oicr; 266 { 267 268 return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); 269 } 270 #endif 271 272 struct sigframe { 273 int sf_signum; 274 int sf_code; 275 struct sigcontext *sf_scp; 276 sig_t sf_handler; 277 int sf_eax; 278 int sf_edx; 279 int sf_ecx; 280 struct sigcontext sf_sc; 281 } ; 282 283 extern int kstack[]; 284 285 /* 286 * Send an interrupt to process. 287 * 288 * Stack is set up to allow sigcode stored 289 * in u. to call routine, followed by kcall 290 * to sigreturn routine below. After sigreturn 291 * resets the signal mask, the stack, and the 292 * frame pointer, it returns to the user 293 * specified pc, psl. 294 */ 295 void 296 sendsig(catcher, sig, mask, code) 297 sig_t catcher; 298 int sig, mask; 299 unsigned code; 300 { 301 register struct proc *p = curproc; 302 register int *regs; 303 register struct sigframe *fp; 304 struct sigacts *psp = p->p_sigacts; 305 int oonstack, frmtrap; 306 307 regs = p->p_md.md_regs; 308 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; 309 frmtrap = curpcb->pcb_flags & FM_TRAP; 310 /* 311 * Allocate and validate space for the signal handler 312 * context. Note that if the stack is in P0 space, the 313 * call to grow() is a nop, and the useracc() check 314 * will fail if the process has not already allocated 315 * the space with a `brk'. 316 */ 317 if ((psp->ps_flags & SAS_ALTSTACK) && 318 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && 319 (psp->ps_sigonstack & sigmask(sig))) { 320 fp = (struct sigframe *)(psp->ps_sigstk.ss_base + 321 psp->ps_sigstk.ss_size - sizeof(struct sigframe)); 322 psp->ps_sigstk.ss_flags |= SA_ONSTACK; 323 } else { 324 if (frmtrap) 325 fp = (struct sigframe *)(regs[tESP] 326 - sizeof(struct sigframe)); 327 else 328 fp = (struct sigframe *)(regs[sESP] 329 - sizeof(struct sigframe)); 330 } 331 332 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) 333 (void)grow(p, (unsigned)fp); 334 335 if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) { 336 /* 337 * Process has trashed its stack; give it an illegal 338 * instruction to halt it in its tracks. 339 */ 340 SIGACTION(p, SIGILL) = SIG_DFL; 341 sig = sigmask(SIGILL); 342 p->p_sigignore &= ~sig; 343 p->p_sigcatch &= ~sig; 344 p->p_sigmask &= ~sig; 345 psignal(p, SIGILL); 346 return; 347 } 348 349 /* 350 * Build the argument list for the signal handler. 351 */ 352 fp->sf_signum = sig; 353 fp->sf_code = code; 354 fp->sf_scp = &fp->sf_sc; 355 fp->sf_handler = catcher; 356 357 /* save scratch registers */ 358 if(frmtrap) { 359 fp->sf_eax = regs[tEAX]; 360 fp->sf_edx = regs[tEDX]; 361 fp->sf_ecx = regs[tECX]; 362 } else { 363 fp->sf_eax = regs[sEAX]; 364 fp->sf_edx = regs[sEDX]; 365 fp->sf_ecx = regs[sECX]; 366 } 367 /* 368 * Build the signal context to be used by sigreturn. 369 */ 370 fp->sf_sc.sc_onstack = oonstack; 371 fp->sf_sc.sc_mask = mask; 372 if(frmtrap) { 373 fp->sf_sc.sc_sp = regs[tESP]; 374 fp->sf_sc.sc_fp = regs[tEBP]; 375 fp->sf_sc.sc_pc = regs[tEIP]; 376 fp->sf_sc.sc_ps = regs[tEFLAGS]; 377 regs[tESP] = (int)fp; 378 regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 379 } else { 380 fp->sf_sc.sc_sp = regs[sESP]; 381 fp->sf_sc.sc_fp = regs[sEBP]; 382 fp->sf_sc.sc_pc = regs[sEIP]; 383 fp->sf_sc.sc_ps = regs[sEFLAGS]; 384 regs[sESP] = (int)fp; 385 regs[sEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 386 } 387 } 388 389 /* 390 * System call to cleanup state after a signal 391 * has been taken. Reset signal mask and 392 * stack state from context left by sendsig (above). 393 * Return to previous pc and psl as specified by 394 * context left by sendsig. Check carefully to 395 * make sure that the user has not modified the 396 * psl to gain improper priviledges or to cause 397 * a machine fault. 398 */ 399 struct sigreturn_args { 400 struct sigcontext *sigcntxp; 401 }; 402 sigreturn(p, uap, retval) 403 struct proc *p; 404 struct sigreturn_args *uap; 405 int *retval; 406 { 407 register struct sigcontext *scp; 408 register struct sigframe *fp; 409 register int *regs = p->p_md.md_regs; 410 411 412 fp = (struct sigframe *) regs[sESP] ; 413 414 if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) 415 return(EINVAL); 416 417 /* restore scratch registers */ 418 regs[sEAX] = fp->sf_eax ; 419 regs[sEDX] = fp->sf_edx ; 420 regs[sECX] = fp->sf_ecx ; 421 422 scp = fp->sf_scp; 423 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) 424 return(EINVAL); 425 #ifdef notyet 426 if ((scp->sc_ps & PSL_MBZ) != 0 || (scp->sc_ps & PSL_MBO) != PSL_MBO) { 427 return(EINVAL); 428 } 429 #endif 430 if (scp->sc_onstack & 01) 431 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 432 else 433 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 434 p->p_sigmask = scp->sc_mask &~ 435 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 436 regs[sEBP] = scp->sc_fp; 437 regs[sESP] = scp->sc_sp; 438 regs[sEIP] = scp->sc_pc; 439 regs[sEFLAGS] = scp->sc_ps; 440 return(EJUSTRETURN); 441 } 442 443 int waittime = -1; 444 445 boot(arghowto) 446 int arghowto; 447 { 448 register long dummy; /* r12 is reserved */ 449 register int howto; /* r11 == how to boot */ 450 register int devtype; /* r10 == major of root dev */ 451 extern char *panicstr; 452 extern int cold; 453 454 howto = arghowto; 455 if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { 456 register struct buf *bp; 457 int iter, nbusy; 458 459 waittime = 0; 460 (void) splnet(); 461 printf("syncing disks... "); 462 /* 463 * Release inodes held by texts before update. 464 */ 465 if (panicstr == 0) 466 vnode_pager_umount(NULL); 467 sync((struct sigcontext *)0); 468 469 for (iter = 0; iter < 20; iter++) { 470 nbusy = 0; 471 for (bp = &buf[nbuf]; --bp >= buf; ) 472 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 473 nbusy++; 474 if (nbusy == 0) 475 break; 476 printf("%d ", nbusy); 477 DELAY(40000 * iter); 478 } 479 if (nbusy) 480 printf("giving up\n"); 481 else 482 printf("done\n"); 483 DELAY(10000); /* wait for printf to finish */ 484 } 485 splhigh(); 486 devtype = major(rootdev); 487 if (howto&RB_HALT) { 488 printf("halting (in tight loop); hit reset\n\n"); 489 splx(0xfffd); /* all but keyboard XXX */ 490 for (;;) ; 491 } else { 492 if (howto & RB_DUMP) { 493 dumpsys(); 494 /*NOTREACHED*/ 495 } 496 } 497 #ifdef lint 498 dummy = 0; dummy = dummy; 499 printf("howto %d, devtype %d\n", arghowto, devtype); 500 #endif 501 #ifdef notdef 502 pg("pausing (hit any key to reset)"); 503 #endif 504 reset_cpu(); 505 for(;;) ; 506 /*NOTREACHED*/ 507 } 508 509 int dumpmag = 0x8fca0101; /* magic number for savecore */ 510 int dumpsize = 0; /* also for savecore */ 511 /* 512 * Doadump comes here after turning off memory management and 513 * getting on the dump stack, either when called above, or by 514 * the auto-restart code. 515 */ 516 dumpsys() 517 { 518 519 if (dumpdev == NODEV) 520 return; 521 if ((minor(dumpdev)&07) != 1) 522 return; 523 dumpsize = physmem; 524 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo); 525 printf("dump "); 526 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 527 528 case ENXIO: 529 printf("device bad\n"); 530 break; 531 532 case EFAULT: 533 printf("device not ready\n"); 534 break; 535 536 case EINVAL: 537 printf("area improper\n"); 538 break; 539 540 case EIO: 541 printf("i/o error\n"); 542 break; 543 544 default: 545 printf("succeeded\n"); 546 break; 547 } 548 printf("\n\n"); 549 DELAY(1000); 550 } 551 552 microtime(tvp) 553 register struct timeval *tvp; 554 { 555 int s = splhigh(); 556 557 *tvp = time; 558 tvp->tv_usec += tick; 559 while (tvp->tv_usec > 1000000) { 560 tvp->tv_sec++; 561 tvp->tv_usec -= 1000000; 562 } 563 splx(s); 564 } 565 566 physstrat(bp, strat, prio) 567 struct buf *bp; 568 int (*strat)(), prio; 569 { 570 register int s; 571 caddr_t baddr; 572 573 /* 574 * vmapbuf clobbers b_addr so we must remember it so that it 575 * can be restored after vunmapbuf. This is truely rude, we 576 * should really be storing this in a field in the buf struct 577 * but none are available and I didn't want to add one at 578 * this time. Note that b_addr for dirty page pushes is 579 * restored in vunmapbuf. (ugh!) 580 */ 581 baddr = bp->b_un.b_addr; 582 vmapbuf(bp); 583 (*strat)(bp); 584 /* pageout daemon doesn't wait for pushed pages */ 585 if (bp->b_flags & B_DIRTY) 586 return; 587 s = splbio(); 588 while ((bp->b_flags & B_DONE) == 0) 589 sleep((caddr_t)bp, prio); 590 splx(s); 591 vunmapbuf(bp); 592 bp->b_un.b_addr = baddr; 593 } 594 595 initcpu() 596 { 597 } 598 599 /* 600 * Clear registers on exec 601 */ 602 setregs(p, entry, retval) 603 register struct proc *p; 604 u_long entry; 605 int retval[2]; 606 { 607 p->p_md.md_regs[sEBP] = 0; /* bottom of the fp chain */ 608 p->p_md.md_regs[sEIP] = entry; 609 610 p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ 611 load_cr0(rcr0() | CR0_EM); /* start emulating */ 612 #include "npx.h" 613 #if NNPX > 0 614 npxinit(0x262); 615 #endif 616 } 617 618 /* 619 * Initialize 386 and configure to run kernel 620 */ 621 622 /* 623 * Initialize segments & interrupt table 624 */ 625 626 627 #define GNULL_SEL 0 /* Null Descriptor */ 628 #define GCODE_SEL 1 /* Kernel Code Descriptor */ 629 #define GDATA_SEL 2 /* Kernel Data Descriptor */ 630 #define GLDT_SEL 3 /* LDT - eventually one per process */ 631 #define GTGATE_SEL 4 /* Process task switch gate */ 632 #define GPANIC_SEL 5 /* Task state to consider panic from */ 633 #define GPROC0_SEL 6 /* Task state process slot zero and up */ 634 #define NGDT GPROC0_SEL+1 635 636 union descriptor gdt[GPROC0_SEL+1]; 637 638 /* interrupt descriptor table */ 639 struct gate_descriptor idt[32+16]; 640 641 /* local descriptor table */ 642 union descriptor ldt[5]; 643 #define LSYS5CALLS_SEL 0 /* forced by intel BCS */ 644 #define LSYS5SIGR_SEL 1 645 646 #define L43BSDCALLS_SEL 2 /* notyet */ 647 #define LUCODE_SEL 3 648 #define LUDATA_SEL 4 649 /* seperate stack, es,fs,gs sels ? */ 650 /* #define LPOSIXCALLS_SEL 5 /* notyet */ 651 652 struct i386tss tss, panic_tss; 653 654 extern struct user *proc0paddr; 655 656 /* software prototypes -- in more palitable form */ 657 struct soft_segment_descriptor gdt_segs[] = { 658 /* Null Descriptor */ 659 { 0x0, /* segment base address */ 660 0x0, /* length - all address space */ 661 0, /* segment type */ 662 0, /* segment descriptor priority level */ 663 0, /* segment descriptor present */ 664 0,0, 665 0, /* default 32 vs 16 bit size */ 666 0 /* limit granularity (byte/page units)*/ }, 667 /* Code Descriptor for kernel */ 668 { 0x0, /* segment base address */ 669 0xfffff, /* length - all address space */ 670 SDT_MEMERA, /* segment type */ 671 0, /* segment descriptor priority level */ 672 1, /* segment descriptor present */ 673 0,0, 674 1, /* default 32 vs 16 bit size */ 675 1 /* limit granularity (byte/page units)*/ }, 676 /* Data Descriptor for kernel */ 677 { 0x0, /* segment base address */ 678 0xfffff, /* length - all address space */ 679 SDT_MEMRWA, /* segment type */ 680 0, /* segment descriptor priority level */ 681 1, /* segment descriptor present */ 682 0,0, 683 1, /* default 32 vs 16 bit size */ 684 1 /* limit granularity (byte/page units)*/ }, 685 /* LDT Descriptor */ 686 { (int) ldt, /* segment base address */ 687 sizeof(ldt)-1, /* length - all address space */ 688 SDT_SYSLDT, /* segment type */ 689 0, /* segment descriptor priority level */ 690 1, /* segment descriptor present */ 691 0,0, 692 0, /* unused - default 32 vs 16 bit size */ 693 0 /* limit granularity (byte/page units)*/ }, 694 /* Null Descriptor - Placeholder */ 695 { 0x0, /* segment base address */ 696 0x0, /* length - all address space */ 697 0, /* segment type */ 698 0, /* segment descriptor priority level */ 699 0, /* segment descriptor present */ 700 0,0, 701 0, /* default 32 vs 16 bit size */ 702 0 /* limit granularity (byte/page units)*/ }, 703 /* Panic Tss Descriptor */ 704 { (int) &panic_tss, /* segment base address */ 705 sizeof(tss)-1, /* length - all address space */ 706 SDT_SYS386TSS, /* segment type */ 707 0, /* segment descriptor priority level */ 708 1, /* segment descriptor present */ 709 0,0, 710 0, /* unused - default 32 vs 16 bit size */ 711 0 /* limit granularity (byte/page units)*/ }, 712 /* Proc 0 Tss Descriptor */ 713 { (int) kstack, /* segment base address */ 714 sizeof(tss)-1, /* length - all address space */ 715 SDT_SYS386TSS, /* segment type */ 716 0, /* segment descriptor priority level */ 717 1, /* segment descriptor present */ 718 0,0, 719 0, /* unused - default 32 vs 16 bit size */ 720 0 /* limit granularity (byte/page units)*/ }}; 721 722 struct soft_segment_descriptor ldt_segs[] = { 723 /* Null Descriptor - overwritten by call gate */ 724 { 0x0, /* segment base address */ 725 0x0, /* length - all address space */ 726 0, /* segment type */ 727 0, /* segment descriptor priority level */ 728 0, /* segment descriptor present */ 729 0,0, 730 0, /* default 32 vs 16 bit size */ 731 0 /* limit granularity (byte/page units)*/ }, 732 /* Null Descriptor - overwritten by call gate */ 733 { 0x0, /* segment base address */ 734 0x0, /* length - all address space */ 735 0, /* segment type */ 736 0, /* segment descriptor priority level */ 737 0, /* segment descriptor present */ 738 0,0, 739 0, /* default 32 vs 16 bit size */ 740 0 /* limit granularity (byte/page units)*/ }, 741 /* Null Descriptor - overwritten by call gate */ 742 { 0x0, /* segment base address */ 743 0x0, /* length - all address space */ 744 0, /* segment type */ 745 0, /* segment descriptor priority level */ 746 0, /* segment descriptor present */ 747 0,0, 748 0, /* default 32 vs 16 bit size */ 749 0 /* limit granularity (byte/page units)*/ }, 750 /* Code Descriptor for user */ 751 { 0x0, /* segment base address */ 752 0xfffff, /* length - all address space */ 753 SDT_MEMERA, /* segment type */ 754 SEL_UPL, /* segment descriptor priority level */ 755 1, /* segment descriptor present */ 756 0,0, 757 1, /* default 32 vs 16 bit size */ 758 1 /* limit granularity (byte/page units)*/ }, 759 /* Data Descriptor for user */ 760 { 0x0, /* segment base address */ 761 0xfffff, /* length - all address space */ 762 SDT_MEMRWA, /* segment type */ 763 SEL_UPL, /* segment descriptor priority level */ 764 1, /* segment descriptor present */ 765 0,0, 766 1, /* default 32 vs 16 bit size */ 767 1 /* limit granularity (byte/page units)*/ } }; 768 769 /* table descriptors - used to load tables by microp */ 770 struct region_descriptor r_gdt = { 771 sizeof(gdt)-1,(char *)gdt 772 }; 773 774 struct region_descriptor r_idt = { 775 sizeof(idt)-1,(char *)idt 776 }; 777 778 setidt(idx, func, typ, dpl) char *func; { 779 struct gate_descriptor *ip = idt + idx; 780 781 ip->gd_looffset = (int)func; 782 ip->gd_selector = 8; 783 ip->gd_stkcpy = 0; 784 ip->gd_xx = 0; 785 ip->gd_type = typ; 786 ip->gd_dpl = dpl; 787 ip->gd_p = 1; 788 ip->gd_hioffset = ((int)func)>>16 ; 789 } 790 791 #define IDTVEC(name) __CONCAT(X, name) 792 extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 793 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), 794 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 795 IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), 796 IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), 797 IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), 798 IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), 799 IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall); 800 801 int lcr0(), lcr3(), rcr0(), rcr2(); 802 int _udatasel, _ucodesel, _gsel_tss; 803 804 init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext; 805 int x, *pi; 806 unsigned biosbasemem, biosextmem; 807 struct gate_descriptor *gdp; 808 extern int sigcode,szsigcode; 809 810 proc0.p_addr = proc0paddr; 811 812 /* 813 * Initialize the console before we print anything out. 814 */ 815 816 cninit (KERNBASE+0xa0000); 817 818 /* make gdt memory segments */ 819 gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG); 820 for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x); 821 /* make ldt memory segments */ 822 ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 823 ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 824 /* Note. eventually want private ldts per process */ 825 for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); 826 827 /* exceptions */ 828 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); 829 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); 830 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); 831 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); 832 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL); 833 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); 834 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); 835 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); 836 setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); 837 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); 838 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); 839 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); 840 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); 841 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); 842 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); 843 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); 844 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); 845 setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); 846 setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); 847 setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); 848 setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); 849 setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); 850 setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); 851 setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); 852 setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); 853 setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); 854 setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); 855 setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); 856 setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); 857 setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); 858 setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); 859 setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); 860 861 #include "isa.h" 862 #if NISA >0 863 isa_defaultirq(); 864 #endif 865 866 lgdt(gdt, sizeof(gdt)-1); 867 lidt(idt, sizeof(idt)-1); 868 lldt(GSEL(GLDT_SEL, SEL_KPL)); 869 870 /* 871 * This memory size stuff is a real mess. Here is a simple 872 * setup that just believes the BIOS. After the rest of 873 * the system is a little more stable, we'll come back to 874 * this and deal with issues if incorrect BIOS information, 875 * and when physical memory is > 16 megabytes. 876 */ 877 biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 878 biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); 879 Maxmem = btoc ((biosextmem + 1024) * 1024); 880 maxmem = Maxmem - 1; 881 physmem = btoc (biosbasemem * 1024 + (biosextmem - 1) * 1024); 882 printf ("bios %dK+%dK. maxmem %x, physmem %x\n", 883 biosbasemem, biosextmem, ctob (maxmem), ctob (physmem)); 884 885 vm_set_page_size(); 886 /* call pmap initialization to make new kernel address space */ 887 pmap_bootstrap (first, 0); 888 /* now running on new page tables, configured,and u/iom is accessible */ 889 890 /* make a initial tss so microp can get interrupt stack on syscall! */ 891 proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; 892 proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 893 _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); 894 ltr(_gsel_tss); 895 896 /* make a call gate to reenter kernel with */ 897 gdp = &ldt[LSYS5CALLS_SEL].gd; 898 899 x = (int) &IDTVEC(syscall); 900 gdp->gd_looffset = x++; 901 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 902 gdp->gd_stkcpy = 0; 903 gdp->gd_type = SDT_SYS386CGT; 904 gdp->gd_dpl = SEL_UPL; 905 gdp->gd_p = 1; 906 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 907 908 /* transfer to user mode */ 909 910 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 911 _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 912 913 /* setup proc 0's pcb */ 914 bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); 915 proc0.p_addr->u_pcb.pcb_flags = 0; 916 proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; 917 } 918 919 extern struct pte *CMAP1, *CMAP2; 920 extern caddr_t CADDR1, CADDR2; 921 /* 922 * zero out physical memory 923 * specified in relocation units (NBPG bytes) 924 */ 925 clearseg(n) { 926 927 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 928 load_cr3(rcr3()); 929 bzero(CADDR2,NBPG); 930 *(int *) CADDR2 = 0; 931 } 932 933 /* 934 * copy a page of physical memory 935 * specified in relocation units (NBPG bytes) 936 */ 937 copyseg(frm, n) { 938 939 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 940 load_cr3(rcr3()); 941 bcopy((void *)frm, (void *)CADDR2, NBPG); 942 } 943 944 /* 945 * copy a page of physical memory 946 * specified in relocation units (NBPG bytes) 947 */ 948 physcopyseg(frm, to) { 949 950 *(int *)CMAP1 = PG_V | PG_KW | ctob(frm); 951 *(int *)CMAP2 = PG_V | PG_KW | ctob(to); 952 load_cr3(rcr3()); 953 bcopy(CADDR1, CADDR2, NBPG); 954 } 955 956 /*aston() { 957 schednetisr(NETISR_AST); 958 }*/ 959 960 setsoftclock() { 961 schednetisr(NETISR_SCLK); 962 } 963 964 /* 965 * insert an element into a queue 966 */ 967 #undef insque 968 _insque(element, head) 969 register struct prochd *element, *head; 970 { 971 element->ph_link = head->ph_link; 972 head->ph_link = (struct proc *)element; 973 element->ph_rlink = (struct proc *)head; 974 ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element; 975 } 976 977 /* 978 * remove an element from a queue 979 */ 980 #undef remque 981 _remque(element) 982 register struct prochd *element; 983 { 984 ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink; 985 ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link; 986 element->ph_rlink = (struct proc *)0; 987 } 988 989 vmunaccess() {} 990 991 /* 992 * Below written in C to allow access to debugging code 993 */ 994 copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 995 void *toaddr, *fromaddr; { 996 int c,tally; 997 998 tally = 0; 999 while (maxlength--) { 1000 c = fubyte(fromaddr++); 1001 if (c == -1) { 1002 if(lencopied) *lencopied = tally; 1003 return(EFAULT); 1004 } 1005 tally++; 1006 *(char *)toaddr++ = (char) c; 1007 if (c == 0){ 1008 if(lencopied) *lencopied = tally; 1009 return(0); 1010 } 1011 } 1012 if(lencopied) *lencopied = tally; 1013 return(ENAMETOOLONG); 1014 } 1015 1016 copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1017 void *fromaddr, *toaddr; { 1018 int c; 1019 int tally; 1020 1021 tally = 0; 1022 while (maxlength--) { 1023 c = subyte(toaddr++, *(char *)fromaddr); 1024 if (c == -1) return(EFAULT); 1025 tally++; 1026 if (*(char *)fromaddr++ == 0){ 1027 if(lencopied) *lencopied = tally; 1028 return(0); 1029 } 1030 } 1031 if(lencopied) *lencopied = tally; 1032 return(ENAMETOOLONG); 1033 } 1034 1035 copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1036 void *fromaddr, *toaddr; { 1037 u_int tally; 1038 1039 tally = 0; 1040 while (maxlength--) { 1041 *(u_char *)toaddr = *(u_char *)fromaddr++; 1042 tally++; 1043 if (*(u_char *)toaddr++ == 0) { 1044 if(lencopied) *lencopied = tally; 1045 return(0); 1046 } 1047 } 1048 if(lencopied) *lencopied = tally; 1049 return(ENAMETOOLONG); 1050 } 1051