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