Whamcloud - gitweb
Branch: HEAD
authorwangdi <wangdi>
Wed, 6 Apr 2005 16:25:49 +0000 (16:25 +0000)
committerwangdi <wangdi>
Wed, 6 Apr 2005 16:25:49 +0000 (16:25 +0000)
minor fix in Makefile for uml patch

lustre/kernel_patches/patches/uml-2.6.10-fc3.patch

index a5abf90..4cbabd9 100644 (file)
-Index: linux-2.6.10/include/asm-um/archparam-i386.h
+Index: linux-2.6.10/lib/Kconfig.debug
 ===================================================================
---- linux-2.6.10.orig/include/asm-um/archparam-i386.h  2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/include/asm-um/archparam-i386.h       2005-04-05 12:40:36.075903800 +0800
-@@ -10,7 +10,8 @@
+--- linux-2.6.10.orig/lib/Kconfig.debug        2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/lib/Kconfig.debug     2005-04-06 23:44:30.189033160 +0800
+@@ -23,7 +23,6 @@
+ config MAGIC_SYSRQ
+       bool "Magic SysRq key"
+       depends on DEBUG_KERNEL && (H8300 || M68KNOMMU || V850)
+-      depends (USERMODE && MCONSOLE)
+       help
+         Enables console device to interpret special characters as
+         commands to dump state information.
+Index: linux-2.6.10/mm/mprotect.c
+===================================================================
+--- linux-2.6.10.orig/mm/mprotect.c    2004-12-25 05:35:50.000000000 +0800
++++ linux-2.6.10/mm/mprotect.c 2005-04-06 23:44:30.204030880 +0800
+@@ -93,19 +93,20 @@
+ {
+       pgd_t *dir;
+       unsigned long beg = start;
++      struct mm_struct * mm = vma->vm_mm;
  
- #include "user.h"
+-      dir = pgd_offset(current->mm, start);
++      dir = pgd_offset(mm, start);
+       flush_cache_range(vma, beg, end);
+       if (start >= end)
+               BUG();
+-      spin_lock(&current->mm->page_table_lock);
++      spin_lock(&mm->page_table_lock);
+       do {
+               change_pmd_range(dir, start, end - start, newprot);
+               start = (start + PGDIR_SIZE) & PGDIR_MASK;
+               dir++;
+       } while (start && (start < end));
+       flush_tlb_range(vma, beg, end);
+-      spin_unlock(&current->mm->page_table_lock);
++      spin_unlock(&mm->page_table_lock);
+       return;
+ }
  
--#define ELF_PLATFORM "i586"
-+extern char * elf_aux_platform;
-+#define ELF_PLATFORM (elf_aux_platform)
+@@ -190,8 +191,9 @@
+       return error;
+ }
  
- #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+-asmlinkage long
+-sys_mprotect(unsigned long start, size_t len, unsigned long prot)
++long
++do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
++           unsigned long prot)
+ {
+       unsigned long vm_flags, nstart, end, tmp;
+       struct vm_area_struct *vma, *prev;
+@@ -220,9 +222,9 @@
  
-@@ -56,15 +57,13 @@
-       pr_reg[16] = PT_REGS_SS(regs);          \
- } while(0);
+       vm_flags = calc_vm_prot_bits(prot);
  
--#if 0 /* Turn this back on when UML has VSYSCALL working */
--#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
--#else
--#define VSYSCALL_BASE 0
--#endif
+-      down_write(&current->mm->mmap_sem);
++      down_write(&mm->mmap_sem);
  
--#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
--#define VSYSCALL_ENTRY        ((unsigned long) &__kernel_vsyscall)
--extern void *__kernel_vsyscall;
-+extern unsigned long vsyscall_ehdr;
-+extern unsigned long vsyscall_end;
-+extern unsigned long __kernel_vsyscall;
+-      vma = find_vma_prev(current->mm, start, &prev);
++      vma = find_vma_prev(mm, start, &prev);
+       error = -ENOMEM;
+       if (!vma)
+               goto out;
+@@ -288,6 +290,11 @@
+               }
+       }
+ out:
+-      up_write(&current->mm->mmap_sem);
++      up_write(&mm->mmap_sem);
+       return error;
+ }
 +
-+#define VSYSCALL_BASE vsyscall_ehdr
-+#define VSYSCALL_END vsyscall_end
- /*
-  * Architecture-neutral AT_ values in 0-17, leave some room
-@@ -75,8 +74,10 @@
- #define ARCH_DLINFO                                           \
- do {                                                          \
--              NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY);        \
--              NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);    \
-+      if ( vsyscall_ehdr ) {                                  \
-+              NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall);     \
-+              NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);    \
-+      }                                                       \
- } while (0)
- /*
-@@ -87,22 +88,18 @@
-  * Dumping its extra ELF program headers includes all the other information
-  * a debugger needs to easily find how the vsyscall DSO was being used.
-  */
--#if 0
--#define ELF_CORE_EXTRA_PHDRS          (VSYSCALL_EHDR->e_phnum)
--#endif
--
--#undef ELF_CORE_EXTRA_PHDRS
-+#define ELF_CORE_EXTRA_PHDRS                                                \
-+      (vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
--#if 0
- #define ELF_CORE_WRITE_EXTRA_PHDRS                                          \
--do {                                                                        \
--      const struct elf_phdr *const vsyscall_phdrs =                         \
--              (const struct elf_phdr *) (VSYSCALL_BASE                      \
--                                         + VSYSCALL_EHDR->e_phoff);         \
-+if ( vsyscall_ehdr ) {                                                              \
-+      const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
-+      const struct elf_phdr *const phdrp =                                  \
-+              (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
-       int i;                                                                \
-       Elf32_Off ofs = 0;                                                    \
--      for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {                        \
--              struct elf_phdr phdr = vsyscall_phdrs[i];                     \
-+      for (i = 0; i < ehdrp->e_phnum; ++i) {                                \
-+              struct elf_phdr phdr = phdrp[i];                              \
-               if (phdr.p_type == PT_LOAD) {                                 \
-                       ofs = phdr.p_offset = offset;                         \
-                       offset += phdr.p_filesz;                              \
-@@ -112,23 +109,19 @@
-               phdr.p_paddr = 0; /* match other core phdrs */                \
-               DUMP_WRITE(&phdr, sizeof(phdr));                              \
-       }                                                                     \
--} while (0)
-+}
- #define ELF_CORE_WRITE_EXTRA_DATA                                           \
--do {                                                                        \
--      const struct elf_phdr *const vsyscall_phdrs =                         \
--              (const struct elf_phdr *) (VSYSCALL_BASE                      \
--                                         + VSYSCALL_EHDR->e_phoff);         \
-+if ( vsyscall_ehdr ) {                                                              \
-+      const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
-+      const struct elf_phdr *const phdrp =                                  \
-+              (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
-       int i;                                                                \
--      for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {                        \
--              if (vsyscall_phdrs[i].p_type == PT_LOAD)                      \
--                      DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,        \
--                                 vsyscall_phdrs[i].p_filesz);               \
-+      for (i = 0; i < ehdrp->e_phnum; ++i) {                                \
-+              if (phdrp[i].p_type == PT_LOAD)                               \
-+                      DUMP_WRITE((void *) phdrp[i].p_vaddr,                 \
-+                                 phdrp[i].p_filesz);                        \
-       }                                                                     \
--} while (0)
--#endif
--
--#undef ELF_CORE_WRITE_EXTRA_PHDRS
--#undef ELF_CORE_WRITE_EXTRA_DATA
++asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
++{
++        return(do_mprotect(current->mm, start, len, prot));
 +}
- #define R_386_NONE    0
- #define R_386_32      1
-Index: linux-2.6.10/include/asm-um/elf.h
-===================================================================
---- linux-2.6.10.orig/include/asm-um/elf.h     2004-12-25 05:35:01.000000000 +0800
-+++ linux-2.6.10/include/asm-um/elf.h  2005-04-05 12:40:36.074903952 +0800
-@@ -3,7 +3,8 @@
- #include "asm/archparam.h"
--#define ELF_HWCAP (0)
-+extern long elf_aux_hwcap;
-+#define ELF_HWCAP (elf_aux_hwcap)
- #define SET_PERSONALITY(ex, ibcs2) do ; while(0)
-Index: linux-2.6.10/include/asm-um/fixmap.h
+Index: linux-2.6.10/mm/mmap.c
 ===================================================================
---- linux-2.6.10.orig/include/asm-um/fixmap.h  2004-12-25 05:35:28.000000000 +0800
-+++ linux-2.6.10/include/asm-um/fixmap.h       2005-04-05 12:40:36.075903800 +0800
-@@ -3,6 +3,7 @@
- #include <linux/config.h>
- #include <asm/kmap_types.h>
-+#include <asm/archparam.h>
- /*
-  * Here we define all the compile-time 'special' virtual
-@@ -34,7 +35,6 @@
-       FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
-       FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
- #endif
--      FIX_VSYSCALL,
-       __end_of_fixed_addresses
- };
-@@ -68,8 +68,8 @@
-  * This is the range that is readable by user mode, and things
-  * acting like user mode such as get_user_pages.
+--- linux-2.6.10.orig/mm/mmap.c        2005-04-06 23:38:33.000000000 +0800
++++ linux-2.6.10/mm/mmap.c     2005-04-06 23:44:30.193032552 +0800
+@@ -759,11 +759,11 @@
+  * The caller must hold down_write(current->mm->mmap_sem).
   */
--#define FIXADDR_USER_START    (__fix_to_virt(FIX_VSYSCALL))
--#define FIXADDR_USER_END      (FIXADDR_USER_START + PAGE_SIZE)
-+#define FIXADDR_USER_START    VSYSCALL_BASE
-+#define FIXADDR_USER_END      VSYSCALL_END
- extern void __this_fixmap_does_not_exist(void);
-Index: linux-2.6.10/include/asm-i386/thread_info.h
-===================================================================
---- linux-2.6.10.orig/include/asm-i386/thread_info.h   2005-03-31 16:20:10.000000000 +0800
-+++ linux-2.6.10/include/asm-i386/thread_info.h        2005-04-05 12:40:36.076903648 +0800
-@@ -139,6 +139,7 @@
- #define TIF_NEED_RESCHED      3       /* rescheduling necessary */
- #define TIF_SINGLESTEP                4       /* restore singlestep on return to user mode */
- #define TIF_IRET              5       /* return with iret */
-+#define TIF_SYSCALL_EMU               6       /* syscall emulation active */
- #define TIF_SYSCALL_AUDIT     7       /* syscall auditing active */
- #define TIF_POLLING_NRFLAG    16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
  
-@@ -148,12 +149,14 @@
- #define _TIF_NEED_RESCHED     (1<<TIF_NEED_RESCHED)
- #define _TIF_SINGLESTEP               (1<<TIF_SINGLESTEP)
- #define _TIF_IRET             (1<<TIF_IRET)
-+#define _TIF_SYSCALL_EMU      (1<<TIF_SYSCALL_EMU)
- #define _TIF_SYSCALL_AUDIT    (1<<TIF_SYSCALL_AUDIT)
- #define _TIF_POLLING_NRFLAG   (1<<TIF_POLLING_NRFLAG)
+-unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+-                      unsigned long len, unsigned long prot,
+-                      unsigned long flags, unsigned long pgoff)
++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)
+ {
+-      struct mm_struct * mm = current->mm;
+       struct vm_area_struct * vma, * prev;
+       struct inode *inode;
+       unsigned int vm_flags;
+@@ -1037,7 +1037,7 @@
+       return error;
+ }
  
- /* work to do on interrupt/exception return */
- #define _TIF_WORK_MASK \
--  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
-+  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|\
-+                _TIF_SYSCALL_EMU))
- #define _TIF_ALLWORK_MASK     0x0000FFFF      /* work to do on any return to u-space */
- /*
-Index: linux-2.6.10/include/asm-i386/mmu_context.h
-===================================================================
---- linux-2.6.10.orig/include/asm-i386/mmu_context.h   2004-12-25 05:33:48.000000000 +0800
-+++ linux-2.6.10/include/asm-i386/mmu_context.h        2005-04-05 12:40:36.077903496 +0800
-@@ -6,13 +6,25 @@
- #include <asm/atomic.h>
- #include <asm/pgalloc.h>
- #include <asm/tlbflush.h>
-+#include <asm/semaphore.h>
- /*
-- * Used for LDT copy/destruction.
-+ * Used for LDT initialization/destruction. You cannot copy an LDT with
-+ * init_new_context, since it thinks you are passing it a new LDT and won't
-+ * deallocate its old content.
-  */
- int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
- void destroy_context(struct mm_struct *mm);
-+/* LDT initialization for a clean environment - needed for SKAS.*/
-+static inline void init_new_empty_context(struct mm_struct *mm)
-+{
-+      init_MUTEX(&mm->context.sem);
-+      mm->context.size = 0;
-+}
-+
-+/* LDT copy for SKAS - for the above problem.*/
-+int copy_context(struct mm_struct *mm, struct mm_struct *old_mm);
- static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
- {
-@@ -29,6 +41,10 @@
- {
-       int cpu = smp_processor_id();
-+#ifdef CONFIG_SMP
-+      prev = per_cpu(cpu_tlbstate, cpu).active_mm;
-+#endif
-+
-       if (likely(prev != next)) {
-               /* stop flush ipis for the previous mm */
-               cpu_clear(cpu, prev->cpu_vm_mask);
-@@ -50,7 +66,6 @@
- #ifdef CONFIG_SMP
-       else {
-               per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
--              BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
-               if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
-                       /* We were in lazy tlb mode and leave_mm disabled 
-Index: linux-2.6.10/include/asm-i386/ptrace.h
-===================================================================
---- linux-2.6.10.orig/include/asm-i386/ptrace.h        2004-12-25 05:33:51.000000000 +0800
-+++ linux-2.6.10/include/asm-i386/ptrace.h     2005-04-05 12:40:36.077903496 +0800
-@@ -64,4 +64,26 @@
- #endif
- #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
-Index: linux-2.6.10/include/asm-i386/desc.h
-===================================================================
---- linux-2.6.10.orig/include/asm-i386/desc.h  2005-03-31 16:20:09.000000000 +0800
-+++ linux-2.6.10/include/asm-i386/desc.h       2005-04-05 12:40:36.078903344 +0800
-@@ -126,6 +126,9 @@
-       put_cpu();
- }
-+extern int __modify_ldt(struct mm_struct * mm, int func, void __user *ptr,
-+                    unsigned long bytecount);
-+
- #endif /* !__ASSEMBLY__ */
- #endif
-Index: linux-2.6.10/include/linux/ptrace.h
-===================================================================
---- linux-2.6.10.orig/include/linux/ptrace.h   2005-03-31 15:35:23.000000000 +0800
-+++ linux-2.6.10/include/linux/ptrace.h        2005-04-05 12:40:36.071904408 +0800
-@@ -20,6 +20,7 @@
- #define PTRACE_DETACH         0x11
- #define PTRACE_SYSCALL                  24
-+#define PTRACE_SYSEMU           31
- /* 0x4200-0x4300 are reserved for architecture-independent additions.  */
- #define PTRACE_SETOPTIONS     0x4200
-Index: linux-2.6.10/include/linux/mm.h
-===================================================================
---- linux-2.6.10.orig/include/linux/mm.h       2005-03-31 16:10:15.000000000 +0800
-+++ linux-2.6.10/include/linux/mm.h    2005-04-05 12:40:36.072904256 +0800
-@@ -625,6 +625,9 @@
- extern struct shrinker *set_shrinker(int, shrinker_t);
- extern void remove_shrinker(struct shrinker *shrinker);
-+extern long do_mprotect(struct mm_struct *mm, unsigned long start,
-+                      size_t len, unsigned long prot);
-+
- /*
-  * On a two-level page table, this ends up being trivial. Thus the
-  * inlining and the symmetry break with pte_alloc_map() that does all
-@@ -684,9 +687,15 @@
- extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
--extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
-+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);
-+      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,
-Index: linux-2.6.10/include/linux/proc_mm.h
-===================================================================
---- linux-2.6.10.orig/include/linux/proc_mm.h  2005-04-05 19:01:49.158500672 +0800
-+++ linux-2.6.10/include/linux/proc_mm.h       2005-04-05 12:40:36.073904104 +0800
-@@ -0,0 +1,48 @@
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __PROC_MM_H
-+#define __PROC_MM_H
-+
-+#include "linux/sched.h"
-+
-+#define MM_MMAP 54
-+#define MM_MUNMAP 55
-+#define MM_MPROTECT 56
-+#define MM_COPY_SEGMENTS 57
-+
-+struct mm_mmap {
-+      unsigned long addr;
-+      unsigned long len;
-+      unsigned long prot;
-+      unsigned long flags;
-+      unsigned long fd;
-+      unsigned long offset;
-+};
-+
-+struct mm_munmap {
-+      unsigned long addr;
-+      unsigned long len;
-+};
-+
-+struct mm_mprotect {
-+      unsigned long addr;
-+      unsigned long len;
-+        unsigned int prot;
-+};
-+
-+struct proc_mm_op {
-+      int op;
-+      union {
-+              struct mm_mmap mmap;
-+              struct mm_munmap munmap;
-+              struct mm_mprotect mprotect;
-+              int copy_segments;
-+      } u;
-+};
-+
-+extern struct mm_struct *proc_mm_get_mm(int fd);
-+
-+#endif
-Index: linux-2.6.10/lib/Kconfig.debug
-===================================================================
---- linux-2.6.10.orig/lib/Kconfig.debug        2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/lib/Kconfig.debug     2005-04-05 12:40:36.010913680 +0800
-@@ -23,7 +23,6 @@
- config MAGIC_SYSRQ
-       bool "Magic SysRq key"
-       depends on DEBUG_KERNEL && (H8300 || M68KNOMMU || V850)
--      depends (USERMODE && MCONSOLE)
-       help
-         Enables console device to interpret special characters as
-         commands to dump state information.
-Index: linux-2.6.10/kernel/fork.c
-===================================================================
---- linux-2.6.10.orig/kernel/fork.c    2005-03-31 15:35:26.000000000 +0800
-+++ linux-2.6.10/kernel/fork.c 2005-04-05 12:40:36.070904560 +0800
-@@ -927,6 +927,9 @@
-        * of CLONE_PTRACE.
-        */
-       clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
-+#ifdef TIF_SYSCALL_EMU
-+      clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
-+#endif
-       /* Our parent execution domain becomes current domain
-          These must match for thread signalling to apply */
-Index: linux-2.6.10/mm/mmap.c
-===================================================================
---- linux-2.6.10.orig/mm/mmap.c        2005-03-31 16:20:10.000000000 +0800
-+++ linux-2.6.10/mm/mmap.c     2005-04-05 12:40:36.013913224 +0800
-@@ -759,11 +759,11 @@
-  * The caller must hold down_write(current->mm->mmap_sem).
-  */
--unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
--                      unsigned long len, unsigned long prot,
--                      unsigned long flags, unsigned long pgoff)
-+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)
- {
--      struct mm_struct * mm = current->mm;
-       struct vm_area_struct * vma, * prev;
-       struct inode *inode;
-       unsigned int vm_flags;
-@@ -1037,7 +1037,7 @@
-       return error;
- }
--EXPORT_SYMBOL(do_mmap_pgoff);
-+EXPORT_SYMBOL(__do_mmap_pgoff);
+-EXPORT_SYMBOL(do_mmap_pgoff);
++EXPORT_SYMBOL(__do_mmap_pgoff);
  
  /* Get an address range which is currently unmapped.
   * For shmat() with addr=0.
 Index: linux-2.6.10/mm/proc_mm.c
 ===================================================================
---- linux-2.6.10.orig/mm/proc_mm.c     2005-04-05 19:01:49.158500672 +0800
-+++ linux-2.6.10/mm/proc_mm.c  2005-04-05 12:40:36.014913072 +0800
+--- linux-2.6.10.orig/mm/proc_mm.c     2005-04-07 06:37:43.373923992 +0800
++++ linux-2.6.10/mm/proc_mm.c  2005-04-06 23:44:30.204030880 +0800
 @@ -0,0 +1,181 @@
 +/*
 + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
@@ -618,1050 +290,322 @@ Index: linux-2.6.10/mm/proc_mm.c
 + * c-file-style: "linux"
 + * End:
 + */
-Index: linux-2.6.10/mm/mprotect.c
+Index: linux-2.6.10/mm/Makefile
 ===================================================================
---- linux-2.6.10.orig/mm/mprotect.c    2005-03-31 16:20:10.000000000 +0800
-+++ linux-2.6.10/mm/mprotect.c 2005-04-05 12:40:36.011913528 +0800
-@@ -93,19 +93,20 @@
- {
-       pgd_t *dir;
-       unsigned long beg = start;
-+      struct mm_struct * mm = vma->vm_mm;
--      dir = pgd_offset(current->mm, start);
-+      dir = pgd_offset(mm, start);
-       flush_cache_range(vma, beg, end);
-       if (start >= end)
-               BUG();
--      spin_lock(&current->mm->page_table_lock);
-+      spin_lock(&mm->page_table_lock);
-       do {
-               change_pmd_range(dir, start, end - start, newprot);
-               start = (start + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (start && (start < end));
-       flush_tlb_range(vma, beg, end);
--      spin_unlock(&current->mm->page_table_lock);
-+      spin_unlock(&mm->page_table_lock);
-       return;
- }
-@@ -190,8 +191,9 @@
-       return error;
- }
--asmlinkage long
--sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-+long
-+do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
-+           unsigned long prot)
- {
-       unsigned long vm_flags, nstart, end, tmp;
-       struct vm_area_struct *vma, *prev;
-@@ -220,9 +222,9 @@
-       vm_flags = calc_vm_prot_bits(prot);
--      down_write(&current->mm->mmap_sem);
-+      down_write(&mm->mmap_sem);
--      vma = find_vma_prev(current->mm, start, &prev);
-+      vma = find_vma_prev(mm, start, &prev);
-       error = -ENOMEM;
-       if (!vma)
-               goto out;
-@@ -288,6 +290,11 @@
-               }
-       }
- out:
--      up_write(&current->mm->mmap_sem);
-+      up_write(&mm->mmap_sem);
-       return error;
- }
-+
-+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-+{
-+        return(do_mprotect(current->mm, start, len, prot));
-+}
-Index: linux-2.6.10/mm/Makefile
-===================================================================
---- linux-2.6.10.orig/mm/Makefile      2004-12-25 05:35:00.000000000 +0800
-+++ linux-2.6.10/mm/Makefile   2005-04-05 12:40:36.014913072 +0800
-@@ -18,3 +18,4 @@
- obj-$(CONFIG_SHMEM) += shmem.o
- obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
+--- linux-2.6.10.orig/mm/Makefile      2004-12-25 05:35:00.000000000 +0800
++++ linux-2.6.10/mm/Makefile   2005-04-06 23:44:30.205030728 +0800
+@@ -18,3 +18,4 @@
+ obj-$(CONFIG_SHMEM) += shmem.o
+ obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
  
 +obj-$(CONFIG_PROC_MM) += proc_mm.o
-Index: linux-2.6.10/arch/i386/kernel/entry.S
-===================================================================
---- linux-2.6.10.orig/arch/i386/kernel/entry.S 2005-03-31 16:20:08.000000000 +0800
-+++ linux-2.6.10/arch/i386/kernel/entry.S      2005-04-05 12:40:36.064905472 +0800
-@@ -222,7 +222,7 @@
-       SAVE_ALL
-       GET_THREAD_INFO(%ebp)
--      testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
-+      testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
-       jnz syscall_trace_entry
-       cmpl $(nr_syscalls), %eax
-       jae syscall_badsys
-@@ -245,8 +245,8 @@
-       pushl %eax                      # save orig_eax
-       SAVE_ALL
-       GET_THREAD_INFO(%ebp)
--                                      # system call tracing in operation
--      testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
-+                                      # system call tracing in operation / emulation
-+      testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
-       jnz syscall_trace_entry
-       cmpl $(nr_syscalls), %eax
-       jae syscall_badsys
-@@ -307,6 +307,9 @@
-       movl %esp, %eax
-       xorl %edx,%edx
-       call do_syscall_trace
-+      cmpl $0, %eax
-+      jne syscall_exit                # ret != 0 -> running under PTRACE_SYSEMU,
-+                                      # so must skip actual syscall
-       movl ORIG_EAX(%esp), %eax
-       cmpl $(nr_syscalls), %eax
-       jnae syscall_call
-Index: linux-2.6.10/arch/i386/kernel/ptrace.c
+Index: linux-2.6.10/arch/um/drivers/mconsole_kern.c
 ===================================================================
---- linux-2.6.10.orig/arch/i386/kernel/ptrace.c        2004-12-25 05:34:29.000000000 +0800
-+++ linux-2.6.10/arch/i386/kernel/ptrace.c     2005-04-05 12:40:36.061905928 +0800
-@@ -15,6 +15,7 @@
- #include <linux/user.h>
- #include <linux/security.h>
- #include <linux/audit.h>
-+#include <linux/proc_mm.h>
- #include <asm/uaccess.h>
- #include <asm/pgtable.h>
-@@ -406,15 +407,27 @@
-                 }
-                 break;
-+      case PTRACE_SYSEMU: /* continue and stop at next syscall, which will not be executed */
-       case PTRACE_SYSCALL:    /* continue and stop at next (return from) syscall */
-       case PTRACE_CONT:       /* restart after signal. */
-               ret = -EIO;
-               if ((unsigned long) data > _NSIG)
-                       break;
-+              /* If we came here with PTRACE_SYSEMU and now continue with
-+               * PTRACE_SYSCALL, entry.S used to intercept the syscall return.
-+               * But it shouldn't!
-+               * So we don't clear TIF_SYSCALL_EMU, which is always unused in
-+               * this special case, to remember, we came from SYSEMU. That
-+               * flag will be cleared by do_syscall_trace().
-+               */
-+              if (request == PTRACE_SYSEMU) {
-+                      set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
-+              } else if (request == PTRACE_CONT) {
-+                      clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
-+              }
-               if (request == PTRACE_SYSCALL) {
-                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
--              }
--              else {
-+              } else {
-                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               }
-               child->exit_code = data;
-@@ -443,6 +456,8 @@
-               ret = -EIO;
-               if ((unsigned long) data > _NSIG)
-                       break;
-+              /*See do_syscall_trace to know why we don't clear
-+               * TIF_SYSCALL_EMU.*/
-               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-               set_singlestep(child);
-               child->exit_code = data;
-@@ -542,6 +557,58 @@
-                                       (struct user_desc __user *) data);
-               break;
+--- linux-2.6.10.orig/arch/um/drivers/mconsole_kern.c  2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/drivers/mconsole_kern.c       2005-04-06 23:44:30.283018872 +0800
+@@ -204,6 +204,68 @@
+ }
+ #endif
  
-+#ifdef CONFIG_PROC_MM
-+      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;
++/* This is a more convoluted version of mconsole_proc, which has some stability
++ * problems; however, we need it fixed, because it is expected that UML users
++ * mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still
++ * show the real procfs content, not the ones from hppfs.*/
++#if 0
++void mconsole_proc(struct mc_request *req)
++{
++      char path[64];
++      char *buf;
++      int len;
++      int fd;
++      int first_chunk = 1;
++      char *ptr = req->request.data;
 +
-+      case PTRACE_LDT: {
-+              struct ptrace_ldt ldt;
++      ptr += strlen("proc");
++      while(isspace(*ptr)) ptr++;
++      snprintf(path, sizeof(path), "/proc/%s", ptr);
 +
-+              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;
++      fd = sys_open(path, 0, 0);
++      if (fd < 0) {
++              mconsole_reply(req, "Failed to open file", 1, 0);
++              printk("open %s: %d\n",path,fd);
++              goto out;
 +      }
 +
-+      case PTRACE_SWITCH_MM: {
-+              struct mm_struct *old = child->mm;
-+              struct mm_struct *new = proc_mm_get_mm(data);
++      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++      if(buf == NULL){
++              mconsole_reply(req, "Failed to allocate buffer", 1, 0);
++              goto out_close;
++      }
 +
-+              if(IS_ERR(new)){
-+                      ret = PTR_ERR(new);
++      for (;;) {
++              len = sys_read(fd, buf, PAGE_SIZE-1);
++              if (len < 0) {
++                      mconsole_reply(req, "Read of file failed", 1, 0);
++                      goto out_free;
++              }
++              /*Begin the file content on his own line.*/
++              if (first_chunk) {
++                      mconsole_reply(req, "\n", 0, 1);
++                      first_chunk = 0;
++              }
++              if (len == PAGE_SIZE-1) {
++                      buf[len] = '\0';
++                      mconsole_reply(req, buf, 0, 1);
++              } else {
++                      buf[len] = '\0';
++                      mconsole_reply(req, buf, 0, 0);
 +                      break;
 +              }
-+
-+              atomic_inc(&new->mm_users);
-+              task_lock(child);
-+              child->mm = new;
-+              child->active_mm = new;
-+              task_unlock(child);
-+              mmput(old);
-+              ret = 0;
-+              break;
 +      }
++      /*END*/
++
++ out_free:
++      kfree(buf);
++ out_close:
++      sys_close(fd);
++ out:
++      /* nothing */;
++}
 +#endif
 +
-       default:
-               ret = ptrace_request(child, request, addr, data);
-               break;
-@@ -557,8 +624,9 @@
-  * - triggered by current->work.syscall_trace
-  */
- __attribute__((regparm(3)))
--void do_syscall_trace(struct pt_regs *regs, int entryexit)
-+int do_syscall_trace(struct pt_regs *regs, int entryexit)
+ void mconsole_proc(struct mc_request *req)
  {
-+      int is_sysemu, is_systrace, is_singlestep;
-       if (unlikely(current->audit_context)) {
-               if (!entryexit)
-                       audit_syscall_entry(current, regs->orig_eax,
-@@ -567,16 +635,27 @@
-               else
-                       audit_syscall_exit(current, regs->eax);
-       }
+       char path[64];
+Index: linux-2.6.10/arch/um/drivers/net_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/drivers/net_kern.c       2004-12-25 05:34:44.000000000 +0800
++++ linux-2.6.10/arch/um/drivers/net_kern.c    2005-04-06 23:44:30.282019024 +0800
+@@ -126,10 +126,6 @@
+       lp->tl.data = (unsigned long) &lp->user;
+       netif_start_queue(dev);
+-      spin_lock(&opened_lock);
+-      list_add(&lp->list, &opened);
+-      spin_unlock(&opened_lock);
 -
--      if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
--          !test_thread_flag(TIF_SINGLESTEP))
--              return;
-+      is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
-+      is_systrace = test_thread_flag(TIF_SYSCALL_TRACE);
-+      is_singlestep = test_thread_flag(TIF_SINGLESTEP);
-+
-+      if (!is_systrace && !is_singlestep && !is_sysemu)
-+              return 0;
-+      /* We can detect the case of coming from PTRACE_SYSEMU and now running
-+       * with PTRACE_SYSCALL or PTRACE_SINGLESTEP, by TIF_SYSCALL_EMU being
-+       * set additionally.
-+       * If so let's reset the flag and return without action.
-+       */
-+      if (is_sysemu && (is_systrace || is_singlestep)) {
-+              clear_thread_flag(TIF_SYSCALL_EMU);
-+              return 0;
-+      }
-       if (!(current->ptrace & PT_PTRACED))
--              return;
-+              return 0;
-       /* the 0x80 provides a way for the tracing parent to distinguish
-          between a syscall stop and SIGTRAP delivery */
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
--                               !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
-+                               !is_singlestep ? 0x80 : 0));
+       /* clear buffer - it can happen that the host side of the interface
+        * is full when we get here.  In this case, new data is never queued,
+        * SIGIOs never arrive, and the net never works.
+@@ -152,9 +148,6 @@
+       free_irq(dev->irq, dev);
+       if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
+       lp->fd = -1;
+-      spin_lock(&opened_lock);
+-      list_del(&lp->list);
+-      spin_unlock(&opened_lock);
  
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-@@ -587,4 +666,6 @@
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
-+      /* != 0 if nullifying the syscall, 0 if running it normally */
-+      return is_sysemu;
- }
-Index: linux-2.6.10/arch/i386/kernel/ldt.c
-===================================================================
---- linux-2.6.10.orig/arch/i386/kernel/ldt.c   2004-12-25 05:35:23.000000000 +0800
-+++ linux-2.6.10/arch/i386/kernel/ldt.c        2005-04-05 12:40:36.062905776 +0800
-@@ -18,6 +18,7 @@
- #include <asm/system.h>
- #include <asm/ldt.h>
- #include <asm/desc.h>
-+#include <asm/mmu_context.h>
+       spin_unlock(&lp->lock);
+       return 0;
+@@ -397,6 +390,11 @@
  
- #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
- static void flush_ldt(void *null)
-@@ -27,11 +28,12 @@
+       if (device->have_mac)
+               set_ether_mac(dev, device->mac);
++
++      spin_lock(&opened_lock);
++      list_add(&lp->list, &opened);
++      spin_unlock(&opened_lock);
++
+       return(0);
  }
- #endif
  
--static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
-+static int alloc_ldt(struct mm_struct *mm, int mincount, int reload)
+@@ -705,7 +703,7 @@
+ static void close_devices(void)
  {
-       void *oldldt;
-       void *newldt;
-       int oldsize;
-+      mm_context_t * pc = &mm->context;
-       if (mincount <= pc->size)
-               return 0;
-@@ -58,13 +60,15 @@
- #ifdef CONFIG_SMP
-               cpumask_t mask;
-               preempt_disable();
--              load_LDT(pc);
-+              if (&current->active_mm->context == pc)
-+                      load_LDT(pc);
-               mask = cpumask_of_cpu(smp_processor_id());
--              if (!cpus_equal(current->mm->cpu_vm_mask, mask))
-+              if (!cpus_equal(mm->cpu_vm_mask, mask))
-                       smp_call_function(flush_ldt, NULL, 1, 1);
-               preempt_enable();
- #else
--              load_LDT(pc);
-+              if (&current->active_mm->context == pc)
-+                      load_LDT(pc);
- #endif
-       }
-       if (oldsize) {
-@@ -76,12 +80,12 @@
-       return 0;
- }
+       struct list_head *ele;
+-      struct uml_net_private *lp;     
++      struct uml_net_private *lp;
  
--static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
-+static inline int copy_ldt(struct mm_struct *new, struct mm_struct *old)
- {
--      int err = alloc_ldt(new, old->size, 0);
-+      int err = alloc_ldt(new, old->context.size, 0);
-       if (err < 0)
-               return err;
--      memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
-+      memcpy(new->context.ldt, old->context.ldt, old->context.size*LDT_ENTRY_SIZE);
-       return 0;
- }
+       list_for_each(ele, &opened){
+               lp = list_entry(ele, struct uml_net_private, list);
+Index: linux-2.6.10/arch/um/drivers/net_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/drivers/net_user.c       2004-12-25 05:34:26.000000000 +0800
++++ linux-2.6.10/arch/um/drivers/net_user.c    2005-04-06 23:44:30.284018720 +0800
+@@ -173,10 +173,12 @@
+       pe_data.stdout = fds[1];
+       pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
  
-@@ -89,22 +93,24 @@
-  * 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 copy_context(struct mm_struct *mm, struct mm_struct *old_mm)
- {
--      struct mm_struct * old_mm;
-       int retval = 0;
+-      os_close_file(fds[1]);
+       read_output(fds[0], output, output_len);
++      os_close_file(fds[0]);
++      os_close_file(fds[1]);
  
--      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);
-+              retval = copy_ldt(mm, old_mm);
-               up(&old_mm->context.sem);
-       }
-       return retval;
+-      CATCH_EINTR(err = waitpid(pid, NULL, 0));
++      if (pid > 0)
++              CATCH_EINTR(err = waitpid(pid, NULL, 0));
+       return(pid);
  }
  
-+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+Index: linux-2.6.10/arch/um/os-Linux/elf_aux.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/os-Linux/elf_aux.c       2005-04-07 06:37:43.373923992 +0800
++++ linux-2.6.10/arch/um/os-Linux/elf_aux.c    2005-04-06 23:44:30.280019328 +0800
+@@ -0,0 +1,67 @@
++/*
++ *  arch/um/kernel/elf_aux.c
++ *
++ *  Scan the Elf auxiliary vector provided by the host to extract
++ *  information about vsyscall-page, etc.
++ *
++ *  Copyright (C) 2004 Fujitsu Siemens Computers GmbH
++ *  Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com)
++ */
++#include <elf.h>
++#include <stddef.h>
++#include "init.h"
++#include "elf_user.h"
++
++#if ELF_CLASS == ELFCLASS32
++typedef Elf32_auxv_t elf_auxv_t;
++#else
++typedef Elf64_auxv_t elf_auxv_t;
++#endif
++
++char * elf_aux_platform;
++long elf_aux_hwcap;
++
++unsigned long vsyscall_ehdr;
++unsigned long vsyscall_end;
++
++unsigned long __kernel_vsyscall;
++
++
++__init void scan_elf_aux( char **envp)
 +{
-+      init_new_empty_context(mm);
-+      return copy_context(mm, current->mm);
++      long page_size = 0;
++      elf_auxv_t * auxv;
++
++      while ( *envp++ != NULL) ;
++
++      for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
++              switch ( auxv->a_type ) {
++                      case AT_SYSINFO:
++                              __kernel_vsyscall = auxv->a_un.a_val;
++                              break;
++                      case AT_SYSINFO_EHDR:
++                              vsyscall_ehdr = auxv->a_un.a_val;
++                              break;
++                      case AT_HWCAP:
++                              elf_aux_hwcap = auxv->a_un.a_val;
++                              break;
++                      case AT_PLATFORM:
++                              elf_aux_platform = auxv->a_un.a_ptr;
++                              break;
++                      case AT_PAGESZ:
++                              page_size = auxv->a_un.a_val;
++                              break;
++              }
++      }
++      if ( ! __kernel_vsyscall || ! vsyscall_ehdr ||
++           ! elf_aux_hwcap || ! elf_aux_platform ||
++           ! page_size || (vsyscall_ehdr % page_size) ) {
++              __kernel_vsyscall = 0;
++              vsyscall_ehdr = 0;
++              elf_aux_hwcap = 0;
++              elf_aux_platform = "i586";
++      }
++      else {
++              vsyscall_end = vsyscall_ehdr + page_size;
++      }
 +}
+Index: linux-2.6.10/arch/um/os-Linux/user_syms.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/os-Linux/user_syms.c     2004-12-25 05:35:23.000000000 +0800
++++ linux-2.6.10/arch/um/os-Linux/user_syms.c  2005-04-06 23:44:30.279019480 +0800
+@@ -26,6 +26,9 @@
+ EXPORT_SYMBOL(strstr);
++EXPORT_SYMBOL(vsyscall_ehdr);
++EXPORT_SYMBOL(vsyscall_end);
 +
- /*
-  * No need to lock the MM as we are the last user
-  */
-@@ -121,11 +127,11 @@
-       }
- }
+ /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
+  * However, the modules will use the CRC defined *here*, no matter if it is
+  * good; so the versions of these symbols will always match
+Index: linux-2.6.10/arch/um/os-Linux/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/os-Linux/Makefile        2004-12-25 05:35:00.000000000 +0800
++++ linux-2.6.10/arch/um/os-Linux/Makefile     2005-04-06 23:44:30.281019176 +0800
+@@ -3,9 +3,9 @@
+ # Licensed under the GPL
+ #
  
--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;
+-obj-y = file.o process.o time.o tty.o user_syms.o drivers/
++obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/
  
-       if (!mm->context.size)
-               return 0;
-@@ -174,9 +180,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;
-@@ -200,7 +205,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, ldt_info.entry_number+1, 1);
-               if (error < 0)
-                       goto out_unlock;
-       }
-@@ -233,23 +238,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);
-+}
-Index: linux-2.6.10/arch/i386/kernel/sys_i386.c
-===================================================================
---- linux-2.6.10.orig/arch/i386/kernel/sys_i386.c      2004-12-25 05:35:39.000000000 +0800
-+++ linux-2.6.10/arch/i386/kernel/sys_i386.c   2005-04-05 12:40:36.063905624 +0800
-@@ -41,7 +41,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)
-@@ -56,9 +56,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);
-@@ -70,7 +70,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);
- }
- /*
-@@ -101,7 +101,7 @@
-       if (a.offset & ~PAGE_MASK)
-               goto out;
+-USER_OBJS := $(foreach file,file.o process.o time.o tty.o,$(obj)/$(file))
++USER_OBJS := $(foreach file,elf_aux.o file.o process.o time.o tty.o,$(obj)/$(file))
  
--      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;
- }
-Index: linux-2.6.10/arch/i386/Kconfig
+ $(USER_OBJS) : %.o: %.c
+       $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+Index: linux-2.6.10/arch/um/sys-i386/signal.c
 ===================================================================
---- linux-2.6.10.orig/arch/i386/Kconfig        2005-03-31 15:35:23.000000000 +0800
-+++ linux-2.6.10/arch/i386/Kconfig     2005-04-05 12:40:36.066905168 +0800
-@@ -738,6 +738,10 @@
-       depends on HIGHMEM64G
-       default y
-+config PROC_MM
-+      bool "/proc/mm support"
-+      default y
+--- linux-2.6.10.orig/arch/um/sys-i386/signal.c        2005-04-07 06:37:43.373923992 +0800
++++ linux-2.6.10/arch/um/sys-i386/signal.c     2005-04-06 23:44:30.236026016 +0800
+@@ -0,0 +1,374 @@
++/*
++ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
++ * Licensed under the GPL
++ */
 +
- # Common NUMA Features
- config NUMA
-       bool "Numa Memory Allocation and Scheduler Support"
-Index: linux-2.6.10/arch/um/include/frame.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/frame.h  2004-12-25 05:34:31.000000000 +0800
-+++ linux-2.6.10/arch/um/include/frame.h       2005-04-05 19:01:49.158500672 +0800
-@@ -1,53 +0,0 @@
--/* 
-- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-- * Licensed under the GPL
-- */
--
--#ifndef __FRAME_H_
--#define __FRAME_H_
--
--#include "sysdep/frame.h"
--
--struct frame_common {
--      void *data;
--      int len;
--      int sig_index;
--      int sr_index;
--      int sr_relative;
--      int sp_index;
--      struct arch_frame_data arch;
--};
--
--struct sc_frame {
--      struct frame_common common;
--      int sc_index;
--};
--
--extern struct sc_frame signal_frame_sc;
--
--extern struct sc_frame signal_frame_sc_sr;
--
--struct si_frame {
--      struct frame_common common;
--      int sip_index;
--      int si_index;
--      int ucp_index;
--      int uc_index;
--};
--
--extern struct si_frame signal_frame_si;
--
--extern void capture_signal_stack(void);
--
--#endif
--
--/*
-- * Overrides for Emacs so that we follow Linus's tabbing style.
-- * Emacs will notice this stuff at the end of the file and automatically
-- * adjust the settings for this buffer only.  This must remain at the end
-- * of the file.
-- * ---------------------------------------------------------------------------
-- * Local variables:
-- * c-file-style: "linux"
-- * End:
-- */
-Index: linux-2.6.10/arch/um/include/frame_kern.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/frame_kern.h     2004-12-25 05:34:57.000000000 +0800
-+++ linux-2.6.10/arch/um/include/frame_kern.h  2005-04-05 12:40:36.056906688 +0800
-@@ -6,8 +6,8 @@
- #ifndef __FRAME_KERN_H_
- #define __FRAME_KERN_H_
--#include "frame.h"
--#include "sysdep/frame_kern.h"
-+#define _S(nr) (1<<((nr)-1))
-+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
- extern int setup_signal_stack_sc(unsigned long stack_top, int sig, 
-                                struct k_sigaction *ka,
-Index: linux-2.6.10/arch/um/include/frame_user.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/frame_user.h     2004-12-25 05:33:50.000000000 +0800
-+++ linux-2.6.10/arch/um/include/frame_user.h  2005-04-05 19:01:49.158500672 +0800
-@@ -1,23 +0,0 @@
--/* 
-- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-- * Licensed under the GPL
-- */
--
--#ifndef __FRAME_USER_H_
--#define __FRAME_USER_H_
--
--#include "sysdep/frame_user.h"
--#include "frame.h"
--
--#endif
--
--/*
-- * Overrides for Emacs so that we follow Linus's tabbing style.
-- * Emacs will notice this stuff at the end of the file and automatically
-- * adjust the settings for this buffer only.  This must remain at the end
-- * of the file.
-- * ---------------------------------------------------------------------------
-- * Local variables:
-- * c-file-style: "linux"
-- * End:
-- */
-Index: linux-2.6.10/arch/um/include/ptrace_user.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/ptrace_user.h    2004-12-25 05:33:51.000000000 +0800
-+++ linux-2.6.10/arch/um/include/ptrace_user.h 2005-04-05 12:40:36.057906536 +0800
-@@ -26,4 +26,35 @@
- int get_using_sysemu(void);
- extern int sysemu_supported;
++#include "linux/signal.h"
++#include "linux/ptrace.h"
++#include "asm/current.h"
++#include "asm/ucontext.h"
++#include "asm/uaccess.h"
++#include "asm/unistd.h"
++#include "frame_kern.h"
++#include "signal_user.h"
++#include "ptrace_user.h"
++#include "sigcontext.h"
++#include "mode.h"
 +
-+/* syscall emulation path in ptrace */
++#ifdef CONFIG_MODE_SKAS
 +
-+#ifndef PTRACE_SYSEMU
-+#define PTRACE_SYSEMU 31
-+#endif
++#include "skas.h"
 +
-+/* On architectures, that started to support PTRACE_O_TRACESYSGOOD
-+ * in linux 2.4, there are two different definitions of
-+ * PTRACE_SETOPTIONS: linux 2.4 uses 21 while linux 2.6 uses 0x4200.
-+ * For binary compatibility, 2.6 also supports the old "21", named
-+ * PTRACE_OLDSETOPTION. On these architectures, UML always must use
-+ * "21", to ensure the kernel runs on 2.4 and 2.6 host without
-+ * recompilation. So, we use PTRACE_OLDSETOPTIONS in UML.
-+ * We also want to be able to build the kernel on 2.4, which doesn't
-+ * have PTRACE_OLDSETOPTIONS. So, if it is missing, we declare
-+ * PTRACE_OLDSETOPTIONS to to be the same as PTRACE_SETOPTIONS.
-+ *
-+ * On architectures, that start to support PTRACE_O_TRACESYSGOOD on
-+ * linux 2.6, PTRACE_OLDSETOPTIONS never is defined, and also isn't
-+ * supported by the host kernel. In that case, our trick lets us use
-+ * the new 0x4200 with the name PTRACE_OLDSETOPTIONS.
-+ */
-+#ifndef PTRACE_OLDSETOPTIONS
-+#define PTRACE_OLDSETOPTIONS PTRACE_SETOPTIONS
-+#endif
++static int copy_sc_from_user_skas(struct pt_regs *regs,
++                                struct sigcontext *from)
++{
++      struct sigcontext sc;
++      unsigned long fpregs[HOST_FP_SIZE];
++      int err;
 +
-+void set_using_sysemu(int value);
-+int get_using_sysemu(void);
-+extern int sysemu_supported;
++      err = copy_from_user(&sc, from, sizeof(sc));
++      err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
++      if(err)
++              return(err);
 +
- #endif
-Index: linux-2.6.10/arch/um/include/sysdep-i386/frame.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/sysdep-i386/frame.h      2004-12-25 05:35:01.000000000 +0800
-+++ linux-2.6.10/arch/um/include/sysdep-i386/frame.h   2005-04-05 19:01:49.158500672 +0800
-@@ -1,29 +0,0 @@
--/* 
-- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-- * Licensed under the GPL
-- */
--
--#ifndef __FRAME_I386_H
--#define __FRAME_I386_H
--
--struct arch_frame_data_raw {
--      unsigned long fp_start;
--      unsigned long sr;
--};
--
--struct arch_frame_data {
--      int fpstate_size;
--};
--
--#endif
--
--/*
-- * Overrides for Emacs so that we follow Linus's tabbing style.
-- * Emacs will notice this stuff at the end of the file and automatically
-- * adjust the settings for this buffer only.  This must remain at the end
-- * of the file.
-- * ---------------------------------------------------------------------------
-- * Local variables:
-- * c-file-style: "linux"
-- * End:
-- */
-Index: linux-2.6.10/arch/um/include/sysdep-i386/frame_kern.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/sysdep-i386/frame_kern.h 2004-12-25 05:34:26.000000000 +0800
-+++ linux-2.6.10/arch/um/include/sysdep-i386/frame_kern.h      2005-04-05 19:01:49.158500672 +0800
-@@ -1,69 +0,0 @@
--/* 
-- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-- * Licensed under the GPL
-- */
--
--#ifndef __FRAME_KERN_I386_H
--#define __FRAME_KERN_I386_H
--
--/* This is called from sys_sigreturn.  It takes the sp at the point of the
-- * sigreturn system call and returns the address of the sigcontext struct
-- * on the stack.
-- */
--
--static inline void *sp_to_sc(unsigned long sp)
--{
--      return((void *) sp);
--}
--
--static inline void *sp_to_uc(unsigned long sp)
--{
--      unsigned long uc;
--
--      uc = sp + signal_frame_si.uc_index - 
--              signal_frame_si.common.sp_index - 4;
--      return((void *) uc);
--}
--
--static inline void *sp_to_rt_sc(unsigned long sp)
--{
--      unsigned long sc;
--
--      sc = sp - signal_frame_si.common.sp_index + 
--              signal_frame_si.common.len - 4;
--      return((void *) sc);
--}
--
--static inline void *sp_to_mask(unsigned long sp)
--{
--      unsigned long mask;
--
--      mask = sp - signal_frame_sc.common.sp_index + 
--              signal_frame_sc.common.len - 8;
--      return((void *) mask);
--}
--
--extern int sc_size(void *data);
--
--static inline void *sp_to_rt_mask(unsigned long sp)
--{
--      unsigned long mask;
--
--      mask = sp - signal_frame_si.common.sp_index + 
--              signal_frame_si.common.len + 
--              sc_size(&signal_frame_si.common.arch) - 4;
--      return((void *) mask);
--}
--
--#endif
--
--/*
-- * Overrides for Emacs so that we follow Linus's tabbing style.
-- * Emacs will notice this stuff at the end of the file and automatically
-- * adjust the settings for this buffer only.  This must remain at the end
-- * of the file.
-- * ---------------------------------------------------------------------------
-- * Local variables:
-- * c-file-style: "linux"
-- * End:
-- */
-Index: linux-2.6.10/arch/um/include/sysdep-i386/frame_user.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/sysdep-i386/frame_user.h 2004-12-25 05:35:28.000000000 +0800
-+++ linux-2.6.10/arch/um/include/sysdep-i386/frame_user.h      2005-04-05 19:01:49.158500672 +0800
-@@ -1,91 +0,0 @@
--/* 
-- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-- * Licensed under the GPL
-- */
--
--#ifndef __FRAME_USER_I386_H
--#define __FRAME_USER_I386_H
--
--#include <asm/page.h>
--#include "sysdep/frame.h"
--
--/* This stuff is to calculate the size of the fp state struct at runtime
-- * because it has changed between 2.2 and 2.4 and it would be good for a
-- * UML compiled on one to work on the other.
-- * So, setup_arch_frame_raw fills in the arch struct with the raw data, which
-- * just contains the address of the end of the sigcontext.  This is invoked
-- * from the signal handler.
-- * setup_arch_frame uses that data to figure out what 
-- * arch_frame_data.fpstate_size should be.  It really has no idea, since it's
-- * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's
-- * everything from the end of the sigcontext up to the top of the stack.  So,
-- * it masks off the page number to get the offset within the page and subtracts
-- * that from the page size, and that's how big the fpstate struct will be
-- * considered to be.
-- */
--
--static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data,
--                                      void *end, unsigned long srp)
--{
--      unsigned long sr = *((unsigned long *) srp);
--
--      data->fp_start = (unsigned long) end;
--      if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK))
--              data->sr = sr;
--      else data->sr = 0;
--}
--
--static inline void setup_arch_frame(struct arch_frame_data_raw *in, 
--                                  struct arch_frame_data *out)
--{
--      unsigned long fpstate_start = in->fp_start;
--
--      if(in->sr == 0){
--              fpstate_start &= ~PAGE_MASK;
--              out->fpstate_size = PAGE_SIZE - fpstate_start;
--      }
--      else {
--              out->fpstate_size = in->sr - fpstate_start;
--      }
--}
--
--/* This figures out where on the stack the SA_RESTORER function address
-- * is stored.  For i386, it's the signal handler return address, so it's
-- * located next to the frame pointer.
-- * This is inlined, so __builtin_frame_address(0) is correct.  Otherwise,
-- * it would have to be __builtin_frame_address(1).
-- */
--
--#define frame_restorer() \
--({ \
--      unsigned long *fp; \
--\
--      fp = __builtin_frame_address(0); \
--      ((unsigned long) (fp + 1)); \
--})
--
--/* Similarly, this returns the value of sp when the handler was first
-- * entered.  This is used to calculate the proper sp when delivering
-- * signals.
-- */
--
--#define frame_sp() \
--({ \
--      unsigned long *fp; \
--\
--      fp = __builtin_frame_address(0); \
--      ((unsigned long) (fp + 1)); \
--})
--
--#endif
--
--/*
-- * Overrides for Emacs so that we follow Linus's tabbing style.
-- * Emacs will notice this stuff at the end of the file and automatically
-- * adjust the settings for this buffer only.  This must remain at the end
-- * of the file.
-- * ---------------------------------------------------------------------------
-- * Local variables:
-- * c-file-style: "linux"
-- * End:
-- */
-Index: linux-2.6.10/arch/um/include/elf_user.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/elf_user.h       2005-04-05 19:01:49.158500672 +0800
-+++ linux-2.6.10/arch/um/include/elf_user.h    2005-04-05 12:40:36.054906992 +0800
-@@ -0,0 +1,19 @@
-+/*
-+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
-+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
-+ * Licensed under the GPL
-+ */
++      REGS_GS(regs->regs.skas.regs) = sc.gs;
++      REGS_FS(regs->regs.skas.regs) = sc.fs;
++      REGS_ES(regs->regs.skas.regs) = sc.es;
++      REGS_DS(regs->regs.skas.regs) = sc.ds;
++      REGS_EDI(regs->regs.skas.regs) = sc.edi;
++      REGS_ESI(regs->regs.skas.regs) = sc.esi;
++      REGS_EBP(regs->regs.skas.regs) = sc.ebp;
++      REGS_SP(regs->regs.skas.regs) = sc.esp;
++      REGS_EBX(regs->regs.skas.regs) = sc.ebx;
++      REGS_EDX(regs->regs.skas.regs) = sc.edx;
++      REGS_ECX(regs->regs.skas.regs) = sc.ecx;
++      REGS_EAX(regs->regs.skas.regs) = sc.eax;
++      REGS_IP(regs->regs.skas.regs) = sc.eip;
++      REGS_CS(regs->regs.skas.regs) = sc.cs;
++      REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
++      REGS_SS(regs->regs.skas.regs) = sc.ss;
++      regs->regs.skas.fault_addr = sc.cr2;
++      regs->regs.skas.fault_type = FAULT_WRITE(sc.err);
++      regs->regs.skas.trap_type = sc.trapno;
 +
-+#ifndef __ELF_USER_H__
-+#define __ELF_USER_H__
++      err = ptrace_setfpregs(userspace_pid[0], fpregs);
++      if(err < 0){
++              printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
++                     "errno = %d\n", err);
++              return(1);
++      }
 +
-+/* For compilation on a host that doesn't support AT_SYSINFO (Linux 2.4)  */
-+
-+#ifndef AT_SYSINFO
-+#define AT_SYSINFO 32
-+#endif
-+#ifndef AT_SYSINFO_EHDR
-+#define AT_SYSINFO_EHDR 33
-+#endif
-+
-+#endif
-Index: linux-2.6.10/arch/um/include/skas_ptrace.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/skas_ptrace.h    2004-12-25 05:35:27.000000000 +0800
-+++ linux-2.6.10/arch/um/include/skas_ptrace.h 2005-04-05 12:40:36.056906688 +0800
-@@ -6,6 +6,7 @@
- #ifndef __SKAS_PTRACE_H
- #define __SKAS_PTRACE_H
-+#ifndef PTRACE_FAULTINFO
- struct ptrace_faultinfo {
-       int is_write;
-       unsigned long addr;
-@@ -21,6 +22,7 @@
- #define PTRACE_SIGPENDING 53
- #define PTRACE_LDT 54
- #define PTRACE_SWITCH_MM 55
-+#endif
- #endif
-Index: linux-2.6.10/arch/um/include/signal_user.h
-===================================================================
---- linux-2.6.10.orig/arch/um/include/signal_user.h    2004-12-25 05:33:49.000000000 +0800
-+++ linux-2.6.10/arch/um/include/signal_user.h 2005-04-05 12:40:36.055906840 +0800
-@@ -14,6 +14,8 @@
- extern int set_signals(int enable);
- extern int get_signals(void);
-+#define SYSCALL_TRAP 0x80
-+
- #endif
- /*
-Index: linux-2.6.10/arch/um/sys-i386/ptrace_user.c
-===================================================================
---- linux-2.6.10.orig/arch/um/sys-i386/ptrace_user.c   2004-12-25 05:35:50.000000000 +0800
-+++ linux-2.6.10/arch/um/sys-i386/ptrace_user.c        2005-04-05 12:40:36.022911856 +0800
-@@ -17,17 +17,30 @@
- int ptrace_getregs(long pid, unsigned long *regs_out)
- {
--      return(ptrace(PTRACE_GETREGS, pid, 0, regs_out));
-+      if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
-+              return(-errno);
-+      return(0);
- }
- int ptrace_setregs(long pid, unsigned long *regs)
- {
--      return(ptrace(PTRACE_SETREGS, pid, 0, regs));
-+      if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
-+              return(-errno);
-+      return(0);
- }
- int ptrace_getfpregs(long pid, unsigned long *regs)
- {
--      return(ptrace(PTRACE_GETFPREGS, pid, 0, regs));
-+      if(ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
-+              return(-errno);
-+      return(0);
-+}
-+
-+int ptrace_setfpregs(long pid, unsigned long *regs)
-+{
-+      if(ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
-+              return(-errno);
-+      return(0);
- }
- static void write_debugregs(int pid, unsigned long *regs)
-Index: linux-2.6.10/arch/um/sys-i386/sigcontext.c
-===================================================================
---- linux-2.6.10.orig/arch/um/sys-i386/sigcontext.c    2004-12-25 05:33:49.000000000 +0800
-+++ linux-2.6.10/arch/um/sys-i386/sigcontext.c 2005-04-05 12:40:36.023911704 +0800
-@@ -9,22 +9,14 @@
- #include <asm/sigcontext.h>
- #include "sysdep/ptrace.h"
- #include "kern_util.h"
--#include "frame_user.h"
--
--int sc_size(void *data)
--{
--      struct arch_frame_data *arch = data;
--
--      return(sizeof(struct sigcontext) + arch->fpstate_size);
--}
- void sc_to_sc(void *to_ptr, void *from_ptr)
- {
-       struct sigcontext *to = to_ptr, *from = from_ptr;
--      int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size;
--      memcpy(to, from, size);
--      if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1);
-+      memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate));
-+      if(from->fpstate != NULL)
-+              to->fpstate = (struct _fpstate *) (to + 1);
- }
- unsigned long *sc_sigmask(void *sc_ptr)
-Index: linux-2.6.10/arch/um/sys-i386/sysrq.c
-===================================================================
---- linux-2.6.10.orig/arch/um/sys-i386/sysrq.c 2004-12-25 05:33:49.000000000 +0800
-+++ linux-2.6.10/arch/um/sys-i386/sysrq.c      2005-04-05 12:40:36.022911856 +0800
-@@ -33,3 +33,13 @@
-         show_trace((unsigned long *) &regs);
- }
-+
-+/* Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only.  This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-Index: linux-2.6.10/arch/um/sys-i386/signal.c
-===================================================================
---- linux-2.6.10.orig/arch/um/sys-i386/signal.c        2005-04-05 19:01:49.158500672 +0800
-+++ linux-2.6.10/arch/um/sys-i386/signal.c     2005-04-05 12:40:36.021912008 +0800
-@@ -0,0 +1,374 @@
-+/*
-+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
-+ * Licensed under the GPL
-+ */
-+
-+#include "linux/signal.h"
-+#include "linux/ptrace.h"
-+#include "asm/current.h"
-+#include "asm/ucontext.h"
-+#include "asm/uaccess.h"
-+#include "asm/unistd.h"
-+#include "frame_kern.h"
-+#include "signal_user.h"
-+#include "ptrace_user.h"
-+#include "sigcontext.h"
-+#include "mode.h"
-+
-+#ifdef CONFIG_MODE_SKAS
-+
-+#include "skas.h"
-+
-+static int copy_sc_from_user_skas(struct pt_regs *regs,
-+                                struct sigcontext *from)
-+{
-+      struct sigcontext sc;
-+      unsigned long fpregs[HOST_FP_SIZE];
-+      int err;
-+
-+      err = copy_from_user(&sc, from, sizeof(sc));
-+      err |= copy_from_user(fpregs, sc.fpstate, sizeof(fpregs));
-+      if(err)
-+              return(err);
-+
-+      REGS_GS(regs->regs.skas.regs) = sc.gs;
-+      REGS_FS(regs->regs.skas.regs) = sc.fs;
-+      REGS_ES(regs->regs.skas.regs) = sc.es;
-+      REGS_DS(regs->regs.skas.regs) = sc.ds;
-+      REGS_EDI(regs->regs.skas.regs) = sc.edi;
-+      REGS_ESI(regs->regs.skas.regs) = sc.esi;
-+      REGS_EBP(regs->regs.skas.regs) = sc.ebp;
-+      REGS_SP(regs->regs.skas.regs) = sc.esp;
-+      REGS_EBX(regs->regs.skas.regs) = sc.ebx;
-+      REGS_EDX(regs->regs.skas.regs) = sc.edx;
-+      REGS_ECX(regs->regs.skas.regs) = sc.ecx;
-+      REGS_EAX(regs->regs.skas.regs) = sc.eax;
-+      REGS_IP(regs->regs.skas.regs) = sc.eip;
-+      REGS_CS(regs->regs.skas.regs) = sc.cs;
-+      REGS_EFLAGS(regs->regs.skas.regs) = sc.eflags;
-+      REGS_SS(regs->regs.skas.regs) = sc.ss;
-+      regs->regs.skas.fault_addr = sc.cr2;
-+      regs->regs.skas.fault_type = FAULT_WRITE(sc.err);
-+      regs->regs.skas.trap_type = sc.trapno;
-+
-+      err = ptrace_setfpregs(userspace_pid[0], fpregs);
-+      if(err < 0){
-+              printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
-+                     "errno = %d\n", err);
-+              return(1);
-+      }
-+
-+      return(0);
-+}
++      return(0);
++}
 +
 +int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
 +                       struct pt_regs *regs, unsigned long fault_addr,
@@ -1903,66 +847,833 @@ Index: linux-2.6.10/arch/um/sys-i386/signal.c
 +      return(0);
 +}
 +
-+long sys_sigreturn(struct pt_regs regs)
-+{
-+      unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
-+      struct sigframe __user *frame = (struct sigframe *)(sp - 8);
-+      sigset_t set;
-+      struct sigcontext __user *sc = &frame->sc;
-+      unsigned long __user *oldmask = &sc->oldmask;
-+      unsigned long __user *extramask = &frame->extramask;
-+      int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
++long sys_sigreturn(struct pt_regs regs)
++{
++      unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
++      struct sigframe __user *frame = (struct sigframe *)(sp - 8);
++      sigset_t set;
++      struct sigcontext __user *sc = &frame->sc;
++      unsigned long __user *oldmask = &sc->oldmask;
++      unsigned long __user *extramask = &frame->extramask;
++      int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
++
++      if(copy_from_user(&set.sig[0], oldmask, sizeof(&set.sig[0])) ||
++         copy_from_user(&set.sig[1], extramask, sig_size))
++              goto segfault;
++
++      sigdelsetmask(&set, ~_BLOCKABLE);
++
++      spin_lock_irq(&current->sighand->siglock);
++      current->blocked = set;
++      recalc_sigpending();
++      spin_unlock_irq(&current->sighand->siglock);
++
++      if(copy_sc_from_user(&current->thread.regs, sc))
++              goto segfault;
++
++      PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; /* Avoid ERESTART handling */
++      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
++
++ segfault:
++      force_sig(SIGSEGV, current);
++      return 0;
++}
++
++long sys_rt_sigreturn(struct pt_regs regs)
++{
++      unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
++      struct rt_sigframe __user *frame = (struct rt_sigframe *) (sp - 4);
++      sigset_t set;
++      struct ucontext __user *uc = &frame->uc;
++      int sig_size = _NSIG_WORDS * sizeof(unsigned long);
++
++      if(copy_from_user(&set, &uc->uc_sigmask, sig_size))
++              goto segfault;
++
++      sigdelsetmask(&set, ~_BLOCKABLE);
++
++      spin_lock_irq(&current->sighand->siglock);
++      current->blocked = set;
++      recalc_sigpending();
++      spin_unlock_irq(&current->sighand->siglock);
++
++      if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
++              goto segfault;
++
++      PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; /* Avoid ERESTART handling */
++      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
++
++ segfault:
++      force_sig(SIGSEGV, current);
++      return 0;
++}
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only.  This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+Index: linux-2.6.10/arch/um/sys-i386/ptrace_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/ptrace_user.c   2004-12-25 05:35:50.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/ptrace_user.c        2005-04-06 23:44:30.233026472 +0800
+@@ -17,17 +17,30 @@
+ int ptrace_getregs(long pid, unsigned long *regs_out)
+ {
+-      return(ptrace(PTRACE_GETREGS, pid, 0, regs_out));
++      if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
++              return(-errno);
++      return(0);
+ }
+ int ptrace_setregs(long pid, unsigned long *regs)
+ {
+-      return(ptrace(PTRACE_SETREGS, pid, 0, regs));
++      if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
++              return(-errno);
++      return(0);
+ }
+ int ptrace_getfpregs(long pid, unsigned long *regs)
+ {
+-      return(ptrace(PTRACE_GETFPREGS, pid, 0, regs));
++      if(ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
++              return(-errno);
++      return(0);
++}
++
++int ptrace_setfpregs(long pid, unsigned long *regs)
++{
++      if(ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
++              return(-errno);
++      return(0);
+ }
+ static void write_debugregs(int pid, unsigned long *regs)
+Index: linux-2.6.10/arch/um/sys-i386/sysrq.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/sysrq.c 2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/sysrq.c      2005-04-06 23:44:30.234026320 +0800
+@@ -33,3 +33,13 @@
+         show_trace((unsigned long *) &regs);
+ }
++
++/* Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only.  This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+Index: linux-2.6.10/arch/um/sys-i386/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/Makefile        2004-12-25 05:34:01.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/Makefile     2005-04-06 23:44:30.236026016 +0800
+@@ -1,5 +1,5 @@
+ obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
+-      ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
++      ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o
+ obj-$(CONFIG_HIGHMEM) += highmem.o
+ obj-$(CONFIG_MODULES) += module.o
+Index: linux-2.6.10/arch/um/sys-i386/sigcontext.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/sigcontext.c    2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/sigcontext.c 2005-04-06 23:44:30.233026472 +0800
+@@ -9,22 +9,14 @@
+ #include <asm/sigcontext.h>
+ #include "sysdep/ptrace.h"
+ #include "kern_util.h"
+-#include "frame_user.h"
+-
+-int sc_size(void *data)
+-{
+-      struct arch_frame_data *arch = data;
+-
+-      return(sizeof(struct sigcontext) + arch->fpstate_size);
+-}
+ void sc_to_sc(void *to_ptr, void *from_ptr)
+ {
+       struct sigcontext *to = to_ptr, *from = from_ptr;
+-      int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size;
+-      memcpy(to, from, size);
+-      if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1);
++      memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate));
++      if(from->fpstate != NULL)
++              to->fpstate = (struct _fpstate *) (to + 1);
+ }
+ unsigned long *sc_sigmask(void *sc_ptr)
+Index: linux-2.6.10/arch/um/kernel/main.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/main.c    2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/main.c 2005-04-06 23:44:30.262022064 +0800
+@@ -81,6 +81,8 @@
+ extern int uml_exitcode;
++extern void scan_elf_aux( char **envp);
++
+ int main(int argc, char **argv, char **envp)
+ {
+       char **new_argv;
+@@ -147,6 +149,8 @@
+       set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+       set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
++      scan_elf_aux( envp);
++
+       do_uml_initcalls();
+       ret = linux_main(argc, argv);
+@@ -155,18 +159,20 @@
+               int err;
+               printf("\n");
+-
+-              /* Let any pending signals fire, then disable them.  This
+-               * ensures that they won't be delivered after the exec, when
+-               * they are definitely not expected.
+-               */
+-              unblock_signals();
++              /* stop timers and set SIG*ALRM to be ignored */
+               disable_timer();
++              /* disable SIGIO for the fds and set SIGIO to be ignored */
+               err = deactivate_all_fds();
+               if(err)
+                       printf("deactivate_all_fds failed, errno = %d\n",
+                              -err);
++              /* Let any pending signals fire now.  This ensures
++               * that they won't be delivered after the exec, when
++               * they are definitely not expected.
++               */
++              unblock_signals();
++
+               execvp(new_argv[0], new_argv);
+               perror("Failed to exec kernel");
+               ret = 1;
+Index: linux-2.6.10/arch/um/kernel/process.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/process.c 2004-12-25 05:35:25.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/process.c      2005-04-06 23:44:30.240025408 +0800
+@@ -13,6 +13,7 @@
+ #include <setjmp.h>
+ #include <sys/time.h>
+ #include <sys/ptrace.h>
++#include <linux/ptrace.h>
+ #include <sys/wait.h>
+ #include <sys/mman.h>
+ #include <asm/ptrace.h>
+@@ -285,6 +286,9 @@
+       printk("Checking that ptrace can change system call numbers...");
+       pid = start_ptraced_child(&stack);
++      if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
++              panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
++
+       while(1){
+               if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
+                       panic("check_ptrace : ptrace failed, errno = %d", 
+@@ -292,8 +296,8 @@
+               CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+               if(n < 0)
+                       panic("check_ptrace : wait failed, errno = %d", errno);
+-              if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+-                      panic("check_ptrace : expected SIGTRAP, "
++              if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP)))
++                      panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
+                             "got status = %d", status);
+               
+               syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+Index: linux-2.6.10/arch/um/kernel/initrd_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/initrd_user.c     2004-12-25 05:34:26.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/initrd_user.c  2005-04-06 23:44:30.252023584 +0800
+@@ -29,6 +29,8 @@
+                      filename, -n);
+               return(-1);
+       }
++
++      os_close_file(fd);
+       return(0);
+ }
+Index: linux-2.6.10/arch/um/kernel/time_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/time_kern.c       2004-12-25 05:35:00.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/time_kern.c    2005-04-06 23:44:30.271020696 +0800
+@@ -170,7 +170,7 @@
+ void timer_handler(int sig, union uml_pt_regs *regs)
+ {
+       local_irq_disable();
+-      update_process_times(user_context(UPT_SP(regs)));
++      update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), (regs)->skas.is_user));
+       local_irq_enable();
+       if(current_thread->cpu == 0)
+               timer_irq(regs);
+Index: linux-2.6.10/arch/um/kernel/helper.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/helper.c  2004-12-25 05:34:45.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/helper.c       2005-04-06 23:44:30.271020696 +0800
+@@ -49,14 +49,14 @@
+       return(0);
+ }
+-/* XXX The alloc_stack here breaks if this is called in the tracing thread */
+-
++/* Returns either the pid of the child process we run or -E* on failure.
++ * XXX The alloc_stack here breaks if this is called in the tracing thread */
+ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
+              unsigned long *stack_out)
+ {
+       struct helper_data data;
+       unsigned long stack, sp;
+-      int pid, fds[2], err, n;
++      int pid, fds[2], ret, n;
+       if((stack_out != NULL) && (*stack_out != 0))
+               stack = *stack_out;
+@@ -64,16 +64,16 @@
+       if(stack == 0)
+               return(-ENOMEM);
+-      err = os_pipe(fds, 1, 0);
+-      if(err < 0){
+-              printk("run_helper : pipe failed, err = %d\n", -err);
++      ret = os_pipe(fds, 1, 0);
++      if(ret < 0){
++              printk("run_helper : pipe failed, ret = %d\n", -ret);
+               goto out_free;
+       }
+-      err = os_set_exec_close(fds[1], 1);
+-      if(err < 0){
+-              printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
+-                     -err);
++      ret = os_set_exec_close(fds[1], 1);
++      if(ret < 0){
++              printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
++                     -ret);
+               goto out_close;
+       }
+@@ -85,34 +85,36 @@
+       pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
+       if(pid < 0){
+               printk("run_helper : clone failed, errno = %d\n", errno);
+-              err = -errno;
++              ret = -errno;
+               goto out_close;
+       }
+       os_close_file(fds[1]);
+-      n = os_read_file(fds[0], &err, sizeof(err));
++      fds[1] = -1;
++
++      /*Read the errno value from the child.*/
++      n = os_read_file(fds[0], &ret, sizeof(ret));
+       if(n < 0){
+-              printk("run_helper : read on pipe failed, err = %d\n", -n);
+-              err = n;
+-              goto out_kill;
++              printk("run_helper : read on pipe failed, ret = %d\n", -n);
++              ret = n;
++              os_kill_process(pid, 1);
+       }
+       else if(n != 0){
+               CATCH_EINTR(n = waitpid(pid, NULL, 0));
+-              pid = -errno;
++              ret = -errno;
++      } else {
++              ret = pid;
+       }
+-      if(stack_out == NULL) free_stack(stack, 0);
+-        else *stack_out = stack;
+-      return(pid);
+-
+- out_kill:
+-      os_kill_process(pid, 1);
+  out_close:
++      if (fds[1] != -1)
++              os_close_file(fds[1]);
+       os_close_file(fds[0]);
+-      os_close_file(fds[1]);
+  out_free:
+-      free_stack(stack, 0);
+-      return(err);
++      if(stack_out == NULL)
++              free_stack(stack, 0);
++        else *stack_out = stack;
++      return(ret);
+ }
+ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, 
+Index: linux-2.6.10/arch/um/kernel/irq_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/irq_user.c        2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/irq_user.c     2005-04-06 23:44:30.263021912 +0800
+@@ -374,6 +374,8 @@
+               if(err)
+                       return(err);
+       }
++      /* If there is a signal already queued, after unblocking ignore it */
++      set_handler(SIGIO, SIG_IGN, 0, -1);
+       return(0);
+ }
+Index: linux-2.6.10/arch/um/kernel/mem.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/mem.c     2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/mem.c  2005-04-06 23:44:30.279019480 +0800
+@@ -175,6 +175,30 @@
+ }
+ #endif /* CONFIG_HIGHMEM */
++static void __init fixaddr_user_init( void)
++{
++      long size = FIXADDR_USER_END - FIXADDR_USER_START;
++      pgd_t *pgd;
++      pmd_t *pmd;
++      pte_t *pte;
++      unsigned long paddr, vaddr = FIXADDR_USER_START;
++
++      if (  ! size )
++              return;
++
++      fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
++      paddr = (unsigned long)alloc_bootmem_low_pages( size);
++      memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
++      paddr = __pa(paddr);
++      for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE) {
++              pgd = swapper_pg_dir + pgd_index(vaddr);
++              pmd = pmd_offset(pgd, vaddr);
++              pte = pte_offset_kernel(pmd, vaddr);
++              /*pte_set_val( (*pte), paddr, PAGE_READONLY);*/
++              pte_val(*pte) = paddr | pgprot_val(PAGE_READONLY);
++      }
++}
++
+ void paging_init(void)
+ {
+       unsigned long zones_size[MAX_NR_ZONES], vaddr;
+@@ -195,6 +219,8 @@
+       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+       fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
++      fixaddr_user_init();
++
+ #ifdef CONFIG_HIGHMEM
+       init_highmem();
+ #endif
+Index: linux-2.6.10/arch/um/kernel/skas/process.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/process.c    2004-12-25 05:35:39.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/process.c 2005-04-06 23:44:30.268021152 +0800
+@@ -11,6 +11,7 @@
+ #include <sched.h>
+ #include <sys/wait.h>
+ #include <sys/ptrace.h>
++#include <linux/ptrace.h>
+ #include <sys/mman.h>
+ #include <sys/user.h>
+ #include <asm/unistd.h>
+@@ -60,15 +61,10 @@
+ /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
+ {
+-      int err, syscall_nr, status;
+-
+-      syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+-      UPT_SYSCALL_NR(regs) = syscall_nr;
+-      if(syscall_nr < 0){
+-              relay_signal(SIGTRAP, regs);
+-              return;
+-      }
++      int err, status;
++  
++      UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); /* Mark this as a syscall */
+       if (!local_using_sysemu)
+       {
+               err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+@@ -82,7 +78,8 @@
+                             "errno = %d\n", errno);
+               CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+-              if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
++              if((err < 0) || !WIFSTOPPED(status) ||
++                              (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP)))
+                       panic("handle_trap - failed to wait at end of syscall, "
+                             "errno = %d, status = %d\n", errno, status);
+       }
+@@ -131,6 +128,10 @@
+               panic("start_userspace : expected SIGSTOP, got status = %d",
+                     status);
++      if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
++              panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n",
++                    errno);
++
+       if(munmap(stack, PAGE_SIZE) < 0)
+               panic("start_userspace : munmap failed, errno = %d\n", errno);
+@@ -160,15 +161,19 @@
+               regs->skas.is_user = 1;
+               save_registers(regs);
++              UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
+               if(WIFSTOPPED(status)){
+                       switch(WSTOPSIG(status)){
+                       case SIGSEGV:
+                               handle_segv(pid);
+                               break;
+-                      case SIGTRAP:
++                      case (SIGTRAP|SYSCALL_TRAP):
+                               handle_trap(pid, regs, local_using_sysemu);
+                               break;
++                      case SIGTRAP:
++                              relay_signal(SIGTRAP, regs);
++                              break;
+                       case SIGIO:
+                       case SIGVTALRM:
+                       case SIGILL:
+@@ -222,9 +227,10 @@
+       block_signals();
+       if(sigsetjmp(fork_buf, 1) == 0)
+               new_thread_proc(stack, handler);
+-      set_signals(flags);
+       remove_sigstack();
++
++      set_signals(flags);
+ }
+ void thread_wait(void *sw, void *fb)
+Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/Makefile    2004-12-25 05:35:27.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile 2005-04-07 06:37:43.373923992 +0800
+@@ -1,12 +0,0 @@
+-# 
+-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+-# Licensed under the GPL
+-#
+-
+-obj-y = sigcontext.o
+-
+-USER_OBJS = sigcontext.o
+-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+-
+-$(USER_OBJS) : %.o: %.c
+-      $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/sigcontext.c        2004-12-25 05:33:51.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c     2005-04-07 06:37:43.373923992 +0800
+@@ -1,114 +0,0 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#include <errno.h>
+-#include <asm/sigcontext.h>
+-#include <sys/ptrace.h>
+-#include <linux/ptrace.h>
+-#include "sysdep/ptrace.h"
+-#include "sysdep/ptrace_user.h"
+-#include "kern_util.h"
+-#include "user.h"
+-#include "sigcontext.h"
+-#include "mode.h"
+-
+-int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
+-{
+-      struct sigcontext sc, *from = from_ptr;
+-      unsigned long fpregs[FP_FRAME_SIZE];
+-      int err;
+-
+-      err = copy_from_user_proc(&sc, from, sizeof(sc));
+-      err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs));
+-      if(err)
+-              return(err);
+-
+-      regs->skas.regs[GS] = sc.gs;
+-      regs->skas.regs[FS] = sc.fs;
+-      regs->skas.regs[ES] = sc.es;
+-      regs->skas.regs[DS] = sc.ds;
+-      regs->skas.regs[EDI] = sc.edi;
+-      regs->skas.regs[ESI] = sc.esi;
+-      regs->skas.regs[EBP] = sc.ebp;
+-      regs->skas.regs[UESP] = sc.esp;
+-      regs->skas.regs[EBX] = sc.ebx;
+-      regs->skas.regs[EDX] = sc.edx;
+-      regs->skas.regs[ECX] = sc.ecx;
+-      regs->skas.regs[EAX] = sc.eax;
+-      regs->skas.regs[EIP] = sc.eip;
+-      regs->skas.regs[CS] = sc.cs;
+-      regs->skas.regs[EFL] = sc.eflags;
+-      regs->skas.regs[SS] = sc.ss;
+-      regs->skas.fault_addr = sc.cr2;
+-      regs->skas.fault_type = FAULT_WRITE(sc.err);
+-      regs->skas.trap_type = sc.trapno;
+-
+-      err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
+-      if(err < 0){
+-              printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
+-                     "errno = %d\n", errno);
+-              return(1);
+-      }
+-
+-      return(0);
+-}
+-
+-int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+-                       union uml_pt_regs *regs, unsigned long fault_addr,
+-                       int fault_type)
+-{
+-      struct sigcontext sc, *to = to_ptr;
+-      struct _fpstate *to_fp;
+-      unsigned long fpregs[FP_FRAME_SIZE];
+-      int err;
+-
+-      sc.gs = regs->skas.regs[GS];
+-      sc.fs = regs->skas.regs[FS];
+-      sc.es = regs->skas.regs[ES];
+-      sc.ds = regs->skas.regs[DS];
+-      sc.edi = regs->skas.regs[EDI];
+-      sc.esi = regs->skas.regs[ESI];
+-      sc.ebp = regs->skas.regs[EBP];
+-      sc.esp = regs->skas.regs[UESP];
+-      sc.ebx = regs->skas.regs[EBX];
+-      sc.edx = regs->skas.regs[EDX];
+-      sc.ecx = regs->skas.regs[ECX];
+-      sc.eax = regs->skas.regs[EAX];
+-      sc.eip = regs->skas.regs[EIP];
+-      sc.cs = regs->skas.regs[CS];
+-      sc.eflags = regs->skas.regs[EFL];
+-      sc.esp_at_signal = regs->skas.regs[UESP];
+-      sc.ss = regs->skas.regs[SS];
+-      sc.cr2 = fault_addr;
+-      sc.err = TO_SC_ERR(fault_type);
+-      sc.trapno = regs->skas.trap_type;
+-
+-      err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
+-      if(err < 0){
+-              printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
+-                     "errno = %d\n", errno);
+-              return(1);
+-      }
+-      to_fp = (struct _fpstate *) 
+-              (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
+-      sc.fpstate = to_fp;
+-
+-      if(err)
+-              return(err);
+-
+-      return(copy_to_user_proc(to, &sc, sizeof(sc)) ||
+-             copy_to_user_proc(to_fp, fpregs, sizeof(fpregs)));
+-}
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only.  This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/um/kernel/skas/process_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/process_kern.c       2004-12-25 05:35:50.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/process_kern.c    2005-04-06 23:44:30.268021152 +0800
+@@ -19,7 +19,6 @@
+ #include "os.h"
+ #include "user_util.h"
+ #include "tlb.h"
+-#include "frame.h"
+ #include "kern.h"
+ #include "mode.h"
+ #include "proc_mm.h"
+@@ -183,7 +182,6 @@
+ int start_uml_skas(void)
+ {
+       start_userspace(0);
+-      capture_signal_stack();
+       init_new_thread_signals(1);
+       uml_idle_timer();
+Index: linux-2.6.10/arch/um/kernel/skas/trap_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/trap_user.c  2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/trap_user.c       2005-04-06 23:44:30.269021000 +0800
+@@ -21,6 +21,14 @@
+       int save_errno = errno;
+       int save_user;
++      /* This is done because to allow SIGSEGV to be delivered inside a SEGV
++       * handler.  This can happen in copy_user, and if SEGV is disabled,
++       * the process will die.
++       * XXX Figure out why this is better than SA_NODEFER
++       */
++      if(sig == SIGSEGV)
++              change_sig(SIGSEGV, 1);
++
+       r = &TASK_REGS(get_current())->skas;
+       save_user = r->is_user;
+       r->is_user = 0;
+Index: linux-2.6.10/arch/um/kernel/skas/syscall_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/syscall_kern.c       2004-12-25 05:35:00.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/syscall_kern.c    2005-04-06 23:44:30.269021000 +0800
+@@ -6,6 +6,7 @@
+ #include "linux/sys.h"
+ #include "linux/ptrace.h"
+ #include "asm/errno.h"
++#include "linux/ptrace.h"
+ #include "asm/unistd.h"
+ #include "asm/ptrace.h"
+ #include "asm/current.h"
+Index: linux-2.6.10/arch/um/kernel/skas/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/Makefile     2004-12-25 05:34:30.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/Makefile  2005-04-06 23:44:30.270020848 +0800
+@@ -4,8 +4,7 @@
+ #
+ obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
+-      syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
+-      sys-$(SUBARCH)/
++      syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o
+ subdir-y := util
+Index: linux-2.6.10/arch/um/kernel/skas/include/mmu-skas.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/include/mmu-skas.h   2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/include/mmu-skas.h        2005-04-06 23:44:30.265021608 +0800
+@@ -22,3 +22,27 @@
+  * c-file-style: "linux"
+  * End:
+  */
++/*
++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
++ */
++
++#ifndef __SKAS_MMU_H
++#define __SKAS_MMU_H
 +
-+      if(copy_from_user(&set.sig[0], oldmask, sizeof(&set.sig[0])) ||
-+         copy_from_user(&set.sig[1], extramask, sig_size))
-+              goto segfault;
++struct mmu_context_skas {
++      int mm_fd;
++};
 +
-+      sigdelsetmask(&set, ~_BLOCKABLE);
++#endif
 +
-+      spin_lock_irq(&current->sighand->siglock);
-+      current->blocked = set;
-+      recalc_sigpending();
-+      spin_unlock_irq(&current->sighand->siglock);
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only.  This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+Index: linux-2.6.10/arch/um/kernel/skas/include/mode-skas.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/include/mode-skas.h  2004-12-25 05:34:58.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/include/mode-skas.h       2005-04-06 23:44:30.265021608 +0800
+@@ -14,6 +14,40 @@
+ extern int have_fpx_regs;
+ extern void user_time_init_skas(void);
++extern void sig_handler_common_skas(int sig, void *sc_ptr);
++extern void halt_skas(void);
++extern void reboot_skas(void);
++extern void kill_off_processes_skas(void);
++extern int is_skas_winch(int pid, int fd, void *data);
 +
-+      if(copy_sc_from_user(&current->thread.regs, sc))
-+              goto segfault;
++#endif
 +
-+      PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; /* Avoid ERESTART handling */
-+      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only.  This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
++/*
++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
++ */
 +
-+ segfault:
-+      force_sig(SIGSEGV, current);
-+      return 0;
-+}
++#ifndef __MODE_SKAS_H__
++#define __MODE_SKAS_H__
 +
-+long sys_rt_sigreturn(struct pt_regs regs)
-+{
-+      unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
-+      struct rt_sigframe __user *frame = (struct rt_sigframe *) (sp - 4);
-+      sigset_t set;
-+      struct ucontext __user *uc = &frame->uc;
-+      int sig_size = _NSIG_WORDS * sizeof(unsigned long);
++#include <sysdep/ptrace.h>
 +
-+      if(copy_from_user(&set, &uc->uc_sigmask, sig_size))
-+              goto segfault;
++extern unsigned long exec_regs[];
++extern unsigned long exec_fp_regs[];
++extern unsigned long exec_fpx_regs[];
++extern int have_fpx_regs;
 +
-+      sigdelsetmask(&set, ~_BLOCKABLE);
++extern void user_time_init_skas(void);
+ extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
+                                 void *from_ptr);
+ extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+Index: linux-2.6.10/arch/um/kernel/skas/include/uaccess-skas.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/include/uaccess-skas.h       2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/include/uaccess-skas.h    2005-04-06 23:44:30.264021760 +0800
+@@ -7,6 +7,51 @@
+ #define __SKAS_UACCESS_H
+ #include "asm/errno.h"
++#include "asm/fixmap.h"
 +
-+      spin_lock_irq(&current->sighand->siglock);
-+      current->blocked = set;
-+      recalc_sigpending();
-+      spin_unlock_irq(&current->sighand->siglock);
++#define access_ok_skas(type, addr, size) \
++      ((segment_eq(get_fs(), KERNEL_DS)) || \
++       (((unsigned long) (addr) < TASK_SIZE) && \
++        ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \
++       ((type == VERIFY_READ ) && \
++        ((unsigned long) (addr) >= FIXADDR_USER_START) && \
++        ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
++        ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
 +
-+      if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
-+              goto segfault;
++static inline int verify_area_skas(int type, const void * addr,
++                                 unsigned long size)
++{
++      return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
++}
 +
-+      PT_REGS_SYSCALL_NR(&current->thread.regs) = -1; /* Avoid ERESTART handling */
-+      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
++extern int copy_from_user_skas(void *to, const void *from, int n);
++extern int copy_to_user_skas(void *to, const void *from, int n);
++extern int strncpy_from_user_skas(char *dst, const char *src, int count);
++extern int __clear_user_skas(void *mem, int len);
++extern int clear_user_skas(void *mem, int len);
++extern int strnlen_user_skas(const void *str, int len);
 +
-+ segfault:
-+      force_sig(SIGSEGV, current);
-+      return 0;
-+}
++#endif
 +
 +/*
 + * Overrides for Emacs so that we follow Linus's tabbing style.
@@ -1974,100 +1685,449 @@ Index: linux-2.6.10/arch/um/sys-i386/signal.c
 + * c-file-style: "linux"
 + * End:
 + */
-Index: linux-2.6.10/arch/um/sys-i386/Makefile
++/*
++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
++ */
++
++#ifndef __SKAS_UACCESS_H
++#define __SKAS_UACCESS_H
++
++#include "asm/errno.h"
+ #define access_ok_skas(type, addr, size) \
+       ((segment_eq(get_fs(), KERNEL_DS)) || \
+Index: linux-2.6.10/arch/um/kernel/tt/syscall_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/tt/syscall_user.c 2004-12-25 05:35:01.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/syscall_user.c      2005-04-06 23:44:30.275020088 +0800
+@@ -42,37 +42,31 @@
+       syscall_trace(regs, 1);
+       record_syscall_end(index, result);
+ }
+-
+-int do_syscall(void *task, int pid, int local_using_sysemu)
+-{
+-      unsigned long proc_regs[FRAME_SIZE];
+-      union uml_pt_regs *regs;
+-      int syscall;
+-
+-      if(ptrace_getregs(pid, proc_regs) < 0)
+-              tracer_panic("Couldn't read registers");
+-      syscall = PT_SYSCALL_NR(proc_regs);
+-
+-      regs = TASK_REGS(task);
+-      UPT_SYSCALL_NR(regs) = syscall;
+-
+-      if(syscall < 0)
+-              return(0);
+-
+-      if((syscall != __NR_sigreturn) &&
+-         ((unsigned long *) PT_IP(proc_regs) >= &_stext) && 
+-         ((unsigned long *) PT_IP(proc_regs) <= &_etext))
+-              tracer_panic("I'm tracing myself and I can't get out");
+-
+-      if(local_using_sysemu)
+-              return(1);
+-
+-      if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 
+-                __NR_getpid) < 0)
+-              tracer_panic("do_syscall : Nullifying syscall failed, "
+-                           "errno = %d", errno);
+-      return(1);
+-}
++  
++ void do_sigtrap(void *task)
++ {
++      UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
++ }
++ 
++ void do_syscall(void *task, int pid, int local_using_sysemu)
++  {
++      unsigned long proc_regs[FRAME_SIZE];
++  
++      if(ptrace_getregs(pid, proc_regs) < 0)
++              tracer_panic("Couldn't read registers");
++  
++      UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
++  
++      if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
++         ((unsigned long *) PT_IP(proc_regs) <= &_etext))
++              tracer_panic("I'm tracing myself and I can't get out");
++  
++      /* syscall number -1 in sysemu skips syscall restarting in host */
++      if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 
++                local_using_sysemu ? -1 : __NR_getpid) < 0)
++              tracer_panic("do_syscall : Nullifying syscall failed, "
++                           "errno = %d", errno);
++  }
+ /*
+  * Overrides for Emacs so that we follow Linus's tabbing style.
+Index: linux-2.6.10/arch/um/kernel/tt/sys-i386/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/tt/sys-i386/Makefile      2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/sys-i386/Makefile   2005-04-07 06:37:43.373923992 +0800
+@@ -1,12 +0,0 @@
+-# 
+-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+-# Licensed under the GPL
+-#
+-
+-obj-y = sigcontext.o
+-
+-USER_OBJS = sigcontext.o
+-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+-
+-$(USER_OBJS) : %.o: %.c
+-      $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+Index: linux-2.6.10/arch/um/kernel/tt/sys-i386/sigcontext.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/tt/sys-i386/sigcontext.c  2004-12-25 05:35:39.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/sys-i386/sigcontext.c       2005-04-07 06:37:43.373923992 +0800
+@@ -1,60 +0,0 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#include <stdlib.h>
+-#include <asm/sigcontext.h>
+-#include "kern_util.h"
+-#include "sysdep/frame.h"
+-
+-int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data)
+-{
+-      struct arch_frame_data *arch = data;
+-      struct sigcontext *to = to_ptr, *from = from_ptr;
+-      struct _fpstate *to_fp, *from_fp;
+-      unsigned long sigs;
+-      int err;
+-
+-      to_fp = to->fpstate;
+-      from_fp = from->fpstate;
+-      sigs = to->oldmask;
+-      err = copy_from_user_proc(to, from, sizeof(*to));
+-      to->oldmask = sigs;
+-      if(to_fp != NULL){
+-              err |= copy_from_user_proc(&to->fpstate, &to_fp,
+-                                         sizeof(to->fpstate));
+-              err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size);
+-      }
+-      return(err);
+-}
+-
+-int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data)
+-{
+-      struct arch_frame_data *arch = data;
+-      struct sigcontext *to = to_ptr, *from = from_ptr;
+-      struct _fpstate *to_fp, *from_fp;
+-      int err;
+-
+-      to_fp = (struct _fpstate *) 
+-              (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
+-      from_fp = from->fpstate;
+-      err = copy_to_user_proc(to, from, sizeof(*to));
+-      if(from_fp != NULL){
+-              err |= copy_to_user_proc(&to->fpstate, &to_fp,
+-                                       sizeof(to->fpstate));
+-              err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size);
+-      }
+-      return(err);
+-}
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only.  This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/um/kernel/tt/exec_user.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/sys-i386/Makefile        2004-12-25 05:34:01.000000000 +0800
-+++ linux-2.6.10/arch/um/sys-i386/Makefile     2005-04-05 12:40:36.023911704 +0800
-@@ -1,5 +1,5 @@
- obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
--      ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
-+      ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o
+--- linux-2.6.10.orig/arch/um/kernel/tt/exec_user.c    2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/exec_user.c 2005-04-06 23:44:30.273020392 +0800
+@@ -10,6 +10,7 @@
+ #include <errno.h>
+ #include <sys/wait.h>
+ #include <sys/ptrace.h>
++#include <linux/ptrace.h>
+ #include <signal.h>
+ #include "user_util.h"
+ #include "kern_util.h"
+@@ -35,7 +36,10 @@
+               tracer_panic("do_exec failed to get registers - errno = %d",
+                            errno);
  
- obj-$(CONFIG_HIGHMEM) += highmem.o
- obj-$(CONFIG_MODULES) += module.o
-Index: linux-2.6.10/arch/um/kernel/mem_user.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/mem_user.c        2004-12-25 05:34:57.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/mem_user.c     2005-04-05 12:40:36.051907448 +0800
-@@ -101,6 +101,8 @@
-       }
-       printf("OK\n");
-       munmap(addr, UM_KERN_PAGE_SIZE);
+-      kill(old_pid, SIGKILL);
++      os_kill_ptraced_process(old_pid, 0);
 +
-+      os_close_file(fd);
- }
++      if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
++              tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno);
  
- static int have_devanon = 0;
-@@ -261,6 +263,39 @@
+       if(ptrace_setregs(new_pid, regs) < 0)
+               tracer_panic("do_exec failed to start new proc - errno = %d",
+Index: linux-2.6.10/arch/um/kernel/tt/tracer.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/tt/tracer.c       2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/tracer.c    2005-04-06 23:44:30.276019936 +0800
+@@ -13,6 +13,7 @@
+ #include <string.h>
+ #include <sys/mman.h>
+ #include <sys/ptrace.h>
++#include <linux/ptrace.h>
+ #include <sys/time.h>
+ #include <sys/wait.h>
+ #include "user.h"
+@@ -25,7 +26,6 @@
+ #include "mem_user.h"
+ #include "process.h"
+ #include "kern_util.h"
+-#include "frame.h"
+ #include "chan_user.h"
+ #include "ptrace_user.h"
+ #include "mode.h"
+@@ -72,6 +72,8 @@
+          (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
+               tracer_panic("OP_FORK failed to attach pid");
+       wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
++      if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
++              tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
+       if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
+               tracer_panic("OP_FORK failed to continue process");
  }
- #endif
+@@ -141,7 +143,7 @@
+        * any more, the trace of those will land here.  So, we need to just 
+        * PTRACE_SYSCALL it.
+        */
+-      case SIGTRAP:
++      case (SIGTRAP|SYSCALL_TRAP):
+               if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
+                       tracer_panic("sleeping_process_signal : Failed to "
+                                    "PTRACE_SYSCALL pid %d, errno = %d\n",
+@@ -184,9 +186,8 @@
+       unsigned long eip = 0;
+       int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
+       int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
+-      int pt_syscall_parm, local_using_sysemu;
++      int pt_syscall_parm, local_using_sysemu = 0;
  
-+#if 0
-+/* Debugging facility for dumping stuff out to the host, avoiding the timing
-+ * problems that come with printf and breakpoints.
-+ * Enable in case of emergency.
+-      capture_signal_stack();
+       signal(SIGPIPE, SIG_IGN);
+       setup_tracer_winch();
+       tracing_pid = os_getpid();
+@@ -198,6 +199,10 @@
+               printf("waitpid on idle thread failed, errno = %d\n", errno);
+               exit(1);
+       }
++      if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
++              printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
++              exit(1);
++      }
+       if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
+               printf("Failed to continue idle thread, errno = %d\n", errno);
+               exit(1);
+@@ -297,7 +302,8 @@
+                       task = cpu_tasks[proc_id].task;
+                       tracing = is_tracing(task);
+                       old_tracing = tracing;
+-
++                      if ( tracing ) /* Assume: no syscall, when coming from user */
++                              do_sigtrap(task);
+                       local_using_sysemu = get_using_sysemu();
+                       pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
+@@ -306,6 +312,15 @@
+                               sig = 0;
+                               op = do_proc_op(task, proc_id);
+                               switch(op){
++                              /*
++                               * This is called when entering user mode; after
++                               * this, we start intercepting syscalls.
++                               *
++                               * In fact, a process is started in kernel mode,
++                               * so with is_tracing() == 0 (and that is reset
++                               * when executing syscalls, since UML kernel has
++                               * the right to do syscalls);
++                               */
+                               case OP_TRACE_ON:
+                                       arch_leave_kernel(task, pid);
+                                       tracing = 1;
+@@ -314,7 +329,13 @@
+                               case OP_HALT:
+                                       unmap_physmem();
+                                       kmalloc_ok = 0;
+-                                      ptrace(PTRACE_KILL, pid, 0, 0);
++                                      os_kill_ptraced_process(pid, 0);
++                                      /* Now let's reap remaining zombies */
++                                      errno = 0;
++                                      do {
++                                              waitpid(-1, &status,
++                                                      WUNTRACED);
++                                      } while (errno != ECHILD);
+                                       return(op == OP_REBOOT);
+                               case OP_NONE:
+                                       printf("Detaching pid %d\n", pid);
+@@ -328,14 +349,26 @@
+                                */
+                               pid = cpu_tasks[proc_id].pid;
+                               break;
++                      case (SIGTRAP|SYSCALL_TRAP):
++                              if(!tracing && (debugger_pid != -1)){
++                                      child_signal(pid, W_STOPCODE(SIGTRAP));
++                                      continue;
++                              }
++                              tracing = 0;
++                              /* local_using_sysemu has been already set
++                               * below, since if we are here, is_tracing() on
++                               * the traced task was 1, i.e. the process had
++                               * already run through one iteration of the
++                               * loop which executed a OP_TRACE_ON request.*/
++                              do_syscall(task, pid, local_using_sysemu);
++                              sig = SIGUSR2;
++                              break;
+                       case SIGTRAP:
+                               if(!tracing && (debugger_pid != -1)){
+                                       child_signal(pid, status);
+                                       continue;
+                               }
+                               tracing = 0;
+-                              if(do_syscall(task, pid, local_using_sysemu))
+-                                      sig = SIGUSR2;
+                               break;
+                       case SIGPROF:
+                               if(tracing) sig = 0;
+@@ -371,6 +404,9 @@
+                               continue;
+                       }
++                      local_using_sysemu = get_using_sysemu();
++                      pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
++ 
+                       if(tracing){
+                               if(singlestepping(task))
+                                       cont_type = PTRACE_SINGLESTEP;
+Index: linux-2.6.10/arch/um/kernel/tt/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/tt/Makefile       2004-12-25 05:34:57.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/Makefile    2005-04-06 23:44:30.277019784 +0800
+@@ -8,7 +8,7 @@
+ obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
+       syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
+-      uaccess.o uaccess_user.o sys-$(SUBARCH)/
++      uaccess.o uaccess_user.o 
+ obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
+Index: linux-2.6.10/arch/um/kernel/tt/include/mode-tt.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/tt/include/mode-tt.h      2004-12-25 05:35:01.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/include/mode-tt.h   2005-04-06 23:44:30.272020544 +0800
+@@ -14,6 +14,41 @@
+ extern int tracer(int (*init_proc)(void *), void *sp);
+ extern void user_time_init_tt(void);
++extern void sig_handler_common_tt(int sig, void *sc);
++extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
++extern void reboot_tt(void);
++extern void halt_tt(void);
++extern int is_tracer_winch(int pid, int fd, void *data);
++extern void kill_off_processes_tt(void);
++
++#endif
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only.  This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
++/*
++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
 + */
 +
-+int logging = 1;
-+int logging_fd = -1;
++#ifndef __MODE_TT_H__
++#define __MODE_TT_H__
 +
-+int logging_line = 0;
-+char logging_buf[512];
++#include "sysdep/ptrace.h"
 +
-+void log(char *fmt, ...)
-+{
-+        va_list ap;
-+        struct timeval tv;
-+        struct openflags flags;
++enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
 +
-+        if(logging == 0) return;
-+        if(logging_fd < 0){
-+                flags = of_create(of_trunc(of_rdwr(OPENFLAGS())));
-+                logging_fd = os_open_file("log", flags, 0644);
-+        }
-+        gettimeofday(&tv, NULL);
-+        sprintf(logging_buf, "%d\t %u.%u  ", logging_line++, tv.tv_sec,
-+                tv.tv_usec);
-+        va_start(ap, fmt);
-+        vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
-+        va_end(ap);
-+        write(logging_fd, logging_buf, strlen(logging_buf));
-+}
-+#endif
++extern int tracing_pid;
 +
- /*
-  * Overrides for Emacs so that we follow Linus's tabbing style.
-  * Emacs will notice this stuff at the end of the file and automatically
-Index: linux-2.6.10/arch/um/kernel/time.c
++extern int tracer(int (*init_proc)(void *), void *sp);
++extern void user_time_init_tt(void);
+ extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data);
+ extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr,
+                             void *data);
+Index: linux-2.6.10/arch/um/kernel/tt/include/tt.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/time.c    2004-12-25 05:34:26.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/time.c 2005-04-05 12:40:36.046908208 +0800
-@@ -60,6 +60,9 @@
-          (setitimer(ITIMER_REAL, &disable, NULL) < 0))
-               printk("disnable_timer - setitimer failed, errno = %d\n",
-                      errno);
-+      /* If there are signals already queued, after unblocking ignore them */
-+      set_handler(SIGALRM, SIG_IGN, 0, -1);
-+      set_handler(SIGVTALRM, SIG_IGN, 0, -1);
- }
+--- linux-2.6.10.orig/arch/um/kernel/tt/include/tt.h   2004-12-25 05:34:58.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/tt/include/tt.h        2005-04-06 23:44:30.273020392 +0800
+@@ -26,7 +26,8 @@
+ extern int is_tracing(void *task);
+ extern void syscall_handler(int sig, union uml_pt_regs *regs);
+ extern void exit_kernel(int pid, void *task);
+-extern int do_syscall(void *task, int pid, int local_using_sysemu);
++extern void do_syscall(void *task, int pid, int local_using_sysemu);
++extern void do_sigtrap(void *task);
+ extern int is_valid_pid(int pid);
+ extern void remap_data(void *segment_start, void *segment_end, int w);
  
- void switch_timers(int to_real)
-Index: linux-2.6.10/arch/um/kernel/ksyms.c
+Index: linux-2.6.10/arch/um/kernel/ptrace.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/ksyms.c   2004-12-25 05:33:50.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/ksyms.c        2005-04-05 12:40:36.049907752 +0800
-@@ -48,6 +48,7 @@
- EXPORT_SYMBOL(mode_tt);
- EXPORT_SYMBOL(handle_page_fault);
- EXPORT_SYMBOL(find_iomem);
-+EXPORT_SYMBOL(end_iomem);
+--- linux-2.6.10.orig/arch/um/kernel/ptrace.c  2004-12-25 05:35:50.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/ptrace.c       2005-04-06 23:44:30.254023280 +0800
+@@ -16,6 +16,7 @@
+ #include "asm/uaccess.h"
+ #include "kern_util.h"
+ #include "ptrace_user.h"
++#include "signal_user.h"
  
- #ifdef CONFIG_MODE_TT
- EXPORT_SYMBOL(strncpy_from_user_tt);
+ /*
+  * Called by kernel/ptrace.c when detaching..
+@@ -328,8 +329,10 @@
+       /* the 0x80 provides a way for the tracing parent to distinguish
+          between a syscall stop and SIGTRAP delivery */
+       tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep;
+-      ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
+-
++      ptrace_notify(SIGTRAP | (tracesysgood ? SYSCALL_TRAP : 0));
++      if ( entryexit ) /* force do_signal() --> is_syscall() */
++              set_thread_flag(TIF_SIGPENDING);
++ 
+       /* force do_signal() --> is_syscall() */
+       set_thread_flag(TIF_SIGPENDING);
+Index: linux-2.6.10/arch/um/kernel/dyn.lds.S
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/dyn.lds.S 2004-12-25 05:34:48.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/dyn.lds.S      2005-04-06 23:44:30.253023432 +0800
+@@ -7,8 +7,11 @@
+ SECTIONS
+ {
++  PROVIDE (__executable_start = START);
+   . = START + SIZEOF_HEADERS;
+   .interp         : { *(.interp) }
++  /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
++   * is remapped.*/
+   __binary_start = .;
+   . = ALIGN(4096);            /* Init code and data */
+   _stext = .;
 Index: linux-2.6.10/arch/um/kernel/um_arch.c
 ===================================================================
 --- linux-2.6.10.orig/arch/um/kernel/um_arch.c 2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/um_arch.c      2005-04-05 12:40:36.045908360 +0800
++++ linux-2.6.10/arch/um/kernel/um_arch.c      2005-04-06 23:44:30.239025560 +0800
 @@ -44,11 +44,6 @@
        .ipi_pipe               = { -1, -1 }
  };
@@ -2092,43 +2152,24 @@ Index: linux-2.6.10/arch/um/kernel/um_arch.c
        brk_start = (unsigned long) sbrk(0);
        CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
        /* Increase physical memory size for exec-shield users
-Index: linux-2.6.10/arch/um/kernel/process.c
+Index: linux-2.6.10/arch/um/kernel/time.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/process.c 2004-12-25 05:35:25.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/process.c      2005-04-05 12:40:36.025911400 +0800
-@@ -13,6 +13,7 @@
- #include <setjmp.h>
- #include <sys/time.h>
- #include <sys/ptrace.h>
-+#include <linux/ptrace.h>
- #include <sys/wait.h>
- #include <sys/mman.h>
- #include <asm/ptrace.h>
-@@ -285,6 +286,9 @@
-       printk("Checking that ptrace can change system call numbers...");
-       pid = start_ptraced_child(&stack);
+--- linux-2.6.10.orig/arch/um/kernel/time.c    2004-12-25 05:34:26.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/time.c 2005-04-06 23:44:30.237025864 +0800
+@@ -60,6 +60,9 @@
+          (setitimer(ITIMER_REAL, &disable, NULL) < 0))
+               printk("disnable_timer - setitimer failed, errno = %d\n",
+                      errno);
++      /* If there are signals already queued, after unblocking ignore them */
++      set_handler(SIGALRM, SIG_IGN, 0, -1);
++      set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+ }
  
-+      if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
-+              panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
-+
-       while(1){
-               if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
-                       panic("check_ptrace : ptrace failed, errno = %d", 
-@@ -292,8 +296,8 @@
-               CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
-               if(n < 0)
-                       panic("check_ptrace : wait failed, errno = %d", errno);
--              if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
--                      panic("check_ptrace : expected SIGTRAP, "
-+              if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP)))
-+                      panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
-                             "got status = %d", status);
-               
-               syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+ void switch_timers(int to_real)
 Index: linux-2.6.10/arch/um/kernel/process_kern.c
 ===================================================================
 --- linux-2.6.10.orig/arch/um/kernel/process_kern.c    2004-12-25 05:34:57.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/process_kern.c 2005-04-05 12:40:36.047908056 +0800
++++ linux-2.6.10/arch/um/kernel/process_kern.c 2005-04-06 23:44:30.240025408 +0800
 @@ -291,8 +291,6 @@
  
  EXPORT_SYMBOL(disable_hlt);
@@ -2138,79 +2179,80 @@ Index: linux-2.6.10/arch/um/kernel/process_kern.c
  void *um_kmalloc(int size)
  {
        return(kmalloc(size, GFP_KERNEL));
-Index: linux-2.6.10/arch/um/kernel/signal_user.c
+Index: linux-2.6.10/arch/um/kernel/trap_user.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/signal_user.c     2004-12-25 05:35:23.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/signal_user.c  2005-04-05 12:40:36.050907600 +0800
-@@ -61,6 +61,10 @@
-  * disable profiling; it's safe because the profiling code does not interact
-  * with the kernel code at all.*/
-+/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
-+ * disable profiling; it's safe because the profiling code does not interact
-+ * with the kernel code at all.*/
-+
- static void change_signals(int type)
- {
-       sigset_t mask;
-Index: linux-2.6.10/arch/um/kernel/initrd_user.c
+--- linux-2.6.10.orig/arch/um/kernel/trap_user.c       2004-12-25 05:34:44.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/trap_user.c    2005-04-06 23:44:30.277019784 +0800
+@@ -18,7 +18,6 @@
+ #include "sigcontext.h"
+ #include "sysdep/sigcontext.h"
+ #include "irq_user.h"
+-#include "frame_user.h"
+ #include "signal_user.h"
+ #include "time_user.h"
+ #include "task.h"
+Index: linux-2.6.10/arch/um/kernel/signal_kern.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/initrd_user.c     2004-12-25 05:34:26.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/initrd_user.c  2005-04-05 12:40:36.026911248 +0800
-@@ -29,6 +29,8 @@
-                      filename, -n);
-               return(-1);
-       }
-+
-+      os_close_file(fd);
-       return(0);
+--- linux-2.6.10.orig/arch/um/kernel/signal_kern.c     2004-12-25 05:34:58.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/signal_kern.c  2005-04-06 23:44:30.264021760 +0800
+@@ -230,53 +230,6 @@
+       return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
  }
  
-Index: linux-2.6.10/arch/um/kernel/dyn.lds.S
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/dyn.lds.S 2004-12-25 05:34:48.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/dyn.lds.S      2005-04-05 12:40:36.044908512 +0800
-@@ -7,8 +7,11 @@
- SECTIONS
- {
-+  PROVIDE (__executable_start = START);
-   . = START + SIZEOF_HEADERS;
-   .interp         : { *(.interp) }
-+  /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
-+   * is remapped.*/
-   __binary_start = .;
-   . = ALIGN(4096);            /* Init code and data */
-   _stext = .;
-Index: linux-2.6.10/arch/um/kernel/ptrace.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/ptrace.c  2004-12-25 05:35:50.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/ptrace.c       2005-04-05 12:40:36.044908512 +0800
-@@ -16,6 +16,7 @@
- #include "asm/uaccess.h"
- #include "kern_util.h"
- #include "ptrace_user.h"
-+#include "signal_user.h"
- /*
-  * Called by kernel/ptrace.c when detaching..
-@@ -328,8 +329,10 @@
-       /* the 0x80 provides a way for the tracing parent to distinguish
-          between a syscall stop and SIGTRAP delivery */
-       tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep;
--      ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0));
+-extern int userspace_pid[];
+-
+-static int copy_sc_from_user(struct pt_regs *to, void *from, 
+-                           struct arch_frame_data *arch)
+-{
+-      int ret;
+-
+-      ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
+-                        copy_sc_from_user_skas(userspace_pid[0],
+-                                               &to->regs, from));
+-      return(ret);
+-}
+-
+-long sys_sigreturn(struct pt_regs regs)
+-{
+-      void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
+-      void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
+-      int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+-
+-      spin_lock_irq(&current->sighand->siglock);
+-      copy_from_user(&current->blocked.sig[0], sc_sigmask(sc), 
+-                     sizeof(current->blocked.sig[0]));
+-      copy_from_user(&current->blocked.sig[1], mask, sig_size);
+-      sigdelsetmask(&current->blocked, ~_BLOCKABLE);
+-      recalc_sigpending();
+-      spin_unlock_irq(&current->sighand->siglock);
+-      copy_sc_from_user(&current->thread.regs, sc, 
+-                        &signal_frame_sc.common.arch);
+-      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
+-}
+-
+-long sys_rt_sigreturn(struct pt_regs regs)
+-{
+-      unsigned long sp = PT_REGS_SP(&current->thread.regs);
+-      struct ucontext __user *uc = sp_to_uc(sp);
+-      int sig_size = _NSIG_WORDS * sizeof(unsigned long);
 -
-+      ptrace_notify(SIGTRAP | (tracesysgood ? SYSCALL_TRAP : 0));
-+      if ( entryexit ) /* force do_signal() --> is_syscall() */
-+              set_thread_flag(TIF_SIGPENDING);
-+ 
-       /* force do_signal() --> is_syscall() */
-       set_thread_flag(TIF_SIGPENDING);
+-      spin_lock_irq(&current->sighand->siglock);
+-      copy_from_user(&current->blocked, &uc->uc_sigmask, sig_size);
+-      sigdelsetmask(&current->blocked, ~_BLOCKABLE);
+-      recalc_sigpending();
+-      spin_unlock_irq(&current->sighand->siglock);
+-      copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
+-                        &signal_frame_si.common.arch);
+-      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
+-}
+-
+ /*
+  * Overrides for Emacs so that we follow Linus's tabbing style.
+  * Emacs will notice this stuff at the end of the file and automatically
 Index: linux-2.6.10/arch/um/kernel/uml.lds.S
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/uml.lds.S 2005-04-01 12:25:25.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/uml.lds.S      2005-04-05 12:40:36.049907752 +0800
+--- linux-2.6.10.orig/arch/um/kernel/uml.lds.S 2004-12-25 05:34:44.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/uml.lds.S      2005-04-06 23:44:30.254023280 +0800
 @@ -7,8 +7,12 @@
  
  SECTIONS
@@ -2239,367 +2281,551 @@ Index: linux-2.6.10/arch/um/kernel/uml.lds.S
    _stext = .;
    __init_begin = .;
    .init.text : {
-Index: linux-2.6.10/arch/um/kernel/main.c
+Index: linux-2.6.10/arch/um/kernel/ksyms.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/main.c    2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/main.c 2005-04-05 12:40:36.024911552 +0800
-@@ -81,6 +81,8 @@
+--- linux-2.6.10.orig/arch/um/kernel/ksyms.c   2004-12-25 05:33:50.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/ksyms.c        2005-04-06 23:44:30.238025712 +0800
+@@ -48,6 +48,7 @@
+ EXPORT_SYMBOL(mode_tt);
+ EXPORT_SYMBOL(handle_page_fault);
+ EXPORT_SYMBOL(find_iomem);
++EXPORT_SYMBOL(end_iomem);
  
- extern int uml_exitcode;
+ #ifdef CONFIG_MODE_TT
+ EXPORT_SYMBOL(strncpy_from_user_tt);
+Index: linux-2.6.10/arch/um/kernel/signal_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/signal_user.c     2004-12-25 05:35:23.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/signal_user.c  2005-04-06 23:44:30.252023584 +0800
+@@ -61,6 +61,10 @@
+  * disable profiling; it's safe because the profiling code does not interact
+  * with the kernel code at all.*/
  
-+extern void scan_elf_aux( char **envp);
++/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
++ * disable profiling; it's safe because the profiling code does not interact
++ * with the kernel code at all.*/
 +
int main(int argc, char **argv, char **envp)
static void change_signals(int type)
  {
-       char **new_argv;
-@@ -147,6 +149,8 @@
-       set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-       set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-+      scan_elf_aux( envp);
+       sigset_t mask;
+Index: linux-2.6.10/arch/um/kernel/mem_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/mem_user.c        2004-12-25 05:34:57.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/mem_user.c     2005-04-06 23:44:30.237025864 +0800
+@@ -101,6 +101,8 @@
+       }
+       printf("OK\n");
+       munmap(addr, UM_KERN_PAGE_SIZE);
 +
-       do_uml_initcalls();
-       ret = linux_main(argc, argv);
-@@ -155,18 +159,20 @@
-               int err;
++      os_close_file(fd);
+ }
  
-               printf("\n");
--
--              /* Let any pending signals fire, then disable them.  This
--               * ensures that they won't be delivered after the exec, when
--               * they are definitely not expected.
--               */
--              unblock_signals();
-+              /* stop timers and set SIG*ALRM to be ignored */
-               disable_timer();
-+              /* disable SIGIO for the fds and set SIGIO to be ignored */
-               err = deactivate_all_fds();
-               if(err)
-                       printf("deactivate_all_fds failed, errno = %d\n",
-                              -err);
+ static int have_devanon = 0;
+@@ -261,6 +263,39 @@
+ }
+ #endif
  
-+              /* Let any pending signals fire now.  This ensures
-+               * that they won't be delivered after the exec, when
-+               * they are definitely not expected.
-+               */
-+              unblock_signals();
++#if 0
++/* Debugging facility for dumping stuff out to the host, avoiding the timing
++ * problems that come with printf and breakpoints.
++ * Enable in case of emergency.
++ */
 +
-               execvp(new_argv[0], new_argv);
-               perror("Failed to exec kernel");
-               ret = 1;
-Index: linux-2.6.10/arch/um/kernel/irq_user.c
++int logging = 1;
++int logging_fd = -1;
++
++int logging_line = 0;
++char logging_buf[512];
++
++void log(char *fmt, ...)
++{
++        va_list ap;
++        struct timeval tv;
++        struct openflags flags;
++
++        if(logging == 0) return;
++        if(logging_fd < 0){
++                flags = of_create(of_trunc(of_rdwr(OPENFLAGS())));
++                logging_fd = os_open_file("log", flags, 0644);
++        }
++        gettimeofday(&tv, NULL);
++        sprintf(logging_buf, "%d\t %u.%u  ", logging_line++, tv.tv_sec,
++                tv.tv_usec);
++        va_start(ap, fmt);
++        vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
++        va_end(ap);
++        write(logging_fd, logging_buf, strlen(logging_buf));
++}
++#endif
++
+ /*
+  * Overrides for Emacs so that we follow Linus's tabbing style.
+  * Emacs will notice this stuff at the end of the file and automatically
+Index: linux-2.6.10/arch/um/kernel/Makefile
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/irq_user.c        2004-12-25 05:34:32.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/irq_user.c     2005-04-05 12:40:36.028910944 +0800
-@@ -374,6 +374,8 @@
-               if(err)
-                       return(err);
-       }
-+      /* If there is a signal already queued, after unblocking ignore it */
-+      set_handler(SIGIO, SIG_IGN, 0, -1);
+--- linux-2.6.10.orig/arch/um/kernel/Makefile  2004-12-25 05:35:01.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/Makefile       2005-04-06 23:44:30.278019632 +0800
+@@ -6,7 +6,7 @@
+ extra-y := vmlinux.lds
+ clean-files := vmlinux.lds.S
  
-       return(0);
- }
-Index: linux-2.6.10/arch/um/kernel/signal_kern.c
+-obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
++obj-y = checksum.o config.o exec_kern.o exitcode.o \
+       helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
+       physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
+       sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
+Index: linux-2.6.10/arch/um/Kconfig
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/signal_kern.c     2004-12-25 05:34:58.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/signal_kern.c  2005-04-05 12:40:36.048907904 +0800
-@@ -230,53 +230,6 @@
-       return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
- }
+--- linux-2.6.10.orig/arch/um/Kconfig  2004-12-25 05:34:45.000000000 +0800
++++ linux-2.6.10/arch/um/Kconfig       2005-04-06 23:44:30.285018568 +0800
+@@ -139,6 +139,25 @@
  
--extern int userspace_pid[];
+         It is safe to say 'Y' here.
++config MAGIC_SYSRQ
++        bool "Magic SysRq key"
++        depends on MCONSOLE
++        ---help---
++        If you say Y here, you will have some control over the system even
++        if the system crashes for example during kernel debugging (e.g., you
++        will be able to flush the buffer cache to disk, reboot the system
++        immediately or dump some status information). A key for each of the
++        possible requests is provided.
++
++        This is the feature normally accomplished by pressing a key
++        while holding SysRq (Alt+PrintScreen).
++
++        On UML, this is accomplished by sending a "sysrq" command with
++        mconsole, followed by the letter for the requested command.
++
++        The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
++        unless you really know what this hack does.
++
+ config HOST_2G_2G
+       bool "2G/2G host address space split"
+       default n
+@@ -153,28 +172,28 @@
+       So, if you do not know what to do here, say 'N'.
+ config SMP
+-      bool "Symmetric multi-processing support (EXPERIMENTAL)"
+-      default n
+-      depends on MODE_TT && EXPERIMENTAL
+-      help
+-      This option enables UML SMP support.
+-      It is NOT related to having a real SMP box. Not directly, at least.
++        bool "Symmetric multi-processing support (EXPERIMENTAL)"
++        default n
++        depends on MODE_TT && EXPERIMENTAL
++        help
++        This option enables UML SMP support.
++        It is NOT related to having a real SMP box. Not directly, at least.
++
++        UML implements virtual SMP by allowing as many processes to run
++        simultaneously on the host as there are virtual processors configured.
++
++        Obviously, if the host is a uniprocessor, those processes will
++        timeshare, but, inside UML, will appear to be running simultaneously.
++        If the host is a multiprocessor, then UML processes may run
++        simultaneously, depending on the host scheduler.
++
++        This, however, is supported only in TT mode. So, if you use the SKAS
++        patch on your host, switching to TT mode and enabling SMP usually gives
++        you worse performances.
++        Also, since the support for SMP has been under-developed, there could
++        be some bugs being exposed by enabling SMP.
+-      UML implements virtual SMP by allowing as many processes to run
+-      simultaneously on the host as there are virtual processors configured.
+-
+-      Obviously, if the host is a uniprocessor, those processes will
+-      timeshare, but, inside UML, will appear to be running simultaneously.
+-      If the host is a multiprocessor, then UML processes may run
+-      simultaneously, depending on the host scheduler.
+-
+-      This, however, is supported only in TT mode. So, if you use the SKAS
+-      patch on your host, switching to TT mode and enabling SMP usually gives
+-      you worse performances.
+-      Also, since the support for SMP has been under-developed, there could
+-      be some bugs being exposed by enabling SMP.
+-
+-      If you don't know what to do, say N.
++        If you don't know what to do, say N.
+ config NR_CPUS
+       int "Maximum number of CPUs (2-32)"
+@@ -282,4 +301,8 @@
+       bool
+       default n
++config INPUT
++      bool
++      default n
++
+ source "arch/um/Kconfig.debug"
+Index: linux-2.6.10/arch/um/include/frame.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/include/frame.h  2004-12-25 05:34:31.000000000 +0800
++++ linux-2.6.10/arch/um/include/frame.h       2005-04-07 06:37:43.373923992 +0800
+@@ -1,53 +0,0 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#ifndef __FRAME_H_
+-#define __FRAME_H_
+-
+-#include "sysdep/frame.h"
 -
--static int copy_sc_from_user(struct pt_regs *to, void *from, 
--                           struct arch_frame_data *arch)
--{
--      int ret;
+-struct frame_common {
+-      void *data;
+-      int len;
+-      int sig_index;
+-      int sr_index;
+-      int sr_relative;
+-      int sp_index;
+-      struct arch_frame_data arch;
+-};
 -
--      ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
--                        copy_sc_from_user_skas(userspace_pid[0],
--                                               &to->regs, from));
--      return(ret);
--}
+-struct sc_frame {
+-      struct frame_common common;
+-      int sc_index;
+-};
 -
--long sys_sigreturn(struct pt_regs regs)
--{
--      void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
--      void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
--      int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+-extern struct sc_frame signal_frame_sc;
 -
--      spin_lock_irq(&current->sighand->siglock);
--      copy_from_user(&current->blocked.sig[0], sc_sigmask(sc), 
--                     sizeof(current->blocked.sig[0]));
--      copy_from_user(&current->blocked.sig[1], mask, sig_size);
--      sigdelsetmask(&current->blocked, ~_BLOCKABLE);
--      recalc_sigpending();
--      spin_unlock_irq(&current->sighand->siglock);
--      copy_sc_from_user(&current->thread.regs, sc, 
--                        &signal_frame_sc.common.arch);
--      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
--}
+-extern struct sc_frame signal_frame_sc_sr;
 -
--long sys_rt_sigreturn(struct pt_regs regs)
--{
--      unsigned long sp = PT_REGS_SP(&current->thread.regs);
--      struct ucontext __user *uc = sp_to_uc(sp);
--      int sig_size = _NSIG_WORDS * sizeof(unsigned long);
+-struct si_frame {
+-      struct frame_common common;
+-      int sip_index;
+-      int si_index;
+-      int ucp_index;
+-      int uc_index;
+-};
 -
--      spin_lock_irq(&current->sighand->siglock);
--      copy_from_user(&current->blocked, &uc->uc_sigmask, sig_size);
--      sigdelsetmask(&current->blocked, ~_BLOCKABLE);
--      recalc_sigpending();
--      spin_unlock_irq(&current->sighand->siglock);
--      copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
--                        &signal_frame_si.common.arch);
--      return(PT_REGS_SYSCALL_RET(&current->thread.regs));
--}
+-extern struct si_frame signal_frame_si;
 -
- /*
-  * Overrides for Emacs so that we follow Linus's tabbing style.
-  * Emacs will notice this stuff at the end of the file and automatically
-Index: linux-2.6.10/arch/um/kernel/skas/include/uaccess-skas.h
+-extern void capture_signal_stack(void);
+-
+-#endif
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only.  This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/um/include/elf_user.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/include/uaccess-skas.h       2004-12-25 05:34:32.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/include/uaccess-skas.h    2005-04-05 12:40:36.037909576 +0800
-@@ -7,6 +7,51 @@
- #define __SKAS_UACCESS_H
- #include "asm/errno.h"
-+#include "asm/fixmap.h"
-+
-+#define access_ok_skas(type, addr, size) \
-+      ((segment_eq(get_fs(), KERNEL_DS)) || \
-+       (((unsigned long) (addr) < TASK_SIZE) && \
-+        ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \
-+       ((type == VERIFY_READ ) && \
-+        ((unsigned long) (addr) >= FIXADDR_USER_START) && \
-+        ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \
-+        ((unsigned long) (addr) + (size) >= (unsigned long)(addr))))
-+
-+static inline int verify_area_skas(int type, const void * addr,
-+                                 unsigned long size)
-+{
-+      return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
-+}
-+
-+extern int copy_from_user_skas(void *to, const void *from, int n);
-+extern int copy_to_user_skas(void *to, const void *from, int n);
-+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
-+extern int __clear_user_skas(void *mem, int len);
-+extern int clear_user_skas(void *mem, int len);
-+extern int strnlen_user_skas(const void *str, int len);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only.  This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
+--- linux-2.6.10.orig/arch/um/include/elf_user.h       2005-04-07 06:37:43.373923992 +0800
++++ linux-2.6.10/arch/um/include/elf_user.h    2005-04-06 23:44:30.231026776 +0800
+@@ -0,0 +1,19 @@
 +/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
++ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
 + * Licensed under the GPL
 + */
 +
-+#ifndef __SKAS_UACCESS_H
-+#define __SKAS_UACCESS_H
-+
-+#include "asm/errno.h"
- #define access_ok_skas(type, addr, size) \
-       ((segment_eq(get_fs(), KERNEL_DS)) || \
-Index: linux-2.6.10/arch/um/kernel/skas/include/mmu-skas.h
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/include/mmu-skas.h   2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/include/mmu-skas.h        2005-04-05 12:40:36.035909880 +0800
-@@ -22,3 +22,27 @@
-  * c-file-style: "linux"
-  * End:
-  */
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
++#ifndef __ELF_USER_H__
++#define __ELF_USER_H__
 +
-+#ifndef __SKAS_MMU_H
-+#define __SKAS_MMU_H
++/* For compilation on a host that doesn't support AT_SYSINFO (Linux 2.4)  */
 +
-+struct mmu_context_skas {
-+      int mm_fd;
-+};
++#ifndef AT_SYSINFO
++#define AT_SYSINFO 32
++#endif
++#ifndef AT_SYSINFO_EHDR
++#define AT_SYSINFO_EHDR 33
++#endif
 +
 +#endif
+Index: linux-2.6.10/arch/um/include/signal_user.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/include/signal_user.h    2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/include/signal_user.h 2005-04-06 23:44:30.232026624 +0800
+@@ -14,6 +14,8 @@
+ extern int set_signals(int enable);
+ extern int get_signals(void);
++#define SYSCALL_TRAP 0x80
 +
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only.  This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-Index: linux-2.6.10/arch/um/kernel/skas/include/mode-skas.h
+ #endif
+ /*
+Index: linux-2.6.10/arch/um/include/skas_ptrace.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/include/mode-skas.h  2004-12-25 05:34:58.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/include/mode-skas.h       2005-04-05 12:40:36.036909728 +0800
-@@ -14,6 +14,40 @@
- extern int have_fpx_regs;
+--- linux-2.6.10.orig/arch/um/include/skas_ptrace.h    2004-12-25 05:35:27.000000000 +0800
++++ linux-2.6.10/arch/um/include/skas_ptrace.h 2005-04-06 23:44:30.232026624 +0800
+@@ -6,6 +6,7 @@
+ #ifndef __SKAS_PTRACE_H
+ #define __SKAS_PTRACE_H
  
- extern void user_time_init_skas(void);
-+extern void sig_handler_common_skas(int sig, void *sc_ptr);
-+extern void halt_skas(void);
-+extern void reboot_skas(void);
-+extern void kill_off_processes_skas(void);
-+extern int is_skas_winch(int pid, int fd, void *data);
++#ifndef PTRACE_FAULTINFO
+ struct ptrace_faultinfo {
+       int is_write;
+       unsigned long addr;
+@@ -21,6 +22,7 @@
+ #define PTRACE_SIGPENDING 53
+ #define PTRACE_LDT 54
+ #define PTRACE_SWITCH_MM 55
++#endif
+ #endif
+Index: linux-2.6.10/arch/um/include/frame_kern.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/include/frame_kern.h     2004-12-25 05:34:57.000000000 +0800
++++ linux-2.6.10/arch/um/include/frame_kern.h  2005-04-06 23:44:30.228027232 +0800
+@@ -6,8 +6,8 @@
+ #ifndef __FRAME_KERN_H_
+ #define __FRAME_KERN_H_
+-#include "frame.h"
+-#include "sysdep/frame_kern.h"
++#define _S(nr) (1<<((nr)-1))
++#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+ extern int setup_signal_stack_sc(unsigned long stack_top, int sig, 
+                                struct k_sigaction *ka,
+Index: linux-2.6.10/arch/um/include/ptrace_user.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/include/ptrace_user.h    2004-12-25 05:33:51.000000000 +0800
++++ linux-2.6.10/arch/um/include/ptrace_user.h 2005-04-06 23:44:30.229027080 +0800
+@@ -26,4 +26,35 @@
+ int get_using_sysemu(void);
+ extern int sysemu_supported;
++
++/* syscall emulation path in ptrace */
 +
++#ifndef PTRACE_SYSEMU
++#define PTRACE_SYSEMU 31
 +#endif
 +
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only.  This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
++/* On architectures, that started to support PTRACE_O_TRACESYSGOOD
++ * in linux 2.4, there are two different definitions of
++ * PTRACE_SETOPTIONS: linux 2.4 uses 21 while linux 2.6 uses 0x4200.
++ * For binary compatibility, 2.6 also supports the old "21", named
++ * PTRACE_OLDSETOPTION. On these architectures, UML always must use
++ * "21", to ensure the kernel runs on 2.4 and 2.6 host without
++ * recompilation. So, we use PTRACE_OLDSETOPTIONS in UML.
++ * We also want to be able to build the kernel on 2.4, which doesn't
++ * have PTRACE_OLDSETOPTIONS. So, if it is missing, we declare
++ * PTRACE_OLDSETOPTIONS to to be the same as PTRACE_SETOPTIONS.
++ *
++ * On architectures, that start to support PTRACE_O_TRACESYSGOOD on
++ * linux 2.6, PTRACE_OLDSETOPTIONS never is defined, and also isn't
++ * supported by the host kernel. In that case, our trick lets us use
++ * the new 0x4200 with the name PTRACE_OLDSETOPTIONS.
 + */
++#ifndef PTRACE_OLDSETOPTIONS
++#define PTRACE_OLDSETOPTIONS PTRACE_SETOPTIONS
++#endif
 +
-+#ifndef __MODE_SKAS_H__
-+#define __MODE_SKAS_H__
-+
-+#include <sysdep/ptrace.h>
-+
-+extern unsigned long exec_regs[];
-+extern unsigned long exec_fp_regs[];
-+extern unsigned long exec_fpx_regs[];
-+extern int have_fpx_regs;
++void set_using_sysemu(int value);
++int get_using_sysemu(void);
++extern int sysemu_supported;
 +
-+extern void user_time_init_skas(void);
- extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
-                                 void *from_ptr);
- extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
-Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c
+ #endif
+Index: linux-2.6.10/arch/um/include/sysdep-i386/frame.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/sigcontext.c        2004-12-25 05:33:51.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c     2005-04-05 19:01:49.158500672 +0800
-@@ -1,114 +0,0 @@
+--- linux-2.6.10.orig/arch/um/include/sysdep-i386/frame.h      2004-12-25 05:35:01.000000000 +0800
++++ linux-2.6.10/arch/um/include/sysdep-i386/frame.h   2005-04-07 06:37:43.373923992 +0800
+@@ -1,29 +0,0 @@
 -/* 
 - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 - * Licensed under the GPL
 - */
 -
--#include <errno.h>
--#include <asm/sigcontext.h>
--#include <sys/ptrace.h>
--#include <linux/ptrace.h>
--#include "sysdep/ptrace.h"
--#include "sysdep/ptrace_user.h"
--#include "kern_util.h"
--#include "user.h"
--#include "sigcontext.h"
--#include "mode.h"
+-#ifndef __FRAME_I386_H
+-#define __FRAME_I386_H
 -
--int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
+-struct arch_frame_data_raw {
+-      unsigned long fp_start;
+-      unsigned long sr;
+-};
+-
+-struct arch_frame_data {
+-      int fpstate_size;
+-};
+-
+-#endif
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only.  This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/um/include/sysdep-i386/frame_kern.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/include/sysdep-i386/frame_kern.h 2004-12-25 05:34:26.000000000 +0800
++++ linux-2.6.10/arch/um/include/sysdep-i386/frame_kern.h      2005-04-07 06:37:43.373923992 +0800
+@@ -1,69 +0,0 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#ifndef __FRAME_KERN_I386_H
+-#define __FRAME_KERN_I386_H
+-
+-/* This is called from sys_sigreturn.  It takes the sp at the point of the
+- * sigreturn system call and returns the address of the sigcontext struct
+- * on the stack.
+- */
+-
+-static inline void *sp_to_sc(unsigned long sp)
 -{
--      struct sigcontext sc, *from = from_ptr;
--      unsigned long fpregs[FP_FRAME_SIZE];
--      int err;
+-      return((void *) sp);
+-}
 -
--      err = copy_from_user_proc(&sc, from, sizeof(sc));
--      err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs));
--      if(err)
--              return(err);
+-static inline void *sp_to_uc(unsigned long sp)
+-{
+-      unsigned long uc;
 -
--      regs->skas.regs[GS] = sc.gs;
--      regs->skas.regs[FS] = sc.fs;
--      regs->skas.regs[ES] = sc.es;
--      regs->skas.regs[DS] = sc.ds;
--      regs->skas.regs[EDI] = sc.edi;
--      regs->skas.regs[ESI] = sc.esi;
--      regs->skas.regs[EBP] = sc.ebp;
--      regs->skas.regs[UESP] = sc.esp;
--      regs->skas.regs[EBX] = sc.ebx;
--      regs->skas.regs[EDX] = sc.edx;
--      regs->skas.regs[ECX] = sc.ecx;
--      regs->skas.regs[EAX] = sc.eax;
--      regs->skas.regs[EIP] = sc.eip;
--      regs->skas.regs[CS] = sc.cs;
--      regs->skas.regs[EFL] = sc.eflags;
--      regs->skas.regs[SS] = sc.ss;
--      regs->skas.fault_addr = sc.cr2;
--      regs->skas.fault_type = FAULT_WRITE(sc.err);
--      regs->skas.trap_type = sc.trapno;
+-      uc = sp + signal_frame_si.uc_index - 
+-              signal_frame_si.common.sp_index - 4;
+-      return((void *) uc);
+-}
 -
--      err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
--      if(err < 0){
--              printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
--                     "errno = %d\n", errno);
--              return(1);
--      }
+-static inline void *sp_to_rt_sc(unsigned long sp)
+-{
+-      unsigned long sc;
 -
--      return(0);
+-      sc = sp - signal_frame_si.common.sp_index + 
+-              signal_frame_si.common.len - 4;
+-      return((void *) sc);
 -}
 -
--int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
--                       union uml_pt_regs *regs, unsigned long fault_addr,
--                       int fault_type)
+-static inline void *sp_to_mask(unsigned long sp)
 -{
--      struct sigcontext sc, *to = to_ptr;
--      struct _fpstate *to_fp;
--      unsigned long fpregs[FP_FRAME_SIZE];
--      int err;
+-      unsigned long mask;
 -
--      sc.gs = regs->skas.regs[GS];
--      sc.fs = regs->skas.regs[FS];
--      sc.es = regs->skas.regs[ES];
--      sc.ds = regs->skas.regs[DS];
--      sc.edi = regs->skas.regs[EDI];
--      sc.esi = regs->skas.regs[ESI];
--      sc.ebp = regs->skas.regs[EBP];
--      sc.esp = regs->skas.regs[UESP];
--      sc.ebx = regs->skas.regs[EBX];
--      sc.edx = regs->skas.regs[EDX];
--      sc.ecx = regs->skas.regs[ECX];
--      sc.eax = regs->skas.regs[EAX];
--      sc.eip = regs->skas.regs[EIP];
--      sc.cs = regs->skas.regs[CS];
--      sc.eflags = regs->skas.regs[EFL];
--      sc.esp_at_signal = regs->skas.regs[UESP];
--      sc.ss = regs->skas.regs[SS];
--      sc.cr2 = fault_addr;
--      sc.err = TO_SC_ERR(fault_type);
--      sc.trapno = regs->skas.trap_type;
+-      mask = sp - signal_frame_sc.common.sp_index + 
+-              signal_frame_sc.common.len - 8;
+-      return((void *) mask);
+-}
+-
+-extern int sc_size(void *data);
+-
+-static inline void *sp_to_rt_mask(unsigned long sp)
+-{
+-      unsigned long mask;
+-
+-      mask = sp - signal_frame_si.common.sp_index + 
+-              signal_frame_si.common.len + 
+-              sc_size(&signal_frame_si.common.arch) - 4;
+-      return((void *) mask);
+-}
+-
+-#endif
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only.  This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/um/include/sysdep-i386/frame_user.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/include/sysdep-i386/frame_user.h 2004-12-25 05:35:28.000000000 +0800
++++ linux-2.6.10/arch/um/include/sysdep-i386/frame_user.h      2005-04-07 06:37:43.373923992 +0800
+@@ -1,91 +0,0 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#ifndef __FRAME_USER_I386_H
+-#define __FRAME_USER_I386_H
+-
+-#include <asm/page.h>
+-#include "sysdep/frame.h"
+-
+-/* This stuff is to calculate the size of the fp state struct at runtime
+- * because it has changed between 2.2 and 2.4 and it would be good for a
+- * UML compiled on one to work on the other.
+- * So, setup_arch_frame_raw fills in the arch struct with the raw data, which
+- * just contains the address of the end of the sigcontext.  This is invoked
+- * from the signal handler.
+- * setup_arch_frame uses that data to figure out what 
+- * arch_frame_data.fpstate_size should be.  It really has no idea, since it's
+- * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's
+- * everything from the end of the sigcontext up to the top of the stack.  So,
+- * it masks off the page number to get the offset within the page and subtracts
+- * that from the page size, and that's how big the fpstate struct will be
+- * considered to be.
+- */
+-
+-static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data,
+-                                      void *end, unsigned long srp)
+-{
+-      unsigned long sr = *((unsigned long *) srp);
+-
+-      data->fp_start = (unsigned long) end;
+-      if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK))
+-              data->sr = sr;
+-      else data->sr = 0;
+-}
+-
+-static inline void setup_arch_frame(struct arch_frame_data_raw *in, 
+-                                  struct arch_frame_data *out)
+-{
+-      unsigned long fpstate_start = in->fp_start;
+-
+-      if(in->sr == 0){
+-              fpstate_start &= ~PAGE_MASK;
+-              out->fpstate_size = PAGE_SIZE - fpstate_start;
+-      }
+-      else {
+-              out->fpstate_size = in->sr - fpstate_start;
+-      }
+-}
+-
+-/* This figures out where on the stack the SA_RESTORER function address
+- * is stored.  For i386, it's the signal handler return address, so it's
+- * located next to the frame pointer.
+- * This is inlined, so __builtin_frame_address(0) is correct.  Otherwise,
+- * it would have to be __builtin_frame_address(1).
+- */
+-
+-#define frame_restorer() \
+-({ \
+-      unsigned long *fp; \
+-\
+-      fp = __builtin_frame_address(0); \
+-      ((unsigned long) (fp + 1)); \
+-})
 -
--      err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
--      if(err < 0){
--              printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
--                     "errno = %d\n", errno);
--              return(1);
--      }
--      to_fp = (struct _fpstate *) 
--              (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
--      sc.fpstate = to_fp;
+-/* Similarly, this returns the value of sp when the handler was first
+- * entered.  This is used to calculate the proper sp when delivering
+- * signals.
+- */
 -
--      if(err)
--              return(err);
+-#define frame_sp() \
+-({ \
+-      unsigned long *fp; \
+-\
+-      fp = __builtin_frame_address(0); \
+-      ((unsigned long) (fp + 1)); \
+-})
 -
--      return(copy_to_user_proc(to, &sc, sizeof(sc)) ||
--             copy_to_user_proc(to_fp, fpregs, sizeof(fpregs)));
--}
+-#endif
 -
 -/*
 - * Overrides for Emacs so that we follow Linus's tabbing style.
@@ -2611,1136 +2837,897 @@ Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c
 - * c-file-style: "linux"
 - * End:
 - */
-Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile
+Index: linux-2.6.10/arch/um/include/frame_user.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/Makefile    2004-12-25 05:35:27.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile 2005-04-05 19:01:49.158500672 +0800
-@@ -1,12 +0,0 @@
--# 
--# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
--# Licensed under the GPL
--#
+--- linux-2.6.10.orig/arch/um/include/frame_user.h     2004-12-25 05:33:50.000000000 +0800
++++ linux-2.6.10/arch/um/include/frame_user.h  2005-04-07 06:37:43.373923992 +0800
+@@ -1,23 +0,0 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
 -
--obj-y = sigcontext.o
+-#ifndef __FRAME_USER_H_
+-#define __FRAME_USER_H_
 -
--USER_OBJS = sigcontext.o
--USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+-#include "sysdep/frame_user.h"
+-#include "frame.h"
 -
--$(USER_OBJS) : %.o: %.c
--      $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-Index: linux-2.6.10/arch/um/kernel/skas/process.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/process.c    2004-12-25 05:35:39.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/process.c 2005-04-05 12:40:36.030910640 +0800
-@@ -11,6 +11,7 @@
- #include <sched.h>
- #include <sys/wait.h>
- #include <sys/ptrace.h>
-+#include <linux/ptrace.h>
- #include <sys/mman.h>
- #include <sys/user.h>
- #include <asm/unistd.h>
-@@ -60,15 +61,10 @@
- /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
- static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
- {
--      int err, syscall_nr, status;
+-#endif
 -
--      syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
--      UPT_SYSCALL_NR(regs) = syscall_nr;
--      if(syscall_nr < 0){
--              relay_signal(SIGTRAP, regs);
--              return;
--      }
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only.  This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/i386/kernel/ptrace.c
+===================================================================
+--- linux-2.6.10.orig/arch/i386/kernel/ptrace.c        2004-12-25 05:34:29.000000000 +0800
++++ linux-2.6.10/arch/i386/kernel/ptrace.c     2005-04-06 23:44:30.208030272 +0800
+@@ -15,6 +15,7 @@
+ #include <linux/user.h>
+ #include <linux/security.h>
+ #include <linux/audit.h>
++#include <linux/proc_mm.h>
  
-+      int err, status;
-+  
-+      UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); /* Mark this as a syscall */
-       if (!local_using_sysemu)
-       {
-               err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-@@ -82,7 +78,8 @@
-                             "errno = %d\n", errno);
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -406,15 +407,27 @@
+                 }
+                 break;
  
-               CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
--              if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-+              if((err < 0) || !WIFSTOPPED(status) ||
-+                              (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP)))
-                       panic("handle_trap - failed to wait at end of syscall, "
-                             "errno = %d, status = %d\n", errno, status);
-       }
-@@ -131,6 +128,10 @@
-               panic("start_userspace : expected SIGSTOP, got status = %d",
-                     status);
++      case PTRACE_SYSEMU: /* continue and stop at next syscall, which will not be executed */
+       case PTRACE_SYSCALL:    /* continue and stop at next (return from) syscall */
+       case PTRACE_CONT:       /* restart after signal. */
+               ret = -EIO;
+               if ((unsigned long) data > _NSIG)
+                       break;
++              /* If we came here with PTRACE_SYSEMU and now continue with
++               * PTRACE_SYSCALL, entry.S used to intercept the syscall return.
++               * But it shouldn't!
++               * So we don't clear TIF_SYSCALL_EMU, which is always unused in
++               * this special case, to remember, we came from SYSEMU. That
++               * flag will be cleared by do_syscall_trace().
++               */
++              if (request == PTRACE_SYSEMU) {
++                      set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
++              } else if (request == PTRACE_CONT) {
++                      clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
++              }
+               if (request == PTRACE_SYSCALL) {
+                       set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+-              }
+-              else {
++              } else {
+                       clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               }
+               child->exit_code = data;
+@@ -443,6 +456,8 @@
+               ret = -EIO;
+               if ((unsigned long) data > _NSIG)
+                       break;
++              /*See do_syscall_trace to know why we don't clear
++               * TIF_SYSCALL_EMU.*/
+               clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               set_singlestep(child);
+               child->exit_code = data;
+@@ -542,6 +557,58 @@
+                                       (struct user_desc __user *) data);
+               break;
  
-+      if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
-+              panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n",
-+                    errno);
++#ifdef CONFIG_PROC_MM
++      case PTRACE_FAULTINFO: {
++              struct ptrace_faultinfo fault;
 +
-       if(munmap(stack, PAGE_SIZE) < 0)
-               panic("start_userspace : munmap failed, errno = %d\n", errno);
-@@ -160,15 +161,19 @@
-               regs->skas.is_user = 1;
-               save_registers(regs);
-+              UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
-               if(WIFSTOPPED(status)){
-                       switch(WSTOPSIG(status)){
-                       case SIGSEGV:
-                               handle_segv(pid);
-                               break;
--                      case SIGTRAP:
-+                      case (SIGTRAP|SYSCALL_TRAP):
-                               handle_trap(pid, regs, local_using_sysemu);
-                               break;
-+                      case SIGTRAP:
-+                              relay_signal(SIGTRAP, regs);
-+                              break;
-                       case SIGIO:
-                       case SIGVTALRM:
-                       case SIGILL:
-@@ -222,9 +227,10 @@
-       block_signals();
-       if(sigsetjmp(fork_buf, 1) == 0)
-               new_thread_proc(stack, handler);
--      set_signals(flags);
-       remove_sigstack();
++              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;
++      }
 +
-+      set_signals(flags);
- }
- void thread_wait(void *sw, void *fb)
-Index: linux-2.6.10/arch/um/kernel/skas/process_kern.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/process_kern.c       2004-12-25 05:35:50.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/process_kern.c    2005-04-05 12:40:36.032910336 +0800
-@@ -19,7 +19,6 @@
- #include "os.h"
- #include "user_util.h"
- #include "tlb.h"
--#include "frame.h"
- #include "kern.h"
- #include "mode.h"
- #include "proc_mm.h"
-@@ -183,7 +182,6 @@
- int start_uml_skas(void)
++      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;
++      }
++
++      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);
++              task_lock(child);
++              child->mm = new;
++              child->active_mm = new;
++              task_unlock(child);
++              mmput(old);
++              ret = 0;
++              break;
++      }
++#endif
++
+       default:
+               ret = ptrace_request(child, request, addr, data);
+               break;
+@@ -557,8 +624,9 @@
+  * - triggered by current->work.syscall_trace
+  */
+ __attribute__((regparm(3)))
+-void do_syscall_trace(struct pt_regs *regs, int entryexit)
++int do_syscall_trace(struct pt_regs *regs, int entryexit)
  {
-       start_userspace(0);
--      capture_signal_stack();
-       init_new_thread_signals(1);
-       uml_idle_timer();
-Index: linux-2.6.10/arch/um/kernel/skas/syscall_kern.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/syscall_kern.c       2004-12-25 05:35:00.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/syscall_kern.c    2005-04-05 12:40:36.034910032 +0800
-@@ -6,6 +6,7 @@
- #include "linux/sys.h"
- #include "linux/ptrace.h"
- #include "asm/errno.h"
-+#include "linux/ptrace.h"
- #include "asm/unistd.h"
- #include "asm/ptrace.h"
- #include "asm/current.h"
-Index: linux-2.6.10/arch/um/kernel/skas/trap_user.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/trap_user.c  2004-12-25 05:34:32.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/trap_user.c       2005-04-05 12:40:36.033910184 +0800
-@@ -21,6 +21,14 @@
-       int save_errno = errno;
-       int save_user;
-+      /* This is done because to allow SIGSEGV to be delivered inside a SEGV
-+       * handler.  This can happen in copy_user, and if SEGV is disabled,
-+       * the process will die.
-+       * XXX Figure out why this is better than SA_NODEFER
-+       */
-+      if(sig == SIGSEGV)
-+              change_sig(SIGSEGV, 1);
++      int is_sysemu, is_systrace, is_singlestep;
+       if (unlikely(current->audit_context)) {
+               if (!entryexit)
+                       audit_syscall_entry(current, regs->orig_eax,
+@@ -567,16 +635,27 @@
+               else
+                       audit_syscall_exit(current, regs->eax);
+       }
+-
+-      if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
+-          !test_thread_flag(TIF_SINGLESTEP))
+-              return;
++      is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
++      is_systrace = test_thread_flag(TIF_SYSCALL_TRACE);
++      is_singlestep = test_thread_flag(TIF_SINGLESTEP);
 +
-       r = &TASK_REGS(get_current())->skas;
-       save_user = r->is_user;
-       r->is_user = 0;
-Index: linux-2.6.10/arch/um/kernel/skas/Makefile
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/skas/Makefile     2004-12-25 05:34:30.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/skas/Makefile  2005-04-05 12:40:36.034910032 +0800
-@@ -4,8 +4,7 @@
- #
- obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
--      syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
--      sys-$(SUBARCH)/
-+      syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o
- subdir-y := util
++      if (!is_systrace && !is_singlestep && !is_sysemu)
++              return 0;
++      /* We can detect the case of coming from PTRACE_SYSEMU and now running
++       * with PTRACE_SYSCALL or PTRACE_SINGLESTEP, by TIF_SYSCALL_EMU being
++       * set additionally.
++       * If so let's reset the flag and return without action.
++       */
++      if (is_sysemu && (is_systrace || is_singlestep)) {
++              clear_thread_flag(TIF_SYSCALL_EMU);
++              return 0;
++      }
+       if (!(current->ptrace & PT_PTRACED))
+-              return;
++              return 0;
+       /* the 0x80 provides a way for the tracing parent to distinguish
+          between a syscall stop and SIGTRAP delivery */
+       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
+-                               !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
++                               !is_singlestep ? 0x80 : 0));
  
-Index: linux-2.6.10/arch/um/kernel/helper.c
+       /*
+        * this isn't the same as continuing with a signal, but it will do
+@@ -587,4 +666,6 @@
+               send_sig(current->exit_code, current, 1);
+               current->exit_code = 0;
+       }
++      /* != 0 if nullifying the syscall, 0 if running it normally */
++      return is_sysemu;
+ }
+Index: linux-2.6.10/arch/i386/kernel/ldt.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/helper.c  2004-12-25 05:34:45.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/helper.c       2005-04-05 12:40:36.027911096 +0800
-@@ -49,14 +49,14 @@
-       return(0);
+--- linux-2.6.10.orig/arch/i386/kernel/ldt.c   2004-12-25 05:35:23.000000000 +0800
++++ linux-2.6.10/arch/i386/kernel/ldt.c        2005-04-06 23:44:30.220028448 +0800
+@@ -18,6 +18,7 @@
+ #include <asm/system.h>
+ #include <asm/ldt.h>
+ #include <asm/desc.h>
++#include <asm/mmu_context.h>
+ #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
+ static void flush_ldt(void *null)
+@@ -27,11 +28,12 @@
  }
+ #endif
  
--/* XXX The alloc_stack here breaks if this is called in the tracing thread */
--
-+/* Returns either the pid of the child process we run or -E* on failure.
-+ * XXX The alloc_stack here breaks if this is called in the tracing thread */
- int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
-              unsigned long *stack_out)
+-static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
++static int alloc_ldt(struct mm_struct *mm, int mincount, int reload)
  {
-       struct helper_data data;
-       unsigned long stack, sp;
--      int pid, fds[2], err, n;
-+      int pid, fds[2], ret, n;
-       if((stack_out != NULL) && (*stack_out != 0))
-               stack = *stack_out;
-@@ -64,16 +64,16 @@
-       if(stack == 0)
-               return(-ENOMEM);
+       void *oldldt;
+       void *newldt;
+       int oldsize;
++      mm_context_t * pc = &mm->context;
  
--      err = os_pipe(fds, 1, 0);
--      if(err < 0){
--              printk("run_helper : pipe failed, err = %d\n", -err);
-+      ret = os_pipe(fds, 1, 0);
-+      if(ret < 0){
-+              printk("run_helper : pipe failed, ret = %d\n", -ret);
-               goto out_free;
+       if (mincount <= pc->size)
+               return 0;
+@@ -58,13 +60,15 @@
+ #ifdef CONFIG_SMP
+               cpumask_t mask;
+               preempt_disable();
+-              load_LDT(pc);
++              if (&current->active_mm->context == pc)
++                      load_LDT(pc);
+               mask = cpumask_of_cpu(smp_processor_id());
+-              if (!cpus_equal(current->mm->cpu_vm_mask, mask))
++              if (!cpus_equal(mm->cpu_vm_mask, mask))
+                       smp_call_function(flush_ldt, NULL, 1, 1);
+               preempt_enable();
+ #else
+-              load_LDT(pc);
++              if (&current->active_mm->context == pc)
++                      load_LDT(pc);
+ #endif
        }
+       if (oldsize) {
+@@ -76,12 +80,12 @@
+       return 0;
+ }
  
--      err = os_set_exec_close(fds[1], 1);
--      if(err < 0){
--              printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
--                     -err);
-+      ret = os_set_exec_close(fds[1], 1);
-+      if(ret < 0){
-+              printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
-+                     -ret);
-               goto out_close;
-       }
+-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
++static inline int copy_ldt(struct mm_struct *new, struct mm_struct *old)
+ {
+-      int err = alloc_ldt(new, old->size, 0);
++      int err = alloc_ldt(new, old->context.size, 0);
+       if (err < 0)
+               return err;
+-      memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
++      memcpy(new->context.ldt, old->context.ldt, old->context.size*LDT_ENTRY_SIZE);
+       return 0;
+ }
  
-@@ -85,34 +85,36 @@
-       pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
-       if(pid < 0){
-               printk("run_helper : clone failed, errno = %d\n", errno);
--              err = -errno;
-+              ret = -errno;
-               goto out_close;
-       }
+@@ -89,22 +93,24 @@
+  * 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 copy_context(struct mm_struct *mm, struct mm_struct *old_mm)
+ {
+-      struct mm_struct * old_mm;
+       int retval = 0;
  
-       os_close_file(fds[1]);
--      n = os_read_file(fds[0], &err, sizeof(err));
-+      fds[1] = -1;
-+
-+      /*Read the errno value from the child.*/
-+      n = os_read_file(fds[0], &ret, sizeof(ret));
-       if(n < 0){
--              printk("run_helper : read on pipe failed, err = %d\n", -n);
--              err = n;
--              goto out_kill;
-+              printk("run_helper : read on pipe failed, ret = %d\n", -n);
-+              ret = n;
-+              os_kill_process(pid, 1);
-       }
-       else if(n != 0){
-               CATCH_EINTR(n = waitpid(pid, NULL, 0));
--              pid = -errno;
-+              ret = -errno;
-+      } else {
-+              ret = pid;
+-      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);
++              retval = copy_ldt(mm, old_mm);
+               up(&old_mm->context.sem);
        }
+       return retval;
+ }
  
--      if(stack_out == NULL) free_stack(stack, 0);
--        else *stack_out = stack;
--      return(pid);
--
-- out_kill:
--      os_kill_process(pid, 1);
-  out_close:
-+      if (fds[1] != -1)
-+              os_close_file(fds[1]);
-       os_close_file(fds[0]);
--      os_close_file(fds[1]);
-  out_free:
--      free_stack(stack, 0);
--      return(err);
-+      if(stack_out == NULL)
-+              free_stack(stack, 0);
-+        else *stack_out = stack;
-+      return(ret);
++int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++      init_new_empty_context(mm);
++      return copy_context(mm, current->mm);
++}
++
+ /*
+  * No need to lock the MM as we are the last user
+  */
+@@ -121,11 +127,11 @@
+       }
  }
  
- int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, 
-Index: linux-2.6.10/arch/um/kernel/time_kern.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/time_kern.c       2004-12-25 05:35:00.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/time_kern.c    2005-04-05 12:40:36.027911096 +0800
-@@ -170,7 +170,7 @@
- void timer_handler(int sig, union uml_pt_regs *regs)
+-static int read_ldt(void __user * ptr, unsigned long bytecount)
++static int read_ldt(struct mm_struct * mm, void __user * ptr,
++                  unsigned long bytecount)
  {
-       local_irq_disable();
--      update_process_times(user_context(UPT_SP(regs)));
-+      update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), (regs)->skas.is_user));
-       local_irq_enable();
-       if(current_thread->cpu == 0)
-               timer_irq(regs);
-Index: linux-2.6.10/arch/um/kernel/tt/include/mode-tt.h
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/include/mode-tt.h      2004-12-25 05:35:01.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/include/mode-tt.h   2005-04-05 12:40:36.042908816 +0800
-@@ -14,6 +14,41 @@
- extern int tracer(int (*init_proc)(void *), void *sp);
- extern void user_time_init_tt(void);
-+extern void sig_handler_common_tt(int sig, void *sc);
-+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
-+extern void reboot_tt(void);
-+extern void halt_tt(void);
-+extern int is_tracer_winch(int pid, int fd, void *data);
-+extern void kill_off_processes_tt(void);
-+
-+#endif
-+
-+/*
-+ * Overrides for Emacs so that we follow Linus's tabbing style.
-+ * Emacs will notice this stuff at the end of the file and automatically
-+ * adjust the settings for this buffer only.  This must remain at the end
-+ * of the file.
-+ * ---------------------------------------------------------------------------
-+ * Local variables:
-+ * c-file-style: "linux"
-+ * End:
-+ */
-+/*
-+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-+ * Licensed under the GPL
-+ */
-+
-+#ifndef __MODE_TT_H__
-+#define __MODE_TT_H__
-+
-+#include "sysdep/ptrace.h"
-+
-+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-+
-+extern int tracing_pid;
-+
-+extern int tracer(int (*init_proc)(void *), void *sp);
-+extern void user_time_init_tt(void);
- extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data);
- extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr,
-                             void *data);
-Index: linux-2.6.10/arch/um/kernel/tt/include/tt.h
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/include/tt.h   2004-12-25 05:34:58.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/include/tt.h        2005-04-05 12:40:36.043908664 +0800
-@@ -26,7 +26,8 @@
- extern int is_tracing(void *task);
- extern void syscall_handler(int sig, union uml_pt_regs *regs);
- extern void exit_kernel(int pid, void *task);
--extern int do_syscall(void *task, int pid, int local_using_sysemu);
-+extern void do_syscall(void *task, int pid, int local_using_sysemu);
-+extern void do_sigtrap(void *task);
- extern int is_valid_pid(int pid);
- extern void remap_data(void *segment_start, void *segment_end, int w);
+       int err;
+       unsigned long size;
+-      struct mm_struct * mm = current->mm;
  
-Index: linux-2.6.10/arch/um/kernel/tt/exec_user.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/exec_user.c    2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/exec_user.c 2005-04-05 12:40:36.039909272 +0800
-@@ -10,6 +10,7 @@
- #include <errno.h>
- #include <sys/wait.h>
- #include <sys/ptrace.h>
-+#include <linux/ptrace.h>
- #include <signal.h>
- #include "user_util.h"
- #include "kern_util.h"
-@@ -35,7 +36,10 @@
-               tracer_panic("do_exec failed to get registers - errno = %d",
-                            errno);
+       if (!mm->context.size)
+               return 0;
+@@ -174,9 +180,8 @@
+       return err;
+ }
  
--      kill(old_pid, SIGKILL);
-+      os_kill_ptraced_process(old_pid, 0);
-+
-+      if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
-+              tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno);
+-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;
+@@ -200,7 +205,7 @@
  
-       if(ptrace_setregs(new_pid, regs) < 0)
-               tracer_panic("do_exec failed to start new proc - errno = %d",
-Index: linux-2.6.10/arch/um/kernel/tt/sys-i386/sigcontext.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/sys-i386/sigcontext.c  2004-12-25 05:35:39.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/sys-i386/sigcontext.c       2005-04-05 19:01:49.158500672 +0800
-@@ -1,60 +0,0 @@
--/* 
-- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
-- * Licensed under the GPL
-- */
--
--#include <stdlib.h>
--#include <asm/sigcontext.h>
--#include "kern_util.h"
--#include "sysdep/frame.h"
--
--int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data)
--{
--      struct arch_frame_data *arch = data;
--      struct sigcontext *to = to_ptr, *from = from_ptr;
--      struct _fpstate *to_fp, *from_fp;
--      unsigned long sigs;
--      int err;
--
--      to_fp = to->fpstate;
--      from_fp = from->fpstate;
--      sigs = to->oldmask;
--      err = copy_from_user_proc(to, from, sizeof(*to));
--      to->oldmask = sigs;
--      if(to_fp != NULL){
--              err |= copy_from_user_proc(&to->fpstate, &to_fp,
--                                         sizeof(to->fpstate));
--              err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size);
--      }
--      return(err);
--}
--
--int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, void *data)
--{
--      struct arch_frame_data *arch = data;
--      struct sigcontext *to = to_ptr, *from = from_ptr;
--      struct _fpstate *to_fp, *from_fp;
--      int err;
--
--      to_fp = (struct _fpstate *) 
--              (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
--      from_fp = from->fpstate;
--      err = copy_to_user_proc(to, from, sizeof(*to));
--      if(from_fp != NULL){
--              err |= copy_to_user_proc(&to->fpstate, &to_fp,
--                                       sizeof(to->fpstate));
--              err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size);
--      }
--      return(err);
--}
--
--/*
-- * Overrides for Emacs so that we follow Linus's tabbing style.
-- * Emacs will notice this stuff at the end of the file and automatically
-- * adjust the settings for this buffer only.  This must remain at the end
-- * of the file.
-- * ---------------------------------------------------------------------------
-- * Local variables:
-- * c-file-style: "linux"
-- * End:
-- */
-Index: linux-2.6.10/arch/um/kernel/tt/sys-i386/Makefile
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/sys-i386/Makefile      2004-12-25 05:34:32.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/sys-i386/Makefile   2005-04-05 19:01:49.158500672 +0800
-@@ -1,12 +0,0 @@
--# 
--# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
--# Licensed under the GPL
--#
--
--obj-y = sigcontext.o
--
--USER_OBJS = sigcontext.o
--USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
--
--$(USER_OBJS) : %.o: %.c
--      $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-Index: linux-2.6.10/arch/um/kernel/tt/syscall_user.c
-===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/syscall_user.c 2004-12-25 05:35:01.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/syscall_user.c      2005-04-05 12:40:36.037909576 +0800
-@@ -42,37 +42,31 @@
-       syscall_trace(regs, 1);
-       record_syscall_end(index, result);
- }
--
--int do_syscall(void *task, int pid, int local_using_sysemu)
--{
--      unsigned long proc_regs[FRAME_SIZE];
--      union uml_pt_regs *regs;
--      int syscall;
--
--      if(ptrace_getregs(pid, proc_regs) < 0)
--              tracer_panic("Couldn't read registers");
--      syscall = PT_SYSCALL_NR(proc_regs);
--
--      regs = TASK_REGS(task);
--      UPT_SYSCALL_NR(regs) = syscall;
--
--      if(syscall < 0)
--              return(0);
--
--      if((syscall != __NR_sigreturn) &&
--         ((unsigned long *) PT_IP(proc_regs) >= &_stext) && 
--         ((unsigned long *) PT_IP(proc_regs) <= &_etext))
--              tracer_panic("I'm tracing myself and I can't get out");
--
--      if(local_using_sysemu)
--              return(1);
--
--      if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 
--                __NR_getpid) < 0)
--              tracer_panic("do_syscall : Nullifying syscall failed, "
--                           "errno = %d", errno);
--      return(1);
--}
-+  
-+ void do_sigtrap(void *task)
-+ {
-+      UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
-+ }
-+ 
-+ void do_syscall(void *task, int pid, int local_using_sysemu)
-+  {
-+      unsigned long proc_regs[FRAME_SIZE];
-+  
-+      if(ptrace_getregs(pid, proc_regs) < 0)
-+              tracer_panic("Couldn't read registers");
-+  
-+      UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
-+  
-+      if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
-+         ((unsigned long *) PT_IP(proc_regs) <= &_etext))
-+              tracer_panic("I'm tracing myself and I can't get out");
-+  
-+      /* syscall number -1 in sysemu skips syscall restarting in host */
-+      if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 
-+                local_using_sysemu ? -1 : __NR_getpid) < 0)
-+              tracer_panic("do_syscall : Nullifying syscall failed, "
-+                           "errno = %d", errno);
-+  }
+       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, ldt_info.entry_number+1, 1);
+               if (error < 0)
+                       goto out_unlock;
+       }
+@@ -233,23 +238,29 @@
+       return error;
+ }
  
- /*
-  * Overrides for Emacs so that we follow Linus's tabbing style.
-Index: linux-2.6.10/arch/um/kernel/tt/tracer.c
+-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);
++}
+Index: linux-2.6.10/arch/i386/kernel/sys_i386.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/tracer.c       2005-04-01 01:16:47.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/tracer.c    2005-04-05 12:40:36.041908968 +0800
-@@ -13,6 +13,7 @@
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/ptrace.h>
-+#include <linux/ptrace.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include "user.h"
-@@ -25,7 +26,6 @@
- #include "mem_user.h"
- #include "process.h"
- #include "kern_util.h"
--#include "frame.h"
- #include "chan_user.h"
- #include "ptrace_user.h"
- #include "mode.h"
-@@ -72,6 +72,8 @@
-          (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
-               tracer_panic("OP_FORK failed to attach pid");
-       wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
-+      if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
-+              tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
-       if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
-               tracer_panic("OP_FORK failed to continue process");
+--- linux-2.6.10.orig/arch/i386/kernel/sys_i386.c      2004-12-25 05:35:39.000000000 +0800
++++ linux-2.6.10/arch/i386/kernel/sys_i386.c   2005-04-06 23:44:30.220028448 +0800
+@@ -41,7 +41,7 @@
  }
-@@ -141,7 +143,7 @@
-        * any more, the trace of those will land here.  So, we need to just 
-        * PTRACE_SYSCALL it.
-        */
--      case SIGTRAP:
-+      case (SIGTRAP|SYSCALL_TRAP):
-               if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
-                       tracer_panic("sleeping_process_signal : Failed to "
-                                    "PTRACE_SYSCALL pid %d, errno = %d\n",
-@@ -184,9 +186,8 @@
-       unsigned long eip = 0;
-       int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
-       int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
--      int pt_syscall_parm, local_using_sysemu;
-+      int pt_syscall_parm, local_using_sysemu = 0;
  
--      capture_signal_stack();
-       signal(SIGPIPE, SIG_IGN);
-       setup_tracer_winch();
-       tracing_pid = os_getpid();
-@@ -198,6 +199,10 @@
-               printf("waitpid on idle thread failed, errno = %d\n", errno);
-               exit(1);
+ /* 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)
+@@ -56,9 +56,9 @@
+                       goto out;
        }
-+      if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
-+              printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
-+              exit(1);
-+      }
-       if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
-               printf("Failed to continue idle thread, errno = %d\n", errno);
-               exit(1);
-@@ -315,7 +320,8 @@
-                       task = cpu_tasks[proc_id].task;
-                       tracing = is_tracing(task);
-                       old_tracing = tracing;
--
-+                      if ( tracing ) /* Assume: no syscall, when coming from user */
-+                              do_sigtrap(task);
-                       local_using_sysemu = get_using_sysemu();
-                       pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
  
-@@ -324,6 +330,15 @@
-                               sig = 0;
-                               op = do_proc_op(task, proc_id);
-                               switch(op){
-+                              /*
-+                               * This is called when entering user mode; after
-+                               * this, we start intercepting syscalls.
-+                               *
-+                               * In fact, a process is started in kernel mode,
-+                               * so with is_tracing() == 0 (and that is reset
-+                               * when executing syscalls, since UML kernel has
-+                               * the right to do syscalls);
-+                               */
-                               case OP_TRACE_ON:
-                                       arch_leave_kernel(task, pid);
-                                       tracing = 1;
-@@ -332,7 +347,13 @@
-                               case OP_HALT:
-                                       unmap_physmem();
-                                       kmalloc_ok = 0;
--                                      ptrace(PTRACE_KILL, pid, 0, 0);
-+                                      os_kill_ptraced_process(pid, 0);
-+                                      /* Now let's reap remaining zombies */
-+                                      errno = 0;
-+                                      do {
-+                                              waitpid(-1, &status,
-+                                                      WUNTRACED);
-+                                      } while (errno != ECHILD);
-                                       return(op == OP_REBOOT);
-                               case OP_NONE:
-                                       printf("Detaching pid %d\n", pid);
-@@ -346,14 +367,26 @@
-                                */
-                               pid = cpu_tasks[proc_id].pid;
-                               break;
-+                      case (SIGTRAP|SYSCALL_TRAP):
-+                              if(!tracing && (debugger_pid != -1)){
-+                                      child_signal(pid, W_STOPCODE(SIGTRAP));
-+                                      continue;
-+                              }
-+                              tracing = 0;
-+                              /* local_using_sysemu has been already set
-+                               * below, since if we are here, is_tracing() on
-+                               * the traced task was 1, i.e. the process had
-+                               * already run through one iteration of the
-+                               * loop which executed a OP_TRACE_ON request.*/
-+                              do_syscall(task, pid, local_using_sysemu);
-+                              sig = SIGUSR2;
-+                              break;
-                       case SIGTRAP:
-                               if(!tracing && (debugger_pid != -1)){
-                                       child_signal(pid, status);
-                                       continue;
-                               }
-                               tracing = 0;
--                              if(do_syscall(task, pid, local_using_sysemu))
--                                      sig = SIGUSR2;
-                               break;
-                       case SIGPROF:
-                               if(tracing) sig = 0;
-@@ -389,6 +422,9 @@
-                               continue;
-                       }
+-      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);
  
-+                      local_using_sysemu = get_using_sysemu();
-+                      pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
-+ 
-                       if(tracing){
-                               if(singlestepping(task))
-                                       cont_type = PTRACE_SINGLESTEP;
-Index: linux-2.6.10/arch/um/kernel/tt/Makefile
+       if (file)
+               fput(file);
+@@ -70,7 +70,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);
+ }
+ /*
+@@ -101,7 +101,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;
+ }
+Index: linux-2.6.10/arch/i386/kernel/entry.S
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/tt/Makefile       2004-12-25 05:34:57.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/tt/Makefile    2005-04-05 12:40:36.041908968 +0800
-@@ -8,7 +8,7 @@
+--- linux-2.6.10.orig/arch/i386/kernel/entry.S 2005-04-06 23:38:35.000000000 +0800
++++ linux-2.6.10/arch/i386/kernel/entry.S      2005-04-06 23:44:30.206030576 +0800
+@@ -222,7 +222,7 @@
+       SAVE_ALL
+       GET_THREAD_INFO(%ebp)
+-      testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++      testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       jnz syscall_trace_entry
+       cmpl $(nr_syscalls), %eax
+       jae syscall_badsys
+@@ -245,8 +245,8 @@
+       pushl %eax                      # save orig_eax
+       SAVE_ALL
+       GET_THREAD_INFO(%ebp)
+-                                      # system call tracing in operation
+-      testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
++                                      # system call tracing in operation / emulation
++      testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+       jnz syscall_trace_entry
+       cmpl $(nr_syscalls), %eax
+       jae syscall_badsys
+@@ -307,6 +307,9 @@
+       movl %esp, %eax
+       xorl %edx,%edx
+       call do_syscall_trace
++      cmpl $0, %eax
++      jne syscall_exit                # ret != 0 -> running under PTRACE_SYSEMU,
++                                      # so must skip actual syscall
+       movl ORIG_EAX(%esp), %eax
+       cmpl $(nr_syscalls), %eax
+       jnae syscall_call
+Index: linux-2.6.10/arch/i386/Kconfig
+===================================================================
+--- linux-2.6.10.orig/arch/i386/Kconfig        2005-04-06 23:38:33.000000000 +0800
++++ linux-2.6.10/arch/i386/Kconfig     2005-04-06 23:44:30.222028144 +0800
+@@ -738,6 +738,10 @@
+       depends on HIGHMEM64G
+       default y
++config PROC_MM
++      bool "/proc/mm support"
++      default y
++
+ # Common NUMA Features
+ config NUMA
+       bool "Numa Memory Allocation and Scheduler Support"
+Index: linux-2.6.10/fs/hostfs/hostfs.h
+===================================================================
+--- linux-2.6.10.orig/fs/hostfs/hostfs.h       2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/fs/hostfs/hostfs.h    2005-04-06 23:44:30.286018416 +0800
+@@ -16,9 +16,30 @@
+ #define HOSTFS_ATTR_CTIME     64
+ #define HOSTFS_ATTR_ATIME_SET 128
+ #define HOSTFS_ATTR_MTIME_SET 256
++
++/* These two are unused by hostfs. */
+ #define HOSTFS_ATTR_FORCE     512     /* Not a change, but a change it */
+ #define HOSTFS_ATTR_ATTR_FLAG 1024
  
- obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
-       syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
--      uaccess.o uaccess_user.o sys-$(SUBARCH)/
-+      uaccess.o uaccess_user.o 
++/* If you are very careful, you'll notice that these two are missing:
++ *
++ * #define ATTR_KILL_SUID     2048
++ * #define ATTR_KILL_SGID     4096
++ *
++ * and this is because they were added in 2.5 development in this patch:
++ *
++ * http://linux.bkbits.net:8080/linux-2.5/
++ * cset@3caf4a12k4XgDzK7wyK-TGpSZ9u2Ww?nav=index.html
++ * |src/.|src/include|src/include/linux|related/include/linux/fs.h
++ *
++ * Actually, they are not needed by most ->setattr() methods - they are set by
++ * callers of notify_change() to notify that the setuid/setgid bits must be
++ * dropped.
++ * notify_change() will delete those flags, make sure attr->ia_valid & ATTR_MODE
++ * is on, and remove the appropriate bits from attr->ia_mode (attr is a
++ * "struct iattr *"). -BlaisorBlade
++ */
++
+ struct hostfs_iattr {
+       unsigned int    ia_valid;
+       mode_t          ia_mode;
+Index: linux-2.6.10/fs/hostfs/hostfs_kern.c
+===================================================================
+--- linux-2.6.10.orig/fs/hostfs/hostfs_kern.c  2004-12-25 05:34:01.000000000 +0800
++++ linux-2.6.10/fs/hostfs/hostfs_kern.c       2005-04-06 23:44:30.287018264 +0800
+@@ -393,6 +393,7 @@
+ static struct file_operations hostfs_file_fops = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_file_read,
++      .sendfile       = generic_file_sendfile,
+       .write          = generic_file_write,
+       .mmap           = generic_file_mmap,
+       .open           = hostfs_file_open,
+@@ -818,6 +819,10 @@
+       char *name;
+       int err;
  
- obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
++      err = inode_change_ok(dentry->d_inode, attr);
++      if (err)
++              return err;
++
+       if(append)
+               attr->ia_valid &= ~ATTR_SIZE;
  
-Index: linux-2.6.10/arch/um/kernel/trap_user.c
+Index: linux-2.6.10/kernel/fork.c
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/trap_user.c       2004-12-25 05:34:44.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/trap_user.c    2005-04-05 12:40:36.047908056 +0800
-@@ -18,7 +18,6 @@
- #include "sigcontext.h"
- #include "sysdep/sigcontext.h"
- #include "irq_user.h"
--#include "frame_user.h"
- #include "signal_user.h"
- #include "time_user.h"
- #include "task.h"
-Index: linux-2.6.10/arch/um/kernel/Makefile
+--- linux-2.6.10.orig/kernel/fork.c    2005-04-06 23:38:35.000000000 +0800
++++ linux-2.6.10/kernel/fork.c 2005-04-06 23:44:30.191032856 +0800
+@@ -927,6 +927,9 @@
+        * of CLONE_PTRACE.
+        */
+       clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
++#ifdef TIF_SYSCALL_EMU
++      clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
++#endif
+       /* Our parent execution domain becomes current domain
+          These must match for thread signalling to apply */
+Index: linux-2.6.10/include/linux/ptrace.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/Makefile  2004-12-25 05:35:01.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/Makefile       2005-04-05 12:40:36.051907448 +0800
-@@ -6,7 +6,7 @@
- extra-y := vmlinux.lds
- clean-files := vmlinux.lds.S
+--- linux-2.6.10.orig/include/linux/ptrace.h   2005-04-06 23:38:33.000000000 +0800
++++ linux-2.6.10/include/linux/ptrace.h        2005-04-06 23:44:30.187033464 +0800
+@@ -20,6 +20,7 @@
+ #define PTRACE_DETACH         0x11
  
--obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
-+obj-y = checksum.o config.o exec_kern.o exitcode.o \
-       helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
-       physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
-       sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
-Index: linux-2.6.10/arch/um/kernel/mem.c
+ #define PTRACE_SYSCALL                  24
++#define PTRACE_SYSEMU           31
+ /* 0x4200-0x4300 are reserved for architecture-independent additions.  */
+ #define PTRACE_SETOPTIONS     0x4200
+Index: linux-2.6.10/include/linux/mm.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/kernel/mem.c     2004-12-25 05:34:32.000000000 +0800
-+++ linux-2.6.10/arch/um/kernel/mem.c  2005-04-05 12:40:36.029910792 +0800
-@@ -175,6 +175,30 @@
- }
- #endif /* CONFIG_HIGHMEM */
+--- linux-2.6.10.orig/include/linux/mm.h       2005-04-06 23:38:33.000000000 +0800
++++ linux-2.6.10/include/linux/mm.h    2005-04-06 23:44:30.188033312 +0800
+@@ -625,6 +625,9 @@
+ extern struct shrinker *set_shrinker(int, shrinker_t);
+ extern void remove_shrinker(struct shrinker *shrinker);
  
-+static void __init fixaddr_user_init( void)
-+{
-+      long size = FIXADDR_USER_END - FIXADDR_USER_START;
-+      pgd_t *pgd;
-+      pmd_t *pmd;
-+      pte_t *pte;
-+      unsigned long paddr, vaddr = FIXADDR_USER_START;
-+
-+      if (  ! size )
-+              return;
-+
-+      fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
-+      paddr = (unsigned long)alloc_bootmem_low_pages( size);
-+      memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
-+      paddr = __pa(paddr);
-+      for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE) {
-+              pgd = swapper_pg_dir + pgd_index(vaddr);
-+              pmd = pmd_offset(pgd, vaddr);
-+              pte = pte_offset_kernel(pmd, vaddr);
-+              /*pte_set_val( (*pte), paddr, PAGE_READONLY);*/
-+              pte_val(*pte) = paddr | pgprot_val(PAGE_READONLY);
-+      }
-+}
++extern long do_mprotect(struct mm_struct *mm, unsigned long start,
++                      size_t len, unsigned long prot);
 +
- void paging_init(void)
- {
-       unsigned long zones_size[MAX_NR_ZONES], vaddr;
-@@ -195,6 +219,8 @@
-       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
+ /*
+  * On a two-level page table, this ends up being trivial. Thus the
+  * inlining and the symmetry break with pte_alloc_map() that does all
+@@ -684,9 +687,15 @@
  
-+      fixaddr_user_init();
-+
- #ifdef CONFIG_HIGHMEM
-       init_highmem();
- #endif
-Index: linux-2.6.10/arch/um/os-Linux/user_syms.c
-===================================================================
---- linux-2.6.10.orig/arch/um/os-Linux/user_syms.c     2004-12-25 05:35:23.000000000 +0800
-+++ linux-2.6.10/arch/um/os-Linux/user_syms.c  2005-04-05 12:40:36.019912312 +0800
-@@ -26,6 +26,9 @@
+ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  
- EXPORT_SYMBOL(strstr);
+-extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
++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);
++      unsigned long flag, unsigned long pgoff) {
++      return __do_mmap_pgoff(current->mm, file, addr, len, prot, flag, pgoff);
++}
  
-+EXPORT_SYMBOL(vsyscall_ehdr);
-+EXPORT_SYMBOL(vsyscall_end);
-+
- /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
-  * However, the modules will use the CRC defined *here*, no matter if it is
-  * good; so the versions of these symbols will always match
-Index: linux-2.6.10/arch/um/os-Linux/elf_aux.c
+ static inline unsigned long do_mmap(struct file *file, unsigned long addr,
+       unsigned long len, unsigned long prot,
+Index: linux-2.6.10/include/linux/proc_mm.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/os-Linux/elf_aux.c       2005-04-05 19:01:49.158500672 +0800
-+++ linux-2.6.10/arch/um/os-Linux/elf_aux.c    2005-04-05 12:40:36.018912464 +0800
-@@ -0,0 +1,67 @@
+--- linux-2.6.10.orig/include/linux/proc_mm.h  2005-04-07 06:37:43.373923992 +0800
++++ linux-2.6.10/include/linux/proc_mm.h       2005-04-06 23:44:30.189033160 +0800
+@@ -0,0 +1,48 @@
 +/*
-+ *  arch/um/kernel/elf_aux.c
-+ *
-+ *  Scan the Elf auxiliary vector provided by the host to extract
-+ *  information about vsyscall-page, etc.
-+ *
-+ *  Copyright (C) 2004 Fujitsu Siemens Computers GmbH
-+ *  Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com)
++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
 + */
-+#include <elf.h>
-+#include <stddef.h>
-+#include "init.h"
-+#include "elf_user.h"
-+
-+#if ELF_CLASS == ELFCLASS32
-+typedef Elf32_auxv_t elf_auxv_t;
-+#else
-+typedef Elf64_auxv_t elf_auxv_t;
-+#endif
-+
-+char * elf_aux_platform;
-+long elf_aux_hwcap;
 +
-+unsigned long vsyscall_ehdr;
-+unsigned long vsyscall_end;
++#ifndef __PROC_MM_H
++#define __PROC_MM_H
 +
-+unsigned long __kernel_vsyscall;
++#include "linux/sched.h"
 +
++#define MM_MMAP 54
++#define MM_MUNMAP 55
++#define MM_MPROTECT 56
++#define MM_COPY_SEGMENTS 57
 +
-+__init void scan_elf_aux( char **envp)
-+{
-+      long page_size = 0;
-+      elf_auxv_t * auxv;
++struct mm_mmap {
++      unsigned long addr;
++      unsigned long len;
++      unsigned long prot;
++      unsigned long flags;
++      unsigned long fd;
++      unsigned long offset;
++};
 +
-+      while ( *envp++ != NULL) ;
++struct mm_munmap {
++      unsigned long addr;
++      unsigned long len;
++};
 +
-+      for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
-+              switch ( auxv->a_type ) {
-+                      case AT_SYSINFO:
-+                              __kernel_vsyscall = auxv->a_un.a_val;
-+                              break;
-+                      case AT_SYSINFO_EHDR:
-+                              vsyscall_ehdr = auxv->a_un.a_val;
-+                              break;
-+                      case AT_HWCAP:
-+                              elf_aux_hwcap = auxv->a_un.a_val;
-+                              break;
-+                      case AT_PLATFORM:
-+                              elf_aux_platform = auxv->a_un.a_ptr;
-+                              break;
-+                      case AT_PAGESZ:
-+                              page_size = auxv->a_un.a_val;
-+                              break;
-+              }
-+      }
-+      if ( ! __kernel_vsyscall || ! vsyscall_ehdr ||
-+           ! elf_aux_hwcap || ! elf_aux_platform ||
-+           ! page_size || (vsyscall_ehdr % page_size) ) {
-+              __kernel_vsyscall = 0;
-+              vsyscall_ehdr = 0;
-+              elf_aux_hwcap = 0;
-+              elf_aux_platform = "i586";
-+      }
-+      else {
-+              vsyscall_end = vsyscall_ehdr + page_size;
-+      }
-+}
-Index: linux-2.6.10/arch/um/os-Linux/Makefile
++struct mm_mprotect {
++      unsigned long addr;
++      unsigned long len;
++        unsigned int prot;
++};
++
++struct proc_mm_op {
++      int op;
++      union {
++              struct mm_mmap mmap;
++              struct mm_munmap munmap;
++              struct mm_mprotect mprotect;
++              int copy_segments;
++      } u;
++};
++
++extern struct mm_struct *proc_mm_get_mm(int fd);
++
++#endif
+Index: linux-2.6.10/include/asm-um/elf.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/os-Linux/Makefile        2004-12-25 05:35:00.000000000 +0800
-+++ linux-2.6.10/arch/um/os-Linux/Makefile     2005-04-05 12:40:36.019912312 +0800
-@@ -3,9 +3,9 @@
- # Licensed under the GPL
- #
+--- linux-2.6.10.orig/include/asm-um/elf.h     2004-12-25 05:35:01.000000000 +0800
++++ linux-2.6.10/include/asm-um/elf.h  2005-04-06 23:44:30.183034072 +0800
+@@ -3,7 +3,8 @@
  
--obj-y = file.o process.o time.o tty.o user_syms.o drivers/
-+obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/
+ #include "asm/archparam.h"
  
--USER_OBJS := $(foreach file,file.o process.o time.o tty.o,$(obj)/$(file))
-+USER_OBJS := $(foreach file,elf_aux.o file.o process.o time.o tty.o,$(obj)/$(file))
+-#define ELF_HWCAP (0)
++extern long elf_aux_hwcap;
++#define ELF_HWCAP (elf_aux_hwcap)
  
- $(USER_OBJS) : %.o: %.c
-       $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-Index: linux-2.6.10/arch/um/drivers/net_kern.c
+ #define SET_PERSONALITY(ex, ibcs2) do ; while(0)
+Index: linux-2.6.10/include/asm-um/archparam-i386.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/drivers/net_kern.c       2004-12-25 05:34:44.000000000 +0800
-+++ linux-2.6.10/arch/um/drivers/net_kern.c    2005-04-05 12:40:36.016912768 +0800
-@@ -126,10 +126,6 @@
-       lp->tl.data = (unsigned long) &lp->user;
-       netif_start_queue(dev);
+--- linux-2.6.10.orig/include/asm-um/archparam-i386.h  2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/include/asm-um/archparam-i386.h       2005-04-06 23:44:30.183034072 +0800
+@@ -10,7 +10,8 @@
  
--      spin_lock(&opened_lock);
--      list_add(&lp->list, &opened);
--      spin_unlock(&opened_lock);
--
-       /* clear buffer - it can happen that the host side of the interface
-        * is full when we get here.  In this case, new data is never queued,
-        * SIGIOs never arrive, and the net never works.
-@@ -152,9 +148,6 @@
-       free_irq(dev->irq, dev);
-       if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
-       lp->fd = -1;
--      spin_lock(&opened_lock);
--      list_del(&lp->list);
--      spin_unlock(&opened_lock);
+ #include "user.h"
  
-       spin_unlock(&lp->lock);
-       return 0;
-@@ -397,6 +390,11 @@
+-#define ELF_PLATFORM "i586"
++extern char * elf_aux_platform;
++#define ELF_PLATFORM (elf_aux_platform)
  
-       if (device->have_mac)
-               set_ether_mac(dev, device->mac);
-+
-+      spin_lock(&opened_lock);
-+      list_add(&lp->list, &opened);
-+      spin_unlock(&opened_lock);
-+
-       return(0);
- }
+ #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
  
-@@ -705,7 +703,7 @@
- static void close_devices(void)
- {
-       struct list_head *ele;
--      struct uml_net_private *lp;     
-+      struct uml_net_private *lp;
+@@ -56,15 +57,13 @@
+       pr_reg[16] = PT_REGS_SS(regs);          \
+ } while(0);
  
-       list_for_each(ele, &opened){
-               lp = list_entry(ele, struct uml_net_private, list);
-Index: linux-2.6.10/arch/um/drivers/mconsole_kern.c
-===================================================================
---- linux-2.6.10.orig/arch/um/drivers/mconsole_kern.c  2004-12-25 05:33:49.000000000 +0800
-+++ linux-2.6.10/arch/um/drivers/mconsole_kern.c       2005-04-05 12:40:36.015912920 +0800
-@@ -204,6 +204,68 @@
- }
- #endif
+-#if 0 /* Turn this back on when UML has VSYSCALL working */
+-#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
+-#else
+-#define VSYSCALL_BASE 0
+-#endif
  
-+/* This is a more convoluted version of mconsole_proc, which has some stability
-+ * problems; however, we need it fixed, because it is expected that UML users
-+ * mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still
-+ * show the real procfs content, not the ones from hppfs.*/
-+#if 0
-+void mconsole_proc(struct mc_request *req)
-+{
-+      char path[64];
-+      char *buf;
-+      int len;
-+      int fd;
-+      int first_chunk = 1;
-+      char *ptr = req->request.data;
-+
-+      ptr += strlen("proc");
-+      while(isspace(*ptr)) ptr++;
-+      snprintf(path, sizeof(path), "/proc/%s", ptr);
-+
-+      fd = sys_open(path, 0, 0);
-+      if (fd < 0) {
-+              mconsole_reply(req, "Failed to open file", 1, 0);
-+              printk("open %s: %d\n",path,fd);
-+              goto out;
-+      }
-+
-+      buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-+      if(buf == NULL){
-+              mconsole_reply(req, "Failed to allocate buffer", 1, 0);
-+              goto out_close;
-+      }
-+
-+      for (;;) {
-+              len = sys_read(fd, buf, PAGE_SIZE-1);
-+              if (len < 0) {
-+                      mconsole_reply(req, "Read of file failed", 1, 0);
-+                      goto out_free;
-+              }
-+              /*Begin the file content on his own line.*/
-+              if (first_chunk) {
-+                      mconsole_reply(req, "\n", 0, 1);
-+                      first_chunk = 0;
-+              }
-+              if (len == PAGE_SIZE-1) {
-+                      buf[len] = '\0';
-+                      mconsole_reply(req, buf, 0, 1);
-+              } else {
-+                      buf[len] = '\0';
-+                      mconsole_reply(req, buf, 0, 0);
-+                      break;
-+              }
-+      }
-+      /*END*/
+-#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
+-#define VSYSCALL_ENTRY        ((unsigned long) &__kernel_vsyscall)
+-extern void *__kernel_vsyscall;
++extern unsigned long vsyscall_ehdr;
++extern unsigned long vsyscall_end;
++extern unsigned long __kernel_vsyscall;
 +
-+ out_free:
-+      kfree(buf);
-+ out_close:
-+      sys_close(fd);
-+ out:
-+      /* nothing */;
++#define VSYSCALL_BASE vsyscall_ehdr
++#define VSYSCALL_END vsyscall_end
+ /*
+  * Architecture-neutral AT_ values in 0-17, leave some room
+@@ -75,8 +74,10 @@
+ #define ARCH_DLINFO                                           \
+ do {                                                          \
+-              NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY);        \
+-              NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);    \
++      if ( vsyscall_ehdr ) {                                  \
++              NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall);     \
++              NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr);    \
++      }                                                       \
+ } while (0)
+ /*
+@@ -87,22 +88,18 @@
+  * Dumping its extra ELF program headers includes all the other information
+  * a debugger needs to easily find how the vsyscall DSO was being used.
+  */
+-#if 0
+-#define ELF_CORE_EXTRA_PHDRS          (VSYSCALL_EHDR->e_phnum)
+-#endif
+-
+-#undef ELF_CORE_EXTRA_PHDRS
++#define ELF_CORE_EXTRA_PHDRS                                                \
++      (vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
+-#if 0
+ #define ELF_CORE_WRITE_EXTRA_PHDRS                                          \
+-do {                                                                        \
+-      const struct elf_phdr *const vsyscall_phdrs =                         \
+-              (const struct elf_phdr *) (VSYSCALL_BASE                      \
+-                                         + VSYSCALL_EHDR->e_phoff);         \
++if ( vsyscall_ehdr ) {                                                              \
++      const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
++      const struct elf_phdr *const phdrp =                                  \
++              (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
+       int i;                                                                \
+       Elf32_Off ofs = 0;                                                    \
+-      for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {                        \
+-              struct elf_phdr phdr = vsyscall_phdrs[i];                     \
++      for (i = 0; i < ehdrp->e_phnum; ++i) {                                \
++              struct elf_phdr phdr = phdrp[i];                              \
+               if (phdr.p_type == PT_LOAD) {                                 \
+                       ofs = phdr.p_offset = offset;                         \
+                       offset += phdr.p_filesz;                              \
+@@ -112,23 +109,19 @@
+               phdr.p_paddr = 0; /* match other core phdrs */                \
+               DUMP_WRITE(&phdr, sizeof(phdr));                              \
+       }                                                                     \
+-} while (0)
 +}
-+#endif
-+
- void mconsole_proc(struct mc_request *req)
- {
-       char path[64];
-Index: linux-2.6.10/arch/um/drivers/net_user.c
+ #define ELF_CORE_WRITE_EXTRA_DATA                                           \
+-do {                                                                        \
+-      const struct elf_phdr *const vsyscall_phdrs =                         \
+-              (const struct elf_phdr *) (VSYSCALL_BASE                      \
+-                                         + VSYSCALL_EHDR->e_phoff);         \
++if ( vsyscall_ehdr ) {                                                              \
++      const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
++      const struct elf_phdr *const phdrp =                                  \
++              (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
+       int i;                                                                \
+-      for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {                        \
+-              if (vsyscall_phdrs[i].p_type == PT_LOAD)                      \
+-                      DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,        \
+-                                 vsyscall_phdrs[i].p_filesz);               \
++      for (i = 0; i < ehdrp->e_phnum; ++i) {                                \
++              if (phdrp[i].p_type == PT_LOAD)                               \
++                      DUMP_WRITE((void *) phdrp[i].p_vaddr,                 \
++                                 phdrp[i].p_filesz);                        \
+       }                                                                     \
+-} while (0)
+-#endif
+-
+-#undef ELF_CORE_WRITE_EXTRA_PHDRS
+-#undef ELF_CORE_WRITE_EXTRA_DATA
++}
+ #define R_386_NONE    0
+ #define R_386_32      1
+Index: linux-2.6.10/include/asm-um/fixmap.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/drivers/net_user.c       2004-12-25 05:34:26.000000000 +0800
-+++ linux-2.6.10/arch/um/drivers/net_user.c    2005-04-05 12:40:36.017912616 +0800
-@@ -173,10 +173,12 @@
-       pe_data.stdout = fds[1];
-       pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
+--- linux-2.6.10.orig/include/asm-um/fixmap.h  2004-12-25 05:35:28.000000000 +0800
++++ linux-2.6.10/include/asm-um/fixmap.h       2005-04-06 23:44:30.184033920 +0800
+@@ -3,6 +3,7 @@
+ #include <linux/config.h>
+ #include <asm/kmap_types.h>
++#include <asm/archparam.h>
  
--      os_close_file(fds[1]);
-       read_output(fds[0], output, output_len);
-+      os_close_file(fds[0]);
-+      os_close_file(fds[1]);
+ /*
+  * Here we define all the compile-time 'special' virtual
+@@ -34,7 +35,6 @@
+       FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
+       FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ #endif
+-      FIX_VSYSCALL,
+       __end_of_fixed_addresses
+ };
  
--      CATCH_EINTR(err = waitpid(pid, NULL, 0));
-+      if (pid > 0)
-+              CATCH_EINTR(err = waitpid(pid, NULL, 0));
-       return(pid);
- }
+@@ -68,8 +68,8 @@
+  * This is the range that is readable by user mode, and things
+  * acting like user mode such as get_user_pages.
+  */
+-#define FIXADDR_USER_START    (__fix_to_virt(FIX_VSYSCALL))
+-#define FIXADDR_USER_END      (FIXADDR_USER_START + PAGE_SIZE)
++#define FIXADDR_USER_START    VSYSCALL_BASE
++#define FIXADDR_USER_END      VSYSCALL_END
  
-Index: linux-2.6.10/arch/um/Kconfig
+ extern void __this_fixmap_does_not_exist(void);
+Index: linux-2.6.10/include/asm-i386/thread_info.h
 ===================================================================
---- linux-2.6.10.orig/arch/um/Kconfig  2004-12-25 05:34:45.000000000 +0800
-+++ linux-2.6.10/arch/um/Kconfig       2005-04-05 12:40:36.053907144 +0800
-@@ -139,6 +139,25 @@
+--- linux-2.6.10.orig/include/asm-i386/thread_info.h   2004-12-25 05:34:00.000000000 +0800
++++ linux-2.6.10/include/asm-i386/thread_info.h        2005-04-06 23:44:30.185033768 +0800
+@@ -139,6 +139,7 @@
+ #define TIF_NEED_RESCHED      3       /* rescheduling necessary */
+ #define TIF_SINGLESTEP                4       /* restore singlestep on return to user mode */
+ #define TIF_IRET              5       /* return with iret */
++#define TIF_SYSCALL_EMU               6       /* syscall emulation active */
+ #define TIF_SYSCALL_AUDIT     7       /* syscall auditing active */
+ #define TIF_POLLING_NRFLAG    16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
  
-         It is safe to say 'Y' here.
+@@ -148,12 +149,14 @@
+ #define _TIF_NEED_RESCHED     (1<<TIF_NEED_RESCHED)
+ #define _TIF_SINGLESTEP               (1<<TIF_SINGLESTEP)
+ #define _TIF_IRET             (1<<TIF_IRET)
++#define _TIF_SYSCALL_EMU      (1<<TIF_SYSCALL_EMU)
+ #define _TIF_SYSCALL_AUDIT    (1<<TIF_SYSCALL_AUDIT)
+ #define _TIF_POLLING_NRFLAG   (1<<TIF_POLLING_NRFLAG)
  
-+config MAGIC_SYSRQ
-+        bool "Magic SysRq key"
-+        depends on MCONSOLE
-+        ---help---
-+        If you say Y here, you will have some control over the system even
-+        if the system crashes for example during kernel debugging (e.g., you
-+        will be able to flush the buffer cache to disk, reboot the system
-+        immediately or dump some status information). A key for each of the
-+        possible requests is provided.
-+
-+        This is the feature normally accomplished by pressing a key
-+        while holding SysRq (Alt+PrintScreen).
-+
-+        On UML, this is accomplished by sending a "sysrq" command with
-+        mconsole, followed by the letter for the requested command.
+ /* work to do on interrupt/exception return */
+ #define _TIF_WORK_MASK \
+-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
++  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|\
++                _TIF_SYSCALL_EMU))
+ #define _TIF_ALLWORK_MASK     0x0000FFFF      /* work to do on any return to u-space */
+ /*
+Index: linux-2.6.10/include/asm-i386/ptrace.h
+===================================================================
+--- linux-2.6.10.orig/include/asm-i386/ptrace.h        2004-12-25 05:33:51.000000000 +0800
++++ linux-2.6.10/include/asm-i386/ptrace.h     2005-04-06 23:44:30.186033616 +0800
+@@ -64,4 +64,26 @@
+ #endif
+ #endif
++/*For SKAS3 support.*/
++#ifndef _LINUX_PTRACE_STRUCT_DEF
++#define _LINUX_PTRACE_STRUCT_DEF
 +
-+        The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-+        unless you really know what this hack does.
++#define PTRACE_FAULTINFO        52
++#define PTRACE_SIGPENDING       53
++#define PTRACE_LDT              54
++#define PTRACE_SWITCH_MM        55
 +
- config HOST_2G_2G
-       bool "2G/2G host address space split"
-       default n
-@@ -153,28 +172,28 @@
-       So, if you do not know what to do here, say 'N'.
- config SMP
--      bool "Symmetric multi-processing support (EXPERIMENTAL)"
--      default n
--      depends on MODE_TT && EXPERIMENTAL
--      help
--      This option enables UML SMP support.
--      It is NOT related to having a real SMP box. Not directly, at least.
-+        bool "Symmetric multi-processing support (EXPERIMENTAL)"
-+        default n
-+        depends on MODE_TT && EXPERIMENTAL
-+        help
-+        This option enables UML SMP support.
-+        It is NOT related to having a real SMP box. Not directly, at least.
++struct ptrace_faultinfo {
++      int is_write;
++      unsigned long addr;
++};
 +
-+        UML implements virtual SMP by allowing as many processes to run
-+        simultaneously on the host as there are virtual processors configured.
++struct ptrace_ldt {
++      int func;
++      void *ptr;
++      unsigned long bytecount;
++};
 +
-+        Obviously, if the host is a uniprocessor, those processes will
-+        timeshare, but, inside UML, will appear to be running simultaneously.
-+        If the host is a multiprocessor, then UML processes may run
-+        simultaneously, depending on the host scheduler.
++#endif /*ifndef _LINUX_PTRACE_STRUCT_DEF*/
 +
-+        This, however, is supported only in TT mode. So, if you use the SKAS
-+        patch on your host, switching to TT mode and enabling SMP usually gives
-+        you worse performances.
-+        Also, since the support for SMP has been under-developed, there could
-+        be some bugs being exposed by enabling SMP.
--      UML implements virtual SMP by allowing as many processes to run
--      simultaneously on the host as there are virtual processors configured.
--
--      Obviously, if the host is a uniprocessor, those processes will
--      timeshare, but, inside UML, will appear to be running simultaneously.
--      If the host is a multiprocessor, then UML processes may run
--      simultaneously, depending on the host scheduler.
--
--      This, however, is supported only in TT mode. So, if you use the SKAS
--      patch on your host, switching to TT mode and enabling SMP usually gives
--      you worse performances.
--      Also, since the support for SMP has been under-developed, there could
--      be some bugs being exposed by enabling SMP.
--
--      If you don't know what to do, say N.
-+        If you don't know what to do, say N.
+ #endif
+Index: linux-2.6.10/include/asm-i386/mmu_context.h
+===================================================================
+--- linux-2.6.10.orig/include/asm-i386/mmu_context.h   2004-12-25 05:33:48.000000000 +0800
++++ linux-2.6.10/include/asm-i386/mmu_context.h        2005-04-06 23:44:30.185033768 +0800
+@@ -6,13 +6,25 @@
+ #include <asm/atomic.h>
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
++#include <asm/semaphore.h>
  
- config NR_CPUS
-       int "Maximum number of CPUs (2-32)"
-@@ -282,4 +301,8 @@
-       bool
-       default n
+ /*
+- * Used for LDT copy/destruction.
++ * Used for LDT initialization/destruction. You cannot copy an LDT with
++ * init_new_context, since it thinks you are passing it a new LDT and won't
++ * deallocate its old content.
+  */
+ int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+ void destroy_context(struct mm_struct *mm);
  
-+config INPUT
-+      bool
-+      default n
++/* LDT initialization for a clean environment - needed for SKAS.*/
++static inline void init_new_empty_context(struct mm_struct *mm)
++{
++      init_MUTEX(&mm->context.sem);
++      mm->context.size = 0;
++}
 +
- source "arch/um/Kconfig.debug"
-Index: linux-2.6.10/arch/um/Makefile
-===================================================================
---- linux-2.6.10.orig/arch/um/Makefile 2004-12-25 05:35:00.000000000 +0800
-+++ linux-2.6.10/arch/um/Makefile      2005-04-05 12:40:53.158306880 +0800
-@@ -77,6 +77,8 @@
-   echo '                 find in the kernel root.'
- endef
++/* LDT copy for SKAS - for the above problem.*/
++int copy_context(struct mm_struct *mm, struct mm_struct *old_mm);
  
-+.PHONY: linux
-+
- prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
-       $(ARCH_DIR)/kernel/vmlinux.lds.S
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+ {
+@@ -29,6 +41,10 @@
+ {
+       int cpu = smp_processor_id();
  
-Index: linux-2.6.10/fs/hostfs/hostfs.h
-===================================================================
---- linux-2.6.10.orig/fs/hostfs/hostfs.h       2004-12-25 05:35:24.000000000 +0800
-+++ linux-2.6.10/fs/hostfs/hostfs.h    2005-04-05 12:40:36.068904864 +0800
-@@ -16,9 +16,30 @@
- #define HOSTFS_ATTR_CTIME     64
- #define HOSTFS_ATTR_ATIME_SET 128
- #define HOSTFS_ATTR_MTIME_SET 256
++#ifdef CONFIG_SMP
++      prev = per_cpu(cpu_tlbstate, cpu).active_mm;
++#endif
 +
-+/* These two are unused by hostfs. */
- #define HOSTFS_ATTR_FORCE     512     /* Not a change, but a change it */
- #define HOSTFS_ATTR_ATTR_FLAG 1024
+       if (likely(prev != next)) {
+               /* stop flush ipis for the previous mm */
+               cpu_clear(cpu, prev->cpu_vm_mask);
+@@ -50,7 +66,6 @@
+ #ifdef CONFIG_SMP
+       else {
+               per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+-              BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
  
-+/* If you are very careful, you'll notice that these two are missing:
-+ *
-+ * #define ATTR_KILL_SUID     2048
-+ * #define ATTR_KILL_SGID     4096
-+ *
-+ * and this is because they were added in 2.5 development in this patch:
-+ *
-+ * http://linux.bkbits.net:8080/linux-2.5/
-+ * cset@3caf4a12k4XgDzK7wyK-TGpSZ9u2Ww?nav=index.html
-+ * |src/.|src/include|src/include/linux|related/include/linux/fs.h
-+ *
-+ * Actually, they are not needed by most ->setattr() methods - they are set by
-+ * callers of notify_change() to notify that the setuid/setgid bits must be
-+ * dropped.
-+ * notify_change() will delete those flags, make sure attr->ia_valid & ATTR_MODE
-+ * is on, and remove the appropriate bits from attr->ia_mode (attr is a
-+ * "struct iattr *"). -BlaisorBlade
-+ */
-+
- struct hostfs_iattr {
-       unsigned int    ia_valid;
-       mode_t          ia_mode;
-Index: linux-2.6.10/fs/hostfs/hostfs_kern.c
+               if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
+                       /* We were in lazy tlb mode and leave_mm disabled 
+Index: linux-2.6.10/include/asm-i386/desc.h
 ===================================================================
---- linux-2.6.10.orig/fs/hostfs/hostfs_kern.c  2004-12-25 05:34:01.000000000 +0800
-+++ linux-2.6.10/fs/hostfs/hostfs_kern.c       2005-04-05 12:40:36.069904712 +0800
-@@ -393,6 +393,7 @@
- static struct file_operations hostfs_file_fops = {
-       .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-+      .sendfile       = generic_file_sendfile,
-       .write          = generic_file_write,
-       .mmap           = generic_file_mmap,
-       .open           = hostfs_file_open,
-@@ -818,6 +819,10 @@
-       char *name;
-       int err;
+--- linux-2.6.10.orig/include/asm-i386/desc.h  2004-12-25 05:33:48.000000000 +0800
++++ linux-2.6.10/include/asm-i386/desc.h       2005-04-06 23:44:30.186033616 +0800
+@@ -126,6 +126,9 @@
+       put_cpu();
+ }
  
-+      err = inode_change_ok(dentry->d_inode, attr);
-+      if (err)
-+              return err;
++extern int __modify_ldt(struct mm_struct * mm, int func, void __user *ptr,
++                    unsigned long bytecount);
 +
-       if(append)
-               attr->ia_valid &= ~ATTR_SIZE;
+ #endif /* !__ASSEMBLY__ */
  
+ #endif