From 39005e16533b5bbaf36d95836bb87c3b20463a0b Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 1 Jul 2007 01:11:38 +0000 Subject: [PATCH] More multi-threaded support for virtualization. Move the save context from the process structure to the lwp structure, cleaning up the vmspace support structures at the same time. This allows multiple LWPs in the same process to be running a virtualization context at the same time. --- sys/kern/kern_exit.c | 18 ++- sys/kern/kern_sig.c | 6 +- sys/platform/pc32/i386/machdep.c | 5 +- sys/platform/pc32/i386/trap.c | 8 +- sys/platform/vkernel/i386/cpu_regs.c | 4 +- sys/platform/vkernel/i386/trap.c | 12 +- sys/sys/proc.h | 9 +- sys/sys/vkernel.h | 23 ++-- sys/vm/pmap.h | 3 +- sys/vm/vm_vmspace.c | 230 +++++++++++++++++------------------ 10 files changed, 162 insertions(+), 156 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 401214f060..8f1183cc91 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -37,7 +37,7 @@ * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 * $FreeBSD: src/sys/kern/kern_exit.c,v 1.92.2.11 2003/01/13 22:51:16 dillon Exp $ - * $DragonFly: src/sys/kern/kern_exit.c,v 1.81 2007/06/30 02:33:04 dillon Exp $ + * $DragonFly: src/sys/kern/kern_exit.c,v 1.82 2007/07/01 01:11:35 dillon Exp $ */ #include "opt_compat.h" @@ -334,9 +334,15 @@ exit1(int rv) if (vm->vm_upcalls) upc_release(vm, lp); - /* clean up data related to virtual kernel operation */ - if (p->p_vkernel) + /* + * Clean up data related to virtual kernel operation. Clean up + * any vkernel context related to the current lwp now so we can + * destroy p_vkernel. + */ + if (p->p_vkernel) { + vkernel_lwp_exit(lp); vkernel_exit(p); + } /* * Release user portion of address space. @@ -518,6 +524,12 @@ lwp_exit(int masterexit) lp->lwp_flag |= LWP_WEXIT; /* + * Clean up any virtualization + */ + if (lp->lwp_vkernel) + vkernel_lwp_exit(lp); + + /* * Nobody actually wakes us when the lock * count reaches zero, so just wait one tick. */ diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 3df5e01cb2..755b012565 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -37,7 +37,7 @@ * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 * $FreeBSD: src/sys/kern/kern_sig.c,v 1.72.2.17 2003/05/16 16:34:34 obrien Exp $ - * $DragonFly: src/sys/kern/kern_sig.c,v 1.81 2007/06/30 23:38:31 dillon Exp $ + * $DragonFly: src/sys/kern/kern_sig.c,v 1.82 2007/07/01 01:11:35 dillon Exp $ */ #include "opt_ktrace.h" @@ -834,7 +834,7 @@ trapsignal(struct lwp *lp, int sig, u_long code) * context, switch back to the virtual kernel context before * trying to post the signal. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { struct trapframe *tf = lp->lwp_md.md_regs; tf->tf_trapno = 0; vkernel_trap(lp, tf); @@ -1769,7 +1769,7 @@ postsig(int sig) * context, switch back to the virtual kernel context before * trying to post the signal. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { struct trapframe *tf = lp->lwp_md.md_regs; tf->tf_trapno = 0; vkernel_trap(lp, tf); diff --git a/sys/platform/pc32/i386/machdep.c b/sys/platform/pc32/i386/machdep.c index 82f1f5a4e0..e63e84345b 100644 --- a/sys/platform/pc32/i386/machdep.c +++ b/sys/platform/pc32/i386/machdep.c @@ -36,7 +36,7 @@ * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $ - * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.124 2007/06/29 21:54:10 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.125 2007/07/01 01:11:38 dillon Exp $ */ #include "use_apm.h" @@ -712,7 +712,6 @@ void sendupcall(struct vmupcall *vu, int morepending) { struct lwp *lp = curthread->td_lwp; - struct proc *p = lp->lwp_proc; struct trapframe *regs; struct upcall upcall; struct upc_frame upc_frame; @@ -723,7 +722,7 @@ sendupcall(struct vmupcall *vu, int morepending) * context, switch back to the virtual kernel context before * trying to post the signal. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { lp->lwp_md.md_regs->tf_trapno = 0; vkernel_trap(lp, lp->lwp_md.md_regs); } diff --git a/sys/platform/pc32/i386/trap.c b/sys/platform/pc32/i386/trap.c index 77a72c9959..44b9180ded 100644 --- a/sys/platform/pc32/i386/trap.c +++ b/sys/platform/pc32/i386/trap.c @@ -36,7 +36,7 @@ * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $ - * $DragonFly: src/sys/platform/pc32/i386/trap.c,v 1.105 2007/06/29 21:54:10 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/trap.c,v 1.106 2007/07/01 01:11:38 dillon Exp $ */ /* @@ -629,7 +629,7 @@ restart: * saved FP state that the virtual kernel needs * to hand over to a different emulated process. */ - if (lp->lwp_ve && + if (lp->lwp_vkernel && lp->lwp_vkernel->ve && (td->td_pcb->pcb_flags & FP_VIRTFP) ) { npxdna(); @@ -857,7 +857,7 @@ kernel_trap: * VM context managed by a virtual kernel then let the virtual kernel * handle it. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { vkernel_trap(lp, frame); goto out; } @@ -1236,7 +1236,7 @@ syscall2(struct trapframe *frame) * Restore the virtual kernel context and return from its system * call. The current frame is copied out to the virtual kernel. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { error = vkernel_trap(lp, frame); frame->tf_eax = error; if (error) diff --git a/sys/platform/vkernel/i386/cpu_regs.c b/sys/platform/vkernel/i386/cpu_regs.c index 2fa15087a2..b4cc0cb61e 100644 --- a/sys/platform/vkernel/i386/cpu_regs.c +++ b/sys/platform/vkernel/i386/cpu_regs.c @@ -37,7 +37,7 @@ * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $ - * $DragonFly: src/sys/platform/vkernel/i386/cpu_regs.c,v 1.16 2007/06/29 21:54:11 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/cpu_regs.c,v 1.17 2007/07/01 01:11:36 dillon Exp $ */ #include "use_ether.h" @@ -525,7 +525,7 @@ sendupcall(struct vmupcall *vu, int morepending) * context, switch back to the virtual kernel context before * trying to post the signal. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { lp->lwp_md.md_regs->tf_trapno = 0; vkernel_trap(lp, lp->lwp_md.md_regs); } diff --git a/sys/platform/vkernel/i386/trap.c b/sys/platform/vkernel/i386/trap.c index 319a7aba5e..018114dd8d 100644 --- a/sys/platform/vkernel/i386/trap.c +++ b/sys/platform/vkernel/i386/trap.c @@ -36,7 +36,7 @@ * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $ - * $DragonFly: src/sys/platform/vkernel/i386/trap.c,v 1.25 2007/06/29 21:54:11 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/trap.c,v 1.26 2007/07/01 01:11:36 dillon Exp $ */ /* @@ -551,7 +551,7 @@ restart: * saved FP state that the (emulated) virtual kernel * needs to hand over to a different emulated process. */ - if (lp->lwp_ve && + if (lp->lwp_vkernel && lp->lwp_vkernel->ve && (td->td_pcb->pcb_flags & FP_VIRTFP) ) { npxdna(frame); @@ -598,7 +598,7 @@ restart: * VM context managed by a virtual kernel then let the virtual kernel * handle it. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { vkernel_trap(lp, frame); goto out; } @@ -952,7 +952,7 @@ trap_fatal(struct trapframe *frame, int usermode, vm_offset_t eva) #ifdef SMP /* two separate prints in case of a trap on an unmapped page */ kprintf("mp_lock = %08x; ", mp_lock); - kprintf("cpuid = %d; ", mycpu->gd_cpuid); + kprintf("cpuid = %d\n", mycpu->gd_cpuid); #endif if (type == T_PAGEFLT) { kprintf("fault virtual address = 0x%x\n", eva); @@ -1047,7 +1047,7 @@ dblfault_handler(void) #ifdef SMP /* two separate prints in case of a trap on an unmapped page */ kprintf("mp_lock = %08x; ", mp_lock); - kprintf("cpuid = %d; ", mycpu->gd_cpuid); + kprintf("cpuid = %d\n", mycpu->gd_cpuid); #endif panic("double fault"); } @@ -1151,7 +1151,7 @@ syscall2(struct trapframe *frame) * Restore the virtual kernel context and return from its system * call. The current frame is copied out to the virtual kernel. */ - if (lp->lwp_ve) { + if (lp->lwp_vkernel && lp->lwp_vkernel->ve) { error = vkernel_trap(lp, frame); frame->tf_eax = error; if (error) diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 157eb9fabe..152374971a 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -37,7 +37,7 @@ * * @(#)proc.h 8.15 (Berkeley) 5/19/95 * $FreeBSD: src/sys/sys/proc.h,v 1.99.2.9 2003/06/06 20:21:32 tegge Exp $ - * $DragonFly: src/sys/sys/proc.h,v 1.109 2007/07/01 00:03:49 swildner Exp $ + * $DragonFly: src/sys/sys/proc.h,v 1.110 2007/07/01 01:11:37 dillon Exp $ */ #ifndef _SYS_PROC_H_ @@ -130,7 +130,8 @@ struct pargs { */ struct jail; -struct vkernel; +struct vkernel_proc; +struct vkernel_lwp; struct vmspace_entry; struct ktrace_node; @@ -153,7 +154,7 @@ struct lwp { struct proc *lwp_proc; /* Link to our proc. */ struct vmspace *lwp_vmspace; /* Inherited from p_vmspace */ - struct vmspace_entry *lwp_ve; /* Used by the vkernel */ + struct vkernel_lwp *lwp_vkernel;/* VKernel support, lwp part */ lwpid_t lwp_tid; /* Our thread id . */ @@ -295,7 +296,7 @@ struct proc { struct proc *p_leader; /* XXX lwp */ void *p_emuldata; /* process-specific emulator state */ struct usched *p_usched; /* Userland scheduling control */ - struct vkernel *p_vkernel; /* Virtual kernel extension */ + struct vkernel_proc *p_vkernel; /* VKernel support, proc part */ int p_numposixlocks; /* number of POSIX locks */ struct spinlock p_spin; /* Spinlock for LWP access to proc */ diff --git a/sys/sys/vkernel.h b/sys/sys/vkernel.h index 5148051968..6fa1aee451 100644 --- a/sys/sys/vkernel.h +++ b/sys/sys/vkernel.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/vkernel.h,v 1.9 2007/06/29 21:54:14 dillon Exp $ + * $DragonFly: src/sys/sys/vkernel.h,v 1.10 2007/07/01 01:11:37 dillon Exp $ */ #ifndef _SYS_VKERNEL_H_ @@ -70,18 +70,18 @@ RB_PROTOTYPE(vmspace_rb_tree, vmspace_entry, rb_entry, rb_vmspace_compare); * original VM space and trap context is saved in the process's vkernel * structure. */ -struct vkernel { - struct trapframe vk_save_trapframe; /* swapped context */ - struct vextframe vk_save_vextframe; - struct trapframe *vk_user_trapframe; /* copyback to vkernel */ - struct vextframe *vk_user_vextframe; - struct vkernel_common *vk_common; /* shared data */ +struct vkernel_lwp { + struct trapframe save_trapframe; /* swapped context */ + struct vextframe save_vextframe; + struct trapframe *user_trapframe; /* copyback to vkernel */ + struct vextframe *user_vextframe; + struct vmspace_entry *ve; }; -struct vkernel_common { - RB_HEAD(vmspace_rb_tree, vmspace_entry) vc_root; - struct spinlock vc_spin; - int vc_refs; +struct vkernel_proc { + RB_HEAD(vmspace_rb_tree, vmspace_entry) root; + struct spinlock spin; + int refs; }; struct vmspace_entry { @@ -96,6 +96,7 @@ struct vmspace_entry { void vkernel_inherit(struct proc *p1, struct proc *p2); void vkernel_exit(struct proc *p); +void vkernel_lwp_exit(struct lwp *lp); int vkernel_trap(struct lwp *lp, struct trapframe *frame); #endif diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h index 06d0281f53..99141d6267 100644 --- a/sys/vm/pmap.h +++ b/sys/vm/pmap.h @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/pmap.h,v 1.33.2.4 2002/03/06 22:44:24 silby Exp $ - * $DragonFly: src/sys/vm/pmap.h,v 1.26 2007/06/29 21:54:15 dillon Exp $ + * $DragonFly: src/sys/vm/pmap.h,v 1.27 2007/07/01 01:11:37 dillon Exp $ */ /* @@ -87,6 +87,7 @@ #include #endif +struct lwp; struct proc; struct thread; struct vm_page; diff --git a/sys/vm/vm_vmspace.c b/sys/vm/vm_vmspace.c index 56016d254b..fb2cdcf77e 100644 --- a/sys/vm/vm_vmspace.c +++ b/sys/vm/vm_vmspace.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vm/vm_vmspace.c,v 1.12 2007/06/29 21:54:15 dillon Exp $ + * $DragonFly: src/sys/vm/vm_vmspace.c,v 1.13 2007/07/01 01:11:37 dillon Exp $ */ #include "opt_ddb.h" @@ -56,10 +56,10 @@ #include #include -static struct vmspace_entry *vkernel_find_vmspace(struct vkernel_common *vc, +static struct vmspace_entry *vkernel_find_vmspace(struct vkernel_proc *vkp, void *id); static void vmspace_entry_delete(struct vmspace_entry *ve, - struct vkernel_common *vc); + struct vkernel_proc *vkp); static MALLOC_DEFINE(M_VKERNEL, "vkernel", "VKernel structures"); @@ -77,9 +77,8 @@ static MALLOC_DEFINE(M_VKERNEL, "vkernel", "VKernel structures"); int sys_vmspace_create(struct vmspace_create_args *uap) { - struct vkernel_common *vc; struct vmspace_entry *ve; - struct vkernel *vk; + struct vkernel_proc *vkp; if (vkernel_enable == 0) return (EOPNOTSUPP); @@ -88,27 +87,24 @@ sys_vmspace_create(struct vmspace_create_args *uap) * Create a virtual kernel side-structure for the process if one * does not exist. */ - if ((vk = curproc->p_vkernel) == NULL) { - vk = kmalloc(sizeof(*vk), M_VKERNEL, M_WAITOK|M_ZERO); - vc = kmalloc(sizeof(*vc), M_VKERNEL, M_WAITOK|M_ZERO); - vc->vc_refs = 1; - spin_init(&vc->vc_spin); - RB_INIT(&vc->vc_root); - vk->vk_common = vc; - curproc->p_vkernel = vk; + if ((vkp = curproc->p_vkernel) == NULL) { + vkp = kmalloc(sizeof(*vkp), M_VKERNEL, M_WAITOK|M_ZERO); + vkp->refs = 1; + spin_init(&vkp->spin); + RB_INIT(&vkp->root); + curproc->p_vkernel = vkp; } - vc = vk->vk_common; /* * Create a new VMSPACE */ - if (vkernel_find_vmspace(vc, uap->id)) + if (vkernel_find_vmspace(vkp, uap->id)) return (EEXIST); ve = kmalloc(sizeof(struct vmspace_entry), M_VKERNEL, M_WAITOK|M_ZERO); ve->vmspace = vmspace_alloc(VM_MIN_USER_ADDRESS, VM_MAX_USER_ADDRESS); ve->id = uap->id; pmap_pinit2(vmspace_pmap(ve->vmspace)); - RB_INSERT(vmspace_rb_tree, &vc->vc_root, ve); + RB_INSERT(vmspace_rb_tree, &vkp->root, ve); return (0); } @@ -120,18 +116,16 @@ sys_vmspace_create(struct vmspace_create_args *uap) int sys_vmspace_destroy(struct vmspace_destroy_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; struct vmspace_entry *ve; - struct vkernel *vk; - if ((vk = curproc->p_vkernel) == NULL) + if ((vkp = curproc->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); if (ve->refs) return (EBUSY); - vmspace_entry_delete(ve, vc); + vmspace_entry_delete(ve, vkp); return(0); } @@ -146,21 +140,20 @@ sys_vmspace_destroy(struct vmspace_destroy_args *uap) int sys_vmspace_ctl(struct vmspace_ctl_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; + struct vkernel_lwp *vklp; struct vmspace_entry *ve; - struct vkernel *vk; - struct lwp *lwp; + struct lwp *lp; struct proc *p; int framesz; int error; - lwp = curthread->td_lwp; - p = lwp->lwp_proc; + lp = curthread->td_lwp; + p = lp->lwp_proc; - if ((vk = p->p_vkernel) == NULL) + if ((vkp = p->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); /* @@ -178,13 +171,18 @@ sys_vmspace_ctl(struct vmspace_ctl_args *uap) * install the passed register context. Return with * EJUSTRETURN so the syscall code doesn't adjust the context. */ - ++ve->refs; + atomic_add_int(&ve->refs, 1); framesz = sizeof(struct trapframe); - vk->vk_user_trapframe = uap->tframe; - vk->vk_user_vextframe = uap->vframe; - bcopy(uap->sysmsg_frame, &vk->vk_save_trapframe, framesz); - bcopy(&curthread->td_tls, &vk->vk_save_vextframe.vx_tls, - sizeof(vk->vk_save_vextframe.vx_tls)); + if ((vklp = lp->lwp_vkernel) == NULL) { + vklp = kmalloc(sizeof(*vklp), M_VKERNEL, + M_WAITOK|M_ZERO); + lp->lwp_vkernel = vklp; + } + vklp->user_trapframe = uap->tframe; + vklp->user_vextframe = uap->vframe; + bcopy(uap->sysmsg_frame, &vklp->save_trapframe, framesz); + bcopy(&curthread->td_tls, &vklp->save_vextframe.vx_tls, + sizeof(vklp->save_vextframe.vx_tls)); error = copyin(uap->tframe, uap->sysmsg_frame, framesz); if (error == 0) error = copyin(&uap->vframe->vx_tls, &curthread->td_tls, sizeof(struct savetls)); @@ -193,14 +191,14 @@ sys_vmspace_ctl(struct vmspace_ctl_args *uap) if (error == 0) error = cpu_sanitize_tls(&curthread->td_tls); if (error) { - bcopy(&vk->vk_save_trapframe, uap->sysmsg_frame, framesz); - bcopy(&vk->vk_save_vextframe.vx_tls, &curthread->td_tls, - sizeof(vk->vk_save_vextframe.vx_tls)); + bcopy(&vklp->save_trapframe, uap->sysmsg_frame, framesz); + bcopy(&vklp->save_vextframe.vx_tls, &curthread->td_tls, + sizeof(vklp->save_vextframe.vx_tls)); set_user_TLS(); - --ve->refs; + atomic_subtract_int(&ve->refs, 1); } else { - lwp->lwp_ve = ve; - pmap_setlwpvm(lwp, ve->vmspace); + vklp->ve = ve; + pmap_setlwpvm(lp, ve->vmspace); set_user_TLS(); set_vkernel_fp(uap->sysmsg_frame); error = EJUSTRETURN; @@ -223,15 +221,13 @@ sys_vmspace_ctl(struct vmspace_ctl_args *uap) int sys_vmspace_mmap(struct vmspace_mmap_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; struct vmspace_entry *ve; - struct vkernel *vk; int error; - if ((vk = curproc->p_vkernel) == NULL) + if ((vkp = curproc->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); error = kern_mmap(ve->vmspace, uap->addr, uap->len, uap->prot, uap->flags, @@ -247,17 +243,15 @@ sys_vmspace_mmap(struct vmspace_mmap_args *uap) int sys_vmspace_munmap(struct vmspace_munmap_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; struct vmspace_entry *ve; - struct vkernel *vk; vm_offset_t addr; vm_size_t size, pageoff; vm_map_t map; - if ((vk = curproc->p_vkernel) == NULL) + if ((vkp = curproc->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); /* @@ -297,14 +291,12 @@ sys_vmspace_munmap(struct vmspace_munmap_args *uap) int sys_vmspace_pread(struct vmspace_pread_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; struct vmspace_entry *ve; - struct vkernel *vk; - if ((vk = curproc->p_vkernel) == NULL) + if ((vkp = curproc->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); return (EINVAL); } @@ -320,14 +312,12 @@ sys_vmspace_pread(struct vmspace_pread_args *uap) int sys_vmspace_pwrite(struct vmspace_pwrite_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; struct vmspace_entry *ve; - struct vkernel *vk; - if ((vk = curproc->p_vkernel) == NULL) + if ((vkp = curproc->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); return (EINVAL); } @@ -340,15 +330,13 @@ sys_vmspace_pwrite(struct vmspace_pwrite_args *uap) int sys_vmspace_mcontrol(struct vmspace_mcontrol_args *uap) { - struct vkernel_common *vc; + struct vkernel_proc *vkp; struct vmspace_entry *ve; - struct vkernel *vk; vm_offset_t start, end; - if ((vk = curproc->p_vkernel) == NULL) + if ((vkp = curproc->p_vkernel) == NULL) return (EINVAL); - vc = vk->vk_common; - if ((ve = vkernel_find_vmspace(vc, uap->id)) == NULL) + if ((ve = vkernel_find_vmspace(vkp, uap->id)) == NULL) return (ENOENT); /* @@ -393,10 +381,10 @@ static int rb_vmspace_delete(struct vmspace_entry *ve, void *data) { - struct vkernel_common *vc = data; + struct vkernel_proc *vkp = data; KKASSERT(ve->refs == 0); - vmspace_entry_delete(ve, vc); + vmspace_entry_delete(ve, vkp); return(0); } @@ -406,9 +394,9 @@ rb_vmspace_delete(struct vmspace_entry *ve, void *data) */ static void -vmspace_entry_delete(struct vmspace_entry *ve, struct vkernel_common *vc) +vmspace_entry_delete(struct vmspace_entry *ve, struct vkernel_proc *vkp) { - RB_REMOVE(vmspace_rb_tree, &vc->vc_root, ve); + RB_REMOVE(vmspace_rb_tree, &vkp->root, ve); pmap_remove_pages(vmspace_pmap(ve->vmspace), VM_MIN_USER_ADDRESS, VM_MAX_USER_ADDRESS); @@ -421,13 +409,13 @@ vmspace_entry_delete(struct vmspace_entry *ve, struct vkernel_common *vc) static struct vmspace_entry * -vkernel_find_vmspace(struct vkernel_common *vc, void *id) +vkernel_find_vmspace(struct vkernel_proc *vkp, void *id) { struct vmspace_entry *ve; struct vmspace_entry key; key.id = id; - ve = RB_FIND(vmspace_rb_tree, &vc->vc_root, &key); + ve = RB_FIND(vmspace_rb_tree, &vkp->root, &key); return (ve); } @@ -438,32 +426,22 @@ vkernel_find_vmspace(struct vkernel_common *vc, void *id) void vkernel_inherit(struct proc *p1, struct proc *p2) { - struct vkernel_common *vc; - struct vkernel *vk; - - vk = p1->p_vkernel; - vc = vk->vk_common; - KKASSERT(vc->vc_refs > 0); - atomic_add_int(&vc->vc_refs, 1); - vk = kmalloc(sizeof(*vk), M_VKERNEL, M_WAITOK|M_ZERO); - p2->p_vkernel = vk; - vk->vk_common = vc; + struct vkernel_proc *vkp; + + vkp = p1->p_vkernel; + KKASSERT(vkp->refs > 0); + atomic_add_int(&vkp->refs, 1); + p2->p_vkernel = vkp; } void vkernel_exit(struct proc *p) { - struct vkernel_common *vc; - struct vmspace_entry *ve; - struct vkernel *vk; + struct vkernel_proc *vkp; struct lwp *lp; int freeme = 0; - vk = p->p_vkernel; - p->p_vkernel = NULL; - vc = vk->vk_common; - vk->vk_common = NULL; - + vkp = p->p_vkernel; /* * Restore the original VM context if we are killed while running * a different one. @@ -473,34 +451,47 @@ vkernel_exit(struct proc *p) * the signal. */ LIST_FOREACH(lp, &p->p_lwps, lwp_list) { - if ((ve = lp->lwp_ve) != NULL) { - kprintf("Warning, pid %d killed with active VC!\n", - p->p_pid); -#ifdef DDB - db_print_backtrace(); -#endif - lp->lwp_ve = NULL; - pmap_setlwpvm(lp, p->p_vmspace); - KKASSERT(ve->refs > 0); - --ve->refs; - } + vkernel_lwp_exit(lp); } /* * Dereference the common area */ - KKASSERT(vc->vc_refs > 0); - spin_lock_wr(&vc->vc_spin); - if (--vc->vc_refs == 0) + p->p_vkernel = NULL; + KKASSERT(vkp->refs > 0); + spin_lock_wr(&vkp->spin); + if (--vkp->refs == 0) freeme = 1; - spin_unlock_wr(&vc->vc_spin); + spin_unlock_wr(&vkp->spin); if (freeme) { - RB_SCAN(vmspace_rb_tree, &vc->vc_root, NULL, - rb_vmspace_delete, vc); - kfree(vc, M_VKERNEL); + RB_SCAN(vmspace_rb_tree, &vkp->root, NULL, + rb_vmspace_delete, vkp); + kfree(vkp, M_VKERNEL); + } +} + +void +vkernel_lwp_exit(struct lwp *lp) +{ + struct vkernel_lwp *vklp; + struct vmspace_entry *ve; + + if ((vklp = lp->lwp_vkernel) != NULL) { + if ((ve = vklp->ve) != NULL) { + kprintf("Warning, pid %d killed with " + "active VC!\n", lp->lwp_proc->p_pid); +#ifdef DDB + db_print_backtrace(); +#endif + pmap_setlwpvm(lp, lp->lwp_proc->p_vmspace); + vklp->ve = NULL; + KKASSERT(ve->refs > 0); + atomic_subtract_int(&ve->refs, 1); + } + lp->lwp_vkernel = NULL; + kfree(vklp, M_VKERNEL); } - kfree(vk, M_VKERNEL); } /* @@ -512,23 +503,24 @@ vkernel_trap(struct lwp *lp, struct trapframe *frame) { struct proc *p = lp->lwp_proc; struct vmspace_entry *ve; - struct vkernel *vk; + struct vkernel_lwp *vklp; int error; /* * Which vmspace entry was running? */ - vk = p->p_vkernel; - ve = lp->lwp_ve; + vklp = lp->lwp_vkernel; + KKASSERT(vklp); + ve = vklp->ve; KKASSERT(ve != NULL); /* * Switch the LWP vmspace back to the virtual kernel's VM space. */ - lp->lwp_ve = NULL; + vklp->ve = NULL; pmap_setlwpvm(lp, p->p_vmspace); KKASSERT(ve->refs > 0); - --ve->refs; + atomic_subtract_int(&ve->refs, 1); /* * Copy the emulated process frame to the virtual kernel process. @@ -538,10 +530,10 @@ vkernel_trap(struct lwp *lp, struct trapframe *frame) * Restore the virtual kernel's saved context so the virtual kernel * process can resume. */ - error = copyout(frame, vk->vk_user_trapframe, sizeof(*frame)); - bcopy(&vk->vk_save_trapframe, frame, sizeof(*frame)); - bcopy(&vk->vk_save_vextframe.vx_tls, &curthread->td_tls, - sizeof(vk->vk_save_vextframe.vx_tls)); + error = copyout(frame, vklp->user_trapframe, sizeof(*frame)); + bcopy(&vklp->save_trapframe, frame, sizeof(*frame)); + bcopy(&vklp->save_vextframe.vx_tls, &curthread->td_tls, + sizeof(vklp->save_vextframe.vx_tls)); set_user_TLS(); return(error); } -- 2.11.4.GIT