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