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