Deleted Added
full compact
vm_machdep.c (24361) vm_machdep.c (24691)
1/*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * Copyright (c) 1989, 1990 William Jolitz
4 * Copyright (c) 1994 John Dyson
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer

--- 24 unchanged lines hidden (view full) ---

33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
40 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
1/*-
2 * Copyright (c) 1982, 1986 The Regents of the University of California.
3 * Copyright (c) 1989, 1990 William Jolitz
4 * Copyright (c) 1994 John Dyson
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer

--- 24 unchanged lines hidden (view full) ---

33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
40 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
41 * $Id: vm_machdep.c,v 1.76 1997/03/22 04:28:16 dyson Exp $
41 * $Id: vm_machdep.c,v 1.77 1997/03/29 04:35:26 bde Exp $
42 */
43
44#include "npx.h"
45#include "opt_bounce.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/proc.h>
50#include <sys/malloc.h>
51#include <sys/buf.h>
52#include <sys/vnode.h>
53#include <sys/vmmeter.h>
54
55#include <machine/clock.h>
56#include <machine/md_var.h>
42 */
43
44#include "npx.h"
45#include "opt_bounce.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/proc.h>
50#include <sys/malloc.h>
51#include <sys/buf.h>
52#include <sys/vnode.h>
53#include <sys/vmmeter.h>
54
55#include <machine/clock.h>
56#include <machine/md_var.h>
57#include <machine/cpu.h>
58#include <machine/reg.h>
57
58#include <vm/vm.h>
59#include <vm/vm_param.h>
60#include <vm/vm_prot.h>
61#include <sys/lock.h>
62#include <vm/vm_kern.h>
63#include <vm/vm_page.h>
64#include <vm/vm_map.h>

--- 488 unchanged lines hidden (view full) ---

553 if (prot & VM_PROT_WRITE)
554 subyte(v, fubyte(v));
555 else
556 fubyte(v);
557}
558
559/*
560 * Finish a fork operation, with process p2 nearly set up.
59
60#include <vm/vm.h>
61#include <vm/vm_param.h>
62#include <vm/vm_prot.h>
63#include <sys/lock.h>
64#include <vm/vm_kern.h>
65#include <vm/vm_page.h>
66#include <vm/vm_map.h>

--- 488 unchanged lines hidden (view full) ---

555 if (prot & VM_PROT_WRITE)
556 subyte(v, fubyte(v));
557 else
558 fubyte(v);
559}
560
561/*
562 * Finish a fork operation, with process p2 nearly set up.
561 * Copy and update the kernel stack and pcb, making the child
562 * ready to run, and marking it so that it can return differently
563 * than the parent. Returns 1 in the child process, 0 in the parent.
564 * We currently double-map the user area so that the stack is at the same
565 * address in each process; in the future we will probably relocate
566 * the frame pointers on the stack after copying.
563 * Copy and update the pcb, set up the stack so that the child
564 * ready to run and return to user mode.
567 */
565 */
568int
566void
569cpu_fork(p1, p2)
570 register struct proc *p1, *p2;
571{
572 struct pcb *pcb2 = &p2->p_addr->u_pcb;
567cpu_fork(p1, p2)
568 register struct proc *p1, *p2;
569{
570 struct pcb *pcb2 = &p2->p_addr->u_pcb;
573 int sp, offset;
574 volatile int retval;
575#ifdef USER_LDT
576 struct pcb *pcb = &p2->p_addr->u_pcb;
577#endif
578
579 /*
571
572 /*
580 * Copy pcb and stack from proc p1 to p2.
581 * We do this as cheaply as possible, copying only the active
582 * part of the stack. The stack and pcb need to agree;
583 * this is tricky, as the final pcb is constructed by savectx,
584 * but its frame isn't yet on the stack when the stack is copied.
585 * This should be done differently, with a single call
586 * that copies and updates the pcb+stack,
587 * replacing the bcopy and savectx.
573 * copy current pcb, and save current context into it while it's
574 * possibly in some writeback cache line.
588 */
575 */
576 bcopy(&p1->p_addr->u_pcb, pcb2, sizeof(struct pcb));
577 pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir);
578 savectx(pcb2); /* irrelevant? fp registers? */
589
579
590 __asm __volatile("movl %%esp,%0" : "=r" (sp));
591 offset = sp - (int)kstack;
580 /*
581 * Create a new fresh stack for the new process.
582 * Copy the trap frame for the return to user mode as if from a syscall.
583 * This copies the user mode register values.
584 */
585 p2->p_md.md_regs = (int *)(((struct trapframe *)
586 ((int)p2->p_addr + (UPAGES * PAGE_SIZE))) - 1);
587 bcopy(p1->p_md.md_regs, p2->p_md.md_regs, sizeof(struct trapframe));
592
588
593 retval = 1; /* return 1 in child */
594 bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset,
595 (unsigned) ctob(UPAGES) - offset);
596 p2->p_md.md_regs = p1->p_md.md_regs;
589 /*
590 * Set registers for trampoline to user mode. Leave space for the
591 * return address on stack. These are the kernel mode register values.
592 */
593 /* XXX these overwrite most of the regs from savectx() above! */
594 pcb2->pcb_eip = (int)fork_trampoline;
595 pcb2->pcb_esi = (int)fork_return;
596 pcb2->pcb_ebx = (int)p2;
597 pcb2->pcb_esp = (int)p2->p_md.md_regs - sizeof(void *);
597
598
598 *pcb2 = p1->p_addr->u_pcb;
599 pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir);
600
601#ifdef USER_LDT
602 /* Copy the LDT, if necessary. */
599#ifdef USER_LDT
600 /* Copy the LDT, if necessary. */
603 if (pcb->pcb_ldt != 0) {
601 if (pcb2->pcb_ldt != 0) {
604 union descriptor *new_ldt;
602 union descriptor *new_ldt;
605 size_t len = pcb->pcb_ldt_len * sizeof(union descriptor);
603 size_t len = pcb2->pcb_ldt_len * sizeof(union descriptor);
606
607 new_ldt = (union descriptor *)kmem_alloc(kernel_map, len);
604
605 new_ldt = (union descriptor *)kmem_alloc(kernel_map, len);
608 bcopy(pcb->pcb_ldt, new_ldt, len);
609 pcb->pcb_ldt = (caddr_t)new_ldt;
606 bcopy(pcb2->pcb_ldt, new_ldt, len);
607 pcb2->pcb_ldt = (caddr_t)new_ldt;
610 }
611#endif
612
608 }
609#endif
610
613 retval = 0; /* return 0 in parent */
614 savectx(pcb2);
615 return (retval);
611 /*
612 * Now, cpu_switch() can schedule the new process.
613 * pcb_esp is loaded pointing to the cpu_switch() stack frame
614 * containing the return address when exiting cpu_switch.
615 * This will normally be to proc_trampoline(), which will have
616 * %ebx loaded with the new proc's pointer. proc_trampoline()
617 * will set up a stack to call fork_return(p, frame); to complete
618 * the return to user-mode.
619 */
616}
617
620}
621
622/*
623 * Intercept the return address from a freshly forked process that has NOT
624 * been scheduled yet.
625 *
626 * This is needed to make kernel threads stay in kernel mode.
627 */
618void
628void
629cpu_set_fork_handler(p, func, arg)
630 struct proc *p;
631 void (*func) __P((void *));
632 void *arg;
633{
634 /*
635 * Note that the trap frame follows the args, so the function
636 * is really called like this: func(arg, frame);
637 */
638 p->p_addr->u_pcb.pcb_esi = (int) func; /* function */
639 p->p_addr->u_pcb.pcb_ebx = (int) arg; /* first arg */
640}
641
642void
619cpu_exit(p)
620 register struct proc *p;
621{
622#ifdef USER_LDT
623 struct pcb *pcb;
624#endif
625
626#if NNPX > 0

--- 271 unchanged lines hidden ---
643cpu_exit(p)
644 register struct proc *p;
645{
646#ifdef USER_LDT
647 struct pcb *pcb;
648#endif
649
650#if NNPX > 0

--- 271 unchanged lines hidden ---