diff -urN linux-2.6.3-uml-jdike/arch/i386/Kconfig linux-2.6.3-uml-jdike+skas/arch/i386/Kconfig
--- linux-2.6.3-uml-jdike/arch/i386/Kconfig	2004-02-17 13:34:50.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/arch/i386/Kconfig	2004-02-27 19:53:45.000000000 +0800
@@ -698,6 +698,9 @@
 	depends on HIGHMEM64G
 	default y
 
+config PROC_MM
+	bool "/proc/mm support"
+
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation Support"
diff -urN linux-2.6.3-uml-jdike/arch/i386/kernel/ldt.c linux-2.6.3-uml-jdike+skas/arch/i386/kernel/ldt.c
--- linux-2.6.3-uml-jdike/arch/i386/kernel/ldt.c	2003-08-26 08:50:02.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/arch/i386/kernel/ldt.c	2004-02-27 20:59:30.000000000 +0800
@@ -54,7 +54,7 @@
 	pc->size = mincount;
 	wmb();
 
-	if (reload) {
+	if (reload && (&current->active_mm->context == pc)) {
 #ifdef CONFIG_SMP
 		cpumask_t mask;
 		preempt_disable();
@@ -89,14 +89,12 @@
  * we do not have to muck with descriptors here, that is
  * done in switch_mm() as needed.
  */
-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+int __init_new_context(struct mm_struct *mm, struct mm_struct *old_mm)
 {
-	struct mm_struct * old_mm;
 	int retval = 0;
 
 	init_MUTEX(&mm->context.sem);
 	mm->context.size = 0;
-	old_mm = current->mm;
 	if (old_mm && old_mm->context.size > 0) {
 		down(&old_mm->context.sem);
 		retval = copy_ldt(&mm->context, &old_mm->context);
@@ -105,6 +103,11 @@
 	return retval;
 }
 
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	return __init_new_context(mm, current->mm);
+}
+
 /*
  * No need to lock the MM as we are the last user
  */
@@ -121,11 +124,11 @@
 	}
 }
 
-static int read_ldt(void __user * ptr, unsigned long bytecount)
+static int read_ldt(struct mm_struct * mm, void __user * ptr,
+		    unsigned long bytecount)
 {
 	int err;
 	unsigned long size;
-	struct mm_struct * mm = current->mm;
 
 	if (!mm->context.size)
 		return 0;
@@ -169,9 +172,8 @@
 	return err;
 }
 
-static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
+static int write_ldt(struct mm_struct * mm, void __user * ptr, unsigned long bytecount, int oldmode)
 {
-	struct mm_struct * mm = current->mm;
 	__u32 entry_1, entry_2, *lp;
 	int error;
 	struct user_desc ldt_info;
@@ -195,7 +197,7 @@
 
 	down(&mm->context.sem);
 	if (ldt_info.entry_number >= mm->context.size) {
-		error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
+		error = alloc_ldt(&mm->context, ldt_info.entry_number+1, 1);
 		if (error < 0)
 			goto out_unlock;
 	}
@@ -228,23 +230,29 @@
 	return error;
 }
 
-asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+int modify_ldt(struct mm_struct * mm, int func, void __user *ptr,
+	       unsigned long bytecount)
 {
 	int ret = -ENOSYS;
 
 	switch (func) {
 	case 0:
-		ret = read_ldt(ptr, bytecount);
+		ret = read_ldt(mm, ptr, bytecount);
 		break;
 	case 1:
-		ret = write_ldt(ptr, bytecount, 1);
+		ret = write_ldt(mm, ptr, bytecount, 1);
 		break;
 	case 2:
 		ret = read_default_ldt(ptr, bytecount);
 		break;
 	case 0x11:
-		ret = write_ldt(ptr, bytecount, 0);
+		ret = write_ldt(mm, ptr, bytecount, 0);
 		break;
 	}
 	return ret;
 }
+
+asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+{
+	return modify_ldt(current->mm, func, ptr, bytecount);
+}
diff -urN linux-2.6.3-uml-jdike/arch/i386/kernel/ptrace.c linux-2.6.3-uml-jdike+skas/arch/i386/kernel/ptrace.c
--- linux-2.6.3-uml-jdike/arch/i386/kernel/ptrace.c	2003-05-27 09:00:27.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/arch/i386/kernel/ptrace.c	2004-02-27 20:40:39.000000000 +0800
@@ -14,6 +14,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/proc_mm.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -507,6 +508,56 @@
 					     addr, (struct user_desc __user *) data);
 		break;
 
+	case PTRACE_FAULTINFO: {
+		struct ptrace_faultinfo fault;
+
+		fault = ((struct ptrace_faultinfo) 
+			{ .is_write	= child->thread.error_code,
+			  .addr		= child->thread.cr2 });
+		ret = copy_to_user((unsigned long *) data, &fault, 
+				   sizeof(fault));
+		if(ret)
+			break;
+		break;
+	}
+
+	case PTRACE_SIGPENDING:
+		ret = copy_to_user((unsigned long *) data, 
+				   &child->pending.signal,
+				   sizeof(child->pending.signal));
+		break;
+
+	case PTRACE_LDT: {
+		struct ptrace_ldt ldt;
+
+		if(copy_from_user(&ldt, (unsigned long *) data, 
+				  sizeof(ldt))){
+			ret = -EIO;
+			break;
+		}
+		ret = modify_ldt(child->mm, ldt.func, ldt.ptr, ldt.bytecount);
+		break;
+	}
+
+#ifdef CONFIG_PROC_MM
+	case PTRACE_SWITCH_MM: {
+		struct mm_struct *old = child->mm;
+		struct mm_struct *new = proc_mm_get_mm(data);
+
+		if(IS_ERR(new)){
+			ret = PTR_ERR(new);
+			break;
+		}
+
+		atomic_inc(&new->mm_users);
+		child->mm = new;
+		child->active_mm = new;
+		mmput(old);
+		ret = 0;
+		break;
+	}
+#endif
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
diff -urN linux-2.6.3-uml-jdike/arch/i386/kernel/sys_i386.c linux-2.6.3-uml-jdike+skas/arch/i386/kernel/sys_i386.c
--- linux-2.6.3-uml-jdike/arch/i386/kernel/sys_i386.c	2003-05-27 09:00:59.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/arch/i386/kernel/sys_i386.c	2004-02-27 20:17:08.000000000 +0800
@@ -40,7 +40,7 @@
 }
 
 /* common code for old and new mmaps */
-static inline long do_mmap2(
+long do_mmap2(struct mm_struct *mm,
 	unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags,
 	unsigned long fd, unsigned long pgoff)
@@ -55,9 +55,9 @@
 			goto out;
 	}
 
-	down_write(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->mm->mmap_sem);
+	down_write(&mm->mmap_sem);
+	error = __do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
+	up_write(&mm->mmap_sem);
 
 	if (file)
 		fput(file);
@@ -69,7 +69,7 @@
 	unsigned long prot, unsigned long flags,
 	unsigned long fd, unsigned long pgoff)
 {
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+	return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
 }
 
 /*
@@ -100,7 +100,7 @@
 	if (a.offset & ~PAGE_MASK)
 		goto out;
 
-	err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+	err = do_mmap2(current->mm, a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
 out:
 	return err;
 }
diff -urN linux-2.6.3-uml-jdike/arch/um/include/skas_ptrace.h linux-2.6.3-uml-jdike+skas/arch/um/include/skas_ptrace.h
--- linux-2.6.3-uml-jdike/arch/um/include/skas_ptrace.h	2004-02-27 21:23:38.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/arch/um/include/skas_ptrace.h	2004-02-27 19:57:36.000000000 +0800
@@ -6,6 +6,10 @@
 #ifndef __SKAS_PTRACE_H
 #define __SKAS_PTRACE_H
 
+
+#ifndef _LINUX_PTRACE_STRUCT_DEF
+#define _LINUX_PTRACE_STRUCT_DEF
+
 struct ptrace_faultinfo {
 	int is_write;
 	unsigned long addr;
@@ -17,6 +21,8 @@
 	unsigned long bytecount;
 };
 
+#endif /*ifndef _LINUX_PTRACE_STRUCT_DEF*/
+
 #define PTRACE_FAULTINFO 52
 #define PTRACE_SIGPENDING 53
 #define PTRACE_LDT 54
diff -urN linux-2.6.3-uml-jdike/arch/um/kernel/syscall_kern.c linux-2.6.3-uml-jdike+skas/arch/um/kernel/syscall_kern.c
--- linux-2.6.3-uml-jdike/arch/um/kernel/syscall_kern.c	2004-02-27 21:23:38.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/arch/um/kernel/syscall_kern.c	2004-02-27 20:02:07.000000000 +0800
@@ -81,7 +81,7 @@
 	}
 
 	down_write(&mm->mmap_sem);
-	error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
+	error = __do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
 	up_write(&mm->mmap_sem);
 
 	if (file)
diff -urN linux-2.6.3-uml-jdike/include/asm-i386/processor.h linux-2.6.3-uml-jdike+skas/include/asm-i386/processor.h
--- linux-2.6.3-uml-jdike/include/asm-i386/processor.h	2004-01-17 13:10:44.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/include/asm-i386/processor.h	2004-02-27 19:57:50.000000000 +0800
@@ -630,4 +630,6 @@
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
+extern int __init_new_context(struct mm_struct *mm, struct mm_struct *old_mm);
+
 #endif /* __ASM_I386_PROCESSOR_H */
diff -urN linux-2.6.3-uml-jdike/include/asm-i386/ptrace.h linux-2.6.3-uml-jdike+skas/include/asm-i386/ptrace.h
--- linux-2.6.3-uml-jdike/include/asm-i386/ptrace.h	2003-05-27 09:00:22.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/include/asm-i386/ptrace.h	2004-02-27 20:45:01.000000000 +0800
@@ -59,4 +59,26 @@
 #define instruction_pointer(regs) ((regs)->eip)
 #endif
 
+/*For SKAS3 support.*/
+#ifndef _LINUX_PTRACE_STRUCT_DEF
+#define _LINUX_PTRACE_STRUCT_DEF
+
+#define PTRACE_FAULTINFO        52
+#define PTRACE_SIGPENDING       53
+#define PTRACE_LDT              54
+#define PTRACE_SWITCH_MM        55
+
+struct ptrace_faultinfo {
+	int is_write;
+	unsigned long addr;
+};
+
+struct ptrace_ldt {
+	int func;
+	void *ptr;
+	unsigned long bytecount;
+};
+
+#endif /*ifndef _LINUX_PTRACE_STRUCT_DEF*/
+
 #endif
diff -urN linux-2.6.3-uml-jdike/include/asm-um/processor-generic.h linux-2.6.3-uml-jdike+skas/include/asm-um/processor-generic.h
--- linux-2.6.3-uml-jdike/include/asm-um/processor-generic.h	2004-02-27 21:23:39.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/include/asm-um/processor-generic.h	2004-02-27 19:57:50.000000000 +0800
@@ -101,9 +101,9 @@
 
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
-static inline void mm_copy_segments(struct mm_struct *from_mm, 
-				    struct mm_struct *new_mm)
+static inline int __init_new_context(struct mm_struct *mm, struct mm_struct *old_mm)
 {
+  return 0;
 }
 
 #define init_stack	(init_thread_union.stack)
diff -urN linux-2.6.3-uml-jdike/include/linux/mm.h linux-2.6.3-uml-jdike+skas/include/linux/mm.h
--- linux-2.6.3-uml-jdike/include/linux/mm.h	2004-02-27 21:23:39.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/include/linux/mm.h	2004-02-27 20:00:16.000000000 +0800
@@ -540,10 +540,15 @@
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
-extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file, 
+extern unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file *file, 
 				   unsigned long addr, unsigned long len,
 				   unsigned long prot, unsigned long flag,
 				   unsigned long pgoff);
+static inline unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
+ 	unsigned long len, unsigned long prot,
+	unsigned long flag, unsigned long pgoff) {
+	return __do_mmap_pgoff(current->mm, file, addr, len, prot, flag, pgoff);
+}
 
 static inline unsigned long do_mmap(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
@@ -553,7 +558,7 @@
 	if ((offset + PAGE_ALIGN(len)) < offset)
 		goto out;
 	if (!(offset & ~PAGE_MASK))
-		ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag, 
+		ret = do_mmap_pgoff(file, addr, len, prot, flag, 
 				    offset >> PAGE_SHIFT);
 out:
 	return ret;
diff -urN linux-2.6.3-uml-jdike/mm/mmap.c linux-2.6.3-uml-jdike+skas/mm/mmap.c
--- linux-2.6.3-uml-jdike/mm/mmap.c	2004-02-27 21:23:39.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/mm/mmap.c	2004-02-27 20:03:47.000000000 +0800
@@ -460,7 +460,7 @@
  * The caller must hold down_write(current->mm->mmap_sem).
  */
 
-unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file, 
+unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file * file, 
 			    unsigned long addr, unsigned long len,
 			    unsigned long prot, unsigned long flags,
 			    unsigned long pgoff)
@@ -712,7 +712,7 @@
 	return error;
 }
 
-EXPORT_SYMBOL(do_mmap_pgoff);
+EXPORT_SYMBOL(__do_mmap_pgoff);
 
 /* Get an address range which is currently unmapped.
  * For shmat() with addr=0.
diff -urN linux-2.6.3-uml-jdike/mm/proc_mm.c linux-2.6.3-uml-jdike+skas/mm/proc_mm.c
--- linux-2.6.3-uml-jdike/mm/proc_mm.c	2004-02-27 21:23:39.000000000 +0800
+++ linux-2.6.3-uml-jdike+skas/mm/proc_mm.c	2004-02-27 20:05:51.000000000 +0800
@@ -93,7 +93,7 @@
 			break;
 		}
 
-		mm_copy_segments(from, mm);
+		__init_new_context(mm, from);
 		break;
 	}
 	default:
