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.16 (Berkeley) 05/21/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 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 * machine dependent system variables. 620 */ 621 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 622 int *name; 623 u_int namelen; 624 void *oldp; 625 size_t *oldlenp; 626 void *newp; 627 size_t newlen; 628 struct proc *p; 629 { 630 631 /* all sysctl names at this level are terminal */ 632 if (namelen != 1) 633 return (ENOTDIR); /* overloaded */ 634 635 switch (name[0]) { 636 case CPU_CONSDEV: 637 return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev, 638 sizeof cn_tty->t_dev)); 639 default: 640 return (EOPNOTSUPP); 641 } 642 /* NOTREACHED */ 643 } 644 645 /* 646 * Initialize 386 and configure to run kernel 647 */ 648 649 /* 650 * Initialize segments & interrupt table 651 */ 652 653 654 #define GNULL_SEL 0 /* Null Descriptor */ 655 #define GCODE_SEL 1 /* Kernel Code Descriptor */ 656 #define GDATA_SEL 2 /* Kernel Data Descriptor */ 657 #define GLDT_SEL 3 /* LDT - eventually one per process */ 658 #define GTGATE_SEL 4 /* Process task switch gate */ 659 #define GPANIC_SEL 5 /* Task state to consider panic from */ 660 #define GPROC0_SEL 6 /* Task state process slot zero and up */ 661 #define NGDT GPROC0_SEL+1 662 663 union descriptor gdt[GPROC0_SEL+1]; 664 665 /* interrupt descriptor table */ 666 struct gate_descriptor idt[32+16]; 667 668 /* local descriptor table */ 669 union descriptor ldt[5]; 670 #define LSYS5CALLS_SEL 0 /* forced by intel BCS */ 671 #define LSYS5SIGR_SEL 1 672 673 #define L43BSDCALLS_SEL 2 /* notyet */ 674 #define LUCODE_SEL 3 675 #define LUDATA_SEL 4 676 /* seperate stack, es,fs,gs sels ? */ 677 /* #define LPOSIXCALLS_SEL 5 /* notyet */ 678 679 struct i386tss tss, panic_tss; 680 681 extern struct user *proc0paddr; 682 683 /* software prototypes -- in more palitable form */ 684 struct soft_segment_descriptor gdt_segs[] = { 685 /* Null Descriptor */ 686 { 0x0, /* segment base address */ 687 0x0, /* length - all address space */ 688 0, /* segment type */ 689 0, /* segment descriptor priority level */ 690 0, /* segment descriptor present */ 691 0,0, 692 0, /* default 32 vs 16 bit size */ 693 0 /* limit granularity (byte/page units)*/ }, 694 /* Code Descriptor for kernel */ 695 { 0x0, /* segment base address */ 696 0xfffff, /* length - all address space */ 697 SDT_MEMERA, /* segment type */ 698 0, /* segment descriptor priority level */ 699 1, /* segment descriptor present */ 700 0,0, 701 1, /* default 32 vs 16 bit size */ 702 1 /* limit granularity (byte/page units)*/ }, 703 /* Data Descriptor for kernel */ 704 { 0x0, /* segment base address */ 705 0xfffff, /* length - all address space */ 706 SDT_MEMRWA, /* segment type */ 707 0, /* segment descriptor priority level */ 708 1, /* segment descriptor present */ 709 0,0, 710 1, /* default 32 vs 16 bit size */ 711 1 /* limit granularity (byte/page units)*/ }, 712 /* LDT Descriptor */ 713 { (int) ldt, /* segment base address */ 714 sizeof(ldt)-1, /* length - all address space */ 715 SDT_SYSLDT, /* 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 /* Null Descriptor - Placeholder */ 722 { 0x0, /* segment base address */ 723 0x0, /* length - all address space */ 724 0, /* segment type */ 725 0, /* segment descriptor priority level */ 726 0, /* segment descriptor present */ 727 0,0, 728 0, /* default 32 vs 16 bit size */ 729 0 /* limit granularity (byte/page units)*/ }, 730 /* Panic Tss Descriptor */ 731 { (int) &panic_tss, /* segment base address */ 732 sizeof(tss)-1, /* length - all address space */ 733 SDT_SYS386TSS, /* segment type */ 734 0, /* segment descriptor priority level */ 735 1, /* segment descriptor present */ 736 0,0, 737 0, /* unused - default 32 vs 16 bit size */ 738 0 /* limit granularity (byte/page units)*/ }, 739 /* Proc 0 Tss Descriptor */ 740 { (int) kstack, /* segment base address */ 741 sizeof(tss)-1, /* length - all address space */ 742 SDT_SYS386TSS, /* segment type */ 743 0, /* segment descriptor priority level */ 744 1, /* segment descriptor present */ 745 0,0, 746 0, /* unused - default 32 vs 16 bit size */ 747 0 /* limit granularity (byte/page units)*/ }}; 748 749 struct soft_segment_descriptor ldt_segs[] = { 750 /* Null Descriptor - overwritten by call gate */ 751 { 0x0, /* segment base address */ 752 0x0, /* length - all address space */ 753 0, /* segment type */ 754 0, /* segment descriptor priority level */ 755 0, /* segment descriptor present */ 756 0,0, 757 0, /* default 32 vs 16 bit size */ 758 0 /* limit granularity (byte/page units)*/ }, 759 /* Null Descriptor - overwritten by call gate */ 760 { 0x0, /* segment base address */ 761 0x0, /* length - all address space */ 762 0, /* segment type */ 763 0, /* segment descriptor priority level */ 764 0, /* segment descriptor present */ 765 0,0, 766 0, /* default 32 vs 16 bit size */ 767 0 /* limit granularity (byte/page units)*/ }, 768 /* Null Descriptor - overwritten by call gate */ 769 { 0x0, /* segment base address */ 770 0x0, /* length - all address space */ 771 0, /* segment type */ 772 0, /* segment descriptor priority level */ 773 0, /* segment descriptor present */ 774 0,0, 775 0, /* default 32 vs 16 bit size */ 776 0 /* limit granularity (byte/page units)*/ }, 777 /* Code Descriptor for user */ 778 { 0x0, /* segment base address */ 779 0xfffff, /* length - all address space */ 780 SDT_MEMERA, /* segment type */ 781 SEL_UPL, /* segment descriptor priority level */ 782 1, /* segment descriptor present */ 783 0,0, 784 1, /* default 32 vs 16 bit size */ 785 1 /* limit granularity (byte/page units)*/ }, 786 /* Data Descriptor for user */ 787 { 0x0, /* segment base address */ 788 0xfffff, /* length - all address space */ 789 SDT_MEMRWA, /* segment type */ 790 SEL_UPL, /* segment descriptor priority level */ 791 1, /* segment descriptor present */ 792 0,0, 793 1, /* default 32 vs 16 bit size */ 794 1 /* limit granularity (byte/page units)*/ } }; 795 796 /* table descriptors - used to load tables by microp */ 797 struct region_descriptor r_gdt = { 798 sizeof(gdt)-1,(char *)gdt 799 }; 800 801 struct region_descriptor r_idt = { 802 sizeof(idt)-1,(char *)idt 803 }; 804 805 setidt(idx, func, typ, dpl) char *func; { 806 struct gate_descriptor *ip = idt + idx; 807 808 ip->gd_looffset = (int)func; 809 ip->gd_selector = 8; 810 ip->gd_stkcpy = 0; 811 ip->gd_xx = 0; 812 ip->gd_type = typ; 813 ip->gd_dpl = dpl; 814 ip->gd_p = 1; 815 ip->gd_hioffset = ((int)func)>>16 ; 816 } 817 818 #define IDTVEC(name) __CONCAT(X, name) 819 extern IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 820 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), 821 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 822 IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), 823 IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), 824 IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), 825 IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), 826 IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(rsvd14), IDTVEC(syscall); 827 828 int lcr0(), lcr3(), rcr0(), rcr2(); 829 int _udatasel, _ucodesel, _gsel_tss; 830 831 init386(first) { extern ssdtosd(), lgdt(), lidt(), lldt(), etext; 832 int x, *pi; 833 unsigned biosbasemem, biosextmem; 834 struct gate_descriptor *gdp; 835 extern int sigcode,szsigcode; 836 837 proc0.p_addr = proc0paddr; 838 839 /* 840 * Initialize the console before we print anything out. 841 */ 842 843 cninit (KERNBASE+0xa0000); 844 845 /* make gdt memory segments */ 846 gdt_segs[GCODE_SEL].ssd_limit = btoc((int) &etext + NBPG); 847 for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x); 848 /* make ldt memory segments */ 849 ldt_segs[LUCODE_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 850 ldt_segs[LUDATA_SEL].ssd_limit = btoc(UPT_MIN_ADDRESS); 851 /* Note. eventually want private ldts per process */ 852 for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); 853 854 /* exceptions */ 855 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); 856 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); 857 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); 858 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); 859 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_KPL); 860 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); 861 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); 862 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); 863 setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); 864 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); 865 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); 866 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); 867 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); 868 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); 869 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); 870 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); 871 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); 872 setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); 873 setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); 874 setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); 875 setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); 876 setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); 877 setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); 878 setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); 879 setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); 880 setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); 881 setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); 882 setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); 883 setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); 884 setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); 885 setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); 886 setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); 887 888 #include "isa.h" 889 #if NISA >0 890 isa_defaultirq(); 891 #endif 892 893 lgdt(gdt, sizeof(gdt)-1); 894 lidt(idt, sizeof(idt)-1); 895 lldt(GSEL(GLDT_SEL, SEL_KPL)); 896 897 /* 898 * This memory size stuff is a real mess. Here is a simple 899 * setup that just believes the BIOS. After the rest of 900 * the system is a little more stable, we'll come back to 901 * this and deal with issues if incorrect BIOS information, 902 * and when physical memory is > 16 megabytes. 903 */ 904 biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 905 biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); 906 Maxmem = btoc ((biosextmem + 1024) * 1024); 907 maxmem = Maxmem - 1; 908 physmem = btoc (biosbasemem * 1024 + (biosextmem - 1) * 1024); 909 printf ("bios %dK+%dK. maxmem %x, physmem %x\n", 910 biosbasemem, biosextmem, ctob (maxmem), ctob (physmem)); 911 912 vm_set_page_size(); 913 /* call pmap initialization to make new kernel address space */ 914 pmap_bootstrap (first, 0); 915 /* now running on new page tables, configured,and u/iom is accessible */ 916 917 /* make a initial tss so microp can get interrupt stack on syscall! */ 918 proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; 919 proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 920 _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); 921 ltr(_gsel_tss); 922 923 /* make a call gate to reenter kernel with */ 924 gdp = &ldt[LSYS5CALLS_SEL].gd; 925 926 x = (int) &IDTVEC(syscall); 927 gdp->gd_looffset = x++; 928 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 929 gdp->gd_stkcpy = 0; 930 gdp->gd_type = SDT_SYS386CGT; 931 gdp->gd_dpl = SEL_UPL; 932 gdp->gd_p = 1; 933 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 934 935 /* transfer to user mode */ 936 937 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 938 _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 939 940 /* setup proc 0's pcb */ 941 bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); 942 proc0.p_addr->u_pcb.pcb_flags = 0; 943 proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; 944 } 945 946 extern struct pte *CMAP1, *CMAP2; 947 extern caddr_t CADDR1, CADDR2; 948 /* 949 * zero out physical memory 950 * specified in relocation units (NBPG bytes) 951 */ 952 clearseg(n) { 953 954 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 955 load_cr3(rcr3()); 956 bzero(CADDR2,NBPG); 957 *(int *) CADDR2 = 0; 958 } 959 960 /* 961 * copy a page of physical memory 962 * specified in relocation units (NBPG bytes) 963 */ 964 copyseg(frm, n) { 965 966 *(int *)CMAP2 = PG_V | PG_KW | ctob(n); 967 load_cr3(rcr3()); 968 bcopy((void *)frm, (void *)CADDR2, NBPG); 969 } 970 971 /* 972 * copy a page of physical memory 973 * specified in relocation units (NBPG bytes) 974 */ 975 physcopyseg(frm, to) { 976 977 *(int *)CMAP1 = PG_V | PG_KW | ctob(frm); 978 *(int *)CMAP2 = PG_V | PG_KW | ctob(to); 979 load_cr3(rcr3()); 980 bcopy(CADDR1, CADDR2, NBPG); 981 } 982 983 /*aston() { 984 schednetisr(NETISR_AST); 985 }*/ 986 987 setsoftclock() { 988 schednetisr(NETISR_SCLK); 989 } 990 991 /* 992 * insert an element into a queue 993 */ 994 #undef insque 995 _insque(element, head) 996 register struct prochd *element, *head; 997 { 998 element->ph_link = head->ph_link; 999 head->ph_link = (struct proc *)element; 1000 element->ph_rlink = (struct proc *)head; 1001 ((struct prochd *)(element->ph_link))->ph_rlink=(struct proc *)element; 1002 } 1003 1004 /* 1005 * remove an element from a queue 1006 */ 1007 #undef remque 1008 _remque(element) 1009 register struct prochd *element; 1010 { 1011 ((struct prochd *)(element->ph_link))->ph_rlink = element->ph_rlink; 1012 ((struct prochd *)(element->ph_rlink))->ph_link = element->ph_link; 1013 element->ph_rlink = (struct proc *)0; 1014 } 1015 1016 vmunaccess() {} 1017 1018 /* 1019 * Below written in C to allow access to debugging code 1020 */ 1021 copyinstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1022 void *toaddr, *fromaddr; { 1023 int c,tally; 1024 1025 tally = 0; 1026 while (maxlength--) { 1027 c = fubyte(fromaddr++); 1028 if (c == -1) { 1029 if(lencopied) *lencopied = tally; 1030 return(EFAULT); 1031 } 1032 tally++; 1033 *(char *)toaddr++ = (char) c; 1034 if (c == 0){ 1035 if(lencopied) *lencopied = tally; 1036 return(0); 1037 } 1038 } 1039 if(lencopied) *lencopied = tally; 1040 return(ENAMETOOLONG); 1041 } 1042 1043 copyoutstr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1044 void *fromaddr, *toaddr; { 1045 int c; 1046 int tally; 1047 1048 tally = 0; 1049 while (maxlength--) { 1050 c = subyte(toaddr++, *(char *)fromaddr); 1051 if (c == -1) return(EFAULT); 1052 tally++; 1053 if (*(char *)fromaddr++ == 0){ 1054 if(lencopied) *lencopied = tally; 1055 return(0); 1056 } 1057 } 1058 if(lencopied) *lencopied = tally; 1059 return(ENAMETOOLONG); 1060 } 1061 1062 copystr(fromaddr, toaddr, maxlength, lencopied) u_int *lencopied, maxlength; 1063 void *fromaddr, *toaddr; { 1064 u_int tally; 1065 1066 tally = 0; 1067 while (maxlength--) { 1068 *(u_char *)toaddr = *(u_char *)fromaddr++; 1069 tally++; 1070 if (*(u_char *)toaddr++ == 0) { 1071 if(lencopied) *lencopied = tally; 1072 return(0); 1073 } 1074 } 1075 if(lencopied) *lencopied = tally; 1076 return(ENAMETOOLONG); 1077 } 1078