Module Name: src Committed By: rmind Date: Sun Nov 29 04:11:51 UTC 2009
Modified Files: src/sys/arch/mips/mips: vm_machdep.c Log Message: cpu_lwp_fork (MIPS): replace l_addr with uvm_lwp_getuarea(), clean up a little. To generate a diff of this commit: cvs rdiff -u -r1.127 -r1.128 src/sys/arch/mips/mips/vm_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/mips/vm_machdep.c diff -u src/sys/arch/mips/mips/vm_machdep.c:1.127 src/sys/arch/mips/mips/vm_machdep.c:1.128 --- src/sys/arch/mips/mips/vm_machdep.c:1.127 Sat Nov 21 17:40:28 2009 +++ src/sys/arch/mips/mips/vm_machdep.c Sun Nov 29 04:11:51 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: vm_machdep.c,v 1.127 2009/11/21 17:40:28 rmind Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.128 2009/11/29 04:11:51 rmind Exp $ */ /* * Copyright (c) 1992, 1993 @@ -77,7 +77,7 @@ */ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.127 2009/11/21 17:40:28 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.128 2009/11/29 04:11:51 rmind Exp $"); #include "opt_ddb.h" @@ -104,22 +104,15 @@ paddr_t kvtophys(vaddr_t); /* XXX */ /* - * Finish a fork operation, with process p2 nearly set up. - * Copy and update the pcb and trap frame, making the child ready to run. + * cpu_lwp_fork: finish a new LWP (l2) operation. * - * Rig the child's kernel stack so that it will start out in - * lwp_trampoline() and call child_return() with p2 as an - * argument. This causes the newly-created child process to go - * directly to user level with an apparent return value of 0 from - * fork(), while the parent process returns normally. - * - * p1 is the process being forked; if p1 == &proc0, we are creating - * a kernel thread, and the return path and argument are specified with - * `func' and `arg'. + * First LWP (l1) is the process being forked. If it is &lwp0, then we + * are creating a kthread, where return path and argument are specified + * with `func' and `arg'. * * If an alternate user-level stack is requested (with non-zero values - * in both the stack and stacksize args), set up the user stack pointer - * accordingly. + * in both the stack and stacksize arguments), then set up the user stack + * pointer accordingly. */ void cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, @@ -127,6 +120,9 @@ { struct pcb *pcb1, *pcb2; struct frame *f; + vaddr_t uv; + + KASSERT(l1 == curlwp || l1 == &lwp0); pcb1 = lwp_getpcb(l1); pcb2 = lwp_getpcb(l2); @@ -135,28 +131,22 @@ l2->l_md.md_ss_instr = 0; l2->l_md.md_astpending = 0; -#ifdef DIAGNOSTIC - /* - * If l1 != curlwp && l1 == &lwp0, we're creating a kernel thread. - */ - if (l1 != curlwp && l1 != &lwp0) - panic("cpu_lwp_fork: curlwp"); -#endif + /* If parent LWP was using FPU, then save the FPU h/w state. */ if ((l1->l_md.md_flags & MDP_FPUSED) && l1 == fpcurlwp) savefpregs(l1); + /* Copy the PCB from parent. */ + memcpy(pcb2, pcb1, sizeof(struct pcb)); + /* - * Copy pcb from proc p1 to p2. - * Copy p1 trapframe atop on p2 stack space, so return to user mode + * Copy the trapframe from parent, so that return to userspace * will be to right address, with correct registers. */ - memcpy(pcb2, pcb1, sizeof(struct pcb)); - f = (struct frame *)((char *)l2->l_addr + USPACE) - 1; + uv = uvm_lwp_getuarea(l2); + f = (struct frame *)(uv + USPACE) - 1; memcpy(f, l1->l_md.md_regs, sizeof(struct frame)); - /* - * If specified, give the child a different stack. - */ + /* If specified, set a different user stack for a child. */ if (stack != NULL) f->f_regs[_R_SP] = (uintptr_t)stack + stacksize; @@ -164,49 +154,49 @@ l2->l_md.md_flags = l1->l_md.md_flags & MDP_FPUSED; #if USPACE > PAGE_SIZE { - size_t i; const int x = (MIPS_HAS_R4K_MMU) ? - (MIPS3_PG_G | MIPS3_PG_RO | MIPS3_PG_WIRED) : - MIPS1_PG_G; - pt_entry_t *pte = kvtopte(l2->l_addr); + (MIPS3_PG_G | MIPS3_PG_RO | MIPS3_PG_WIRED) : MIPS1_PG_G; + pt_entry_t *pte = kvtopte(uv); + size_t i; + for (i = 0; i < UPAGES; i++) l2->l_md.md_upte[i] = pte[i].pt_entry &~ x; } #endif - - pcb2->pcb_context[0] = (intptr_t)func; /* S0 */ - pcb2->pcb_context[1] = (intptr_t)arg; /* S1 */ + /* + * Rig kernel stack so that it would start out in lwp_trampoline() + * and call child_return() with l2 as an argument. This causes the + * newly-created child process to go directly to user level with a + * parent return value of 0 from fork(), while the parent process + * returns normally. + */ + pcb2->pcb_context[0] = (intptr_t)func; /* S0 */ + pcb2->pcb_context[1] = (intptr_t)arg; /* S1 */ pcb2->pcb_context[MIPS_CURLWP_CARD - 16] = (intptr_t)l2;/* S? */ - pcb2->pcb_context[8] = (intptr_t)f; /* SP */ - pcb2->pcb_context[10] = (intptr_t)lwp_trampoline;/* RA */ + pcb2->pcb_context[8] = (intptr_t)f; /* SP */ + pcb2->pcb_context[10] = (intptr_t)lwp_trampoline; /* RA */ #ifdef IPL_ICU_MASK - pcb2->pcb_ppl = 0; /* machine dependent interrupt mask */ + /* Machine depenedend interrupt mask. */ + pcb2->pcb_ppl = 0; #endif } -/* - * Set the given LWP to start at the given function via the - * lwp_trampoline. - */ void cpu_setfunc(struct lwp *l, void (*func)(void *), void *arg) { - struct pcb *pcb; - struct frame *f; + struct pcb *pcb = lwp_getpcb(l); + struct frame *f = l->l_md.md_regs; - f = (struct frame *)((char *)l->l_addr + USPACE) - 1; - KASSERT(l->l_md.md_regs == f); - - pcb = lwp_getpcb(l); pcb->pcb_context[0] = (intptr_t)func; /* S0 */ pcb->pcb_context[1] = (intptr_t)arg; /* S1 */ pcb->pcb_context[MIPS_CURLWP_CARD - 16] = (intptr_t)l; /* S? */ pcb->pcb_context[8] = (intptr_t)f; /* SP */ pcb->pcb_context[10] = (intptr_t)setfunc_trampoline; /* RA */ #ifdef IPL_ICU_MASK - pcb->pcb_ppl = 0; /* machine depenedend interrupt mask */ + /* Machine depenedend interrupt mask. */ + pcb->pcb_ppl = 0; #endif -} +} void cpu_lwp_free(struct lwp *l, int proc)