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