Make some adjustments to low level madvise/mcontrol/mmap support code to
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 17 Sep 2006 21:09:40 +0000 (21:09 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 17 Sep 2006 21:09:40 +0000 (21:09 +0000)
accomodate vmspace_*() calls.

Reformulate the new vmspace_*() calls so they operate similarly to the
MAP_VPAGETABLE and mcontrol() calls.  This also makes vmspace's more
'programmable' in the sense that it will be possible to mix virtual
pagetable mmap()ings with other mmap()ing in a vmspace.

Fill in the code for all the new vmspace_*() calls except for
vmspace_ctl().  NOTE: vmspace calls are effectively disabled unless
vm.vkernel_enable is turned on, just like MAP_VPAGETABLE.

Renumber the new mcontrol() and vmspace_*() calls and regenerate.

sys/sys/kern_syscall.h
sys/sys/proc.h
sys/sys/syscall-hide.h
sys/sys/syscall.h
sys/sys/syscall.mk
sys/sys/sysproto.h
sys/sys/sysunion.h
sys/sys/vmspace.h
sys/vm/vm_extern.h
sys/vm/vm_mmap.c
sys/vm/vm_vmspace.c

index 3a48bed..f019f85 100644 (file)
@@ -25,7 +25,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/kern_syscall.h,v 1.32 2006/06/13 21:04:17 dillon Exp $
+ * $DragonFly: src/sys/sys/kern_syscall.h,v 1.33 2006/09/17 21:09:39 dillon Exp $
  */
 
 #ifndef _SYS_KERN_SYSCALL_H_
@@ -58,6 +58,7 @@ struct stat;
 struct statfs;
 struct timeval;
 struct uio;
+struct vmspace;
 struct vnode;
 struct file;
 struct ucred;
@@ -165,7 +166,7 @@ char *kern_getcwd(char *, size_t, int *);
 /*
  * Prototypes for syscalls in vm/vm_mmap.c
  */
-int kern_mmap(caddr_t addr, size_t len, int prot, int flags, int fd,
-       off_t pos, void **res);
+int kern_mmap(struct vmspace *, caddr_t addr, size_t len,
+             int prot, int flags, int fd, off_t pos, void **res);
 
 #endif /* !_SYS_KERN_SYSCALL_H_ */
index 0ca040c..0ebb680 100644 (file)
@@ -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.83 2006/08/27 12:54:59 davidxu Exp $
+ * $DragonFly: src/sys/sys/proc.h,v 1.84 2006/09/17 21:09:39 dillon Exp $
  */
 
 #ifndef _SYS_PROC_H_
@@ -132,6 +132,7 @@ struct      pargs {
  */
 
 struct jail;
+struct vkernel;
 struct ktrace_node;
 
 struct lwp {
@@ -218,7 +219,7 @@ struct      proc {
 
        pid_t           p_oppid;        /* Save parent pid during ptrace. XXX */
 
-       struct vmspace  *p_vmspace;     /* Address space. */
+       struct vmspace  *p_vmspace;     /* Current address space. */
 
 #define p_cpticks p_lwp.lwp_cpticks
 #define p_cpbase p_lwp.lwp_cpbase
@@ -293,6 +294,7 @@ struct      proc {
        void            *p_emuldata;    /* process-specific emulator state */
 #define p_thread p_lwp.lwp_thread
        struct usched   *p_usched;      /* Userland scheduling control */
+       struct vkernel  *p_vkernel;     /* Virtual kernel extension */
        int             p_numposixlocks; /* number of POSIX locks */
 
        struct lwp      p_lwp;          /* Embedded lwp XXX */
index b307c85..f979a99 100644 (file)
@@ -2,8 +2,8 @@
  * System call hiders.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/syscall-hide.h,v 1.45 2006/09/13 17:10:40 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.42 2006/09/03 17:11:48 dillon Exp 
+ * $DragonFly: src/sys/sys/syscall-hide.h,v 1.46 2006/09/17 21:09:39 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.43 2006/09/13 17:10:39 dillon Exp 
  */
 
 #ifdef COMPAT_43
@@ -315,9 +315,10 @@ HIDE_BSD(usched_set)
 HIDE_BSD(__accept)
 HIDE_BSD(__connect)
 HIDE_BSD(syslink)
-HIDE_BSD(vmspace_ctl)
-HIDE_BSD(vmspace_map)
-HIDE_BSD(vmspace_protect)
-HIDE_BSD(vmspace_read)
-HIDE_BSD(vmspace_write)
 HIDE_BSD(mcontrol)
+HIDE_BSD(vmspace_create)
+HIDE_BSD(vmspace_destroy)
+HIDE_BSD(vmspace_ctl)
+HIDE_BSD(vmspace_mmap)
+HIDE_BSD(vmspace_munmap)
+HIDE_BSD(vmspace_mcontrol)
index 1f4c9d1..e2312a9 100644 (file)
@@ -2,8 +2,8 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/syscall.h,v 1.45 2006/09/13 17:10:40 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.42 2006/09/03 17:11:48 dillon Exp 
+ * $DragonFly: src/sys/sys/syscall.h,v 1.46 2006/09/17 21:09:39 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.43 2006/09/13 17:10:39 dillon Exp 
  */
 
 #define        SYS_syscall     0
 #define        SYS___accept    482
 #define        SYS___connect   483
 #define        SYS_syslink     484
-#define        SYS_vmspace_ctl 485
-#define        SYS_vmspace_map 486
-#define        SYS_vmspace_protect     487
-#define        SYS_vmspace_read        488
-#define        SYS_vmspace_write       489
-#define        SYS_mcontrol    490
-#define        SYS_MAXSYSCALL  491
+#define        SYS_mcontrol    485
+#define        SYS_vmspace_create      486
+#define        SYS_vmspace_destroy     487
+#define        SYS_vmspace_ctl 488
+#define        SYS_vmspace_mmap        489
+#define        SYS_vmspace_munmap      490
+#define        SYS_vmspace_mcontrol    491
+#define        SYS_MAXSYSCALL  492
index 1f4edf1..ad747e5 100644 (file)
@@ -1,7 +1,7 @@
 # DragonFly system call names.
 # DO NOT EDIT-- this file is automatically generated.
-# $DragonFly: src/sys/sys/syscall.mk,v 1.45 2006/09/13 17:10:40 dillon Exp $
-# created from DragonFly: src/sys/kern/syscalls.master,v 1.42 2006/09/03 17:11:48 dillon Exp 
+# $DragonFly: src/sys/sys/syscall.mk,v 1.46 2006/09/17 21:09:39 dillon Exp $
+# created from DragonFly: src/sys/kern/syscalls.master,v 1.43 2006/09/13 17:10:39 dillon Exp 
 MIASM =  \
        syscall.o \
        exit.o \
@@ -267,9 +267,10 @@ MIASM =  \
        __accept.o \
        __connect.o \
        syslink.o \
+       mcontrol.o \
+       vmspace_create.o \
+       vmspace_destroy.o \
        vmspace_ctl.o \
-       vmspace_map.o \
-       vmspace_protect.o \
-       vmspace_read.o \
-       vmspace_write.o \
-       mcontrol.o
+       vmspace_mmap.o \
+       vmspace_munmap.o \
+       vmspace_mcontrol.o
index 56fca1b..5295310 100644 (file)
@@ -2,8 +2,8 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/sysproto.h,v 1.45 2006/09/13 17:10:40 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.42 2006/09/03 17:11:48 dillon Exp 
+ * $DragonFly: src/sys/sys/sysproto.h,v 1.46 2006/09/17 21:09:39 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.43 2006/09/13 17:10:39 dillon Exp 
  */
 
 #ifndef _SYS_SYSPROTO_H_
@@ -1986,53 +1986,64 @@ struct  syslink_args {
        sysid_t *       mask;   char mask_[PAD_(sysid_t *)];
        sysid_t *       match;  char match_[PAD_(sysid_t *)];
 };
-struct vmspace_ctl_args {
+struct mcontrol_args {
+#ifdef _KERNEL
+       struct sysmsg sysmsg;
+#endif
+       void *  addr;   char addr_[PAD_(void *)];
+       size_t  len;    char len_[PAD_(size_t)];
+       int     behav;  char behav_[PAD_(int)];
+       off_t   value;  char value_[PAD_(off_t)];
+};
+struct vmspace_create_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
 #endif
        void *  id;     char id_[PAD_(void *)];
-       void *  ctx;    char ctx_[PAD_(void *)];
-       int     what;   char what_[PAD_(int)];
+       int     type;   char type_[PAD_(int)];
+       void *  data;   char data_[PAD_(void *)];
 };
-struct vmspace_map_args {
+struct vmspace_destroy_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
 #endif
        void *  id;     char id_[PAD_(void *)];
-       off_t   offset; char offset_[PAD_(off_t)];
-       void *  ptr;    char ptr_[PAD_(void *)];
-       int     bytes;  char bytes_[PAD_(int)];
-       int     prot;   char prot_[PAD_(int)];
 };
-struct vmspace_protect_args {
+struct vmspace_ctl_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
 #endif
        void *  id;     char id_[PAD_(void *)];
-       off_t   offset; char offset_[PAD_(off_t)];
-       int     bytes;  char bytes_[PAD_(int)];
-       int     prot;   char prot_[PAD_(int)];
+       int     cmd;    char cmd_[PAD_(int)];
+       void *  ctx;    char ctx_[PAD_(void *)];
+       int     ctx_bytes;      char ctx_bytes_[PAD_(int)];
+       int     timeout_us;     char timeout_us_[PAD_(int)];
 };
-struct vmspace_read_args {
+struct vmspace_mmap_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
 #endif
        void *  id;     char id_[PAD_(void *)];
-       void *  ptr;    char ptr_[PAD_(void *)];
-       int     bytes;  char bytes_[PAD_(int)];
+       void *  addr;   char addr_[PAD_(void *)];
+       size_t  len;    char len_[PAD_(size_t)];
+       int     prot;   char prot_[PAD_(int)];
+       int     flags;  char flags_[PAD_(int)];
+       int     fd;     char fd_[PAD_(int)];
+       off_t   offset; char offset_[PAD_(off_t)];
 };
-struct vmspace_write_args {
+struct vmspace_munmap_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
 #endif
        void *  id;     char id_[PAD_(void *)];
-       const void *    ptr;    char ptr_[PAD_(const void *)];
-       int     bytes;  char bytes_[PAD_(int)];
+       void *  addr;   char addr_[PAD_(void *)];
+       size_t  len;    char len_[PAD_(size_t)];
 };
-struct mcontrol_args {
+struct vmspace_mcontrol_args {
 #ifdef _KERNEL
        struct sysmsg sysmsg;
 #endif
+       void *  id;     char id_[PAD_(void *)];
        void *  addr;   char addr_[PAD_(void *)];
        size_t  len;    char len_[PAD_(size_t)];
        int     behav;  char behav_[PAD_(int)];
@@ -2603,12 +2614,13 @@ int     sys_usched_set (struct usched_set_args *);
 int    sys___accept (struct __accept_args *);
 int    sys___connect (struct __connect_args *);
 int    sys_syslink (struct syslink_args *);
-int    sys_vmspace_ctl (struct vmspace_ctl_args *);
-int    sys_vmspace_map (struct vmspace_map_args *);
-int    sys_vmspace_protect (struct vmspace_protect_args *);
-int    sys_vmspace_read (struct vmspace_read_args *);
-int    sys_vmspace_write (struct vmspace_write_args *);
 int    sys_mcontrol (struct mcontrol_args *);
+int    sys_vmspace_create (struct vmspace_create_args *);
+int    sys_vmspace_destroy (struct vmspace_destroy_args *);
+int    sys_vmspace_ctl (struct vmspace_ctl_args *);
+int    sys_vmspace_mmap (struct vmspace_mmap_args *);
+int    sys_vmspace_munmap (struct vmspace_munmap_args *);
+int    sys_vmspace_mcontrol (struct vmspace_mcontrol_args *);
 
 #endif /* !_SYS_SYSPROTO_H_ */
 #undef PAD_
index 4401a52..df6e089 100644 (file)
@@ -2,8 +2,8 @@
  * Union of syscall args for messaging.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/sys/sysunion.h,v 1.42 2006/09/13 17:10:40 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.42 2006/09/03 17:11:48 dillon Exp 
+ * $DragonFly: src/sys/sys/sysunion.h,v 1.43 2006/09/17 21:09:39 dillon Exp $
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.43 2006/09/13 17:10:39 dillon Exp 
  */
 
 union sysunion {
@@ -371,10 +371,11 @@ union sysunion {
        struct  __accept_args __accept;
        struct  __connect_args __connect;
        struct  syslink_args syslink;
-       struct  vmspace_ctl_args vmspace_ctl;
-       struct  vmspace_map_args vmspace_map;
-       struct  vmspace_protect_args vmspace_protect;
-       struct  vmspace_read_args vmspace_read;
-       struct  vmspace_write_args vmspace_write;
        struct  mcontrol_args mcontrol;
+       struct  vmspace_create_args vmspace_create;
+       struct  vmspace_destroy_args vmspace_destroy;
+       struct  vmspace_ctl_args vmspace_ctl;
+       struct  vmspace_mmap_args vmspace_mmap;
+       struct  vmspace_munmap_args vmspace_munmap;
+       struct  vmspace_mcontrol_args vmspace_mcontrol;
 };
index da7617c..fb9b222 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/sys/vmspace.h,v 1.1 2006/09/03 17:11:50 dillon Exp $
+ * $DragonFly: src/sys/sys/vmspace.h,v 1.2 2006/09/17 21:09:39 dillon Exp $
  */
 /*
  * VMSPACE - Virtualized Environment control from user mode.  The VMSPACE
 #include <sys/types.h>
 #endif
 
-#define VMSPACE_CTL_CREATE     1
-#define VMSPACE_CTL_DESTROY    2
-#define VMSPACE_CTL_RUN                3
+#define VMSPACE_CTL_VKERNEL    1
+#define VMSPACE_CTL_CREATE     2
+#define VMSPACE_CTL_DESTROY    3
+#define VMSPACE_CTL_RUN                4
 
 #define VMSPACE_PAGEFAULT      1
 #define VMSPACE_TIMEOUT                2
index c09a97d..30b2033 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)vm_extern.h 8.2 (Berkeley) 1/12/94
  * $FreeBSD: src/sys/vm/vm_extern.h,v 1.46.2.3 2003/01/13 22:51:17 dillon Exp $
- * $DragonFly: src/sys/vm/vm_extern.h,v 1.17 2006/09/12 18:41:32 dillon Exp $
+ * $DragonFly: src/sys/vm/vm_extern.h,v 1.18 2006/09/17 21:09:40 dillon Exp $
  */
 
 #ifndef _VM_VM_EXTERN_H_
@@ -53,6 +53,7 @@ struct proc;
 struct vmspace;
 struct vmtotal;
 struct mount;
+struct vmspace;
 struct vnode;
 
 #ifdef _KERNEL
index ccbf029..be6f588 100644 (file)
@@ -39,7 +39,7 @@
  *
  *     @(#)vm_mmap.c   8.4 (Berkeley) 1/12/94
  * $FreeBSD: src/sys/vm/vm_mmap.c,v 1.108.2.6 2002/07/02 20:06:19 dillon Exp $
- * $DragonFly: src/sys/vm/vm_mmap.c,v 1.33 2006/09/13 17:10:42 dillon Exp $
+ * $DragonFly: src/sys/vm/vm_mmap.c,v 1.34 2006/09/17 21:09:40 dillon Exp $
  */
 
 /*
@@ -146,8 +146,8 @@ sys_sstk(struct sstk_args *uap)
  */
 
 int
-kern_mmap(caddr_t uaddr, size_t ulen, int uprot, int uflags, int fd, 
-    off_t upos, void **res)
+kern_mmap(struct vmspace *vms, caddr_t uaddr, size_t ulen,
+         int uprot, int uflags, int fd, off_t upos, void **res)
 {
        struct thread *td = curthread;
        struct proc *p = td->td_proc;
@@ -160,7 +160,6 @@ kern_mmap(caddr_t uaddr, size_t ulen, int uprot, int uflags, int fd,
        int flags, error;
        int disablexworkaround;
        off_t pos;
-       struct vmspace *vms = p->p_vmspace;
        vm_object_t obj;
 
        KKASSERT(p);
@@ -400,8 +399,9 @@ sys_mmap(struct mmap_args *uap)
 {
        int error;
 
-       error = kern_mmap(uap->addr, uap->len, uap->prot, uap->flags,
-           uap->fd, uap->pos, &uap->sysmsg_resultp);
+       error = kern_mmap(curproc->p_vmspace, uap->addr, uap->len,
+                         uap->prot, uap->flags,
+                         uap->fd, uap->pos, &uap->sysmsg_resultp);
 
        return (error);
 }
@@ -974,23 +974,23 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
        boolean_t fitit;
        vm_object_t object;
        struct vnode *vp = NULL;
+       struct proc *p;
        objtype_t type;
        int rv = KERN_SUCCESS;
        off_t objsize;
        int docow;
-       struct thread *td = curthread;  /* XXX */
-       struct proc *p = td->td_proc;
-
-       KKASSERT(p);
 
        if (size == 0)
                return (0);
 
        objsize = size = round_page(size);
 
-       if (p->p_vmspace->vm_map.size + size >
-           p->p_rlimit[RLIMIT_VMEM].rlim_cur) {
-               return(ENOMEM);
+       /*
+        * XXX messy code, fixme
+        */
+       if ((p = curproc) != NULL && map == &p->p_vmspace->vm_map) {
+               if (map->size + size > p->p_rlimit[RLIMIT_VMEM].rlim_cur)
+                       return(ENOMEM);
        }
 
        /*
index ee65607..e712efb 100644 (file)
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vm/vm_vmspace.c,v 1.1 2006/09/03 17:11:51 dillon Exp $
+ * $DragonFly: src/sys/vm/vm_vmspace.c,v 1.2 2006/09/17 21:09:40 dillon Exp $
  */
 
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/mman.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/vkernel.h>
+
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+
+static struct vmspace_entry *vkernel_find_vmspace(struct vkernel *vk, void *id);
+
+static MALLOC_DEFINE(M_VKERNEL, "vkernel", "VKernel structures");
 
 /*
- * vmspace_ctl {void *id, void *ctx, int what }
+ * vmspace_create (void *id, int type, void *data)
  *
- * Create, destroy, or execute a VM space.  This functions returns when
- * the VM space has run for a specified period of time, a signal occurs,
- * or the VM space traps or makes a system call.
+ * Create a VMSPACE under the control of the caller with the specified id.
+ * An id of NULL cannot be used.  The type and data fields must currently
+ * be 0.
  *
- * Execution of a VM space is accomplished by swapping out the caller's
- * current VM space.  Any signal or condition applicable to the caller
- * will swap the caller's VM space back in for processing, then return
- * EINTR.  A trap, system call, or page fault in the VM space will swap
- * the caller's VM space back in, adjust the context, and return the
- * appropriate code.
+ * The vmspace starts out completely empty.  Memory may be mapped into the
+ * VMSPACE with vmspace_mmap() and MAP_VPAGETABLE section(s) controlled
+ * with vmspace_mcontrol().
+ */
+int
+sys_vmspace_create(struct vmspace_create_args *uap)
+{
+       struct vkernel *vk;
+       struct vmspace_entry *ve;
+
+       if (vkernel_enable == 0)
+               return (EOPNOTSUPP);
+
+       /*
+        * 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);
+               vk->vk_refs = 1;
+               RB_INIT(&vk->vk_root);
+               curproc->p_vkernel = vk;
+       }
+
+       /*
+        * Create a new VMSPACE
+        */
+       if (vkernel_find_vmspace(vk, uap->id))
+               return (EEXIST);
+       ve = kmalloc(sizeof(struct vmspace_entry), M_VKERNEL, M_WAITOK|M_ZERO);
+       ve->vmspace = vmspace_alloc(VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
+       ve->id = uap->id;
+       pmap_pinit2(vmspace_pmap(ve->vmspace));
+       RB_INSERT(vmspace_rb_tree, &vk->vk_root, ve);
+       return (0);
+}
+
+/*
+ * vmspace_destroy (void *id)
  *
- * A virtual kernel manages multiple 'process' VM spaces this way, the
- * real kernel only sees only the processes representing the virtual kernel
- * itself, typically one per virtual cpu.
+ * Destroy a VMSPACE.
  */
 int
-sys_vmspace_ctl(struct vmspace_ctl_args *uap)
+sys_vmspace_destroy(struct vmspace_destroy_args *uap)
 {
-       return (EINVAL);
+       struct vkernel *vk;
+       struct vmspace_entry *ve;
+
+       if ((vk = curproc->p_vkernel) == NULL)
+               return (EINVAL);
+       if ((ve = vkernel_find_vmspace(vk, uap->id)) == NULL)
+               return (ENOENT);
+       /* XXX check if active */
+       RB_REMOVE(vmspace_rb_tree, &vk->vk_root, ve);
+       vmspace_free(ve->vmspace);
+       kfree(ve, M_VKERNEL);
+       return(0);
 }
 
 /*
- * vmspace_map { void *id, off_t offset, void *ptr, int bytes, int prot }
+ * vmspace_ctl (void *id, int cmd, void *ctx, int ctx_bytes, int timeout_us)
  *
- * Map pages backing the specified memory in the caller's context into
- * the specified VM space and reduce their protection using 'prot'.  A
- * protection value of 0 removes the page mapping.  Page mappings can be
- * removed by the kernel at any time and cause execution of the VM space
- * to return with VMSPACE_PAGEFAULT.
+ * Transfer control to a VMSPACE.  Control is returned after the specified
+ * number of microseconds or if a page fault, signal, trap, or system call
+ * occurs.
  */
 int
-sys_vmspace_map(struct vmspace_map_args *uap)
+sys_vmspace_ctl(struct vmspace_ctl_args *uap)
 {
-       return (EINVAL);
+       struct vkernel *vk;
+       struct vmspace_entry *ve;
+
+       if ((vk = curproc->p_vkernel) == NULL)
+               return (EINVAL);
+       if ((ve = vkernel_find_vmspace(vk, uap->id)) == NULL)
+               return (ENOENT);
+       return(EINVAL);
 }
 
 /*
- * vmspace_protect { void *id, off_t offset, int bytes, int prot }
+ * vmspace_mmap(id, addr, len, prot, flags, fd, offset)
  *
- * Adjust the protection of mapped pages in the specified VM context.  Pages
- * that are not mapped or whos mapping was removed by the kernel are not
- * effected.
+ * map memory within a VMSPACE.  This function is just like a normal mmap()
+ * but operates on the vmspace's memory map.  Most callers use this to create
+ * a MAP_VPAGETABLE mapping.
  */
 int
-sys_vmspace_protect(struct vmspace_protect_args *uap)
+sys_vmspace_mmap(struct vmspace_mmap_args *uap)
 {
-       return (EINVAL);
+       struct vkernel *vk;
+       struct vmspace_entry *ve;
+
+       if ((vk = curproc->p_vkernel) == NULL)
+               return (EINVAL);
+       if ((ve = vkernel_find_vmspace(vk, uap->id)) == NULL)
+               return (ENOENT);
+       return(EINVAL);
 }
 
 /*
- * vmspace_read { void *id, void *ptr, int bytes }
+ * vmspace_munmap(id, addr, len)
  *
- * Read data from the VM space.  Only data in mapped pages can be read.  If
- * an unmapped page is encountered this function will return fewer then the
- * requested number of bytes and the caller must map the additional pages
- * before restarting the call.
+ * unmap memory within a VMSPACE.
  */
 int
-sys_vmspace_read(struct vmspace_read_args *uap)
+sys_vmspace_munmap(struct vmspace_munmap_args *uap)
 {
-       return (EINVAL);
+       struct vkernel *vk;
+       struct vmspace_entry *ve;
+
+       if ((vk = curproc->p_vkernel) == NULL)
+               return (EINVAL);
+       if ((ve = vkernel_find_vmspace(vk, uap->id)) == NULL)
+               return (ENOENT);
+       return(EINVAL);
 }
 
 /*
- * vmspace_write { void *id, const void *ptr, int bytes }
+ * vmspace_mcontrol(id, addr, len, behav, value)
  *
- * Write data to the VM space.  Only mapped, writable pages can be written.
- * If an unmapped or read-only page is encountered this function will return
- * fewer then the requested number of bytes and the caller must map the
- * additional pages before restarting the call.
+ * madvise/mcontrol support for a vmspace.
  */
 int
-sys_vmspace_write(struct vmspace_write_args *uap)
+sys_vmspace_mcontrol(struct vmspace_mcontrol_args *uap)
+{
+       struct vkernel *vk;
+       struct vmspace_entry *ve;
+       vm_offset_t start, end;
+
+       if ((vk = curproc->p_vkernel) == NULL)
+               return (EINVAL);
+       if ((ve = vkernel_find_vmspace(vk, uap->id)) == NULL)
+               return (ENOENT);
+
+       /*
+        * This code is basically copied from sys_mcontrol()
+        */
+       if (uap->behav < 0 || uap->behav > MADV_CONTROL_END)
+               return (EINVAL);
+
+       if (VM_MAXUSER_ADDRESS > 0 &&
+               ((vm_offset_t) uap->addr + uap->len) > VM_MAXUSER_ADDRESS)
+               return (EINVAL);
+#ifndef i386
+        if (VM_MIN_ADDRESS > 0 && uap->addr < VM_MIN_ADDRESS)
+               return (EINVAL);
+#endif
+       if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
+               return (EINVAL);
+
+       start = trunc_page((vm_offset_t) uap->addr);
+       end = round_page((vm_offset_t) uap->addr + uap->len);
+
+       return (vm_map_madvise(&ve->vmspace->vm_map, start, end,
+                               uap->behav, uap->value));
+}
+
+/*
+ * Red black tree functions
+ */
+static int rb_vmspace_compare(struct vmspace_entry *, struct vmspace_entry *);
+RB_GENERATE(vmspace_rb_tree, vmspace_entry, rb_entry, rb_vmspace_compare);
+   
+/* a->start is address, and the only field has to be initialized */
+static int
+rb_vmspace_compare(struct vmspace_entry *a, struct vmspace_entry *b)
+{
+        if ((char *)a->id < (char *)b->id)
+                return(-1);
+        else if ((char *)a->id > (char *)b->id)
+                return(1);
+        return(0);
+}
+
+static
+int
+rb_vmspace_delete(struct vmspace_entry *ve, void *data)
+{
+       struct vkernel *vk = data;
+
+       RB_REMOVE(vmspace_rb_tree, &vk->vk_root, ve);
+       vmspace_free(ve->vmspace);
+       kfree(ve, M_VKERNEL);
+       return(0);
+}
+
+static
+struct vmspace_entry *
+vkernel_find_vmspace(struct vkernel *vk, void *id)
+{
+       struct vmspace_entry *ve;
+       struct vmspace_entry key;
+
+       key.id = id;
+       ve = RB_FIND(vmspace_rb_tree, &vk->vk_root, &key);
+       return (ve);
+}
+
+/*
+ * Manage vkernel refs, used by the kernel when fork()ing or exit()ing
+ * a vkernel process.
+ */
+void
+vkernel_hold(struct vkernel *vk)
+{
+       ++vk->vk_refs;
+}
+
+void
+vkernel_drop(struct vkernel *vk)
 {
-       return (EINVAL);
+       KKASSERT(vk->vk_refs > 0);
+       if (--vk->vk_refs == 0) {
+               RB_SCAN(vmspace_rb_tree, &vk->vk_root, NULL,
+                       rb_vmspace_delete, vk);
+               kfree(vk, M_VKERNEL);
+       }
 }