diff options
author | peter <peter@FreeBSD.org> | 1997-05-07 20:19:18 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1997-05-07 20:19:18 +0000 |
commit | 27b2936ad3bbcfef8e9dbe7ce4ee35b3fca07436 (patch) | |
tree | 4b4b12317a3b5a392dd36a7a5bd1dcb08ea64e05 /sys | |
parent | 2a925f680350c68481e736fc208bbe2dfc61d836 (diff) | |
download | FreeBSD-src-27b2936ad3bbcfef8e9dbe7ce4ee35b3fca07436.zip FreeBSD-src-27b2936ad3bbcfef8e9dbe7ce4ee35b3fca07436.tar.gz |
clean up forked child creation. This is simplified also by having
md_regs being struct trapframe *. Do a npxsave() if needed and copy the
pcb rather than use the increasingly defunct savectx(). Copy %edi and
%ebp explicitly.
Submitted by: bde
XXX npxproc could be declared in npx.h so the externs with smp fruit
are not needed.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/vm_machdep.c | 53 | ||||
-rw-r--r-- | sys/i386/i386/vm_machdep.c | 53 |
2 files changed, 72 insertions, 34 deletions
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index 37fa090..6f1a4b6 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -38,7 +38,7 @@ * * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $Id: vm_machdep.c,v 1.78 1997/04/07 07:15:56 peter Exp $ + * $Id: vm_machdep.c,v 1.79 1997/04/16 12:11:37 kato Exp $ */ #include "npx.h" @@ -53,9 +53,13 @@ #include <sys/vmmeter.h> #include <machine/clock.h> -#include <machine/md_var.h> #include <machine/cpu.h> #include <machine/reg.h> +#include <machine/md_var.h> +#include <machine/npx.h> +#ifdef SMP +#include <machine/smp.h> +#endif #include <vm/vm.h> #include <vm/vm_param.h> @@ -74,6 +78,13 @@ #include <i386/isa/isa.h> #endif +#ifdef SMP +extern struct proc *SMPnpxproc[]; +#define npxproc (SMPnpxproc[cpunumber()]) +#else +extern struct proc *npxproc; +#endif + #ifdef BOUNCE_BUFFERS static vm_offset_t vm_bounce_kva __P((int size, int waitok)); @@ -569,32 +580,40 @@ cpu_fork(p1, p2) { struct pcb *pcb2 = &p2->p_addr->u_pcb; - /* - * copy current pcb, and save current context into it while it's - * possibly in some writeback cache line. - */ - bcopy(&p1->p_addr->u_pcb, pcb2, sizeof(struct pcb)); - pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir); - savectx(pcb2); /* irrelevant? fp registers? */ + /* Ensure that p1's pcb is up to date. */ + if (npxproc == p1) + npxsave(&p1->p_addr->u_pcb.pcb_savefpu); + + /* Copy p1's pcb. */ + p2->p_addr->u_pcb = p1->p_addr->u_pcb; /* * Create a new fresh stack for the new process. - * Copy the trap frame for the return to user mode as if from a syscall. - * This copies the user mode register values. + * Copy the trap frame for the return to user mode as if from a + * syscall. This copies the user mode register values. */ - p2->p_md.md_regs = (int *)(((struct trapframe *) - ((int)p2->p_addr + (UPAGES * PAGE_SIZE))) - 1); - bcopy(p1->p_md.md_regs, p2->p_md.md_regs, sizeof(struct trapframe)); + p2->p_md.md_regs = (struct trapframe *) + ((int)p2->p_addr + UPAGES * PAGE_SIZE) - 1; + *p2->p_md.md_regs = *p1->p_md.md_regs; /* * Set registers for trampoline to user mode. Leave space for the * return address on stack. These are the kernel mode register values. */ - /* XXX these overwrite most of the regs from savectx() above! */ - pcb2->pcb_eip = (int)fork_trampoline; + pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir); + pcb2->pcb_edi = p2->p_md.md_regs->tf_edi; pcb2->pcb_esi = (int)fork_return; - pcb2->pcb_ebx = (int)p2; + pcb2->pcb_ebp = p2->p_md.md_regs->tf_ebp; pcb2->pcb_esp = (int)p2->p_md.md_regs - sizeof(void *); + pcb2->pcb_ebx = (int)p2; + pcb2->pcb_eip = (int)fork_trampoline; + /* + * pcb2->pcb_ldt: duplicated below, if necessary. + * pcb2->pcb_ldt_len: cloned above. + * pcb2->pcb_savefpu: cloned above. + * pcb2->pcb_flags: cloned above (always 0 here?). + * pcb2->pcb_onfault: cloned above (always NULL here?). + */ #ifdef USER_LDT /* Copy the LDT, if necessary. */ diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index 37fa090..6f1a4b6 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -38,7 +38,7 @@ * * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ - * $Id: vm_machdep.c,v 1.78 1997/04/07 07:15:56 peter Exp $ + * $Id: vm_machdep.c,v 1.79 1997/04/16 12:11:37 kato Exp $ */ #include "npx.h" @@ -53,9 +53,13 @@ #include <sys/vmmeter.h> #include <machine/clock.h> -#include <machine/md_var.h> #include <machine/cpu.h> #include <machine/reg.h> +#include <machine/md_var.h> +#include <machine/npx.h> +#ifdef SMP +#include <machine/smp.h> +#endif #include <vm/vm.h> #include <vm/vm_param.h> @@ -74,6 +78,13 @@ #include <i386/isa/isa.h> #endif +#ifdef SMP +extern struct proc *SMPnpxproc[]; +#define npxproc (SMPnpxproc[cpunumber()]) +#else +extern struct proc *npxproc; +#endif + #ifdef BOUNCE_BUFFERS static vm_offset_t vm_bounce_kva __P((int size, int waitok)); @@ -569,32 +580,40 @@ cpu_fork(p1, p2) { struct pcb *pcb2 = &p2->p_addr->u_pcb; - /* - * copy current pcb, and save current context into it while it's - * possibly in some writeback cache line. - */ - bcopy(&p1->p_addr->u_pcb, pcb2, sizeof(struct pcb)); - pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir); - savectx(pcb2); /* irrelevant? fp registers? */ + /* Ensure that p1's pcb is up to date. */ + if (npxproc == p1) + npxsave(&p1->p_addr->u_pcb.pcb_savefpu); + + /* Copy p1's pcb. */ + p2->p_addr->u_pcb = p1->p_addr->u_pcb; /* * Create a new fresh stack for the new process. - * Copy the trap frame for the return to user mode as if from a syscall. - * This copies the user mode register values. + * Copy the trap frame for the return to user mode as if from a + * syscall. This copies the user mode register values. */ - p2->p_md.md_regs = (int *)(((struct trapframe *) - ((int)p2->p_addr + (UPAGES * PAGE_SIZE))) - 1); - bcopy(p1->p_md.md_regs, p2->p_md.md_regs, sizeof(struct trapframe)); + p2->p_md.md_regs = (struct trapframe *) + ((int)p2->p_addr + UPAGES * PAGE_SIZE) - 1; + *p2->p_md.md_regs = *p1->p_md.md_regs; /* * Set registers for trampoline to user mode. Leave space for the * return address on stack. These are the kernel mode register values. */ - /* XXX these overwrite most of the regs from savectx() above! */ - pcb2->pcb_eip = (int)fork_trampoline; + pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir); + pcb2->pcb_edi = p2->p_md.md_regs->tf_edi; pcb2->pcb_esi = (int)fork_return; - pcb2->pcb_ebx = (int)p2; + pcb2->pcb_ebp = p2->p_md.md_regs->tf_ebp; pcb2->pcb_esp = (int)p2->p_md.md_regs - sizeof(void *); + pcb2->pcb_ebx = (int)p2; + pcb2->pcb_eip = (int)fork_trampoline; + /* + * pcb2->pcb_ldt: duplicated below, if necessary. + * pcb2->pcb_ldt_len: cloned above. + * pcb2->pcb_savefpu: cloned above. + * pcb2->pcb_flags: cloned above (always 0 here?). + * pcb2->pcb_onfault: cloned above (always NULL here?). + */ #ifdef USER_LDT /* Copy the LDT, if necessary. */ |