diff -NurpP --minimal linux-2.6.0/arch/alpha/kernel/systbls.S linux-2.6.0-vs0.02/arch/alpha/kernel/systbls.S
--- linux-2.6.0/arch/alpha/kernel/systbls.S	Thu Dec 18 03:59:05 2003
+++ linux-2.6.0-vs0.02/arch/alpha/kernel/systbls.S	Sun Jan  4 22:14:18 2004
@@ -291,7 +291,7 @@ sys_call_table:
 	.quad alpha_ni_syscall			/* 270 */
 	.quad alpha_ni_syscall
 	.quad alpha_ni_syscall
-	.quad alpha_ni_syscall
+	.quad sys_vserver			/* 273 sys_vserver */
 	.quad alpha_ni_syscall
 	.quad alpha_ni_syscall			/* 275 */
 	.quad alpha_ni_syscall
diff -NurpP --minimal linux-2.6.0/arch/i386/kernel/entry.S linux-2.6.0-vs0.02/arch/i386/kernel/entry.S
--- linux-2.6.0/arch/i386/kernel/entry.S	Thu Dec 18 03:58:30 2003
+++ linux-2.6.0-vs0.02/arch/i386/kernel/entry.S	Sun Jan  4 22:14:18 2004
@@ -881,6 +881,6 @@ ENTRY(sys_call_table)
 	.long sys_tgkill	/* 270 */
 	.long sys_utimes
  	.long sys_fadvise64_64
-	.long sys_ni_syscall	/* sys_vserver */
+	.long sys_vserver
 
 syscall_table_size=(.-sys_call_table)
diff -NurpP --minimal linux-2.6.0/arch/ppc/kernel/misc.S linux-2.6.0-vs0.02/arch/ppc/kernel/misc.S
--- linux-2.6.0/arch/ppc/kernel/misc.S	Thu Dec 18 03:59:38 2003
+++ linux-2.6.0-vs0.02/arch/ppc/kernel/misc.S	Sun Jan  4 22:14:18 2004
@@ -1385,3 +1385,23 @@ _GLOBAL(sys_call_table)
 	.long sys_statfs64
 	.long sys_fstatfs64
 	.long ppc_fadvise64_64
+	.long sys_ni_syscall	/* 255 */
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall	/* 260 */
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall	/* 265 */
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_ni_syscall	/* 270 */
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_vserver	/* 273 sys_vserver */
+
diff -NurpP --minimal linux-2.6.0/arch/ppc64/kernel/misc.S linux-2.6.0-vs0.02/arch/ppc64/kernel/misc.S
--- linux-2.6.0/arch/ppc64/kernel/misc.S	Thu Dec 18 03:59:29 2003
+++ linux-2.6.0-vs0.02/arch/ppc64/kernel/misc.S	Sun Jan  4 22:14:18 2004
@@ -852,6 +852,26 @@ _GLOBAL(sys_call_table32)
 	.llong .sys32_utimes
 	.llong .sys_statfs64
 	.llong .sys_fstatfs64
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 255 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 260 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 265 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 270 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_vserver		/* 273 sys_vserver */
 
 	.balign 8
 _GLOBAL(sys_call_table)
@@ -1109,3 +1129,24 @@ _GLOBAL(sys_call_table)
 	.llong .sys_utimes
 	.llong .sys_statfs64
 	.llong .sys_fstatfs64
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 255 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 260 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 265 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall	/* 270 */
+	.llong .sys_ni_syscall
+	.llong .sys_ni_syscall
+	.llong .sys_vserver		/* 273 sys_vserver */
+
diff -NurpP --minimal linux-2.6.0/arch/s390/kernel/syscalls.S linux-2.6.0-vs0.02/arch/s390/kernel/syscalls.S
--- linux-2.6.0/arch/s390/kernel/syscalls.S	Thu Dec 18 03:58:08 2003
+++ linux-2.6.0-vs0.02/arch/s390/kernel/syscalls.S	Sun Jan  4 22:14:18 2004
@@ -271,4 +271,4 @@ SYSCALL(sys_clock_settime,sys_clock_sett
 SYSCALL(sys_clock_gettime,sys_clock_gettime,sys_ni_syscall)	/* 260 */
 SYSCALL(sys_clock_getres,sys_clock_getres,sys_ni_syscall)
 SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys_ni_syscall)
-NI_SYSCALL							/* reserved for vserver */
+SYSCALL(sys_vserver,sys_vserver,sys_vserver)
diff -NurpP --minimal linux-2.6.0/arch/sparc/kernel/systbls.S linux-2.6.0-vs0.02/arch/sparc/kernel/systbls.S
--- linux-2.6.0/arch/sparc/kernel/systbls.S	Thu Dec 18 03:58:49 2003
+++ linux-2.6.0-vs0.02/arch/sparc/kernel/systbls.S	Sun Jan  4 22:14:18 2004
@@ -72,7 +72,7 @@ sys_call_table:
 /*250*/	.long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
 /*255*/	.long sys_nis_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/	.long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
-/*265*/	.long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
+/*265*/	.long sys_timer_delete, sys_timer_create, sys_vserver, sys_io_setup, sys_io_destroy
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_nis_syscall
 
 #ifdef CONFIG_SUNOS_EMUL
diff -NurpP --minimal linux-2.6.0/arch/sparc64/kernel/systbls.S linux-2.6.0-vs0.02/arch/sparc64/kernel/systbls.S
--- linux-2.6.0/arch/sparc64/kernel/systbls.S	Thu Dec 18 03:58:48 2003
+++ linux-2.6.0-vs0.02/arch/sparc64/kernel/systbls.S	Sun Jan  4 22:14:18 2004
@@ -72,7 +72,7 @@ sys_call_table32:
 /*250*/	.word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
 	.word sys_ni_syscall, compat_clock_settime, compat_clock_gettime, compat_clock_getres, compat_clock_nanosleep
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, compat_timer_settime, compat_timer_gettime, sys_timer_getoverrun
-	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
+	.word sys_timer_delete, sys32_timer_create, sys_vserver, sys_ni_syscall, sys_ni_syscall
 /*270*/	.word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 	/* Now the 64-bit native Linux syscall table. */
@@ -134,7 +134,7 @@ sys_call_table:
 /*250*/	.word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
 	.word sys_ni_syscall, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
 /*260*/	.word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
-	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
+	.word sys_timer_delete, sys_timer_create, sys_vserver, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_ni_syscall
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
diff -NurpP --minimal linux-2.6.0/arch/x86_64/ia32/ia32entry.S linux-2.6.0-vs0.02/arch/x86_64/ia32/ia32entry.S
--- linux-2.6.0/arch/x86_64/ia32/ia32entry.S	Thu Dec 18 03:58:48 2003
+++ linux-2.6.0-vs0.02/arch/x86_64/ia32/ia32entry.S	Sun Jan  4 22:14:18 2004
@@ -448,34 +448,35 @@ ia32_sys_call_table:
         .quad compat_sys_sched_getaffinity
 	.quad sys32_set_thread_area
 	.quad sys32_get_thread_area
-	.quad sys32_io_setup
+	.quad sys32_io_setup	/* 245 */
 	.quad sys_io_destroy
 	.quad sys32_io_getevents
 	.quad sys32_io_submit
 	.quad sys_io_cancel
-	.quad sys_fadvise64
+	.quad sys_fadvise64	/* 250 */
 	.quad sys_ni_syscall /* free_huge_pages */
 	.quad sys_exit_group /* exit_group */
 	.quad sys_lookup_dcookie
 	.quad sys_epoll_create
-	.quad sys_epoll_ctl
+	.quad sys_epoll_ctl	/* 255 */
 	.quad sys_epoll_wait
 	.quad sys_remap_file_pages
 	.quad sys_set_tid_address
 	.quad sys32_timer_create
-	.quad compat_timer_settime
+	.quad compat_timer_settime	/* 260 */
 	.quad compat_timer_gettime
 	.quad sys_timer_getoverrun
 	.quad sys_timer_delete
 	.quad compat_clock_settime
-	.quad compat_clock_gettime
+	.quad compat_clock_gettime	/* 265 */
 	.quad compat_clock_getres
 	.quad compat_clock_nanosleep
 	.quad compat_statfs64   /* statfs64 */
 	.quad compat_fstatfs64  /* fstatfs64 */
-	.quad sys_tgkill
+	.quad sys_tgkill	/* 270 */
 	.quad compat_sys_utimes
 	.quad sys32_fadvise64_64
+	.quad sys_vserver	/* 273 sys_vserver */
 	/* don't forget to change IA32_NR_syscalls */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
diff -NurpP --minimal linux-2.6.0/fs/inode.c linux-2.6.0-vs0.02/fs/inode.c
--- linux-2.6.0/fs/inode.c	Thu Dec 18 03:59:55 2003
+++ linux-2.6.0-vs0.02/fs/inode.c	Sun Jan  4 22:14:18 2004
@@ -131,6 +131,7 @@ static struct inode *alloc_inode(struct 
 		inode->i_bdev = NULL;
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
+		inode->i_xid = 0;	/* maybe not too wise ... */
 		inode->i_security = NULL;
 		if (security_inode_alloc(inode)) {
 			if (inode->i_sb->s_op->destroy_inode)
diff -NurpP --minimal linux-2.6.0/fs/proc/Makefile linux-2.6.0-vs0.02/fs/proc/Makefile
--- linux-2.6.0/fs/proc/Makefile	Thu Dec 18 03:58:07 2003
+++ linux-2.6.0-vs0.02/fs/proc/Makefile	Sun Jan  4 22:14:18 2004
@@ -8,7 +8,7 @@ proc-y			:= task_nommu.o
 proc-$(CONFIG_MMU)	:= task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
-		kmsg.o proc_tty.o proc_misc.o
+		kmsg.o proc_tty.o proc_misc.o virtual.o
 
 proc-$(CONFIG_PROC_KCORE)	+= kcore.o
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
diff -NurpP --minimal linux-2.6.0/fs/proc/base.c linux-2.6.0-vs0.02/fs/proc/base.c
--- linux-2.6.0/fs/proc/base.c	Thu Dec 18 03:58:58 2003
+++ linux-2.6.0-vs0.02/fs/proc/base.c	Sun Jan  4 22:14:18 2004
@@ -32,6 +32,7 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include <linux/vcontext.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -67,6 +68,7 @@ enum pid_directory_inos {
 	PROC_TGID_ATTR_EXEC,
 	PROC_TGID_ATTR_FSCREATE,
 #endif
+	PROC_TGID_VINFO,
 	PROC_TGID_FD_DIR,
 	PROC_TID_INO,
 	PROC_TID_STATUS,
@@ -90,6 +92,7 @@ enum pid_directory_inos {
 	PROC_TID_ATTR_EXEC,
 	PROC_TID_ATTR_FSCREATE,
 #endif
+	PROC_TID_VINFO,
 	PROC_TID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
@@ -123,6 +126,7 @@ static struct pid_entry tgid_base_stuff[
 #ifdef CONFIG_KALLSYMS
 	E(PROC_TGID_WCHAN,     "wchan",   S_IFREG|S_IRUGO),
 #endif
+	E(PROC_TGID_VINFO,     "vinfo",   S_IFREG|S_IRUGO),
 	{0,0,NULL,0}
 };
 static struct pid_entry tid_base_stuff[] = {
@@ -145,6 +149,7 @@ static struct pid_entry tid_base_stuff[]
 #ifdef CONFIG_KALLSYMS
 	E(PROC_TID_WCHAN,      "wchan",   S_IFREG|S_IRUGO),
 #endif
+	E(PROC_TID_VINFO,      "vinfo",   S_IFREG|S_IRUGO),
 	{0,0,NULL,0}
 };
 
@@ -181,6 +186,7 @@ int proc_pid_stat(struct task_struct*,ch
 int proc_pid_status(struct task_struct*,char*);
 int proc_pid_statm(struct task_struct*,char*);
 int proc_pid_cpu(struct task_struct*,char*);
+int proc_pid_vinfo(struct task_struct*,char*);
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
@@ -932,6 +938,7 @@ static struct inode *proc_pid_make_inode
 		inode->i_uid = task->euid;
 		inode->i_gid = task->egid;
 	}
+	inode->i_xid = vx_task_id(task);
 	security_task_to_inode(task, inode);
 
 out:
@@ -1361,6 +1368,11 @@ static struct dentry *proc_pident_lookup
 			ei->op.proc_read = proc_pid_wchan;
 			break;
 #endif
+		case PROC_TID_VINFO:
+		case PROC_TGID_VINFO:
+			inode->i_fop = &proc_info_file_operations;
+			ei->op.proc_read = proc_pid_vinfo;
+			break;
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
@@ -1552,6 +1564,10 @@ struct dentry *proc_pid_lookup(struct in
 	if (!task)
 		goto out;
 
+	if (tgid != 1 && !vx_check(task->vx_info, VX_WATCH|VX_IDENT)) {
+		put_task_struct(task);
+		goto out;
+	}
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
 
 
@@ -1599,7 +1615,6 @@ static struct dentry *proc_task_lookup(s
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
 
-
 	if (!inode) {
 		put_task_struct(task);
 		goto out;
@@ -1641,6 +1656,10 @@ static int get_tgid_list(int index, unsi
 	for_each_process(p) {
 		int tgid = p->pid;
 		if (!pid_alive(p))
+			continue;
+		if (tgid != 1 && !vx_check(p->vx_info, VX_WATCH|VX_IDENT))
+			continue;
+		if (current->vx_info && current->vx_info->vx_initpid == tgid)
 			continue;
 		if (--index >= 0)
 			continue;
diff -NurpP --minimal linux-2.6.0/fs/proc/generic.c linux-2.6.0-vs0.02/fs/proc/generic.c
--- linux-2.6.0/fs/proc/generic.c	Thu Dec 18 03:59:57 2003
+++ linux-2.6.0-vs0.02/fs/proc/generic.c	Sun Jan  4 22:14:18 2004
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/smp_lock.h>
+#include <linux/vcontext.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 
@@ -424,9 +425,12 @@ int proc_readdir(struct file * filp,
 			}
 
 			do {
+				if (de->vx_flags && !vx_check_id(de->xid, de->vx_flags))
+					goto skip;
 				if (filldir(dirent, de->name, de->namelen, filp->f_pos,
 					    de->low_ino, de->mode >> 12) < 0)
 					goto out;
+			skip:
 				filp->f_pos++;
 				de = de->next;
 			} while (de);
diff -NurpP --minimal linux-2.6.0/fs/proc/inode.c linux-2.6.0-vs0.02/fs/proc/inode.c
--- linux-2.6.0/fs/proc/inode.c	Thu Dec 18 03:59:36 2003
+++ linux-2.6.0-vs0.02/fs/proc/inode.c	Sun Jan  4 22:14:18 2004
@@ -207,6 +207,9 @@ printk("proc_iget: using deleted entry %
 			inode->i_uid = de->uid;
 			inode->i_gid = de->gid;
 		}
+		inode->i_xid = de->xid;
+		if (de->vx_flags)
+			PROC_I(inode)->vx_flags = de->vx_flags;
 		if (de->size)
 			inode->i_size = de->size;
 		if (de->nlink)
diff -NurpP --minimal linux-2.6.0/fs/proc/root.c linux-2.6.0-vs0.02/fs/proc/root.c
--- linux-2.6.0/fs/proc/root.c	Thu Dec 18 03:59:17 2003
+++ linux-2.6.0-vs0.02/fs/proc/root.c	Sun Jan  4 22:14:18 2004
@@ -23,6 +23,7 @@ struct proc_dir_entry *proc_net, *proc_b
 #ifdef CONFIG_SYSCTL
 struct proc_dir_entry *proc_sys_root;
 #endif
+struct proc_dir_entry *proc_virtual;
 
 static struct super_block *proc_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
@@ -78,6 +79,7 @@ void __init proc_root_init(void)
 	proc_rtas_init();
 #endif
 	proc_bus = proc_mkdir("bus", 0);
+	proc_virtual = proc_mkdir("virtual", 0);
 }
 
 static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
diff -NurpP --minimal linux-2.6.0/fs/proc/virtual.c linux-2.6.0-vs0.02/fs/proc/virtual.c
--- linux-2.6.0/fs/proc/virtual.c	Thu Jan  1 01:00:00 1970
+++ linux-2.6.0-vs0.02/fs/proc/virtual.c	Sun Jan  4 22:14:18 2004
@@ -0,0 +1,181 @@
+/*
+ *  linux/fs/proc/virtual.c
+ *
+ *  Virtual Context ProcFS Support
+ *
+ *  Copyright (C) 2003  Herbert Pötzl
+ *
+ *  V0.01  basic directory array
+ *  V0.02  per context info & stat
+ *  V0.03  proc permissions
+ *
+ */
+
+#include <asm/uaccess.h>
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <linux/vcontext.h>
+#include <linux/vswitch.h>
+
+
+extern struct proc_dir_entry *proc_virtual;
+static struct proc_dir_entry *proc_virtual_info;
+
+
+char *task_vinfo(struct task_struct *p, char *buffer)
+{
+	return buffer + sprintf(buffer,
+		"VxID:\t%d\n"
+		,__vx_id(p->vx_info));
+}
+
+int proc_pid_vinfo(struct task_struct *p, char *buffer)
+{
+	char * orig = buffer;
+
+        buffer = task_vinfo(p, buffer);
+        return buffer - orig;
+}
+
+
+static int __generic_info_read_func(char *page, char **start,
+	off_t off, int count, int *eof, void *data,
+	char *(*info_func)(void *, char *))
+{
+	int len;
+	char *buffer = page;
+
+	buffer = info_func(data, buffer);
+
+	len = buffer-page;
+	if (len <= off+count) *eof = 1;
+	
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
+	return len;
+}
+
+char *vx_proc_info (void *data, char *buffer)
+{
+	struct vx_info *vxi = data;
+	buffer += sprintf(buffer,
+		"VxID:\t%d\n"
+		"Info:\t%p\n"
+		"Init:\t%d\n"
+		,__vx_id(vxi)
+		,vxi
+		,vxi->vx_initpid);
+	return buffer;
+}
+
+int vx_info_read_func (char *page, char **start,
+	off_t off, int count, int *eof, void *data)
+{
+	return __generic_info_read_func(page, start,
+	    off, count, eof, data, vx_proc_info);
+}
+
+char *vx_proc_status (void *data, char *buffer)
+{
+	struct vx_info *vxi = data;
+	buffer += sprintf(buffer,
+		"RefC:\t%d\n"		
+		"Flags:\t%08x\n"
+		"Ticks:\t%d\n"		
+		,atomic_read(&vxi->vx_refcount)
+		,vxi->vx_flags
+		,atomic_read(&vxi->limit.ticks));
+	return buffer;
+}
+
+int vx_status_read_func (char *page, char **start,
+	off_t off, int count, int *eof, void *data)
+{
+	return __generic_info_read_func(page, start,
+	    off, count, eof, data, vx_proc_status);
+}
+
+
+static int vx_proc_permission(struct inode *inode,
+	int mask, struct nameidata *nd)
+{
+	dprintk("vx_proc_permission(%p) = #%d,%04x\n",
+		inode, inode->i_xid, PROC_I(inode)->vx_flags);
+	if (vx_check_id(inode->i_xid, PROC_I(inode)->vx_flags))
+		return 0;
+	dprintk("vx_proc_permission(%p) #%d != #%d\n",
+		inode, inode->i_xid, vx_current_id());
+	return -ENOENT;
+}
+
+static struct inode_operations vx_proc_inode_operations = {
+	.lookup = proc_lookup,
+	.permission = vx_proc_permission,
+};
+
+
+int vx_proc_create(struct vx_info *vxi)
+{
+	struct proc_dir_entry *entry, *sub;
+	char name[8];
+
+	snprintf(name, sizeof(name)-1, "%d", __vx_id(vxi));
+	entry = create_proc_entry(name,
+		S_IFDIR|S_IXUGO, proc_virtual);
+	entry->vx_flags = VX_ADMIN|VX_WATCH|VX_SAME;
+	entry->xid = __vx_id(vxi);
+	entry->proc_iops = &vx_proc_inode_operations;
+        vxi->vx_procent = entry;
+	sub = create_proc_read_entry("info",
+		S_IFREG|S_IRUGO|S_IWUSR,
+		entry, vx_info_read_func, vxi);
+	sub = create_proc_read_entry("status",
+		S_IFREG|S_IRUGO|S_IWUSR,
+		entry, vx_status_read_func, vxi);
+	return 0;
+}
+
+int vx_proc_destroy(struct vx_info *vxi)
+{
+	struct proc_dir_entry *entry = vxi->vx_procent;
+	if (!entry)
+	    return 0;
+	remove_proc_entry(entry->name, proc_virtual);
+	vxi->vx_procent = NULL;
+	return 0;
+}
+
+char *vs_proc_info(void *data, char *buffer)
+{
+	buffer += sprintf(buffer,
+		"VCIVersion:\t%04x:%04x\n"
+		,VCI_VERSION >> 16
+		,VCI_VERSION & 0xFFFF);
+	return buffer;
+}
+
+int vs_info_read_func(char *page, char **start,
+	off_t off, int count, int *eof, void *data)
+{
+	return __generic_info_read_func(page, start,
+	    off, count, eof, data, vs_proc_info);
+}
+
+
+static int __init virtual_proc_init(void)
+{
+	proc_virtual_info = create_proc_read_entry("info",
+		S_IFREG|S_IRUGO|S_IWUSR,
+		proc_virtual, vs_info_read_func, NULL);
+	return 0;
+}
+
+__initcall(virtual_proc_init);
diff -NurpP --minimal linux-2.6.0/include/asm-alpha/unistd.h linux-2.6.0-vs0.02/include/asm-alpha/unistd.h
--- linux-2.6.0/include/asm-alpha/unistd.h	Thu Dec 18 03:58:47 2003
+++ linux-2.6.0-vs0.02/include/asm-alpha/unistd.h	Sun Jan  4 22:14:18 2004
@@ -233,6 +233,7 @@
 #define __NR_osf_memcntl	260	/* not implemented */
 #define __NR_osf_fdatasync	261	/* not implemented */
 
+#define __NR_vserver		273
 
 /*
  * Linux-specific system calls begin at 300
diff -NurpP --minimal linux-2.6.0/include/asm-m68k/unistd.h linux-2.6.0-vs0.02/include/asm-m68k/unistd.h
--- linux-2.6.0/include/asm-m68k/unistd.h	Thu Dec 18 03:58:49 2003
+++ linux-2.6.0-vs0.02/include/asm-m68k/unistd.h	Sun Jan  4 22:14:18 2004
@@ -239,7 +239,9 @@
 #define __NR_fremovexattr	234
 #define __NR_futex		235
 
-#define NR_syscalls		236
+#define __NR_vserver		273
+
+#define NR_syscalls		274
 
 /* user-visible error numbers are in the range -1 - -124: see
    <asm-m68k/errno.h> */
diff -NurpP --minimal linux-2.6.0/include/asm-m68knommu/unistd.h linux-2.6.0-vs0.02/include/asm-m68knommu/unistd.h
--- linux-2.6.0/include/asm-m68knommu/unistd.h	Thu Dec 18 03:58:50 2003
+++ linux-2.6.0-vs0.02/include/asm-m68knommu/unistd.h	Sun Jan  4 22:14:18 2004
@@ -221,7 +221,9 @@
 #define __NR_setfsuid32		215
 #define __NR_setfsgid32		216
 
-#define	NR_syscalls		256
+#define __NR_vserver		273
+
+#define	NR_syscalls		274
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
diff -NurpP --minimal linux-2.6.0/include/asm-mips/unistd.h linux-2.6.0-vs0.02/include/asm-mips/unistd.h
--- linux-2.6.0/include/asm-mips/unistd.h	Thu Dec 18 03:58:04 2003
+++ linux-2.6.0-vs0.02/include/asm-mips/unistd.h	Sun Jan  4 22:14:18 2004
@@ -289,10 +289,12 @@
 #define __NR_tgkill			(__NR_Linux + 266)
 #define __NR_utimes			(__NR_Linux + 267)
 
+#define __NR_vserver			(__NR_Linux + 273)
+
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		267
+#define __NR_Linux_syscalls		273
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
diff -NurpP --minimal linux-2.6.0/include/asm-parisc/unistd.h linux-2.6.0-vs0.02/include/asm-parisc/unistd.h
--- linux-2.6.0/include/asm-parisc/unistd.h	Thu Dec 18 03:57:59 2003
+++ linux-2.6.0-vs0.02/include/asm-parisc/unistd.h	Sun Jan  4 22:14:18 2004
@@ -722,8 +722,9 @@
 #define __NR_remap_file_pages	(__NR_Linux + 227)
 #define __NR_semtimedop		(__NR_Linux + 228)
 
+#define __NR_vserver		(__NR_Linux + 273)
 
-#define __NR_Linux_syscalls     228
+#define __NR_Linux_syscalls     273
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
diff -NurpP --minimal linux-2.6.0/include/asm-ppc/unistd.h linux-2.6.0-vs0.02/include/asm-ppc/unistd.h
--- linux-2.6.0/include/asm-ppc/unistd.h	Thu Dec 18 03:58:18 2003
+++ linux-2.6.0-vs0.02/include/asm-ppc/unistd.h	Sun Jan  4 22:14:18 2004
@@ -260,7 +260,9 @@
 #define __NR_fstatfs64		253
 #define __NR_fadvise64_64	254
 
-#define __NR_syscalls		255
+#define __NR_vserver		273
+
+#define __NR_syscalls		274
 
 #define __NR(n)	#n
 
diff -NurpP --minimal linux-2.6.0/include/asm-ppc64/unistd.h linux-2.6.0-vs0.02/include/asm-ppc64/unistd.h
--- linux-2.6.0/include/asm-ppc64/unistd.h	Thu Dec 18 03:58:04 2003
+++ linux-2.6.0-vs0.02/include/asm-ppc64/unistd.h	Sun Jan  4 22:14:18 2004
@@ -265,7 +265,9 @@
 #define __NR_statfs64		252
 #define __NR_fstatfs64		253
 
-#define __NR_syscalls		254
+#define __NR_vserver		273
+
+#define __NR_syscalls		274
 #ifdef __KERNEL__
 #define NR_syscalls	__NR_syscalls
 #endif
diff -NurpP --minimal linux-2.6.0/include/asm-s390/unistd.h linux-2.6.0-vs0.02/include/asm-s390/unistd.h
--- linux-2.6.0/include/asm-s390/unistd.h	Thu Dec 18 04:00:01 2003
+++ linux-2.6.0-vs0.02/include/asm-s390/unistd.h	Sun Jan  4 22:14:18 2004
@@ -256,9 +256,7 @@
 #define __NR_clock_gettime	(__NR_timer_create+6)
 #define __NR_clock_getres	(__NR_timer_create+7)
 #define __NR_clock_nanosleep	(__NR_timer_create+8)
-/*
- * Number 263 is reserved for vserver
- */
+#define __NR_vserver		263
 
 #define NR_syscalls 264
 
diff -NurpP --minimal linux-2.6.0/include/asm-sh/unistd.h linux-2.6.0-vs0.02/include/asm-sh/unistd.h
--- linux-2.6.0/include/asm-sh/unistd.h	Thu Dec 18 03:59:29 2003
+++ linux-2.6.0-vs0.02/include/asm-sh/unistd.h	Sun Jan  4 22:14:18 2004
@@ -276,7 +276,9 @@
 #define __NR_clock_getres	(__NR_timer_create+7)
 #define __NR_clock_nanosleep	(__NR_timer_create+8)
 
-#define NR_syscalls 268
+#define __NR_vserver		273
+
+#define NR_syscalls		274
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
 
diff -NurpP --minimal linux-2.6.0/include/asm-sparc/unistd.h linux-2.6.0-vs0.02/include/asm-sparc/unistd.h
--- linux-2.6.0/include/asm-sparc/unistd.h	Thu Dec 18 03:58:08 2003
+++ linux-2.6.0-vs0.02/include/asm-sparc/unistd.h	Sun Jan  4 22:14:18 2004
@@ -283,7 +283,7 @@
 #define __NR_timer_getoverrun	264
 #define __NR_timer_delete	265
 #define __NR_timer_create	266
-/* #define __NR_vserver		267 Reserved for VSERVER */
+#define __NR_vserver		267
 #define __NR_io_setup		268
 #define __NR_io_destroy		268
 #define __NR_io_submit		269
diff -NurpP --minimal linux-2.6.0/include/asm-sparc64/unistd.h linux-2.6.0-vs0.02/include/asm-sparc64/unistd.h
--- linux-2.6.0/include/asm-sparc64/unistd.h	Thu Dec 18 03:58:16 2003
+++ linux-2.6.0-vs0.02/include/asm-sparc64/unistd.h	Sun Jan  4 22:14:18 2004
@@ -285,7 +285,7 @@
 #define __NR_timer_getoverrun	264
 #define __NR_timer_delete	265
 #define __NR_timer_create	266
-/* #define __NR_vserver		267 Reserved for VSERVER */
+#define __NR_vserver		267
 #define __NR_io_setup		268
 #define __NR_io_destroy		268
 #define __NR_io_submit		269
diff -NurpP --minimal linux-2.6.0/include/asm-x86_64/ia32_unistd.h linux-2.6.0-vs0.02/include/asm-x86_64/ia32_unistd.h
--- linux-2.6.0/include/asm-x86_64/ia32_unistd.h	Thu Dec 18 03:59:05 2003
+++ linux-2.6.0-vs0.02/include/asm-x86_64/ia32_unistd.h	Sun Jan  4 22:14:18 2004
@@ -278,6 +278,7 @@
 #define __NR_ia32_tgkill		270
 #define __NR_ia32_utimes		271
 #define __NR_ia32_fadvise64_64		272
+#define __NR_ia32_vserver		273
 
 #define IA32_NR_syscalls 275	/* must be > than biggest syscall! */	
 
diff -NurpP --minimal linux-2.6.0/include/linux/fs.h linux-2.6.0-vs0.02/include/linux/fs.h
--- linux-2.6.0/include/linux/fs.h	Thu Dec 18 03:58:29 2003
+++ linux-2.6.0-vs0.02/include/linux/fs.h	Sun Jan  4 22:14:18 2004
@@ -376,6 +376,7 @@ struct inode {
 	unsigned int		i_nlink;
 	uid_t			i_uid;
 	gid_t			i_gid;
+	xid_t			i_xid;
 	dev_t			i_rdev;
 	loff_t			i_size;
 	struct timespec		i_atime;
diff -NurpP --minimal linux-2.6.0/include/linux/proc_fs.h linux-2.6.0-vs0.02/include/linux/proc_fs.h
--- linux-2.6.0/include/linux/proc_fs.h	Thu Dec 18 03:57:58 2003
+++ linux-2.6.0-vs0.02/include/linux/proc_fs.h	Sun Jan  4 22:14:18 2004
@@ -60,6 +60,8 @@ struct proc_dir_entry {
 	nlink_t nlink;
 	uid_t uid;
 	gid_t gid;
+	xid_t xid;
+	int vx_flags;
 	unsigned long size;
 	struct inode_operations * proc_iops;
 	struct file_operations * proc_fops;
@@ -236,6 +238,7 @@ extern struct kcore_list *kclist_del(voi
 struct proc_inode {
 	struct task_struct *task;
 	int type;
+	int vx_flags;
 	union {
 		int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
 		int (*proc_read)(struct task_struct *task, char *page);
diff -NurpP --minimal linux-2.6.0/include/linux/sched.h linux-2.6.0-vs0.02/include/linux/sched.h
--- linux-2.6.0/include/linux/sched.h	Thu Dec 18 03:58:08 2003
+++ linux-2.6.0-vs0.02/include/linux/sched.h	Sun Jan  4 22:14:18 2004
@@ -297,9 +297,10 @@ struct user_struct {
 	/* Hash table maintenance information */
 	struct list_head uidhash_list;
 	uid_t uid;
+	int vx_id;
 };
 
-extern struct user_struct *find_user(uid_t);
+extern struct user_struct *find_user(xid_t, uid_t);
 
 extern struct user_struct root_user;
 #define INIT_USER (&root_user)
@@ -441,6 +442,10 @@ struct task_struct {
 	
 	void *security;
 
+	kernel_cap_t cap_bset;
+	struct vx_info *vx_info;
+	// struct iproot_info *ip_info;
+
 /* Thread group tracking */
    	u32 parent_exec_id;
    	u32 self_exec_id;
@@ -562,7 +567,7 @@ extern void set_special_pids(pid_t sessi
 extern void __set_special_pids(pid_t session, pid_t pgrp);
 
 /* per-UID process charging. */
-extern struct user_struct * alloc_uid(uid_t);
+extern struct user_struct * alloc_uid(xid_t, uid_t);
 extern void free_uid(struct user_struct *);
 extern void switch_uid(struct user_struct *);
 
diff -NurpP --minimal linux-2.6.0/include/linux/types.h linux-2.6.0-vs0.02/include/linux/types.h
--- linux-2.6.0/include/linux/types.h	Thu Dec 18 03:59:30 2003
+++ linux-2.6.0-vs0.02/include/linux/types.h	Sun Jan  4 22:14:18 2004
@@ -37,6 +37,7 @@ typedef __kernel_uid32_t	uid_t;
 typedef __kernel_gid32_t	gid_t;
 typedef __kernel_uid16_t        uid16_t;
 typedef __kernel_gid16_t        gid16_t;
+typedef unsigned int		xid_t;
 
 #ifdef CONFIG_UID16
 /* This is defined by include/asm-{arch}/posix_types.h */
diff -NurpP --minimal linux-2.6.0/include/linux/vcontext.h linux-2.6.0-vs0.02/include/linux/vcontext.h
--- linux-2.6.0/include/linux/vcontext.h	Thu Jan  1 01:00:00 1970
+++ linux-2.6.0-vs0.02/include/linux/vcontext.h	Sun Jan  4 22:14:18 2004
@@ -0,0 +1,164 @@
+#ifndef _VX_CONTEXT_H
+#define _VX_CONTEXT_H
+
+#define DEBUG_VX
+#if defined(DEBUG) || defined(DEBUG_VX)
+#include <linux/kernel.h>
+#define dprintk(x...) printk("vxd: " x)
+#else
+#define dprintk(x...)
+#endif
+
+
+#define VX_INFO_LOCK		1	/* Can't request a new vx_id */
+#define VX_INFO_SCHED		2	/* All process in the vx_id */
+					/* Contribute to the schedular */
+#define VX_INFO_NPROC		4	/* Limit number of processes in a context */
+#define VX_INFO_PRIVATE		8	/* Noone can join this security context */
+#define VX_INFO_INIT		16	/* This process wants to become the */
+					/* logical process 1 of the security */
+					/* context */
+#define VX_INFO_HIDEINFO	32	/* Hide some information in /proc */
+#define VX_INFO_ULIMIT		64	/* Use ulimit of the current process */
+					/* to become the global limits */
+					/* of the context */
+	
+#define MAX_S_CONTEXT 65535	/* Arbitrary limit */
+#define MIN_D_CONTEXT 49152	/* dynamic contexts start here */
+
+#define NB_S_CONTEXT	16
+
+#define NB_IPV4ROOT	16
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/utsname.h>
+#include <asm/resource.h>
+#include <asm/atomic.h>
+
+
+extern struct list_head vx_infos;
+extern spinlock_t vxlist_lock;
+
+
+struct _vx_virt {
+	int nr_threads;
+	int nr_running;
+	int max_threads;
+	unsigned long total_forks;
+		
+	unsigned int bias_cswtch;
+	long bias_jiffies;
+	long bias_idle;
+
+	struct new_utsname utsname;
+};
+
+struct _vx_limit {
+	atomic_t ticks;
+
+	unsigned long rlim[RLIM_NLIMITS];	/* Per context limit */
+	atomic_t res[RLIM_NLIMITS];		/* Current value */
+};
+
+struct vx_info {
+	struct list_head vx_list;		/* linked list of contexts */
+	xid_t vx_id;				/* context id */
+	atomic_t vx_refcount;			/* refcount */
+	struct vx_info *vx_parent;		/* parent context */
+
+	struct proc_dir_entry *vx_procent;	/* proc entry */
+	unsigned int vx_flags;			/* VX_INFO_xxx */
+	pid_t vx_initpid;			/* PID of fake init process */
+
+	struct _vx_virt virt;			/* virtual/bias stuff */
+	struct _vx_limit limit;			/* vserver limits */
+};
+
+struct vx_net {
+	atomic_t refcount;
+};
+
+
+void free_vx_info(struct vx_info *);
+extern int proc_pid_vinfo(struct task_struct *, char *);
+
+static inline struct vx_info *get_vx_info(struct vx_info *vxi)
+{
+	dprintk("get_vx_info(%p[#%d.%d])\n", vxi,
+		vxi->vx_id, atomic_read(&vxi->vx_refcount));
+	atomic_inc(&vxi->vx_refcount);
+	return vxi;
+}
+
+static inline void put_vx_info(struct vx_info *vxi)
+{
+	/* for now we allow vxi to be null */
+	if (!vxi)
+		return;
+	dprintk("put_vx_info(%p[#%d.%d])\n", vxi,
+		vxi->vx_id, atomic_read(&vxi->vx_refcount));
+	if (atomic_dec_and_lock(&vxi->vx_refcount, &vxlist_lock)) {
+		list_del(&vxi->vx_list);
+		spin_unlock(&vxlist_lock);
+		free_vx_info(vxi);
+	}
+}
+
+
+#define	VX_ADMIN	0x0001
+#define	VX_WATCH	0x0002
+
+#define	VX_IDENT	0x0010		/* pointer based */
+#define	VX_SAME		0x0020		/* id based */
+#define	VX_PARENT	0x0040
+#define	VX_CHILD	0x0080
+
+#define	VX_ARG_MASK	0x00F0
+
+#include <asm/current.h>
+
+/* required to resolve recursive dependancies */
+#define vx_task_id(t)	__vx_id(t->vx_info)
+
+#define vx_current_id() vx_task_id(current)
+
+static inline int __vx_id(struct vx_info *vxi)
+{
+	if (!vxi)
+		return 0;
+	return vxi->vx_id;
+}
+
+/* required to resolve recursive dependancies */
+#define vx_check(c,m)		\
+	__vx_check(current->vx_info,c,__vx_id(c),m)
+	
+#define vx_check_id(c,m)	\
+	__vx_check(current->vx_info,0,c,m)
+
+/*
+ * check current context for ADMIN/WATCH and
+ * optionally agains supplied argument
+ */
+static inline int __vx_check(struct vx_info *cvxi,
+	struct vx_info *vxi, int id, unsigned int mode)
+{
+	if (mode & VX_ARG_MASK) {
+		if ((mode & VX_IDENT) &&
+			(vxi == cvxi))
+			return 1;
+		if ((mode & VX_SAME) &&
+			(__vx_id(cvxi) == id))
+			return 1;
+	}
+	return (((mode & VX_ADMIN) && (cvxi == 0)) ||
+		((mode & VX_WATCH) && (cvxi) &&
+		(__vx_id(cvxi) == 1)));
+}
+
+
+int vc_new_s_context(uint32_t, void *);
+int vc_set_ipv4root(uint32_t, void *);
+
+#endif
diff -NurpP --minimal linux-2.6.0/include/linux/vswitch.h linux-2.6.0-vs0.02/include/linux/vswitch.h
--- linux-2.6.0/include/linux/vswitch.h	Thu Jan  1 01:00:00 1970
+++ linux-2.6.0-vs0.02/include/linux/vswitch.h	Sun Jan  4 22:14:18 2004
@@ -0,0 +1,122 @@
+#ifndef _LINUX_VIRTUAL_H
+#define _LINUX_VIRTUAL_H
+
+#include <linux/types.h>
+#include <linux/vcontext.h>
+
+#define VC_CATEGORY(c)		(((c) >> 24) & 0x3F)
+#define VC_COMMAND(c)		(((c) >> 16) & 0xFF)
+#define VC_VERSION(c)		((c) & 0xFFF)
+
+#define VC_CMD(c,i,v)		((((VC_CAT_ ## c) & 0x3F) << 24) \
+				| (((i) & 0xFF) << 16) | ((v) & 0xFFF))
+
+/*
+
+  Syscall Matrix V2.3
+
+         |VERSION|CREATE |MODIFY |MIGRATE|CONTROL|EXPERIM| |SPECIAL|SPECIAL|
+         |STATS  |DESTROY|ALTER  |CHANGE |LIMIT  |TEST   | |       |       |
+         |INFO   |SETUP  |       |MOVE   |       |       | |       |       |
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  SYSTEM |VERSION|       |       |       |       |       | |DEVICES|       |
+  HOST   |     00|     01|     02|     03|     04|     05| |     06|     07|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  CPU    |       |       |       |       |       |       | |SCHED. |       |
+  PROCESS|     08|     09|     10|     11|     12|     13| |     14|     15|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  MEMORY |       |       |       |       |       |       | |SWAP   |       |
+         |     16|     17|     18|     19|     20|     21| |     22|     23|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  NETWORK|       |       |       |       |       |       | |SERIAL |       |
+         |     24|     25|     26|     27|     28|     29| |     30|     31|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  DISK   |       |       |       |       |       |       | |       |       |
+  VFS    |     32|     33|     34|     35|     36|     37| |     38|     39|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  OTHER  |       |       |       |       |       |       | |       |       |
+         |     40|     41|     42|     43|     44|     45| |     46|     47|
+  =======+=======+=======+=======+=======+=======+=======+ +=======+=======+
+  SPECIAL|       |       |       |       |       |       | |       |       |
+         |     48|     49|     50|     51|     52|     53| |     54|     55|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+  SPECIAL|       |       |       |       |RLIMIT |SYSCALL| |       |COMPAT |
+         |     56|     57|     58|     59|     60|TEST 61| |     62|     63|
+  -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
+
+*/
+
+#define VC_CAT_VERSION		0
+	
+#define VC_CAT_PROCTRL		12
+
+#define VC_CAT_RLIMIT		60
+
+#define VC_CAT_SYSTEST		61
+#define VC_CAT_COMPAT		63
+	
+/*  interface version */
+
+#define VCI_VERSION		0x00010004
+
+
+
+/*  query version */
+
+#define VCMD_get_version	VC_CMD(VERSION, 0, 0)
+
+
+/*  compatibiliy vserver commands */
+
+#define VCMD_new_s_context	VC_CMD(COMPAT, 1, 1)
+#define VCMD_set_ipv4root	VC_CMD(COMPAT, 2, 3)
+
+/*  compatibiliy vserver arguments */
+
+struct  vcmd_new_s_context_v1 {
+	uint32_t remove_cap;
+	uint32_t flags;
+};
+
+struct  vcmd_set_ipv4root_v3 {
+	/* number of pairs in id */
+	uint32_t broadcast;
+	struct {
+		uint32_t ip;
+		uint32_t mask;
+	} ip_mask_pair[NB_IPV4ROOT];
+};
+
+/*  context signalling */
+
+#define VCMD_ctx_kill		VC_CMD(PROCTRL, 1, 0)
+
+struct  vcmd_ctx_kill_v0 {
+	int32_t pid;
+	int32_t sig;
+};
+
+/*  rlimit vserver commands */
+
+#define VCMD_get_rlimit		VC_CMD(RLIMIT, 1, 0)
+#define VCMD_set_rlimit		VC_CMD(RLIMIT, 2, 0)
+#define VCMD_get_rlimit_mask	VC_CMD(RLIMIT, 3, 0)
+
+struct  vcmd_ctx_rlimit_v0 {
+	uint32_t id;
+	uint64_t minimum;
+	uint64_t softlimit;
+	uint64_t maximum;
+};
+
+struct  vcmd_ctx_rlimit_mask_v0 {
+	uint32_t minimum;
+	uint32_t softlimit;
+	uint32_t maximum;
+};
+
+#define CRLIM_INFINITY		(~0ULL)
+#define CRLIM_KEEP		(~1ULL)
+
+
+#endif /* _LINUX_VIRTUAL_H */
diff -NurpP --minimal linux-2.6.0/kernel/Makefile linux-2.6.0-vs0.02/kernel/Makefile
--- linux-2.6.0/kernel/Makefile	Thu Dec 18 03:58:18 2003
+++ linux-2.6.0-vs0.02/kernel/Makefile	Sun Jan  4 22:14:18 2004
@@ -3,9 +3,9 @@
 #
 
 obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
-	    exit.o itimer.o time.o softirq.o resource.o \
+	    exit.o itimer.o time.o softirq.o resource.o vswitch.o \
 	    sysctl.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o workqueue.o pid.o \
+	    signal.o sys.o kmod.o workqueue.o pid.o vcontext.o \
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o
 
 obj-$(CONFIG_FUTEX) += futex.o
diff -NurpP --minimal linux-2.6.0/kernel/fork.c linux-2.6.0-vs0.02/kernel/fork.c
--- linux-2.6.0/kernel/fork.c	Thu Dec 18 03:58:08 2003
+++ linux-2.6.0-vs0.02/kernel/fork.c	Sun Jan  4 22:14:18 2004
@@ -30,6 +30,7 @@
 #include <linux/futex.h>
 #include <linux/ptrace.h>
 #include <linux/mount.h>
+#include <linux/vcontext.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -76,6 +77,7 @@ static kmem_cache_t *task_struct_cachep;
 static void free_task(struct task_struct *tsk)
 {
 	free_thread_info(tsk->thread_info);
+	put_vx_info(tsk->vx_info);
 	free_task_struct(tsk);
 }
 
@@ -858,6 +860,11 @@ struct task_struct *copy_process(unsigne
 				p->user != &root_user)
 			goto bad_fork_free;
 	}
+
+	if (current->vx_info)
+		p->vx_info = get_vx_info(current->vx_info);
+	else
+		p->vx_info = NULL;
 
 	atomic_inc(&p->user->__count);
 	atomic_inc(&p->user->processes);
diff -NurpP --minimal linux-2.6.0/kernel/sys.c linux-2.6.0-vs0.02/kernel/sys.c
--- linux-2.6.0/kernel/sys.c	Thu Dec 18 03:58:08 2003
+++ linux-2.6.0-vs0.02/kernel/sys.c	Sun Jan  4 22:14:18 2004
@@ -23,6 +23,7 @@
 #include <linux/security.h>
 #include <linux/dcookies.h>
 #include <linux/suspend.h>
+#include <linux/vcontext.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -314,7 +315,7 @@ asmlinkage long sys_setpriority(int whic
 			if (!who)
 				user = current->user;
 			else
-				user = find_user(who);
+				user = find_user(vx_current_id(), who);
 
 			if (!user)
 				goto out_unlock;
@@ -373,7 +374,7 @@ asmlinkage long sys_getpriority(int whic
 			if (!who)
 				user = current->user;
 			else
-				user = find_user(who);
+				user = find_user(vx_current_id(), who);
 
 			if (!user)
 				goto out_unlock;
@@ -614,7 +615,7 @@ static int set_user(uid_t new_ruid, int 
 {
 	struct user_struct *new_user;
 
-	new_user = alloc_uid(new_ruid);
+	new_user = alloc_uid(vx_current_id(), new_ruid);
 	if (!new_user)
 		return -EAGAIN;
 
diff -NurpP --minimal linux-2.6.0/kernel/user.c linux-2.6.0-vs0.02/kernel/user.c
--- linux-2.6.0/kernel/user.c	Thu Dec 18 03:58:40 2003
+++ linux-2.6.0-vs0.02/kernel/user.c	Sun Jan  4 22:14:18 2004
@@ -20,8 +20,8 @@
 #define UIDHASH_BITS		8
 #define UIDHASH_SZ		(1 << UIDHASH_BITS)
 #define UIDHASH_MASK		(UIDHASH_SZ - 1)
-#define __uidhashfn(uid)	(((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
-#define uidhashentry(uid)	(uidhash_table + __uidhashfn((uid)))
+#define __uidhashfn(xid,uid)	((((uid) >> UIDHASH_BITS) + ((uid)^(xid))) & UIDHASH_MASK)
+#define uidhashentry(xid,uid)	(uidhash_table + __uidhashfn((xid),(uid)))
 
 static kmem_cache_t *uid_cachep;
 static struct list_head uidhash_table[UIDHASH_SZ];
@@ -46,7 +46,7 @@ static inline void uid_hash_remove(struc
 	list_del(&up->uidhash_list);
 }
 
-static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *hashent)
+static inline struct user_struct *uid_hash_find(xid_t xid, uid_t uid, struct list_head *hashent)
 {
 	struct list_head *up;
 
@@ -55,7 +55,7 @@ static inline struct user_struct *uid_ha
 
 		user = list_entry(up, struct user_struct, uidhash_list);
 
-		if(user->uid == uid) {
+		if(user->uid == uid && user->vx_id == xid) {
 			atomic_inc(&user->__count);
 			return user;
 		}
@@ -64,9 +64,9 @@ static inline struct user_struct *uid_ha
 	return NULL;
 }
 
-struct user_struct *find_user(uid_t uid)
+struct user_struct *find_user(xid_t xid, uid_t uid)
 {
-	return uid_hash_find(uid, uidhashentry(uid));
+	return uid_hash_find(xid, uid, uidhashentry(xid, uid));
 }
 
 void free_uid(struct user_struct *up)
@@ -78,13 +78,13 @@ void free_uid(struct user_struct *up)
 	}
 }
 
-struct user_struct * alloc_uid(uid_t uid)
+struct user_struct * alloc_uid(xid_t xid, uid_t uid)
 {
-	struct list_head *hashent = uidhashentry(uid);
+	struct list_head *hashent = uidhashentry(xid, uid);
 	struct user_struct *up;
 
 	spin_lock(&uidhash_lock);
-	up = uid_hash_find(uid, hashent);
+	up = uid_hash_find(xid, uid, hashent);
 	spin_unlock(&uidhash_lock);
 
 	if (!up) {
@@ -94,6 +94,7 @@ struct user_struct * alloc_uid(uid_t uid
 		if (!new)
 			return NULL;
 		new->uid = uid;
+		new->vx_id = xid;
 		atomic_set(&new->__count, 1);
 		atomic_set(&new->processes, 0);
 		atomic_set(&new->files, 0);
@@ -103,7 +104,7 @@ struct user_struct * alloc_uid(uid_t uid
 		 * on adding the same user already..
 		 */
 		spin_lock(&uidhash_lock);
-		up = uid_hash_find(uid, hashent);
+		up = uid_hash_find(xid, uid, hashent);
 		if (up) {
 			kmem_cache_free(uid_cachep, new);
 		} else {
@@ -148,7 +149,7 @@ static int __init uid_cache_init(void)
 
 	/* Insert the root user immediately (init already runs as root) */
 	spin_lock(&uidhash_lock);
-	uid_hash_insert(&root_user, uidhashentry(0));
+	uid_hash_insert(&root_user, uidhashentry(0,0));
 	spin_unlock(&uidhash_lock);
 
 	return 0;
diff -NurpP --minimal linux-2.6.0/kernel/vcontext.c linux-2.6.0-vs0.02/kernel/vcontext.c
--- linux-2.6.0/kernel/vcontext.c	Thu Jan  1 01:00:00 1970
+++ linux-2.6.0-vs0.02/kernel/vcontext.c	Sun Jan  4 22:14:18 2004
@@ -0,0 +1,405 @@
+/*
+ *  linux/kernel/vcontext.c
+ *
+ *  Virtual Context Support
+ *
+ *  Copyright (C) 2003  Herbert Pötzl
+ *
+ *  V0.01  context helper
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/utsname.h>
+#include <linux/vmalloc.h>
+#include <linux/vcontext.h>
+#include <linux/vswitch.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+
+
+int vc_ctx_kill(uint32_t id, void *data)
+{
+	int retval, count=0;
+	struct vcmd_ctx_kill_v0 vc_data;
+	struct siginfo info;
+	struct task_struct *p;
+	pid_t initpid = 0;
+
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+	if (!vx_check(0, VX_ADMIN))
+		return -EPERM;
+	
+	info.si_signo = vc_data.sig;
+	info.si_errno = 0;
+	info.si_code = SI_USER;
+	info.si_pid = current->pid;
+	info.si_uid = current->uid;
+
+	retval = -ESRCH;
+	read_lock(&tasklist_lock);
+	switch (vc_data.pid) {
+	case -1:
+	case  0:
+		for_each_process(p) {
+			if (!initpid && vx_task_id(p) == id && p->vx_info)
+				initpid = p->vx_info->vx_initpid;
+			if (vx_task_id(p) == id  && p->pid > 1
+				&& (!vc_data.pid || initpid != p->pid)
+				&& thread_group_leader(p)) {
+				int err = send_sig_info(vc_data.sig, &info, p);
+
+				++count;
+				if (err != -EPERM)
+					retval = err;
+			}
+		}
+		break;
+		
+	default:
+	p = find_task_by_pid(vc_data.pid);
+		if (p) {
+			if (!thread_group_leader(p)) {
+				struct task_struct *tg;
+			
+				tg = find_task_by_pid(p->tgid);
+				if (tg)
+					p = tg;
+			}
+			if ((id == -1) || (vx_task_id(p) == id))
+				retval = send_sig_info(vc_data.sig, &info, p);
+		}
+		break;
+	}
+	read_unlock(&tasklist_lock);
+	return retval;
+}
+
+int vc_get_rlimit(uint32_t id, void *data)
+{
+	return -ENOSYS;
+}
+
+int vc_set_rlimit(uint32_t id, void *data)
+{
+	return -ENOSYS;
+}
+
+int vc_get_rlimit_mask(uint32_t id, void *data)
+{
+	return -ENOSYS;
+}
+
+
+
+/*  system functions */
+
+
+LIST_HEAD(vx_infos);
+
+spinlock_t vxlist_lock
+	__cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ *	struct vx_info allocation and deallocation
+ */
+
+static struct vx_info *alloc_vx_info(int id)
+{
+	struct vx_info *new = NULL;
+	
+	dprintk("alloc_vx_info(%d)\n", id);
+	/* would this benefit from a slab cache? */
+	new = kmalloc(sizeof(struct vx_info), GFP_KERNEL);
+	if (!new)
+		return 0;
+	
+	memset (new, 0, sizeof(struct vx_info));
+	new->vx_id = id;
+	/* rest of init goes here */
+	
+	// atomic_set(&new->limit.ticks, current->counter); // timestamp?
+	new->virt.nr_threads = 1;
+	// new->virt.bias_cswtch = kstat.context_swtch;
+	new->virt.bias_jiffies = jiffies;
+	// new->virt.bias_idle = init_tasks[0]->times.tms_utime +
+	//	init_tasks[0]->times.tms_stime;
+	down_read(&uts_sem);
+	new->virt.utsname = system_utsname;
+	up_read(&uts_sem);
+	
+	dprintk("alloc_vx_info(%d) = %p\n", id, new);
+	return new;
+}
+
+extern int vx_proc_destroy(struct vx_info *);
+
+void free_vx_info(struct vx_info *vxi)
+{
+	dprintk("free_vx_info(%p)\n", vxi);
+	vx_proc_destroy(vxi);
+        kfree(vxi);
+}
+
+
+/*
+ *	struct vx_info search by id
+ *	needs the vxlist_lock
+ */
+
+static inline struct vx_info *__find_vx_info(int id)
+{
+	struct vx_info *vxi;
+
+	list_for_each_entry(vxi, &vx_infos, vx_list)
+		if (vxi->vx_id == id)
+			return vxi;
+	return 0;
+}
+
+
+/*
+ *	struct vx_info ref stuff
+ */
+
+static struct vx_info *find_vx_info(int id)
+{
+	struct vx_info *vxi;
+	
+        spin_lock(&vxlist_lock);
+	if ((vxi = __find_vx_info(id)))
+		get_vx_info(vxi);
+	spin_unlock(&vxlist_lock);
+	return vxi;
+}
+
+extern int vx_proc_create(struct vx_info *);
+
+static struct vx_info *find_or_create_vx_info(int id)
+{
+	struct vx_info *vxi, *new;
+	
+	dprintk("find_or_create_vx_info(%d)\n", id);
+	if (!(new = alloc_vx_info(id)))
+		return 0;
+	atomic_set(&new->vx_refcount, 1);
+	spin_lock(&vxlist_lock);
+	if ((vxi = __find_vx_info(id))) {
+		dprintk("find_or_create_vx_info(%d) = %p (found)\n", id, vxi);
+		get_vx_info(vxi);
+		spin_unlock(&vxlist_lock);
+		free_vx_info(new);
+		return vxi;
+	}
+	list_add(&new->vx_list, &vx_infos);
+	vx_proc_create(new);
+	dprintk("find_or_create_vx_info(%d) = %p (new)\n", id, new);
+	spin_unlock(&vxlist_lock);
+	return new;
+}
+
+
+
+static int vx_migrate_user(struct task_struct *p, struct vx_info *vxi)
+{
+	struct user_struct *new_user, *old_user;
+	
+	if (!p || !vxi)
+		BUG();
+	new_user = alloc_uid(vxi->vx_id, p->uid);
+	if (!new_user)
+		return -ENOMEM;
+
+	old_user = p->user;
+	if (new_user != old_user) {
+		atomic_inc(&new_user->processes);
+		atomic_dec(&old_user->processes);
+		p->user = new_user;
+	}
+	free_uid(old_user);
+	return 0;
+}
+
+/*
+ *	migrate task to new context
+ *	gets vxi, puts old_vxi on change
+ */
+
+static int vx_migrate_task(struct task_struct *p, struct vx_info *vxi)
+{
+	struct vx_info *old_vxi;
+	int ret = 0;
+	
+	if (!p || !vxi)
+		BUG();
+
+	dprintk("vx_migrate_task(%p,%p[#%d.%d)\n", p, vxi,
+		vxi->vx_id, atomic_read(&vxi->vx_refcount));
+	spin_lock(&p->alloc_lock);
+	if ((old_vxi = p->vx_info) == vxi)
+		goto out;
+
+	if (!(ret = vx_migrate_user(p, vxi))) {
+		if (old_vxi)
+			old_vxi->virt.nr_threads--;
+		vxi->virt.nr_threads++;
+		p->vx_info = get_vx_info(vxi);
+		if (old_vxi)
+			put_vx_info(old_vxi);
+	}
+out:
+	spin_unlock(&p->alloc_lock);
+	return ret;
+}
+
+
+static int vx_set_initpid(struct vx_info *vxi, int pid)
+{
+	int ret = 0;
+	if (vxi->vx_initpid)
+		ret = -EPERM;
+	else
+		vxi->vx_initpid = pid;
+	return ret;
+}
+
+int vc_new_s_context(uint32_t ctx, void *data)
+{
+	int ret = -EPERM;
+	struct vcmd_new_s_context_v1 vc_data;
+	struct vx_info *new_vxi;
+
+	if (copy_from_user(&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+	switch (ctx) {
+	case -1:
+		/* allocate dynamic context */
+		if (current->vx_info == NULL
+			|| !(current->vx_info->vx_flags & VX_INFO_LOCK)) {
+			static int new_xid = MAX_S_CONTEXT;
+			static spinlock_t alloc_ctx_lock = SPIN_LOCK_UNLOCKED;
+			int barrier = new_xid;
+			int done = 0;
+
+			do {
+				spin_lock(&alloc_ctx_lock);
+				if (++new_xid > MAX_S_CONTEXT)
+					new_xid = MIN_D_CONTEXT;
+				spin_unlock(&alloc_ctx_lock);
+
+				new_vxi = find_or_create_vx_info(new_xid);
+				if (atomic_read(&new_vxi->vx_refcount) > 1)
+					put_vx_info(new_vxi);
+				else {
+					done = 1;
+					break;
+				}
+			} while (barrier != new_xid);
+			
+			if (!done)
+				return -EDEADLK;
+			
+			ret = vx_migrate_task(current, new_vxi);
+			if (ret == 0) {
+				current->cap_bset &= (~vc_data.remove_cap);
+				new_vxi->vx_flags |= vc_data.flags;
+				if (vc_data.flags & VX_INFO_INIT)
+					vx_set_initpid(new_vxi, current->tgid);
+				ret = new_vxi->vx_id;
+			}
+			put_vx_info(new_vxi);
+		}
+		break;
+	
+	case -2:
+		/* assign flags and initpid */
+		if (!current->vx_info)
+			return -EINVAL;
+		ret = 0;
+		if (vc_data.flags & VX_INFO_INIT)
+			ret = vx_set_initpid(current->vx_info, current->tgid);
+		if (ret == 0) {
+			/* We keep the same vx_id, but lower the capabilities */
+			current->cap_bset &= (~vc_data.remove_cap);
+			ret = vx_current_id();
+			current->vx_info->vx_flags |= vc_data.flags;
+		}
+		break;
+	
+	case 0:
+		return -EINVAL;
+		break;
+	
+	default:
+		if (ctx <= 0 || ctx > MAX_S_CONTEXT)
+			return -EINVAL;
+		if (!vx_check(0, VX_ADMIN) ||
+			!capable(CAP_SYS_ADMIN) ||
+			(current->vx_info &&
+			(current->vx_info->vx_flags & VX_INFO_LOCK)))
+			return -EPERM;
+		if (ctx >= MIN_D_CONTEXT)
+			new_vxi = find_vx_info(ctx);
+		else
+			new_vxi = find_or_create_vx_info(ctx);
+		if (!new_vxi)
+			return -EINVAL;
+		ret = vx_migrate_task(current, new_vxi);
+		if (ret == 0) {
+			current->cap_bset &= (~vc_data.remove_cap);
+			new_vxi->vx_flags |= vc_data.flags;
+			if (vc_data.flags & VX_INFO_INIT)
+				vx_set_initpid(new_vxi, current->tgid);
+			ret = new_vxi->vx_id;
+		}
+		put_vx_info(new_vxi);
+		break;
+	}
+	return ret;
+}
+
+int vc_new_context(uint32_t ctx, void *data)
+{
+	int ret = -EPERM;
+	struct vcmd_new_s_context_v1 vc_data;
+	struct vx_info *vxi;
+
+	#define MAX_S_CONTEXT 65535	/* Arbitrary limit */
+
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+	if (ctx > MAX_S_CONTEXT)
+		return -EINVAL;
+
+	if (vx_check(0, VX_ADMIN)
+		&& capable(CAP_SYS_ADMIN)) {
+		dprintk("vxdbg: vc_new_s_context(%d)\n", ctx);
+		vxi = find_or_create_vx_info(ctx);
+		if (!vxi)
+			return -ENOMEM;
+		ret = vx_migrate_task(current, vxi);
+		put_vx_info(vxi);
+		if (ret)
+			return -ENOMEM;
+		return 0;
+	}
+	return -EPERM;
+}
+
+
+
+/*  set ipv4 root (syscall) */
+
+int vc_set_ipv4root(uint32_t nbip, void *data)
+{
+	int ret = -ENOSYS;
+	ret = 0;
+	return ret;
+}
+
diff -NurpP --minimal linux-2.6.0/kernel/vswitch.c linux-2.6.0-vs0.02/kernel/vswitch.c
--- linux-2.6.0/kernel/vswitch.c	Thu Jan  1 01:00:00 1970
+++ linux-2.6.0-vs0.02/kernel/vswitch.c	Sun Jan  4 22:14:18 2004
@@ -0,0 +1,71 @@
+/*
+ *  linux/kernel/vswitch.c
+ *
+ *  Virtual Context Support
+ *
+ *  Copyright (C) 2003  Herbert Pötzl
+ *
+ *  V0.01  syscall switch
+ *  V0.02  added signal to context
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/errno.h>
+
+#include <linux/vswitch.h>
+
+
+static inline int
+vc_get_version(uint32_t id)
+{
+	return VCI_VERSION;
+}
+
+
+extern int vc_new_s_context(uint32_t, void *);
+extern int vc_set_ipv4root(uint32_t, void *);
+
+extern int vc_get_rlimit(uint32_t, void *);
+extern int vc_set_rlimit(uint32_t, void *);
+extern int vc_get_rlimit_mask(uint32_t, void *);
+
+extern int vc_ctx_kill(uint32_t, void *);
+
+
+asmlinkage int
+sys_vserver(uint32_t cmd, uint32_t id, void *data)
+{
+	int ret = -EINVAL;
+
+	switch (cmd) {
+	case VCMD_get_version:
+		ret = vc_get_version(id);
+		break;
+		
+	case VCMD_new_s_context:
+		ret = vc_new_s_context(id, data);
+		break;
+	case VCMD_set_ipv4root:
+		ret = vc_set_ipv4root(id, data);
+		break;
+
+	case VCMD_get_rlimit:
+		ret = vc_get_rlimit(id, data);
+		break;
+	case VCMD_set_rlimit:
+		ret = vc_set_rlimit(id, data);
+		break;
+	case VCMD_get_rlimit_mask:
+		ret = vc_get_rlimit_mask(id, data);
+		break;
+		
+	case VCMD_ctx_kill:
+		ret = vc_ctx_kill(id, data);
+		break;
+
+	}
+	return ret;
+}
+
