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