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