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