-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(¤t->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(¤t->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(¤t->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(¤t->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)
+ * 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(¤t->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(¤t->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(¤t->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(¤t->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 (¤t->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 (¤t->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(¤t->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(¤t->mm->mmap_sem);
-- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-- up_write(¤t->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 *) ®s);
- }
-+
-+/* 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,
+ return(0);
+}
+
-+long sys_sigreturn(struct pt_regs regs)
-+{
-+ unsigned long __user sp = PT_REGS_SP(¤t->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(¤t->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(¤t->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ if(copy_sc_from_user(¤t->thread.regs, sc))
++ goto segfault;
++
++ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; /* Avoid ERESTART handling */
++ return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
++
++ segfault:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++long sys_rt_sigreturn(struct pt_regs regs)
++{
++ unsigned long __user sp = PT_REGS_SP(¤t->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(¤t->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext))
++ goto segfault;
++
++ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; /* Avoid ERESTART handling */
++ return(PT_REGS_SYSCALL_RET(¤t->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 *) ®s);
+ }
++
++/* 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(¤t->sighand->siglock);
-+ current->blocked = set;
-+ recalc_sigpending();
-+ spin_unlock_irq(¤t->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(¤t->thread.regs, sc))
-+ goto segfault;
++#endif
+
-+ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; /* Avoid ERESTART handling */
-+ return(PT_REGS_SYSCALL_RET(¤t->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(¤t->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(¤t->sighand->siglock);
-+ current->blocked = set;
-+ recalc_sigpending();
-+ spin_unlock_irq(¤t->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(¤t->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(¤t->thread.regs) = -1; /* Avoid ERESTART handling */
-+ return(PT_REGS_SYSCALL_RET(¤t->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.
+ * 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 }
};
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);
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(¤t->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(¤t->thread.regs));
+- void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
+- int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+-
+- spin_lock_irq(¤t->sighand->siglock);
+- copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc),
+- sizeof(current->blocked.sig[0]));
+- copy_from_user(¤t->blocked.sig[1], mask, sig_size);
+- sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- copy_sc_from_user(¤t->thread.regs, sc,
+- &signal_frame_sc.common.arch);
+- return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
+-}
+-
+-long sys_rt_sigreturn(struct pt_regs regs)
+-{
+- unsigned long sp = PT_REGS_SP(¤t->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(¤t->sighand->siglock);
+- copy_from_user(¤t->blocked, &uc->uc_sigmask, sig_size);
+- sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
+- recalc_sigpending();
+- spin_unlock_irq(¤t->sighand->siglock);
+- copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext,
+- &signal_frame_si.common.arch);
+- return(PT_REGS_SYSCALL_RET(¤t->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
_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(¤t->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(¤t->thread.regs));
-- void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
-- int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
+-extern struct sc_frame signal_frame_sc;
-
-- spin_lock_irq(¤t->sighand->siglock);
-- copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc),
-- sizeof(current->blocked.sig[0]));
-- copy_from_user(¤t->blocked.sig[1], mask, sig_size);
-- sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
-- recalc_sigpending();
-- spin_unlock_irq(¤t->sighand->siglock);
-- copy_sc_from_user(¤t->thread.regs, sc,
-- &signal_frame_sc.common.arch);
-- return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
--}
+-extern struct sc_frame signal_frame_sc_sr;
-
--long sys_rt_sigreturn(struct pt_regs regs)
--{
-- unsigned long sp = PT_REGS_SP(¤t->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(¤t->sighand->siglock);
-- copy_from_user(¤t->blocked, &uc->uc_sigmask, sig_size);
-- sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
-- recalc_sigpending();
-- spin_unlock_irq(¤t->sighand->siglock);
-- copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext,
-- &signal_frame_si.common.arch);
-- return(PT_REGS_SYSCALL_RET(¤t->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.
- * 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 (¤t->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 (¤t->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(¤t->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(¤t->mm->mmap_sem);
+- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+- up_write(¤t->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