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