machdep.c revision 3907
1/*- 2 * Copyright (c) 1992 Terrence R. Lambert. 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 38 * $Id: machdep.c,v 1.80 1994/10/25 08:58:33 davidg Exp $ 39 */ 40 41#include "npx.h" 42#include "isa.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/signalvar.h> 47#include <sys/kernel.h> 48#include <sys/proc.h> 49#include <sys/user.h> 50#include <sys/buf.h> 51#include <sys/reboot.h> 52#include <sys/conf.h> 53#include <sys/file.h> 54#include <sys/callout.h> 55#include <sys/malloc.h> 56#include <sys/mbuf.h> 57#include <sys/msgbuf.h> 58#include <sys/ioctl.h> 59#include <sys/sysent.h> 60#include <sys/tty.h> 61#include <sys/sysctl.h> 62 63#ifdef SYSVSHM 64#include <sys/shm.h> 65#endif 66 67#ifdef SYSVMSG 68#include <sys/msg.h> 69#endif 70 71#ifdef SYSVSEM 72#include <sys/sem.h> 73#endif 74 75#include <vm/vm.h> 76#include <vm/vm_kern.h> 77#include <vm/vm_page.h> 78 79#include <sys/exec.h> 80#include <sys/vnode.h> 81 82#include <net/netisr.h> 83 84extern vm_offset_t avail_start, avail_end; 85 86#include <machine/cpu.h> 87#include <machine/reg.h> 88#include <machine/psl.h> 89#include <machine/specialreg.h> 90#include <machine/sysarch.h> 91#include <machine/cons.h> 92#include <machine/devconf.h> 93 94#include <i386/isa/isa.h> 95#include <i386/isa/rtc.h> 96#include <ether.h> 97 98static void identifycpu(void); 99static void initcpu(void); 100static int test_page(int *, int); 101 102char machine[] = "i386"; 103char cpu_model[sizeof("Cy486DLC") + 1]; 104 105#ifndef PANIC_REBOOT_WAIT_TIME 106#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ 107#endif 108 109/* 110 * Declare these as initialized data so we can patch them. 111 */ 112int nswbuf = 0; 113#ifdef NBUF 114int nbuf = NBUF; 115#else 116int nbuf = 0; 117#endif 118#ifdef BUFPAGES 119int bufpages = BUFPAGES; 120#else 121int bufpages = 0; 122#endif 123 124#ifdef BOUNCE_BUFFERS 125extern char *bouncememory; 126extern int maxbkva; 127#ifdef BOUNCEPAGES 128int bouncepages = BOUNCEPAGES; 129#else 130int bouncepages = 0; 131#endif 132#endif /* BOUNCE_BUFFERS */ 133 134extern int freebufspace; 135int msgbufmapped = 0; /* set when safe to use msgbuf */ 136int _udatasel, _ucodesel; 137 138extern int adjkerntz, disable_rtc_set; /* from clock.c */ 139 140/* 141 * Machine-dependent startup code 142 */ 143int boothowto = 0, Maxmem = 0, badpages = 0, physmem = 0; 144long dumplo; 145extern int bootdev; 146int biosmem; 147 148vm_offset_t phys_avail[6]; 149 150int cpu_class; 151 152void dumpsys __P((void)); 153vm_offset_t buffer_sva, buffer_eva; 154vm_offset_t clean_sva, clean_eva; 155vm_offset_t pager_sva, pager_eva; 156extern int pager_map_size; 157 158#define offsetof(type, member) ((size_t)(&((type *)0)->member)) 159 160void 161cpu_startup() 162{ 163 register unsigned i; 164 register caddr_t v; 165 extern void (*netisrs[32])(void); 166 vm_offset_t maxaddr; 167 vm_size_t size = 0; 168 int firstaddr; 169#ifdef BOUNCE_BUFFERS 170 vm_offset_t minaddr; 171#endif /* BOUNCE_BUFFERS */ 172 173 /* 174 * Initialize error message buffer (at end of core). 175 */ 176 177 /* avail_end was pre-decremented in init_386() to compensate */ 178 for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) 179 pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp, 180 avail_end + i * NBPG, 181 VM_PROT_ALL, TRUE); 182 msgbufmapped = 1; 183 184 /* 185 * Good {morning,afternoon,evening,night}. 186 */ 187 printf(version); 188 startrtclock(); 189 identifycpu(); 190 printf("real memory = %d (%d pages)\n", ptoa(physmem), physmem); 191 if (badpages) 192 printf("bad memory = %d (%d pages)\n", ptoa(badpages), badpages); 193 194 /* 195 * Quickly wire in netisrs. 196 */ 197#define DONET(isr, n) do { extern void isr(void); netisrs[n] = isr; } while(0) 198#ifdef INET 199#if NETHER > 0 200 DONET(arpintr, NETISR_ARP); 201#endif 202 DONET(ipintr, NETISR_IP); 203#endif 204#ifdef NS 205 DONET(nsintr, NETISR_NS); 206#endif 207#ifdef ISO 208 DONET(clnlintr, NETISR_ISO); 209#endif 210#ifdef CCITT 211 DONET(ccittintr, NETISR_CCITT); 212#endif 213#undef DONET 214 215 /* 216 * Allocate space for system data structures. 217 * The first available kernel virtual address is in "v". 218 * As pages of kernel virtual memory are allocated, "v" is incremented. 219 * As pages of memory are allocated and cleared, 220 * "firstaddr" is incremented. 221 * An index into the kernel page table corresponding to the 222 * virtual memory address maintained in "v" is kept in "mapaddr". 223 */ 224 225 /* 226 * Make two passes. The first pass calculates how much memory is 227 * needed and allocates it. The second pass assigns virtual 228 * addresses to the various data structures. 229 */ 230 firstaddr = 0; 231again: 232 v = (caddr_t)firstaddr; 233 234#define valloc(name, type, num) \ 235 (name) = (type *)v; v = (caddr_t)((name)+(num)) 236#define valloclim(name, type, num, lim) \ 237 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 238 valloc(callout, struct callout, ncallout); 239#ifdef SYSVSHM 240 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 241#endif 242#ifdef SYSVSEM 243 valloc(sema, struct semid_ds, seminfo.semmni); 244 valloc(sem, struct sem, seminfo.semmns); 245 /* This is pretty disgusting! */ 246 valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); 247#endif 248#ifdef SYSVMSG 249 valloc(msgpool, char, msginfo.msgmax); 250 valloc(msgmaps, struct msgmap, msginfo.msgseg); 251 valloc(msghdrs, struct msg, msginfo.msgtql); 252 valloc(msqids, struct msqid_ds, msginfo.msgmni); 253#endif 254 /* 255 * Determine how many buffers to allocate. 256 * Use 20% of memory of memory beyond the first 2MB 257 * Insure a minimum of 16 fs buffers. 258 * We allocate 1/2 as many swap buffer headers as file i/o buffers. 259 */ 260 if (bufpages == 0) 261 bufpages = ((physmem << PGSHIFT) - 2048*1024) / NBPG / 6; 262 if (bufpages < 64) 263 bufpages = 64; 264 265 /* 266 * We must still limit the maximum number of buffers to be no 267 * more than 750 because we'll run out of kernel VM otherwise. 268 */ 269 bufpages = min(bufpages, 1500); 270 if (nbuf == 0) { 271 nbuf = bufpages / 2; 272 if (nbuf < 32) 273 nbuf = 32; 274 } 275 freebufspace = bufpages * NBPG; 276 if (nswbuf == 0) { 277 nswbuf = (nbuf / 2) &~ 1; /* force even */ 278 if (nswbuf > 64) 279 nswbuf = 64; /* sanity */ 280 } 281 valloc(swbuf, struct buf, nswbuf); 282 valloc(buf, struct buf, nbuf); 283 284#ifdef BOUNCE_BUFFERS 285 /* 286 * If there is more than 16MB of memory, allocate some bounce buffers 287 */ 288 if (Maxmem > 4096) { 289 if (bouncepages == 0) 290 bouncepages = 96; /* largest physio size + extra */ 291 v = (caddr_t)((vm_offset_t)((vm_offset_t)v + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); 292 valloc(bouncememory, char, bouncepages * PAGE_SIZE); 293 } 294#endif 295 296 /* 297 * End of first pass, size has been calculated so allocate memory 298 */ 299 if (firstaddr == 0) { 300 size = (vm_size_t)(v - firstaddr); 301 firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); 302 if (firstaddr == 0) 303 panic("startup: no room for tables"); 304 goto again; 305 } 306 307 /* 308 * End of second pass, addresses have been assigned 309 */ 310 if ((vm_size_t)(v - firstaddr) != size) 311 panic("startup: table size inconsistency"); 312 313#ifdef BOUNCE_BUFFERS 314 clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, 315 (nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + 316 maxbkva + pager_map_size, TRUE); 317 io_map = kmem_suballoc(clean_map, &minaddr, &maxaddr, maxbkva, FALSE); 318#else 319 clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, 320 (nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + pager_map_size, TRUE); 321#endif 322 buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, 323 (nbuf*MAXBSIZE), TRUE); 324 pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, 325 (nswbuf*MAXPHYS) + pager_map_size, TRUE); 326 327 /* 328 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 329 * we use the more space efficient malloc in place of kmem_alloc. 330 */ 331 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, 332 M_MBUF, M_NOWAIT); 333 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); 334 mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr, 335 VM_MBUF_SIZE, FALSE); 336 /* 337 * Initialize callouts 338 */ 339 callfree = callout; 340 for (i = 1; i < ncallout; i++) 341 callout[i-1].c_next = &callout[i]; 342#ifdef USERCONFIG 343 if (boothowto & RB_CONFIG) 344 userconfig(); 345#endif 346 printf("avail memory = %d (%d pages)\n", ptoa(cnt.v_free_count), cnt.v_free_count); 347 printf("using %d buffers containing %d bytes of memory\n", 348 nbuf, bufpages * CLBYTES); 349 350#ifdef BOUNCE_BUFFERS 351 /* 352 * init bounce buffers 353 */ 354 vm_bounce_init(); 355#endif 356 357 /* 358 * Set up CPU-specific registers, cache, etc. 359 */ 360 initcpu(); 361 362 /* 363 * Set up buffers, so they can be used to read disk labels. 364 */ 365 bufinit(); 366 vm_pager_bufferinit(); 367 368 /* 369 * Configure the system. 370 */ 371 configure(); 372} 373 374 375struct cpu_nameclass i386_cpus[] = { 376 { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */ 377 { "i386SX", CPUCLASS_386 }, /* CPU_386SX */ 378 { "i386DX", CPUCLASS_386 }, /* CPU_386 */ 379 { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ 380 { "i486DX", CPUCLASS_486 }, /* CPU_486 */ 381 { "Pentium", CPUCLASS_586 }, /* CPU_586 */ 382 { "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */ 383}; 384 385static void 386identifycpu() 387{ 388 extern u_long cpu_id; 389 extern char cpu_vendor[]; 390 printf("CPU: "); 391 if (cpu >= 0 392 && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) { 393 printf("%s", i386_cpus[cpu].cpu_name); 394 cpu_class = i386_cpus[cpu].cpu_class; 395 strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); 396 } else { 397 printf("unknown cpu type %d\n", cpu); 398 panic("startup: bad cpu id"); 399 } 400 printf(" ("); 401 switch(cpu_class) { 402 case CPUCLASS_286: 403 printf("286"); 404 break; 405 case CPUCLASS_386: 406 printf("386"); 407 break; 408 case CPUCLASS_486: 409 printf("486"); 410 break; 411 case CPUCLASS_586: 412 printf("Pentium"); 413 break; 414 default: 415 printf("unknown"); /* will panic below... */ 416 } 417 printf("-class CPU)"); 418#ifdef I586_CPU 419 if(cpu_class == CPUCLASS_586) { 420 extern void calibrate_cyclecounter(); 421 extern int pentium_mhz; 422 calibrate_cyclecounter(); 423 printf(" %d MHz", pentium_mhz); 424 } 425#endif 426 if(cpu_id) 427 printf(" Id = 0x%lx",cpu_id); 428 if(*cpu_vendor) 429 printf(" Origin = \"%s\"",cpu_vendor); 430 printf("\n"); /* cpu speed would be nice, but how? */ 431 432 /* 433 * Now that we have told the user what they have, 434 * let them know if that machine type isn't configured. 435 */ 436 switch (cpu_class) { 437 case CPUCLASS_286: /* a 286 should not make it this far, anyway */ 438#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) 439#error This kernel is not configured for one of the supported CPUs 440#endif 441#if !defined(I386_CPU) 442 case CPUCLASS_386: 443#endif 444#if !defined(I486_CPU) 445 case CPUCLASS_486: 446#endif 447#if !defined(I586_CPU) 448 case CPUCLASS_586: 449#endif 450 panic("CPU class not configured"); 451 default: 452 break; 453 } 454} 455 456#ifdef PGINPROF 457/* 458 * Return the difference (in microseconds) 459 * between the current time and a previous 460 * time as represented by the arguments. 461 * If there is a pending clock interrupt 462 * which has not been serviced due to high 463 * ipl, return error code. 464 */ 465/*ARGSUSED*/ 466vmtime(otime, olbolt, oicr) 467 register int otime, olbolt, oicr; 468{ 469 470 return (((time.tv_sec-otime)*60 + lbolt-olbolt)*16667); 471} 472#endif 473 474extern int kstack[]; 475 476/* 477 * Send an interrupt to process. 478 * 479 * Stack is set up to allow sigcode stored 480 * in u. to call routine, followed by kcall 481 * to sigreturn routine below. After sigreturn 482 * resets the signal mask, the stack, and the 483 * frame pointer, it returns to the user 484 * specified pc, psl. 485 */ 486void 487sendsig(catcher, sig, mask, code) 488 sig_t catcher; 489 int sig, mask; 490 unsigned code; 491{ 492 register struct proc *p = curproc; 493 register int *regs; 494 register struct sigframe *fp; 495 struct sigacts *psp = p->p_sigacts; 496 int oonstack; 497 498 regs = p->p_md.md_regs; 499 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; 500 /* 501 * Allocate and validate space for the signal handler 502 * context. Note that if the stack is in P0 space, the 503 * call to grow() is a nop, and the useracc() check 504 * will fail if the process has not already allocated 505 * the space with a `brk'. 506 */ 507 if ((psp->ps_flags & SAS_ALTSTACK) && 508 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && 509 (psp->ps_sigonstack & sigmask(sig))) { 510 fp = (struct sigframe *)(psp->ps_sigstk.ss_base + 511 psp->ps_sigstk.ss_size - sizeof(struct sigframe)); 512 psp->ps_sigstk.ss_flags |= SA_ONSTACK; 513 } else { 514 fp = (struct sigframe *)(regs[tESP] 515 - sizeof(struct sigframe)); 516 } 517 518 /* 519 * grow() will return FALSE if the fp will not fit inside the stack 520 * and the stack can not be grown. useracc will return FALSE 521 * if access is denied. 522 */ 523 if ((grow(p, (int)fp) == FALSE) || 524 (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == FALSE)) { 525 /* 526 * Process has trashed its stack; give it an illegal 527 * instruction to halt it in its tracks. 528 */ 529 SIGACTION(p, SIGILL) = SIG_DFL; 530 sig = sigmask(SIGILL); 531 p->p_sigignore &= ~sig; 532 p->p_sigcatch &= ~sig; 533 p->p_sigmask &= ~sig; 534 psignal(p, SIGILL); 535 return; 536 } 537 538 /* 539 * Build the argument list for the signal handler. 540 */ 541 if (p->p_sysent->sv_sigtbl) { 542 if (sig < p->p_sysent->sv_sigsize) 543 sig = p->p_sysent->sv_sigtbl[sig]; 544 else 545 sig = p->p_sysent->sv_sigsize + 1; 546 } 547 fp->sf_signum = sig; 548 fp->sf_code = code; 549 fp->sf_scp = &fp->sf_sc; 550 fp->sf_addr = (char *) regs[tERR]; 551 fp->sf_handler = catcher; 552 553 /* save scratch registers */ 554 fp->sf_sc.sc_eax = regs[tEAX]; 555 fp->sf_sc.sc_ebx = regs[tEBX]; 556 fp->sf_sc.sc_ecx = regs[tECX]; 557 fp->sf_sc.sc_edx = regs[tEDX]; 558 fp->sf_sc.sc_esi = regs[tESI]; 559 fp->sf_sc.sc_edi = regs[tEDI]; 560 fp->sf_sc.sc_cs = regs[tCS]; 561 fp->sf_sc.sc_ds = regs[tDS]; 562 fp->sf_sc.sc_ss = regs[tSS]; 563 fp->sf_sc.sc_es = regs[tES]; 564 fp->sf_sc.sc_isp = regs[tISP]; 565 566 /* 567 * Build the signal context to be used by sigreturn. 568 */ 569 fp->sf_sc.sc_onstack = oonstack; 570 fp->sf_sc.sc_mask = mask; 571 fp->sf_sc.sc_sp = regs[tESP]; 572 fp->sf_sc.sc_fp = regs[tEBP]; 573 fp->sf_sc.sc_pc = regs[tEIP]; 574 fp->sf_sc.sc_ps = regs[tEFLAGS]; 575 regs[tESP] = (int)fp; 576 regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; 577 regs[tEFLAGS] &= ~PSL_VM; 578 regs[tCS] = _ucodesel; 579 regs[tDS] = _udatasel; 580 regs[tES] = _udatasel; 581 regs[tSS] = _udatasel; 582} 583 584/* 585 * System call to cleanup state after a signal 586 * has been taken. Reset signal mask and 587 * stack state from context left by sendsig (above). 588 * Return to previous pc and psl as specified by 589 * context left by sendsig. Check carefully to 590 * make sure that the user has not modified the 591 * psl to gain improper privileges or to cause 592 * a machine fault. 593 */ 594struct sigreturn_args { 595 struct sigcontext *sigcntxp; 596}; 597 598int 599sigreturn(p, uap, retval) 600 struct proc *p; 601 struct sigreturn_args *uap; 602 int *retval; 603{ 604 register struct sigcontext *scp; 605 register struct sigframe *fp; 606 register int *regs = p->p_md.md_regs; 607 int eflags; 608 609 /* 610 * (XXX old comment) regs[tESP] points to the return address. 611 * The user scp pointer is above that. 612 * The return address is faked in the signal trampoline code 613 * for consistency. 614 */ 615 scp = uap->sigcntxp; 616 fp = (struct sigframe *) 617 ((caddr_t)scp - offsetof(struct sigframe, sf_sc)); 618 619 if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) 620 return(EINVAL); 621 622 eflags = scp->sc_ps; 623 if ((eflags & PSL_USERCLR) != 0 || 624 (eflags & PSL_USERSET) != PSL_USERSET || 625 (eflags & PSL_IOPL) < (regs[tEFLAGS] & PSL_IOPL)) { 626#ifdef DEBUG 627 printf("sigreturn: eflags=0x%x\n", eflags); 628#endif 629 return(EINVAL); 630 } 631 632 /* 633 * Sanity check the user's selectors and error if they 634 * are suspect. 635 */ 636#define max_ldt_sel(pcb) \ 637 ((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0]))) 638 639#define valid_ldt_sel(sel) \ 640 (ISLDT(sel) && ISPL(sel) == SEL_UPL && \ 641 IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb)) 642 643#define null_sel(sel) \ 644 (!ISLDT(sel) && IDXSEL(sel) == 0) 645 646 if (((scp->sc_cs&0xffff) != _ucodesel && !valid_ldt_sel(scp->sc_cs)) || 647 ((scp->sc_ss&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ss)) || 648 ((scp->sc_ds&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ds) && 649 !null_sel(scp->sc_ds)) || 650 ((scp->sc_es&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_es) && 651 !null_sel(scp->sc_es))) { 652#ifdef DEBUG 653 printf("sigreturn: cs=0x%x ss=0x%x ds=0x%x es=0x%x\n", 654 scp->sc_cs, scp->sc_ss, scp->sc_ds, scp->sc_es); 655#endif 656 trapsignal(p, SIGBUS, T_PROTFLT); 657 return(EINVAL); 658 } 659 660#undef max_ldt_sel 661#undef valid_ldt_sel 662#undef null_sel 663 664 /* restore scratch registers */ 665 regs[tEAX] = scp->sc_eax; 666 regs[tEBX] = scp->sc_ebx; 667 regs[tECX] = scp->sc_ecx; 668 regs[tEDX] = scp->sc_edx; 669 regs[tESI] = scp->sc_esi; 670 regs[tEDI] = scp->sc_edi; 671 regs[tCS] = scp->sc_cs; 672 regs[tDS] = scp->sc_ds; 673 regs[tES] = scp->sc_es; 674 regs[tSS] = scp->sc_ss; 675 regs[tISP] = scp->sc_isp; 676 677 if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) 678 return(EINVAL); 679 680 if (scp->sc_onstack & 01) 681 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; 682 else 683 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; 684 p->p_sigmask = scp->sc_mask &~ 685 (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); 686 regs[tEBP] = scp->sc_fp; 687 regs[tESP] = scp->sc_sp; 688 regs[tEIP] = scp->sc_pc; 689 regs[tEFLAGS] = eflags; 690 return(EJUSTRETURN); 691} 692 693/* 694 * a simple function to make the system panic (and dump a vmcore) 695 * in a predictable fashion 696 */ 697void diediedie() 698{ 699 panic("because you said to!"); 700} 701 702int waittime = -1; 703struct pcb dumppcb; 704 705__dead void 706boot(arghowto) 707 int arghowto; 708{ 709 register long dummy; /* r12 is reserved */ 710 register int howto; /* r11 == how to boot */ 711 register int devtype; /* r10 == major of root dev */ 712 extern int cold; 713 714 if (cold) { 715 printf("hit reset please"); 716 for(;;); 717 } 718 howto = arghowto; 719 if ((howto&RB_NOSYNC) == 0 && waittime < 0) { 720 register struct buf *bp; 721 int iter, nbusy; 722 723 waittime = 0; 724 printf("\nsyncing disks... "); 725 /* 726 * Release inodes held by texts before update. 727 */ 728 if (panicstr == 0) 729 vnode_pager_umount(NULL); 730 sync(curproc, NULL, NULL); 731 732 for (iter = 0; iter < 20; iter++) { 733 nbusy = 0; 734 for (bp = &buf[nbuf]; --bp >= buf; ) 735 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY) 736 nbusy++; 737 if (nbusy == 0) 738 break; 739 printf("%d ", nbusy); 740 DELAY(40000 * iter); 741 } 742 if (nbusy) { 743 /* 744 * Failed to sync all blocks. Indicate this and don't 745 * unmount filesystems (thus forcing an fsck on reboot). 746 */ 747 printf("giving up\n"); 748 } else { 749 printf("done\n"); 750 /* 751 * Unmount filesystems 752 */ 753 if (panicstr == 0) 754 vfs_unmountall(); 755 } 756 DELAY(100000); /* wait for console output to finish */ 757 } 758 splhigh(); 759 devtype = major(rootdev); 760 if (howto&RB_HALT) { 761 printf("\n"); 762 printf("The operating system has halted.\n"); 763 printf("Please press any key to reboot.\n\n"); 764 cngetc(); 765 } else { 766 if (howto & RB_DUMP) { 767 savectx(&dumppcb, 0); 768 dumppcb.pcb_ptd = rcr3(); 769 dumpsys(); 770 771 if (PANIC_REBOOT_WAIT_TIME != 0) { 772 if (PANIC_REBOOT_WAIT_TIME != -1) { 773 int loop; 774 printf("Automatic reboot in %d seconds - press a key on the console to abort\n", 775 PANIC_REBOOT_WAIT_TIME); 776 for (loop = PANIC_REBOOT_WAIT_TIME; loop > 0; --loop) { 777 DELAY(1000 * 1000); /* one second */ 778 if (cncheckc()) /* Did user type a key? */ 779 break; 780 } 781 if (!loop) 782 goto die; 783 } 784 } else { /* zero time specified - reboot NOW */ 785 goto die; 786 } 787 printf("--> Press a key on the console to reboot <--\n"); 788 cngetc(); 789 } 790 } 791#ifdef lint 792 dummy = 0; dummy = dummy; 793 printf("howto %d, devtype %d\n", arghowto, devtype); 794#endif 795die: 796 printf("Rebooting...\n"); 797 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 798 cpu_reset(); 799 for(;;) ; 800 /* NOTREACHED */ 801} 802 803unsigned long dumpmag = 0x8fca0101UL; /* magic number for savecore */ 804int dumpsize = 0; /* also for savecore */ 805/* 806 * Doadump comes here after turning off memory management and 807 * getting on the dump stack, either when called above, or by 808 * the auto-restart code. 809 */ 810void 811dumpsys() 812{ 813 814 if (dumpdev == NODEV) 815 return; 816 if ((minor(dumpdev)&07) != 1) 817 return; 818 dumpsize = Maxmem; 819 printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo); 820 printf("dump "); 821 switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) { 822 823 case ENXIO: 824 printf("device bad\n"); 825 break; 826 827 case EFAULT: 828 printf("device not ready\n"); 829 break; 830 831 case EINVAL: 832 printf("area improper\n"); 833 break; 834 835 case EIO: 836 printf("i/o error\n"); 837 break; 838 839 case EINTR: 840 printf("aborted from console\n"); 841 break; 842 843 default: 844 printf("succeeded\n"); 845 break; 846 } 847} 848 849#ifdef HZ 850/* 851 * If HZ is defined we use this code, otherwise the code in 852 * /sys/i386/i386/microtime.s is used. The othercode only works 853 * for HZ=100. 854 */ 855microtime(tvp) 856 register struct timeval *tvp; 857{ 858 int s = splhigh(); 859 860 *tvp = time; 861 tvp->tv_usec += tick; 862 while (tvp->tv_usec > 1000000) { 863 tvp->tv_sec++; 864 tvp->tv_usec -= 1000000; 865 } 866 splx(s); 867} 868#endif /* HZ */ 869 870static void 871initcpu() 872{ 873} 874 875/* 876 * Clear registers on exec 877 */ 878void 879setregs(p, entry, stack) 880 struct proc *p; 881 u_long entry; 882 u_long stack; 883{ 884 p->p_md.md_regs[tEBP] = 0; /* bottom of the fp chain */ 885 p->p_md.md_regs[tEIP] = entry; 886 p->p_md.md_regs[tESP] = stack; 887 p->p_md.md_regs[tSS] = _udatasel; 888 p->p_md.md_regs[tDS] = _udatasel; 889 p->p_md.md_regs[tES] = _udatasel; 890 p->p_md.md_regs[tCS] = _ucodesel; 891 892 p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ 893 load_cr0(rcr0() | CR0_TS); /* start emulating */ 894#if NNPX > 0 895 npxinit(__INITIAL_NPXCW__); 896#endif /* NNPX > 0 */ 897} 898 899/* 900 * machine dependent system variables. 901 */ 902int 903cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 904 int *name; 905 u_int namelen; 906 void *oldp; 907 size_t *oldlenp; 908 void *newp; 909 size_t newlen; 910 struct proc *p; 911{ 912 913 /* all sysctl names at this level are terminal */ 914 if (namelen != 1) 915 return (ENOTDIR); /* overloaded */ 916 917 switch (name[0]) { 918 case CPU_CONSDEV: 919 return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tty->t_dev, 920 sizeof cn_tty->t_dev)); 921 case CPU_ADJKERNTZ: 922 return (sysctl_int(oldp, oldlenp, newp, newlen, &adjkerntz)); 923 case CPU_DISRTCSET: 924 return (sysctl_int(oldp, oldlenp, newp, newlen, &disable_rtc_set)); 925 default: 926 return (EOPNOTSUPP); 927 } 928 /* NOTREACHED */ 929} 930 931/* 932 * Initialize 386 and configure to run kernel 933 */ 934 935/* 936 * Initialize segments & interrupt table 937 */ 938 939union descriptor gdt[NGDT]; 940union descriptor ldt[NLDT]; /* local descriptor table */ 941struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */ 942 943int _default_ldt, currentldt; 944 945struct i386tss tss, panic_tss; 946 947extern struct user *proc0paddr; 948 949/* software prototypes -- in more palatable form */ 950struct soft_segment_descriptor gdt_segs[] = { 951/* GNULL_SEL 0 Null Descriptor */ 952{ 0x0, /* segment base address */ 953 0x0, /* length */ 954 0, /* segment type */ 955 0, /* segment descriptor priority level */ 956 0, /* segment descriptor present */ 957 0, 0, 958 0, /* default 32 vs 16 bit size */ 959 0 /* limit granularity (byte/page units)*/ }, 960/* GCODE_SEL 1 Code Descriptor for kernel */ 961{ 0x0, /* segment base address */ 962 0xfffff, /* length - all address space */ 963 SDT_MEMERA, /* segment type */ 964 0, /* segment descriptor priority level */ 965 1, /* segment descriptor present */ 966 0, 0, 967 1, /* default 32 vs 16 bit size */ 968 1 /* limit granularity (byte/page units)*/ }, 969/* GDATA_SEL 2 Data Descriptor for kernel */ 970{ 0x0, /* segment base address */ 971 0xfffff, /* length - all address space */ 972 SDT_MEMRWA, /* segment type */ 973 0, /* segment descriptor priority level */ 974 1, /* segment descriptor present */ 975 0, 0, 976 1, /* default 32 vs 16 bit size */ 977 1 /* limit granularity (byte/page units)*/ }, 978/* GLDT_SEL 3 LDT Descriptor */ 979{ (int) ldt, /* segment base address */ 980 sizeof(ldt)-1, /* length - all address space */ 981 SDT_SYSLDT, /* segment type */ 982 0, /* segment descriptor priority level */ 983 1, /* segment descriptor present */ 984 0, 0, 985 0, /* unused - default 32 vs 16 bit size */ 986 0 /* limit granularity (byte/page units)*/ }, 987/* GTGATE_SEL 4 Null Descriptor - Placeholder */ 988{ 0x0, /* segment base address */ 989 0x0, /* length - all address space */ 990 0, /* segment type */ 991 0, /* segment descriptor priority level */ 992 0, /* segment descriptor present */ 993 0, 0, 994 0, /* default 32 vs 16 bit size */ 995 0 /* limit granularity (byte/page units)*/ }, 996/* GPANIC_SEL 5 Panic Tss Descriptor */ 997{ (int) &panic_tss, /* segment base address */ 998 sizeof(tss)-1, /* length - all address space */ 999 SDT_SYS386TSS, /* segment type */ 1000 0, /* segment descriptor priority level */ 1001 1, /* segment descriptor present */ 1002 0, 0, 1003 0, /* unused - default 32 vs 16 bit size */ 1004 0 /* limit granularity (byte/page units)*/ }, 1005/* GPROC0_SEL 6 Proc 0 Tss Descriptor */ 1006{ (int) kstack, /* segment base address */ 1007 sizeof(tss)-1, /* length - all address space */ 1008 SDT_SYS386TSS, /* segment type */ 1009 0, /* segment descriptor priority level */ 1010 1, /* segment descriptor present */ 1011 0, 0, 1012 0, /* unused - default 32 vs 16 bit size */ 1013 0 /* limit granularity (byte/page units)*/ }, 1014/* GUSERLDT_SEL 7 User LDT Descriptor per process */ 1015{ (int) ldt, /* segment base address */ 1016 (512 * sizeof(union descriptor)-1), /* length */ 1017 SDT_SYSLDT, /* segment type */ 1018 0, /* segment descriptor priority level */ 1019 1, /* segment descriptor present */ 1020 0, 0, 1021 0, /* unused - default 32 vs 16 bit size */ 1022 0 /* limit granularity (byte/page units)*/ }, 1023/* GAPMCODE32_SEL 8 APM BIOS 32-bit interface (32bit Code) */ 1024{ 0, /* segment base address (overwritten by APM) */ 1025 0xfffff, /* length */ 1026 SDT_MEMERA, /* segment type */ 1027 0, /* segment descriptor priority level */ 1028 1, /* segment descriptor present */ 1029 0, 0, 1030 1, /* default 32 vs 16 bit size */ 1031 1 /* limit granularity (byte/page units)*/ }, 1032/* GAPMCODE16_SEL 9 APM BIOS 32-bit interface (16bit Code) */ 1033{ 0, /* segment base address (overwritten by APM) */ 1034 0xfffff, /* length */ 1035 SDT_MEMERA, /* segment type */ 1036 0, /* segment descriptor priority level */ 1037 1, /* segment descriptor present */ 1038 0, 0, 1039 0, /* default 32 vs 16 bit size */ 1040 1 /* limit granularity (byte/page units)*/ }, 1041/* GAPMDATA_SEL 10 APM BIOS 32-bit interface (Data) */ 1042{ 0, /* segment base address (overwritten by APM) */ 1043 0xfffff, /* length */ 1044 SDT_MEMRWA, /* segment type */ 1045 0, /* segment descriptor priority level */ 1046 1, /* segment descriptor present */ 1047 0, 0, 1048 1, /* default 32 vs 16 bit size */ 1049 1 /* limit granularity (byte/page units)*/ }, 1050}; 1051 1052struct soft_segment_descriptor ldt_segs[] = { 1053 /* Null Descriptor - overwritten by call gate */ 1054{ 0x0, /* segment base address */ 1055 0x0, /* length - all address space */ 1056 0, /* segment type */ 1057 0, /* segment descriptor priority level */ 1058 0, /* segment descriptor present */ 1059 0, 0, 1060 0, /* default 32 vs 16 bit size */ 1061 0 /* limit granularity (byte/page units)*/ }, 1062 /* Null Descriptor - overwritten by call gate */ 1063{ 0x0, /* segment base address */ 1064 0x0, /* length - all address space */ 1065 0, /* segment type */ 1066 0, /* segment descriptor priority level */ 1067 0, /* segment descriptor present */ 1068 0, 0, 1069 0, /* default 32 vs 16 bit size */ 1070 0 /* limit granularity (byte/page units)*/ }, 1071 /* Null Descriptor - overwritten by call gate */ 1072{ 0x0, /* segment base address */ 1073 0x0, /* length - all address space */ 1074 0, /* segment type */ 1075 0, /* segment descriptor priority level */ 1076 0, /* segment descriptor present */ 1077 0, 0, 1078 0, /* default 32 vs 16 bit size */ 1079 0 /* limit granularity (byte/page units)*/ }, 1080 /* Code Descriptor for user */ 1081{ 0x0, /* segment base address */ 1082 0xfffff, /* length - all address space */ 1083 SDT_MEMERA, /* segment type */ 1084 SEL_UPL, /* segment descriptor priority level */ 1085 1, /* segment descriptor present */ 1086 0, 0, 1087 1, /* default 32 vs 16 bit size */ 1088 1 /* limit granularity (byte/page units)*/ }, 1089 /* Data Descriptor for user */ 1090{ 0x0, /* segment base address */ 1091 0xfffff, /* length - all address space */ 1092 SDT_MEMRWA, /* segment type */ 1093 SEL_UPL, /* segment descriptor priority level */ 1094 1, /* segment descriptor present */ 1095 0, 0, 1096 1, /* default 32 vs 16 bit size */ 1097 1 /* limit granularity (byte/page units)*/ } }; 1098 1099void 1100setidt(idx, func, typ, dpl) 1101 int idx; 1102 void (*func)(); 1103 int typ; 1104 int dpl; 1105{ 1106 struct gate_descriptor *ip = idt + idx; 1107 1108 ip->gd_looffset = (int)func; 1109 ip->gd_selector = 8; 1110 ip->gd_stkcpy = 0; 1111 ip->gd_xx = 0; 1112 ip->gd_type = typ; 1113 ip->gd_dpl = dpl; 1114 ip->gd_p = 1; 1115 ip->gd_hioffset = ((int)func)>>16 ; 1116} 1117 1118#define IDTVEC(name) __CONCAT(X,name) 1119typedef void idtvec_t(); 1120 1121extern idtvec_t 1122 IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 1123 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm), 1124 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 1125 IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0), 1126 IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4), 1127 IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8), 1128 IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12), 1129 IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall); 1130 1131int _gsel_tss; 1132 1133/* added sdtossd() by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp> */ 1134int 1135sdtossd(sd, ssd) 1136 struct segment_descriptor *sd; 1137 struct soft_segment_descriptor *ssd; 1138{ 1139 ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase; 1140 ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit; 1141 ssd->ssd_type = sd->sd_type; 1142 ssd->ssd_dpl = sd->sd_dpl; 1143 ssd->ssd_p = sd->sd_p; 1144 ssd->ssd_def32 = sd->sd_def32; 1145 ssd->ssd_gran = sd->sd_gran; 1146 return 0; 1147} 1148 1149void 1150init386(first) 1151 int first; 1152{ 1153 extern lgdt(), lidt(), lldt(); 1154 int x; 1155 unsigned biosbasemem, biosextmem; 1156 struct gate_descriptor *gdp; 1157 extern int sigcode,szsigcode; 1158 /* table descriptors - used to load tables by microp */ 1159 struct region_descriptor r_gdt, r_idt; 1160 int pagesinbase, pagesinext; 1161 int target_page; 1162 extern struct pte *CMAP1; 1163 extern caddr_t CADDR1; 1164 1165 proc0.p_addr = proc0paddr; 1166 1167 /* 1168 * Initialize the console before we print anything out. 1169 */ 1170 1171 cninit (); 1172 1173 /* 1174 * make gdt memory segments, the code segment goes up to end of the 1175 * page with etext in it, the data segment goes to the end of 1176 * the address space 1177 */ 1178 gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1 /* i386_btop(i386_round_page(&etext)) - 1 */; 1179 gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1; 1180 for (x=0; x < NGDT; x++) ssdtosd(gdt_segs+x, gdt+x); 1181 1182 /* make ldt memory segments */ 1183 /* 1184 * The data segment limit must not cover the user area because we 1185 * don't want the user area to be writable in copyout() etc. (page 1186 * level protection is lost in kernel mode on 386's). Also, we 1187 * don't want the user area to be writable directly (page level 1188 * protection of the user area is not available on 486's with 1189 * CR0_WP set, because there is no user-read/kernel-write mode). 1190 * 1191 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. And it 1192 * should be spelled ...MAX_USER... 1193 */ 1194#define VM_END_USER_RW_ADDRESS VM_MAXUSER_ADDRESS 1195 /* 1196 * The code segment limit has to cover the user area until we move 1197 * the signal trampoline out of the user area. This is safe because 1198 * the code segment cannot be written to directly. 1199 */ 1200#define VM_END_USER_R_ADDRESS (VM_END_USER_RW_ADDRESS + UPAGES * NBPG) 1201 ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1; 1202 ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1; 1203 /* Note. eventually want private ldts per process */ 1204 for (x=0; x < 5; x++) ssdtosd(ldt_segs+x, ldt+x); 1205 1206 /* exceptions */ 1207 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL); 1208 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL); 1209 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL); 1210 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL); 1211 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL); 1212 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL); 1213 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL); 1214 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL); 1215 setidt(8, &IDTVEC(dble), SDT_SYS386TGT, SEL_KPL); 1216 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL); 1217 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL); 1218 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL); 1219 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL); 1220 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL); 1221 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL); 1222 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL); 1223 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL); 1224 setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL); 1225 setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL); 1226 setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL); 1227 setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL); 1228 setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL); 1229 setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL); 1230 setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL); 1231 setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL); 1232 setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL); 1233 setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL); 1234 setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL); 1235 setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL); 1236 setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL); 1237 setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL); 1238 setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL); 1239 1240#include "isa.h" 1241#if NISA >0 1242 isa_defaultirq(); 1243#endif 1244 1245 r_gdt.rd_limit = sizeof(gdt) - 1; 1246 r_gdt.rd_base = (int) gdt; 1247 lgdt(&r_gdt); 1248 1249 r_idt.rd_limit = sizeof(idt) - 1; 1250 r_idt.rd_base = (int) idt; 1251 lidt(&r_idt); 1252 1253 _default_ldt = GSEL(GLDT_SEL, SEL_KPL); 1254 lldt(_default_ldt); 1255 currentldt = _default_ldt; 1256 1257#ifdef DDB 1258 kdb_init(); 1259 if (boothowto & RB_KDB) 1260 Debugger("Boot flags requested debugger"); 1261#endif 1262 1263 /* Use BIOS values stored in RTC CMOS RAM, since probing 1264 * breaks certain 386 AT relics. 1265 */ 1266 biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 1267 biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); 1268 1269 /* 1270 * If BIOS tells us that it has more than 640k in the basemem, 1271 * don't believe it - set it to 640k. 1272 */ 1273 if (biosbasemem > 640) 1274 biosbasemem = 640; 1275 1276 /* 1277 * Some 386 machines might give us a bogus number for extended 1278 * mem. If this happens, stop now. 1279 */ 1280#ifndef LARGEMEM 1281 if (biosextmem > 65536) { 1282 panic("extended memory beyond limit of 64MB"); 1283 /* NOTREACHED */ 1284 } 1285#endif 1286 1287 pagesinbase = biosbasemem * 1024 / NBPG; 1288 pagesinext = biosextmem * 1024 / NBPG; 1289 1290 /* 1291 * Special hack for chipsets that still remap the 384k hole when 1292 * there's 16MB of memory - this really confuses people that 1293 * are trying to use bus mastering ISA controllers with the 1294 * "16MB limit"; they only have 16MB, but the remapping puts 1295 * them beyond the limit. 1296 * XXX - this should be removed when bounce buffers are 1297 * implemented. 1298 */ 1299 /* 1300 * If extended memory is between 15-16MB (16-17MB phys address range), 1301 * chop it to 15MB. 1302 */ 1303 if ((pagesinext > 3840) && (pagesinext < 4096)) 1304 pagesinext = 3840; 1305 1306 /* 1307 * Maxmem isn't the "maximum memory", it's the highest page of 1308 * of the physical address space. It should be "Maxphyspage". 1309 */ 1310 Maxmem = pagesinext + 0x100000/PAGE_SIZE; 1311 1312#ifdef MAXMEM 1313 if (MAXMEM/4 < Maxmem) 1314 Maxmem = MAXMEM/4; 1315#endif 1316 /* 1317 * Calculate number of physical pages, but account for Maxmem 1318 * adjustment above. 1319 */ 1320 physmem = pagesinbase + Maxmem - 0x100000/PAGE_SIZE; 1321 1322 /* call pmap initialization to make new kernel address space */ 1323 pmap_bootstrap (first, 0); 1324 1325 /* 1326 * Do simple memory test over range of extended memory that BIOS 1327 * indicates exists. Adjust Maxmem to the highest page of 1328 * good memory. 1329 */ 1330 printf("Testing memory (%dMB)...", ptoa(Maxmem)/1024/1024); 1331 1332 for (target_page = Maxmem - 1; target_page >= atop(first); target_page--) { 1333 1334 /* 1335 * map page into kernel: valid, read/write, non-cacheable 1336 */ 1337 *(int *)CMAP1 = PG_V | PG_KW | PG_N | ptoa(target_page); 1338 pmap_update(); 1339 1340 /* 1341 * Test for alternating 1's and 0's 1342 */ 1343 filli(0xaaaaaaaa, CADDR1, PAGE_SIZE/sizeof(int)); 1344 if (test_page((int *)CADDR1, 0xaaaaaaaa)) { 1345 Maxmem = target_page; 1346 badpages++; 1347 continue; 1348 } 1349 /* 1350 * Test for alternating 0's and 1's 1351 */ 1352 filli(0x55555555, CADDR1, PAGE_SIZE/sizeof(int)); 1353 if (test_page((int *)CADDR1, 0x55555555)) { 1354 Maxmem = target_page; 1355 badpages++; 1356 continue; 1357 } 1358 /* 1359 * Test for all 1's 1360 */ 1361 filli(0xffffffff, CADDR1, PAGE_SIZE/sizeof(int)); 1362 if (test_page((int *)CADDR1, 0xffffffff)) { 1363 Maxmem = target_page; 1364 badpages++; 1365 continue; 1366 } 1367 /* 1368 * Test zeroing of page 1369 */ 1370 bzero(CADDR1, PAGE_SIZE); 1371 if (test_page((int *)CADDR1, 0)) { 1372 /* 1373 * test of page failed 1374 */ 1375 Maxmem = target_page; 1376 badpages++; 1377 continue; 1378 } 1379 } 1380 printf("done.\n"); 1381 1382 *(int *)CMAP1 = 0; 1383 pmap_update(); 1384 1385 avail_end = (Maxmem << PAGE_SHIFT) 1386 - i386_round_page(sizeof(struct msgbuf)); 1387 1388 /* 1389 * Initialize pointers to the two chunks of memory; for use 1390 * later in vm_page_startup. 1391 */ 1392 /* avail_start is initialized in pmap_bootstrap */ 1393 x = 0; 1394 if (pagesinbase > 1) { 1395 phys_avail[x++] = NBPG; /* skip first page of memory */ 1396 phys_avail[x++] = pagesinbase * NBPG; /* memory up to the ISA hole */ 1397 } 1398 phys_avail[x++] = avail_start; /* memory up to the end */ 1399 phys_avail[x++] = avail_end; 1400 phys_avail[x++] = 0; /* no more chunks */ 1401 phys_avail[x++] = 0; 1402 1403 /* now running on new page tables, configured,and u/iom is accessible */ 1404 1405 /* make a initial tss so microp can get interrupt stack on syscall! */ 1406 proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; 1407 proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 1408 _gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); 1409 1410 ((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt = 1411 (sizeof(tss))<<16; 1412 1413 ltr(_gsel_tss); 1414 1415 /* make a call gate to reenter kernel with */ 1416 gdp = &ldt[LSYS5CALLS_SEL].gd; 1417 1418 x = (int) &IDTVEC(syscall); 1419 gdp->gd_looffset = x++; 1420 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 1421 gdp->gd_stkcpy = 1; 1422 gdp->gd_type = SDT_SYS386CGT; 1423 gdp->gd_dpl = SEL_UPL; 1424 gdp->gd_p = 1; 1425 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 1426 1427 /* transfer to user mode */ 1428 1429 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 1430 _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 1431 1432 /* setup proc 0's pcb */ 1433 bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); 1434 proc0.p_addr->u_pcb.pcb_flags = 0; 1435 proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; 1436} 1437 1438int 1439test_page(address, pattern) 1440 int *address; 1441 int pattern; 1442{ 1443 int *x; 1444 1445 for (x = address; x < (int *)((char *)address + PAGE_SIZE); x++) { 1446 if (*x != pattern) 1447 return (1); 1448 } 1449 return(0); 1450} 1451 1452/* 1453 * The registers are in the frame; the frame is in the user area of 1454 * the process in question; when the process is active, the registers 1455 * are in "the kernel stack"; when it's not, they're still there, but 1456 * things get flipped around. So, since p->p_md.md_regs is the whole address 1457 * of the register set, take its offset from the kernel stack, and 1458 * index into the user block. Don't you just *love* virtual memory? 1459 * (I'm starting to think seymour is right...) 1460 */ 1461 1462int 1463ptrace_set_pc (struct proc *p, unsigned int addr) { 1464 void *regs = (char*)p->p_addr + 1465 ((char*) p->p_md.md_regs - (char*) kstack); 1466 1467 ((struct trapframe *)regs)->tf_eip = addr; 1468 return 0; 1469} 1470 1471int 1472ptrace_single_step (struct proc *p) { 1473 void *regs = (char*)p->p_addr + 1474 ((char*) p->p_md.md_regs - (char*) kstack); 1475 1476 ((struct trapframe *)regs)->tf_eflags |= PSL_T; 1477 return 0; 1478} 1479 1480/* 1481 * Copy the registers to user-space. 1482 */ 1483 1484int 1485ptrace_getregs (struct proc *p, unsigned int *addr) { 1486 int error; 1487 struct reg regs = {0}; 1488 1489 error = fill_regs (p, ®s); 1490 if (error) 1491 return error; 1492 1493 return copyout (®s, addr, sizeof (regs)); 1494} 1495 1496int 1497ptrace_setregs (struct proc *p, unsigned int *addr) { 1498 int error; 1499 struct reg regs = {0}; 1500 1501 error = copyin (addr, ®s, sizeof(regs)); 1502 if (error) 1503 return error; 1504 1505 return set_regs (p, ®s); 1506} 1507 1508int 1509fill_regs(struct proc *p, struct reg *regs) { 1510 struct trapframe *tp; 1511 void *ptr = (char*)p->p_addr + 1512 ((char*) p->p_md.md_regs - (char*) kstack); 1513 1514 tp = ptr; 1515 regs->r_es = tp->tf_es; 1516 regs->r_ds = tp->tf_ds; 1517 regs->r_edi = tp->tf_edi; 1518 regs->r_esi = tp->tf_esi; 1519 regs->r_ebp = tp->tf_ebp; 1520 regs->r_ebx = tp->tf_ebx; 1521 regs->r_edx = tp->tf_edx; 1522 regs->r_ecx = tp->tf_ecx; 1523 regs->r_eax = tp->tf_eax; 1524 regs->r_eip = tp->tf_eip; 1525 regs->r_cs = tp->tf_cs; 1526 regs->r_eflags = tp->tf_eflags; 1527 regs->r_esp = tp->tf_esp; 1528 regs->r_ss = tp->tf_ss; 1529 return 0; 1530} 1531 1532int 1533set_regs (struct proc *p, struct reg *regs) { 1534 struct trapframe *tp; 1535 void *ptr = (char*)p->p_addr + 1536 ((char*) p->p_md.md_regs - (char*) kstack); 1537 1538 tp = ptr; 1539 tp->tf_es = regs->r_es; 1540 tp->tf_ds = regs->r_ds; 1541 tp->tf_edi = regs->r_edi; 1542 tp->tf_esi = regs->r_esi; 1543 tp->tf_ebp = regs->r_ebp; 1544 tp->tf_ebx = regs->r_ebx; 1545 tp->tf_edx = regs->r_edx; 1546 tp->tf_ecx = regs->r_ecx; 1547 tp->tf_eax = regs->r_eax; 1548 tp->tf_eip = regs->r_eip; 1549 tp->tf_cs = regs->r_cs; 1550 tp->tf_eflags = regs->r_eflags; 1551 tp->tf_esp = regs->r_esp; 1552 tp->tf_ss = regs->r_ss; 1553 return 0; 1554} 1555 1556#ifndef DDB 1557void 1558Debugger(const char *msg) 1559{ 1560 printf("Debugger(\"%s\") called.\n", msg); 1561} 1562#endif /* no DDB */ 1563 1564#include <sys/disklabel.h> 1565#define b_cylin b_resid 1566#define dkpart(dev) (minor(dev) & 7) 1567/* 1568 * Determine the size of the transfer, and make sure it is 1569 * within the boundaries of the partition. Adjust transfer 1570 * if needed, and signal errors or early completion. 1571 */ 1572int 1573bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel) 1574{ 1575 struct partition *p = lp->d_partitions + dkpart(bp->b_dev); 1576 int labelsect = lp->d_partitions[0].p_offset; 1577 int maxsz = p->p_size, 1578 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 1579 1580 /* overwriting disk label ? */ 1581 /* XXX should also protect bootstrap in first 8K */ 1582 if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && 1583#if LABELSECTOR != 0 1584 bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && 1585#endif 1586 (bp->b_flags & B_READ) == 0 && wlabel == 0) { 1587 bp->b_error = EROFS; 1588 goto bad; 1589 } 1590 1591#if defined(DOSBBSECTOR) && defined(notyet) 1592 /* overwriting master boot record? */ 1593 if (bp->b_blkno + p->p_offset <= DOSBBSECTOR && 1594 (bp->b_flags & B_READ) == 0 && wlabel == 0) { 1595 bp->b_error = EROFS; 1596 goto bad; 1597 } 1598#endif 1599 1600 /* beyond partition? */ 1601 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 1602 /* if exactly at end of disk, return an EOF */ 1603 if (bp->b_blkno == maxsz) { 1604 bp->b_resid = bp->b_bcount; 1605 return(0); 1606 } 1607 /* or truncate if part of it fits */ 1608 sz = maxsz - bp->b_blkno; 1609 if (sz <= 0) { 1610 bp->b_error = EINVAL; 1611 goto bad; 1612 } 1613 bp->b_bcount = sz << DEV_BSHIFT; 1614 } 1615 1616 /* calculate cylinder for disksort to order transfers with */ 1617 bp->b_pblkno = bp->b_blkno + p->p_offset; 1618 bp->b_cylin = bp->b_pblkno / lp->d_secpercyl; 1619 return(1); 1620 1621bad: 1622 bp->b_flags |= B_ERROR; 1623 return(-1); 1624} 1625 1626int 1627disk_externalize(int drive, void *userp, size_t *maxlen) 1628{ 1629 if(*maxlen < sizeof drive) { 1630 return ENOMEM; 1631 } 1632 1633 *maxlen -= sizeof drive; 1634 return copyout(&drive, userp, sizeof drive); 1635} 1636 1637