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