Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/vax Rewrite cpu_fork(), it now looks like and works...



details:   https://anonhg.NetBSD.org/src/rev/3853c5dd4687
branches:  trunk
changeset: 486700:3853c5dd4687
user:      ragge <ragge%NetBSD.org@localhost>
date:      Sat May 27 16:33:04 2000 +0000

description:
Rewrite cpu_fork(), it now looks like and works as other ports' cpu_fork()
(calling child_return() etc...). Have fun, Jason!

diffstat:

 sys/arch/vax/include/cpu.h    |    4 +-
 sys/arch/vax/vax/trap.c       |   16 ++++-
 sys/arch/vax/vax/vm_machdep.c |  130 ++++++++++++++++++++---------------------
 3 files changed, 79 insertions(+), 71 deletions(-)

diffs (239 lines):

diff -r a091d81a96a6 -r 3853c5dd4687 sys/arch/vax/include/cpu.h
--- a/sys/arch/vax/include/cpu.h        Sat May 27 16:32:08 2000 +0000
+++ b/sys/arch/vax/include/cpu.h        Sat May 27 16:33:04 2000 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: cpu.h,v 1.46 2000/05/27 03:23:22 matt Exp $      */
+/*      $NetBSD: cpu.h,v 1.47 2000/05/27 16:33:04 ragge Exp $      */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden
@@ -136,7 +136,6 @@
 
 extern struct device *booted_from;
 extern int mastercpu;
-extern int bootdev;
 
 #define        setsoftnet()    mtpr(12,PR_SIRR)
 #define setsoftclock() mtpr(8,PR_SIRR)
@@ -179,6 +178,7 @@
 void   ioaccess __P((vaddr_t, paddr_t, int));
 void   iounaccess __P((vaddr_t, int));
 void   findcpu(void);
+void   child_return(void *);
 #ifdef DDB
 int    kdbrint __P((int));
 #endif
diff -r a091d81a96a6 -r 3853c5dd4687 sys/arch/vax/vax/trap.c
--- a/sys/arch/vax/vax/trap.c   Sat May 27 16:32:08 2000 +0000
+++ b/sys/arch/vax/vax/trap.c   Sat May 27 16:33:04 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: trap.c,v 1.52 2000/05/27 00:40:43 sommerfeld Exp $     */
+/*     $NetBSD: trap.c,v 1.53 2000/05/27 16:33:04 ragge Exp $     */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -421,3 +421,17 @@
                ktrsysret(p, frame->code, err, rval[0]);
 #endif
 }
+
+void
+child_return(void *arg)
+{
+        struct proc *p = arg;
+
+       userret(p, p->p_addr->u_pcb.framep, 0);
+
+#ifdef KTRACE
+       if (KTRPOINT(p, KTR_SYSRET))
+               ktrsysret(p, SYS_fork, 0, 0);
+#endif
+}
+
diff -r a091d81a96a6 -r 3853c5dd4687 sys/arch/vax/vax/vm_machdep.c
--- a/sys/arch/vax/vax/vm_machdep.c     Sat May 27 16:32:08 2000 +0000
+++ b/sys/arch/vax/vax/vm_machdep.c     Sat May 27 16:33:04 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vm_machdep.c,v 1.60 2000/05/26 21:20:27 thorpej Exp $       */
+/*     $NetBSD: vm_machdep.c,v 1.61 2000/05/27 16:33:04 ragge Exp $         */
 
 /*
  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@@ -69,9 +69,7 @@
  * block moved of size size. Using fast insn bcopy for pte move.
  */
 void
-pagemove(from, to, size)
-       caddr_t from, to;
-       size_t size;
+pagemove(caddr_t from, caddr_t to, size_t size)
 {
        pt_entry_t *fpte, *tpte;
        int     stor;
@@ -102,24 +100,18 @@
  * in both the stack and stacksize args), set up the user stack pointer
  * accordingly.
  *
- * cpu_fork() copies parent process trapframe directly into child PCB
- * so that when we swtch() to the child process it will go directly
- * back to user mode without any need to jump back through kernel.
- * We also take away mapping for the second page after pcb, so that
- * we get something like a "red zone".
- * No need for either double-map kernel stack or relocate it when
- * forking.
+ * cpu_fork() copies parent process trapframe and creates a fake CALLS
+ * frame on top of it, so that it can safely call child_return().
+ * We also take away mapping for the fourth page after pcb, so that
+ * we get something like a "red zone" for the kernel stack.
  */
 void
-cpu_fork(p1, p2, stack, stacksize)
-       struct proc *p1, *p2;
-       void *stack;
-       size_t stacksize;
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize)
 {
-       struct pte *pt;
-       struct pcb *nyproc;
+       struct pcb *pcb;
        struct trapframe *tf;
-       struct pmap *pmap, *opmap;
+       struct callsframe *cf;
+       extern int sret; /* Return address in trap routine */
 
 #ifdef DIAGNOSTIC
        /*
@@ -129,28 +121,46 @@
                panic("cpu_fork: curproc");
 #endif
 
-       nyproc = &p2->p_addr->u_pcb;
-       tf = p1->p_addr->u_pcb.framep;
-       opmap = p1->p_vmspace->vm_map.pmap;
-       pmap = p2->p_vmspace->vm_map.pmap;
-
-       /* Mark page invalid */
-       pt = kvtopte((u_int)p2->p_addr + REDZONEADDR);
-       pt->pg_v = 0; 
+       /*
+        * Copy the trap frame.
+        */
+       tf = (struct trapframe *)((u_int)p2->p_addr + USPACE) - 1;
+       p2->p_addr->u_pcb.framep = tf;
+       bcopy(p1->p_addr->u_pcb.framep, tf, sizeof(*tf));
 
        /*
         * Activate address space for the new process.  The PTEs have
         * already been allocated by way of pmap_create().
+        * This writes the page table registers to the PCB.
         */
        pmap_activate(p2);
 
-       /* Set up internal defs in PCB. */
-       nyproc->iftrap = NULL;
-       nyproc->KSP = (u_int)p2->p_addr + USPACE;
+       /* Mark guard page invalid in kernel stack */
+       kvtopte((u_int)p2->p_addr + REDZONEADDR)->pg_v = 0;
 
-       /* General registers as taken from userspace */
-       /* trapframe should be synced with pcb */
-       bcopy(&tf->r2,&nyproc->R[2],10*sizeof(int));
+       /*
+        * Set up the calls frame above (below) the trapframe
+        * and populate it with something good.
+        * This is so that we can simulate that we were called by a
+        * CALLS insn in the function given as argument.
+        */
+       cf = (struct callsframe *)tf - 1;
+       cf->ca_cond = 0;
+       cf->ca_maskpsw = 0x20000000;
+       cf->ca_pc = (unsigned)&sret;
+       cf->ca_argno = 1;
+       cf->ca_arg1 = (int)p2;
+
+       /*
+        * Set up internal defs in PCB. This matches the "fake" CALLS frame
+        * that were constructed earlier.
+        */
+       pcb = &p2->p_addr->u_pcb;
+       pcb->iftrap = NULL;
+       pcb->KSP = (long)cf;
+       pcb->FP = (long)cf;
+       pcb->AP = (long)&cf->ca_argno;
+       pcb->PC = (int)child_return + 2; /* Skip save mask */
 
        /*
         * If specified, give the child a different stack.
@@ -158,52 +168,36 @@
        if (stack != NULL)
                tf->sp = (u_long)stack + stacksize;
 
-       nyproc->AP = tf->ap;
-       nyproc->FP = tf->fp;
-       nyproc->USP = tf->sp;
-       nyproc->PC = tf->pc;
-       nyproc->PSL = tf->psl & ~PSL_C;
-       nyproc->R[0] = p1->p_pid; /* parent pid. (shouldn't be needed) */
-       nyproc->R[1] = 1;
+       /*
+        * Set the last return information after fork().
+        * This is only interesting if the child will return to userspace,
+        * but doesn't hurt otherwise.
+        */
+       tf->r0 = p1->p_pid; /* parent pid. (shouldn't be needed) */
+       tf->r1 = 1;
+       tf->psl = PSL_U|PSL_PREVU;
 
        return; /* Child is ready. Parent, return! */
 }
 
 /*
- * cpu_set_kpc() sets up pcb for the new kernel process so that it will
- * start at the procedure pointed to by pc next time swtch() is called.
- * When that procedure returns, it will pop off everything from the
- * faked calls frame on the kernel stack, do an REI and go down to
- * user mode.
+ * cpu_set_kpc() is called after cpu_fork() if another function is to
+ * be called instead of child_return(). (i.e. not a normal fork).
+ * Only the function and its argument needs to be changed.
  */
 void
-cpu_set_kpc(p, pc, arg)
-       struct proc *p;
-       void (*pc) __P((void *));
-       void *arg;
+cpu_set_kpc(struct proc *p, void (*pc)(void *), void *arg)
 {
-       struct pcb *nyproc;
-       struct {
-               struct  callsframe cf;
-               struct  trapframe tf;
-       } *kc;
-       extern int sret, boothowto;
+       struct pcb *pcb;
+       struct trapframe *tf;
+       struct callsframe *cf;
 
-       nyproc = &p->p_addr->u_pcb;
-       (unsigned)kc = nyproc->FP = nyproc->KSP =
-           (unsigned)p->p_addr + USPACE - sizeof(*kc);
-       kc->cf.ca_cond = 0;
-       kc->cf.ca_maskpsw = 0x20000000;
-       kc->cf.ca_pc = (unsigned)&sret;
-       kc->cf.ca_argno = 1;
-       kc->cf.ca_arg1 = (unsigned)arg;
-       kc->tf.r11 = boothowto; /* If we have old init */
-       kc->tf.psl = 0x3c00000;
+       pcb = &p->p_addr->u_pcb;
+       pcb->PC = (long)pc + 2;
 
-       nyproc->framep = (void *)&kc->tf;
-       nyproc->AP = (unsigned)&kc->cf.ca_argno;
-       nyproc->FP = nyproc->KSP = (unsigned)kc;
-       nyproc->PC = (unsigned)pc + 2;
+       tf = pcb->framep;
+       cf = (struct callsframe *)tf - 1;
+       cf->ca_arg1 = (long)arg;
 }
 
 int



Home | Main Index | Thread Index | Old Index