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