diff -urN linux.wrk.orig/Makefile linux.wrk/Makefile
--- linux.wrk.orig/Makefile	Mon Jan 14 21:05:57 2002
+++ linux.wrk/Makefile	Wed Jan 23 01:32:13 2002
@@ -226,7 +226,7 @@
 	drivers/sound/pndsperm.c \
 	drivers/sound/pndspini.c \
 	drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw \
-	.version .config* config.in config.old \
+	.uniquebytes .version .config* config.in config.old \
 	scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp \
 	scripts/lxdialog/*.o scripts/lxdialog/lxdialog \
 	.menuconfig.log \
@@ -268,6 +268,7 @@
 		--end-group \
 		-o vmlinux
 	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
+	@$(MAKE) -C ulib
 
 symlinks:
 	rm -f include/asm
@@ -305,6 +306,8 @@
 newversion:
 	. scripts/mkversion > .tmpversion
 	@mv -f .tmpversion .version
+	rm -f .uniquebytes
+	dd if=/dev/urandom of=.uniquebytes bs=1 count=16
 
 include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
 	@echo -n \#define UTS_VERSION \"\#`cat .version` > .ver
@@ -328,6 +331,9 @@
 	@echo \#define UTS_RELEASE \"$(KERNELRELEASE)\" > .ver
 	@echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver
 	@echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
+	@echo -n \#"define LINUX_UNIQUE_BYTES " >>.ver
+	@hexdump -v -e '1/1 "0x%02x, "' .uniquebytes | sed -e 's/, $$//g' >>.ver
+	@echo "" >>.ver
 	@mv -f .ver $@
 
 comma	:= ,
@@ -420,6 +426,7 @@
 	rm -f $(CLEAN_FILES)
 	rm -rf $(CLEAN_DIRS)
 	$(MAKE) -C Documentation/DocBook clean
+	$(MAKE) -C ulib clean
 
 mrproper: clean archmrproper
 	find . \( -size 0 -o -name .depend \) -type f -print | xargs rm -f
diff -urN linux.wrk.orig/arch/i386/Makefile linux.wrk/arch/i386/Makefile
--- linux.wrk.orig/arch/i386/Makefile	Thu May  3 11:22:07 2001
+++ linux.wrk/arch/i386/Makefile	Wed Jan 23 01:28:26 2002
@@ -98,7 +98,7 @@
 DRIVERS += arch/i386/math-emu/math.o
 endif
 
-arch/i386/kernel: dummy
+arch/i386/kernel: dummy include/linux/compile.h
 	$(MAKE) linuxsubdirs SUBDIRS=arch/i386/kernel
 
 arch/i386/mm: dummy
diff -urN linux.wrk.orig/arch/i386/kernel/Makefile linux.wrk/arch/i386/kernel/Makefile
--- linux.wrk.orig/arch/i386/kernel/Makefile	Mon Nov 26 23:43:07 2001
+++ linux.wrk/arch/i386/kernel/Makefile	Wed Jan 23 01:33:42 2002
@@ -20,6 +20,9 @@
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
 
+obj-y	+= vsysdata.o vunique.o dynamic_syscall.o
+
+vunique.o: $(TOPDIR)/include/linux/compile.h
 
 ifdef CONFIG_PCI
 obj-y			+= pci-i386.o
diff -urN linux.wrk.orig/arch/i386/kernel/dynamic_syscall.c linux.wrk/arch/i386/kernel/dynamic_syscall.c
--- linux.wrk.orig/arch/i386/kernel/dynamic_syscall.c	Wed Dec 31 19:00:00 1969
+++ linux.wrk/arch/i386/kernel/dynamic_syscall.c	Wed Jan 23 01:28:26 2002
@@ -0,0 +1,69 @@
+/* arch/i386/kernel/dynamic_syscall.c
+ *	Entry code for dynamic syscalls on i386.
+ */
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+struct dummy_args {
+	long data[8];
+};
+
+extern struct vsyscall_entry {
+	long eip;
+	long (*call)(struct dummy_args args);
+} vsyscall_list_begin, vsyscall_list_end;
+
+long sys_dynamic_syscall(struct pt_regs regs) __attribute__((regparm(0)));
+
+long sys_dynamic_syscall(struct pt_regs regs)
+{
+	struct dummy_args dummy_args;
+	struct vsyscall_entry *ent = (void *)regs.edx;
+	void *args = (void *)regs.ecx;
+	long ret;
+
+	pr_debug("ent = %p  args = %p\n", ent, args);
+	pr_debug("eip = 0x%08lx\n", regs.eip);
+
+	if (unlikely(!current->mm->vsys_mapped))
+		goto err;
+
+	/* The pointer must be aligned in the table. */
+	if (unlikely((long)ent & (sizeof(*ent) - 1))) {
+		pr_debug("unaligned\n");
+		goto err;
+	}
+
+	/* Bounds checking... */
+	if (unlikely(ent < &vsyscall_list_begin) ||
+	    unlikely(ent >= &vsyscall_list_end)) {
+		pr_debug("out of range %p <= %p < %p\n", 
+			&vsyscall_list_begin, ent,
+			&vsyscall_list_end);
+		goto err;
+	}
+	/* The entry should be valid now.  Verify that the caller's eip 
+	 * is correct.
+	 */
+	if (unlikely(ent->eip != regs.eip)) {
+		pr_debug("eip mismatch (0x%lx vs 0x%lx)\n", ent->eip, regs.eip);
+		goto err;
+	}
+
+	pr_debug("ent->call = %p\n", ent->call);
+
+	if (unlikely(copy_from_user(&dummy_args, args, sizeof(dummy_args))))
+		return -EFAULT;
+
+	ret = ent->call(dummy_args);
+
+	pr_debug("ret = 0x%08lx\n", ret);
+
+	return ret;
+err:
+	return -ENOSYS;
+}
diff -urN linux.wrk.orig/arch/i386/kernel/entry.S linux.wrk/arch/i386/kernel/entry.S
--- linux.wrk.orig/arch/i386/kernel/entry.S	Mon Nov 12 17:49:47 2001
+++ linux.wrk/arch/i386/kernel/entry.S	Wed Jan 23 01:28:26 2002
@@ -45,6 +45,7 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/smp.h>
+#include <asm/unistd.h>
 
 EBX		= 0x00
 ECX		= 0x04
@@ -623,6 +624,11 @@
 	.long SYMBOL_NAME(sys_gettid)
 	.long SYMBOL_NAME(sys_readahead)	/* 225 */
 
+ 	.rept __NR_sys_dynamic_syscall-(.-sys_call_table)/4
+ 		.long SYMBOL_NAME(sys_ni_syscall)
+ 	.endr
+ 	.long SYMBOL_NAME(sys_dynamic_syscall)
+
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -urN linux.wrk.orig/arch/i386/kernel/vsysdata.c linux.wrk/arch/i386/kernel/vsysdata.c
--- linux.wrk.orig/arch/i386/kernel/vsysdata.c	Wed Dec 31 19:00:00 1969
+++ linux.wrk/arch/i386/kernel/vsysdata.c	Wed Jan 23 01:28:26 2002
@@ -0,0 +1,11 @@
+/* vsysdata.c	- declarations for variables shared with the kernel
+ *
+ *	Items placed in .data.vsyscall have a kernel virtual address 
+ *	and are read/write from kernel space only.  The copy placed 
+ *	in .vsyscall_data are linked at a userspace address and are 
+ *	read only accessible from userland.
+ */
+#include <linux/vsyscall.h>
+
+union vsys_union user_vsys_cpudata[256] __attribute__((section(".vsyscall_data")));
+//asm(".globl vsys_cpudata ; bobbob = user_vsys_cpudata - vsyscall_text_begin ; vsys_cpudata = bobbob + VSYSCALL_text");
diff -urN linux.wrk.orig/arch/i386/kernel/vunique.S linux.wrk/arch/i386/kernel/vunique.S
--- linux.wrk.orig/arch/i386/kernel/vunique.S	Wed Dec 31 19:00:00 1969
+++ linux.wrk/arch/i386/kernel/vunique.S	Wed Jan 23 01:28:26 2002
@@ -0,0 +1,7 @@
+#include <linux/compile.h>
+
+	.section .first_vsyscall_text,"xa"
+	.globl	signature
+signature:
+	.byte	LINUX_UNIQUE_BYTES
+	.size	signature,.-signature
diff -urN linux.wrk.orig/arch/i386/vmlinux.lds linux.wrk/arch/i386/vmlinux.lds
--- linux.wrk.orig/arch/i386/vmlinux.lds	Mon Jan 14 21:05:57 2002
+++ linux.wrk/arch/i386/vmlinux.lds	Wed Jan 23 01:37:52 2002
@@ -14,6 +14,27 @@
 	*(.gnu.warning)
 	} = 0x9090
 
+	/* Note: most of these declarations are in kernel/vsysdata.c,vsyscall.S.
+	 * We use two segments for the data liked at a kernel virtual address 
+	 * (.data.vsyscall) and user virtual address (.vsyscall_data).
+	 * .vsyscall_text is linked at a kernel virtual address
+	 */
+	. = ALIGN(4096);
+	VSYSCALL_text = .;
+	VSYSCALL 0xbfff0000 : AT ( VSYSCALL_text ) {
+		vsyscall_text_begin = .;
+		*(.first_vsyscall_text)
+		*(.vsyscall_text)
+		. = ALIGN(4096);
+		vsyscall_text_end = .;
+		*(.vsyscall_data)
+		. = ALIGN(4096);
+		vsyscall_data_end = .;
+	}
+	vsys_cpudata = user_vsys_cpudata - vsyscall_text_begin + VSYSCALL_text;
+	. = VSYSCALL_text + SIZEOF(VSYSCALL);
+	VSYSCALL_text_end = .;
+
   _etext = .;			/* End of text section */
 
   .rodata : { *(.rodata) *(.rodata.*) }
@@ -30,6 +51,17 @@
 
   .data : {			/* Data */
 	*(.data)
+
+	. = ALIGN(8);
+	vsyscall_list_begin = .;
+	*(.data.vsyscall_list)
+	vsyscall_list_end = .;
+	. = ALIGN(4096);
+	kernel_vsyscall_data_begin = .;
+	*(.data.vsyscall)
+	. = ALIGN(4096);
+	kernel_vsyscall_data_end = .;
+
 	CONSTRUCTORS
 	}
 
@@ -79,4 +111,15 @@
   .stab.index 0 : { *(.stab.index) }
   .stab.indexstr 0 : { *(.stab.indexstr) }
   .comment 0 : { *(.comment) }
+/*
+#  VSYSCALL : {
+#	/ * vsyscall area *i /
+#	__vsyscall_begin = .;
+#	*(vsyscall_text)
+#	. = ALIGN(4096);
+#	*(.data.vsyscall)
+#	. = ALIGN(4096);
+#	__vsyscall_end = .;
+#  } >vsyscall_area
+*/
 }
diff -urN linux.wrk.orig/drivers/char/mem.c linux.wrk/drivers/char/mem.c
--- linux.wrk.orig/drivers/char/mem.c	Tue Jan  1 14:09:34 2002
+++ linux.wrk/drivers/char/mem.c	Wed Jan 23 01:28:30 2002
@@ -25,6 +25,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
+#include <asm/a.out.h>
 
 #ifdef CONFIG_I2C
 extern int i2c_init_all(void);
@@ -572,6 +573,87 @@
 	write:		write_full,
 };
 
+void vsys_mmap_close(struct vm_area_struct *area)
+{
+	area->vm_mm->vsys_mapped = 0;
+}
+
+static struct vm_operations_struct vsys_mmap_ops = {
+	close:		vsys_mmap_close,
+};
+
+int vsys_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	extern unsigned char vsyscall_text_begin, vsyscall_text_end, VSYSCALL_text[];
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long len = vma->vm_end - vma->vm_start;
+	unsigned long actual_len = &vsyscall_text_end - &vsyscall_text_begin;
+
+	if ((offset + len) > actual_len)
+		len = actual_len - offset;
+
+	pr_debug("len = 0x%lx, actual_len = 0x%lx\n", len, actual_len);
+
+	vma->vm_start = (unsigned long)&vsyscall_text_begin + offset;
+	vma->vm_end = vma->vm_start + len;
+	vma->vm_flags |= VM_RESERVED;
+
+	pr_debug("vm_start = 0x%lx, vm_end = 0x%lx\n",
+		vma->vm_start, vma->vm_end);
+	pr_debug("va=%p  pa=0x%lx\n",
+		VSYSCALL_text + offset,
+		__pa(VSYSCALL_text) + offset);
+
+	if (vma->vm_start < (unsigned long)&vsyscall_text_begin) {
+		pr_debug("vsys_mmap: start < begin\n");
+		return -EINVAL;
+	}
+
+	if (vma->vm_end < (unsigned long)&vsyscall_text_begin) {
+		pr_debug("vsys_mmap: end < begin\n");
+		return -EINVAL;
+	}
+
+	if (vma->vm_end > (unsigned long)&vsyscall_text_end) {
+		pr_debug("vsys_mmap: end(%lx) > text_end(%p)\n",
+			vma->vm_end, &vsyscall_text_end);
+		return -EINVAL;
+	}
+
+	if (vma->vm_start >= vma->vm_end) {
+		pr_debug("vsys_mmap: end\n");
+		return -EINVAL;
+	}
+
+	if (find_vma_intersection(current->mm, vma->vm_start, vma->vm_end)) {
+		pr_debug("vsyscall: mapping collision\n");
+		return -EINVAL;
+	}
+
+	if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == (VM_SHARED | VM_WRITE)) {
+		pr_debug("vsyscall: attempt to write to mapping\n");
+		return -EPERM;
+	}
+
+	if (remap_page_range(vma->vm_start,
+			     __pa(VSYSCALL_text) + offset,
+			     vma->vm_end-vma->vm_start,
+			     vma->vm_page_prot))
+		return -EAGAIN;
+
+	pr_debug("VSYSCALL_text(%p): %02x %02x %02x %02x\n",
+		VSYSCALL_text,
+		VSYSCALL_text[0], VSYSCALL_text[1],
+		VSYSCALL_text[2], VSYSCALL_text[3]);
+
+	current->mm->vsys_mapped = 1;
+	return 0;
+}
+
+static struct file_operations vsys_fops = {
+	mmap:		vsys_mmap,
+};
+
 static int memory_open(struct inode * inode, struct file * filp)
 {
 	switch (MINOR(inode->i_rdev)) {
@@ -601,6 +683,9 @@
 		case 9:
 			filp->f_op = &urandom_fops;
 			break;
+		case 10:
+			filp->f_op = &vsys_fops;
+			break;
 		default:
 			return -ENXIO;
 	}
@@ -625,7 +710,8 @@
 	{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
 	{7, "full",    S_IRUGO | S_IWUGO,           &full_fops},
 	{8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
-	{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops}
+	{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops},
+	{10,"vsys",    S_IRUGO,			    &vsys_fops},
     };
     int i;
 
diff -urN linux.wrk.orig/fs/aio.c linux.wrk/fs/aio.c
--- linux.wrk.orig/fs/aio.c	Wed Jan 23 01:21:14 2002
+++ linux.wrk/fs/aio.c	Wed Jan 23 01:28:30 2002
@@ -39,6 +39,7 @@
 #include <linux/poll.h>
 
 #include <asm/uaccess.h>
+#include <asm/vsyscall.h>
 
 //#define static	/**/
 //#define inline	/**/
@@ -927,3 +928,10 @@
 }
 
 __initcall(aio_setup);
+
+add_dynamic_syscall(sys_io_setup);
+add_dynamic_syscall(sys_io_destroy);
+add_dynamic_syscall(sys_io_submit);
+add_dynamic_syscall(sys_io_cancel);
+add_dynamic_syscall(sys_io_wait);
+add_dynamic_syscall(sys_io_getevents);
diff -urN linux.wrk.orig/include/asm-i386/a.out.h linux.wrk/include/asm-i386/a.out.h
--- linux.wrk.orig/include/asm-i386/a.out.h	Fri Jun 16 14:33:06 1995
+++ linux.wrk/include/asm-i386/a.out.h	Wed Jan 23 01:28:30 2002
@@ -19,7 +19,9 @@
 
 #ifdef __KERNEL__
 
-#define STACK_TOP	TASK_SIZE
+#define VSYSCALL_SIZE		0x10000		/* 64KB for vsyscalls */
+#define STACK_GUARD_SIZE	0x02000		/* 8KB guard area */
+#define STACK_TOP	(TASK_SIZE - VSYSCALL_SIZE - STACK_GUARD_SIZE)
 
 #endif
 
diff -urN linux.wrk.orig/include/asm-i386/unistd.h linux.wrk/include/asm-i386/unistd.h
--- linux.wrk.orig/include/asm-i386/unistd.h	Thu Nov  1 16:40:03 2001
+++ linux.wrk/include/asm-i386/unistd.h	Wed Jan 23 01:28:30 2002
@@ -231,6 +231,8 @@
 #define __NR_gettid		224
 #define __NR_readahead		225
 
+#define __NR_sys_dynamic_syscall	230
+
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
 #define __syscall_return(type, res) \
diff -urN linux.wrk.orig/include/asm-i386/vsyscall.h linux.wrk/include/asm-i386/vsyscall.h
--- linux.wrk.orig/include/asm-i386/vsyscall.h	Wed Dec 31 19:00:00 1969
+++ linux.wrk/include/asm-i386/vsyscall.h	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,41 @@
+#ifndef __ASM__VSYSCALL_H
+#define __ASM__VSYSCALL_H
+/* include/asm-i386/vsyscall.h
+ *	Copyright 2002 Red Hat, Inc.
+ */
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+/* We call sys_dynamic_syscall(long nr, void *args) using regparm(2)
+ * convention.  The .text.vsyscall section is mapped into userspace, 
+ * whereas .data.vsyscall_list is a kernel-only array of the vsyscalls 
+ * and the valid userspace address to call them from.  All vsyscalls 
+ * are called with C calling convention (ie args on the stack for x86).
+ *
+ * Note: the layout of .data.vsyscall_list must match the entries in
+ * dynamic_syscall.c.
+ */
+#define STRINGIFYa(x)	#x
+#define STRINGIFY(x)	STRINGIFYa(x)
+#define NR_dyn_sys	STRINGIFY(__NR_sys_dynamic_syscall)
+#define add_dynamic_syscall(name)				\
+	__asm__("						\n\
+	.section .vsyscall_text, \"xa\"				\n\
+	.globl v" #name "					\n\
+	v" #name ":						\n\
+		push %ecx					\n\
+		push %edx					\n\
+		movl $" NR_dyn_sys ",%eax			\n\
+		movl $2f,%edx					\n\
+		leal 12(%esp),%ecx				\n\
+		int $0x80					\n\
+	1:							\n\
+		popl %edx					\n\
+		popl %ecx					\n\
+		ret						\n\
+	.size v" #name ",.-v" #name "				\n\
+	.section .data.vsyscall_list,\"a\"			\n\
+	2:	.long	1b," #name "				\n\
+	.previous")
+
+#endif
diff -urN linux.wrk.orig/include/linux/sched.h linux.wrk/include/linux/sched.h
--- linux.wrk.orig/include/linux/sched.h	Wed Jan 23 01:21:14 2002
+++ linux.wrk/include/linux/sched.h	Wed Jan 23 01:28:30 2002
@@ -233,6 +233,7 @@
 
 	struct kioctx	*ioctx_list;
 	unsigned long	new_ioctx_id;
+	int		vsys_mapped;
 };
 
 extern int mmlist_nr;
@@ -245,6 +246,7 @@
 	mm_count:	ATOMIC_INIT(1), 		\
 	mmap_sem:	__RWSEM_INITIALIZER(name.mmap_sem), \
 	page_table_lock: SPIN_LOCK_UNLOCKED, 		\
+    	vsys_mapped:	0,				\
 	mmlist:		LIST_HEAD_INIT(name.mmlist),	\
 }
 
diff -urN linux.wrk.orig/include/linux/vsyscall.h linux.wrk/include/linux/vsyscall.h
--- linux.wrk.orig/include/linux/vsyscall.h	Wed Dec 31 19:00:00 1969
+++ linux.wrk/include/linux/vsyscall.h	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,20 @@
+#ifndef _LINUX__VSYSCALL_H
+#define _LINUX__VSYSCALL_H
+
+struct vsys_cpudata {
+	unsigned long	context_switches;
+	unsigned long	tv_sec;
+	unsigned long	tsc_low, tsc_high;
+	unsigned long	cycles_per_sec;
+};
+
+union vsys_union {
+	struct vsys_cpudata	data;
+	char			pad[128];
+};
+
+extern union vsys_union	vsys_cpudata[256] __attribute__((section(".data.vsyscall")));
+
+#define vsys_data(cpu)	(&vsys_cpudata[cpu].data)
+
+#endif /*ndef _LINUX__VSYSCALL_H*/
diff -urN linux.wrk.orig/ulib/Makefile linux.wrk/ulib/Makefile
--- linux.wrk.orig/ulib/Makefile	Wed Dec 31 19:00:00 1969
+++ linux.wrk/ulib/Makefile	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,30 @@
+all: libredhat-kernel.so
+
+ASFLAGS=-D__KERNEL__ -D__ASSEMBLY__ -I../include -nostdlib -nostartfiles
+CFLAGS=-D__KERNEL__ -I../include -nostdlib -nostartfiles
+
+so_objs=vsysaddr.o kso_init.o
+
+vsysaddr.S: ../System.map stub.S Makefile
+	rm -f vsysaddr.S
+	echo '#include "stub.S"' >vsysaddr.S
+	awk -- "/^bfff.* vsys_/ { print \"dynamic_syscall(\"\$$3 \",0x\" \$$1 \")\"; }" <../System.map >>vsysaddr.S
+
+vsysaddr.o: vsysaddr.S
+
+kso_init.o: ../include/linux/compile.h
+
+libredhat-kernel.so.1: $(so_objs) libredhat-kernel.map
+	gcc -nostdlib -nostartfiles -shared -Wl,--version-script=libredhat-kernel.map -Wl,-soname=libredhat-kernel.so.1 -o $@  $(so_objs)
+	cp $@ $@.save
+	strip $@
+
+libredhat-kernel.so: libredhat-kernel.so.1
+	ln -sf $< $@
+
+clean:
+	rm -f *.o libredhat-kernel.so myln libredhat-kernel.so.1 vsysaddr.S libredhat-kernel.so.1.save
+
+# test app
+myln: myln.c libredhat-kernel.so Makefile
+	cc -g -o myln myln.c -L. -lredhat-kernel
diff -urN linux.wrk.orig/ulib/kso_init.c linux.wrk/ulib/kso_init.c
--- linux.wrk.orig/ulib/kso_init.c	Wed Dec 31 19:00:00 1969
+++ linux.wrk/ulib/kso_init.c	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,48 @@
+#include <linux/compile.h>
+#include <linux/types.h>
+#include <asm/unistd.h>
+#include <asm/fcntl.h>
+#include <asm/mman.h>
+#include <asm/a.out.h>
+
+char libredhat_kernel_enosys = 1;	/* the asm in stub.S depends on this */
+
+long _init(void)
+{
+	static char unique[] = { LINUX_UNIQUE_BYTES };
+	int errno;
+	long addr;
+	int fd;
+	int i;
+
+	_syscall6(int, mmap2, unsigned long, addr, unsigned long, len,
+        	  unsigned long, prot, unsigned long, flags,
+        	  unsigned long, fd, unsigned long, pgoff)
+	_syscall2(long, munmap, unsigned long, addr, size_t, len)
+	_syscall2(int, open, const char *, name, int, flags)
+	_syscall1(int, close, int, fd)
+
+	if (sizeof(unique) != 16)
+		return -1;
+
+	fd = open("/dev/vsys", O_RDONLY);
+	if (-1 == fd)
+		return -1;
+
+	addr = mmap2(0, VSYSCALL_SIZE, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
+	if (-1 == addr)
+		return -1;
+
+	close(fd);
+
+	for (i=0; i<sizeof(unique); i++)
+		if (unique[i] != ((char *)addr)[i]) {
+			munmap(addr, VSYSCALL_SIZE);
+			return -1;
+		}
+
+	/* okay, all the syscalls we provide are now good */
+	libredhat_kernel_enosys = 0;
+	return 0;
+}
+
diff -urN linux.wrk.orig/ulib/libredhat-kernel.map linux.wrk/ulib/libredhat-kernel.map
--- linux.wrk.orig/ulib/libredhat-kernel.map	Wed Dec 31 19:00:00 1969
+++ linux.wrk/ulib/libredhat-kernel.map	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,11 @@
+REDHAT_0.90 {
+	global:
+		vsys_io_setup;
+		vsys_io_destroy;
+		vsys_io_submit;
+		vsys_io_cancel;
+		vsys_io_wait;
+		vsys_io_getevents;
+	local:
+		*;
+};
diff -urN linux.wrk.orig/ulib/myln.c linux.wrk/ulib/myln.c
--- linux.wrk.orig/ulib/myln.c	Wed Dec 31 19:00:00 1969
+++ linux.wrk/ulib/myln.c	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,25 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+int main ()
+{
+	long ctx = 0;
+	extern long vsys_io_setup(long, long *);
+	unsigned char *bob = (void*)&vsys_io_setup;
+	long ret;
+	int i;
+	printf("%p\n", bob);
+	//printf("%p\n", mmap(0, 65536, PROT_READ | PROT_EXEC, MAP_SHARED,
+	//	open("/dev/vsys", O_RDONLY), 0));
+	//for (i=0; i<16; i++)
+	//	printf(" %02x\n", bob[i]);
+	//printf("\n");
+
+	ret = vsys_io_setup(100, &ctx);
+
+	printf("ret=%ld, ctx=0x%lx\n", ret, ctx);
+	return 0;
+}
diff -urN linux.wrk.orig/ulib/stub.S linux.wrk/ulib/stub.S
--- linux.wrk.orig/ulib/stub.S	Wed Dec 31 19:00:00 1969
+++ linux.wrk/ulib/stub.S	Wed Jan 23 01:28:30 2002
@@ -0,0 +1,19 @@
+/* stub.S */
+#include <asm/segment.h>
+#include <asm/errno.h>
+
+	.text
+
+#define dynamic_syscall(x,a) \
+	.globl	x				;\
+	.type	x, @function			;\
+	.align 16				;\
+	x:					;\
+		cmpb $0,libredhat_kernel_enosys	;\
+		jne 1f				;\
+		ljmp $__USER_CS, $a		;\
+	1:					;\
+		movl	$-ENOSYS,%eax		;\
+		ret				;\
+	.size	 x,.-x
+
