From: wangdi Date: Wed, 6 Apr 2005 16:25:49 +0000 (+0000) Subject: Branch: HEAD X-Git-Tag: v1_7_100~1470 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=4076fe1806f5851a51295c92bc113b6ca73feaa3 Branch: HEAD minor fix in Makefile for uml patch --- diff --git a/lustre/kernel_patches/patches/uml-2.6.10-fc3.patch b/lustre/kernel_patches/patches/uml-2.6.10-fc3.patch index a5abf90..4cbabd9 100644 --- a/lustre/kernel_patches/patches/uml-2.6.10-fc3.patch +++ b/lustre/kernel_patches/patches/uml-2.6.10-fc3.patch @@ -1,441 +1,113 @@ -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 - #include -+#include - - /* - * 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<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 - #include - #include -+#include - - /* -- * Used for LDT copy/destruction. -+ * Used for LDT initialization/destruction. You cannot copy an LDT with -+ * init_new_context, since it thinks you are passing it a new LDT and won't -+ * deallocate its old content. - */ - int init_new_context(struct task_struct *tsk, struct mm_struct *mm); - void destroy_context(struct mm_struct *mm); - -+/* LDT initialization for a clean environment - needed for SKAS.*/ -+static inline void init_new_empty_context(struct mm_struct *mm) -+{ -+ init_MUTEX(&mm->context.sem); -+ mm->context.size = 0; -+} -+ -+/* LDT copy for SKAS - for the above problem.*/ -+int copy_context(struct mm_struct *mm, struct mm_struct *old_mm); - - static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) - { -@@ -29,6 +41,10 @@ - { - int cpu = smp_processor_id(); - -+#ifdef CONFIG_SMP -+ prev = per_cpu(cpu_tlbstate, cpu).active_mm; -+#endif -+ - if (likely(prev != next)) { - /* stop flush ipis for the previous mm */ - cpu_clear(cpu, prev->cpu_vm_mask); -@@ -50,7 +66,6 @@ - #ifdef CONFIG_SMP - else { - per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK; -- BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next); - - if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { - /* We were in lazy tlb mode and leave_mm disabled -Index: linux-2.6.10/include/asm-i386/ptrace.h -=================================================================== ---- linux-2.6.10.orig/include/asm-i386/ptrace.h 2004-12-25 05:33:51.000000000 +0800 -+++ linux-2.6.10/include/asm-i386/ptrace.h 2005-04-05 12:40:36.077903496 +0800 -@@ -64,4 +64,26 @@ - #endif - #endif - -+/*For SKAS3 support.*/ -+#ifndef _LINUX_PTRACE_STRUCT_DEF -+#define _LINUX_PTRACE_STRUCT_DEF -+ -+#define PTRACE_FAULTINFO 52 -+#define PTRACE_SIGPENDING 53 -+#define PTRACE_LDT 54 -+#define PTRACE_SWITCH_MM 55 -+ -+struct ptrace_faultinfo { -+ int is_write; -+ unsigned long addr; -+}; -+ -+struct ptrace_ldt { -+ int func; -+ void *ptr; -+ unsigned long bytecount; -+}; -+ -+#endif /*ifndef _LINUX_PTRACE_STRUCT_DEF*/ -+ - #endif -Index: linux-2.6.10/include/asm-i386/desc.h -=================================================================== ---- linux-2.6.10.orig/include/asm-i386/desc.h 2005-03-31 16:20:09.000000000 +0800 -+++ linux-2.6.10/include/asm-i386/desc.h 2005-04-05 12:40:36.078903344 +0800 -@@ -126,6 +126,9 @@ - put_cpu(); - } - -+extern int __modify_ldt(struct mm_struct * mm, int func, void __user *ptr, -+ unsigned long bytecount); -+ - #endif /* !__ASSEMBLY__ */ - - #endif -Index: linux-2.6.10/include/linux/ptrace.h -=================================================================== ---- linux-2.6.10.orig/include/linux/ptrace.h 2005-03-31 15:35:23.000000000 +0800 -+++ linux-2.6.10/include/linux/ptrace.h 2005-04-05 12:40:36.071904408 +0800 -@@ -20,6 +20,7 @@ - #define PTRACE_DETACH 0x11 - - #define PTRACE_SYSCALL 24 -+#define PTRACE_SYSEMU 31 - - /* 0x4200-0x4300 are reserved for architecture-independent additions. */ - #define PTRACE_SETOPTIONS 0x4200 -Index: linux-2.6.10/include/linux/mm.h -=================================================================== ---- linux-2.6.10.orig/include/linux/mm.h 2005-03-31 16:10:15.000000000 +0800 -+++ linux-2.6.10/include/linux/mm.h 2005-04-05 12:40:36.072904256 +0800 -@@ -625,6 +625,9 @@ - extern struct shrinker *set_shrinker(int, shrinker_t); - extern void remove_shrinker(struct shrinker *shrinker); - -+extern long do_mprotect(struct mm_struct *mm, unsigned long start, -+ size_t len, unsigned long prot); -+ - /* - * On a two-level page table, this ends up being trivial. Thus the - * inlining and the symmetry break with pte_alloc_map() that does all -@@ -684,9 +687,15 @@ - - extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); - --extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, -+extern unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file *file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flag, -+ unsigned long pgoff); -+static inline unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, -- unsigned long flag, unsigned long pgoff); -+ unsigned long flag, unsigned long pgoff) { -+ return __do_mmap_pgoff(current->mm, file, addr, len, prot, flag, pgoff); -+} - - static inline unsigned long do_mmap(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, -Index: linux-2.6.10/include/linux/proc_mm.h -=================================================================== ---- linux-2.6.10.orig/include/linux/proc_mm.h 2005-04-05 19:01:49.158500672 +0800 -+++ linux-2.6.10/include/linux/proc_mm.h 2005-04-05 12:40:36.073904104 +0800 -@@ -0,0 +1,48 @@ -+/* -+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) -+ * Licensed under the GPL -+ */ -+ -+#ifndef __PROC_MM_H -+#define __PROC_MM_H -+ -+#include "linux/sched.h" -+ -+#define MM_MMAP 54 -+#define MM_MUNMAP 55 -+#define MM_MPROTECT 56 -+#define MM_COPY_SEGMENTS 57 -+ -+struct mm_mmap { -+ unsigned long addr; -+ unsigned long len; -+ unsigned long prot; -+ unsigned long flags; -+ unsigned long fd; -+ unsigned long offset; -+}; -+ -+struct mm_munmap { -+ unsigned long addr; -+ unsigned long len; -+}; -+ -+struct mm_mprotect { -+ unsigned long addr; -+ unsigned long len; -+ unsigned int prot; -+}; -+ -+struct proc_mm_op { -+ int op; -+ union { -+ struct mm_mmap mmap; -+ struct mm_munmap munmap; -+ struct mm_mprotect mprotect; -+ int copy_segments; -+ } u; -+}; -+ -+extern struct mm_struct *proc_mm_get_mm(int fd); -+ -+#endif -Index: linux-2.6.10/lib/Kconfig.debug -=================================================================== ---- linux-2.6.10.orig/lib/Kconfig.debug 2004-12-25 05:35:24.000000000 +0800 -+++ linux-2.6.10/lib/Kconfig.debug 2005-04-05 12:40:36.010913680 +0800 -@@ -23,7 +23,6 @@ - config MAGIC_SYSRQ - bool "Magic SysRq key" - depends on DEBUG_KERNEL && (H8300 || M68KNOMMU || V850) -- depends (USERMODE && MCONSOLE) - help - Enables console device to interpret special characters as - commands to dump state information. -Index: linux-2.6.10/kernel/fork.c -=================================================================== ---- linux-2.6.10.orig/kernel/fork.c 2005-03-31 15:35:26.000000000 +0800 -+++ linux-2.6.10/kernel/fork.c 2005-04-05 12:40:36.070904560 +0800 -@@ -927,6 +927,9 @@ - * of CLONE_PTRACE. - */ - clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); -+#ifdef TIF_SYSCALL_EMU -+ clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); -+#endif - - /* Our parent execution domain becomes current domain - These must match for thread signalling to apply */ -Index: linux-2.6.10/mm/mmap.c -=================================================================== ---- linux-2.6.10.orig/mm/mmap.c 2005-03-31 16:20:10.000000000 +0800 -+++ linux-2.6.10/mm/mmap.c 2005-04-05 12:40:36.013913224 +0800 -@@ -759,11 +759,11 @@ - * The caller must hold down_write(current->mm->mmap_sem). - */ - --unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, -- unsigned long len, unsigned long prot, -- unsigned long flags, unsigned long pgoff) -+unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file * file, -+ unsigned long addr, unsigned long len, -+ unsigned long prot, unsigned long flags, -+ unsigned long pgoff) - { -- struct mm_struct * mm = current->mm; - struct vm_area_struct * vma, * prev; - struct inode *inode; - unsigned int vm_flags; -@@ -1037,7 +1037,7 @@ - return error; - } - --EXPORT_SYMBOL(do_mmap_pgoff); -+EXPORT_SYMBOL(__do_mmap_pgoff); +-EXPORT_SYMBOL(do_mmap_pgoff); ++EXPORT_SYMBOL(__do_mmap_pgoff); /* Get an address range which is currently unmapped. * For shmat() with addr=0. Index: linux-2.6.10/mm/proc_mm.c =================================================================== ---- linux-2.6.10.orig/mm/proc_mm.c 2005-04-05 19:01:49.158500672 +0800 -+++ linux-2.6.10/mm/proc_mm.c 2005-04-05 12:40:36.014913072 +0800 +--- linux-2.6.10.orig/mm/proc_mm.c 2005-04-07 06:37:43.373923992 +0800 ++++ linux-2.6.10/mm/proc_mm.c 2005-04-06 23:44:30.204030880 +0800 @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) @@ -618,1050 +290,322 @@ Index: linux-2.6.10/mm/proc_mm.c + * c-file-style: "linux" + * End: + */ -Index: linux-2.6.10/mm/mprotect.c +Index: linux-2.6.10/mm/Makefile =================================================================== ---- linux-2.6.10.orig/mm/mprotect.c 2005-03-31 16:20:10.000000000 +0800 -+++ linux-2.6.10/mm/mprotect.c 2005-04-05 12:40:36.011913528 +0800 -@@ -93,19 +93,20 @@ - { - pgd_t *dir; - unsigned long beg = start; -+ struct mm_struct * mm = vma->vm_mm; - -- dir = pgd_offset(current->mm, start); -+ dir = pgd_offset(mm, start); - flush_cache_range(vma, beg, end); - if (start >= end) - BUG(); -- spin_lock(¤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 - #include - #include -+#include - - #include - #include -@@ -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 - #include - #include -+#include + 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 ++#include ++#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 --#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 -+ * 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 - #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, @@ -1903,66 +847,833 @@ Index: linux-2.6.10/arch/um/sys-i386/signal.c + return(0); +} + -+long sys_sigreturn(struct pt_regs regs) -+{ -+ unsigned long __user sp = PT_REGS_SP(¤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 + #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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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 +-#include +-#include +-#include +-#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 + -+ 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. @@ -1974,100 +1685,449 @@ Index: linux-2.6.10/arch/um/sys-i386/signal.c + * c-file-style: "linux" + * End: + */ -Index: linux-2.6.10/arch/um/sys-i386/Makefile ++/* ++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) ++ * Licensed under the GPL ++ */ ++ ++#ifndef __SKAS_UACCESS_H ++#define __SKAS_UACCESS_H ++ ++#include "asm/errno.h" + + #define access_ok_skas(type, addr, size) \ + ((segment_eq(get_fs(), KERNEL_DS)) || \ +Index: linux-2.6.10/arch/um/kernel/tt/syscall_user.c +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/tt/syscall_user.c 2004-12-25 05:35:01.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/tt/syscall_user.c 2005-04-06 23:44:30.275020088 +0800 +@@ -42,37 +42,31 @@ + syscall_trace(regs, 1); + record_syscall_end(index, result); + } +- +-int do_syscall(void *task, int pid, int local_using_sysemu) +-{ +- unsigned long proc_regs[FRAME_SIZE]; +- union uml_pt_regs *regs; +- int syscall; +- +- if(ptrace_getregs(pid, proc_regs) < 0) +- tracer_panic("Couldn't read registers"); +- syscall = PT_SYSCALL_NR(proc_regs); +- +- regs = TASK_REGS(task); +- UPT_SYSCALL_NR(regs) = syscall; +- +- if(syscall < 0) +- return(0); +- +- if((syscall != __NR_sigreturn) && +- ((unsigned long *) PT_IP(proc_regs) >= &_stext) && +- ((unsigned long *) PT_IP(proc_regs) <= &_etext)) +- tracer_panic("I'm tracing myself and I can't get out"); +- +- if(local_using_sysemu) +- return(1); +- +- if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, +- __NR_getpid) < 0) +- tracer_panic("do_syscall : Nullifying syscall failed, " +- "errno = %d", errno); +- return(1); +-} ++ ++ void do_sigtrap(void *task) ++ { ++ UPT_SYSCALL_NR(TASK_REGS(task)) = -1; ++ } ++ ++ void do_syscall(void *task, int pid, int local_using_sysemu) ++ { ++ unsigned long proc_regs[FRAME_SIZE]; ++ ++ if(ptrace_getregs(pid, proc_regs) < 0) ++ tracer_panic("Couldn't read registers"); ++ ++ UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs); ++ ++ if(((unsigned long *) PT_IP(proc_regs) >= &_stext) && ++ ((unsigned long *) PT_IP(proc_regs) <= &_etext)) ++ tracer_panic("I'm tracing myself and I can't get out"); ++ ++ /* syscall number -1 in sysemu skips syscall restarting in host */ ++ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, ++ local_using_sysemu ? -1 : __NR_getpid) < 0) ++ tracer_panic("do_syscall : Nullifying syscall failed, " ++ "errno = %d", errno); ++ } + + /* + * Overrides for Emacs so that we follow Linus's tabbing style. +Index: linux-2.6.10/arch/um/kernel/tt/sys-i386/Makefile +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/tt/sys-i386/Makefile 2004-12-25 05:34:32.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/tt/sys-i386/Makefile 2005-04-07 06:37:43.373923992 +0800 +@@ -1,12 +0,0 @@ +-# +-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +-# Licensed under the GPL +-# +- +-obj-y = sigcontext.o +- +-USER_OBJS = sigcontext.o +-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) +- +-$(USER_OBJS) : %.o: %.c +- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< +Index: linux-2.6.10/arch/um/kernel/tt/sys-i386/sigcontext.c +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/tt/sys-i386/sigcontext.c 2004-12-25 05:35:39.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/tt/sys-i386/sigcontext.c 2005-04-07 06:37:43.373923992 +0800 +@@ -1,60 +0,0 @@ +-/* +- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +- * Licensed under the GPL +- */ +- +-#include +-#include +-#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 + #include + #include ++#include + #include + #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 + #include + #include ++#include + #include + #include + #include "user.h" +@@ -25,7 +26,6 @@ + #include "mem_user.h" + #include "process.h" + #include "kern_util.h" +-#include "frame.h" + #include "chan_user.h" + #include "ptrace_user.h" + #include "mode.h" +@@ -72,6 +72,8 @@ + (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) + tracer_panic("OP_FORK failed to attach pid"); + wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); ++ if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) ++ tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno); + if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) + tracer_panic("OP_FORK failed to continue process"); } - #endif +@@ -141,7 +143,7 @@ + * any more, the trace of those will land here. So, we need to just + * PTRACE_SYSCALL it. + */ +- case SIGTRAP: ++ case (SIGTRAP|SYSCALL_TRAP): + if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) + tracer_panic("sleeping_process_signal : Failed to " + "PTRACE_SYSCALL pid %d, errno = %d\n", +@@ -184,9 +186,8 @@ + unsigned long eip = 0; + int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; + int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; +- int pt_syscall_parm, local_using_sysemu; ++ int pt_syscall_parm, local_using_sysemu = 0; -+#if 0 -+/* Debugging facility for dumping stuff out to the host, avoiding the timing -+ * problems that come with printf and breakpoints. -+ * Enable in case of emergency. +- capture_signal_stack(); + signal(SIGPIPE, SIG_IGN); + setup_tracer_winch(); + tracing_pid = os_getpid(); +@@ -198,6 +199,10 @@ + printf("waitpid on idle thread failed, errno = %d\n", errno); + exit(1); + } ++ if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) { ++ printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno); ++ exit(1); ++ } + if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ + printf("Failed to continue idle thread, errno = %d\n", errno); + exit(1); +@@ -297,7 +302,8 @@ + task = cpu_tasks[proc_id].task; + tracing = is_tracing(task); + old_tracing = tracing; +- ++ if ( tracing ) /* Assume: no syscall, when coming from user */ ++ do_sigtrap(task); + local_using_sysemu = get_using_sysemu(); + pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; + +@@ -306,6 +312,15 @@ + sig = 0; + op = do_proc_op(task, proc_id); + switch(op){ ++ /* ++ * This is called when entering user mode; after ++ * this, we start intercepting syscalls. ++ * ++ * In fact, a process is started in kernel mode, ++ * so with is_tracing() == 0 (and that is reset ++ * when executing syscalls, since UML kernel has ++ * the right to do syscalls); ++ */ + case OP_TRACE_ON: + arch_leave_kernel(task, pid); + tracing = 1; +@@ -314,7 +329,13 @@ + case OP_HALT: + unmap_physmem(); + kmalloc_ok = 0; +- ptrace(PTRACE_KILL, pid, 0, 0); ++ os_kill_ptraced_process(pid, 0); ++ /* Now let's reap remaining zombies */ ++ errno = 0; ++ do { ++ waitpid(-1, &status, ++ WUNTRACED); ++ } while (errno != ECHILD); + return(op == OP_REBOOT); + case OP_NONE: + printf("Detaching pid %d\n", pid); +@@ -328,14 +349,26 @@ + */ + pid = cpu_tasks[proc_id].pid; + break; ++ case (SIGTRAP|SYSCALL_TRAP): ++ if(!tracing && (debugger_pid != -1)){ ++ child_signal(pid, W_STOPCODE(SIGTRAP)); ++ continue; ++ } ++ tracing = 0; ++ /* local_using_sysemu has been already set ++ * below, since if we are here, is_tracing() on ++ * the traced task was 1, i.e. the process had ++ * already run through one iteration of the ++ * loop which executed a OP_TRACE_ON request.*/ ++ do_syscall(task, pid, local_using_sysemu); ++ sig = SIGUSR2; ++ break; + case SIGTRAP: + if(!tracing && (debugger_pid != -1)){ + child_signal(pid, status); + continue; + } + tracing = 0; +- if(do_syscall(task, pid, local_using_sysemu)) +- sig = SIGUSR2; + break; + case SIGPROF: + if(tracing) sig = 0; +@@ -371,6 +404,9 @@ + continue; + } + ++ local_using_sysemu = get_using_sysemu(); ++ pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; ++ + if(tracing){ + if(singlestepping(task)) + cont_type = PTRACE_SINGLESTEP; +Index: linux-2.6.10/arch/um/kernel/tt/Makefile +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/tt/Makefile 2004-12-25 05:34:57.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/tt/Makefile 2005-04-06 23:44:30.277019784 +0800 +@@ -8,7 +8,7 @@ + + obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ + syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ +- uaccess.o uaccess_user.o sys-$(SUBARCH)/ ++ uaccess.o uaccess_user.o + + obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ + +Index: linux-2.6.10/arch/um/kernel/tt/include/mode-tt.h +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/tt/include/mode-tt.h 2004-12-25 05:35:01.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/tt/include/mode-tt.h 2005-04-06 23:44:30.272020544 +0800 +@@ -14,6 +14,41 @@ + + extern int tracer(int (*init_proc)(void *), void *sp); + extern void user_time_init_tt(void); ++extern void sig_handler_common_tt(int sig, void *sc); ++extern void syscall_handler_tt(int sig, union uml_pt_regs *regs); ++extern void reboot_tt(void); ++extern void halt_tt(void); ++extern int is_tracer_winch(int pid, int fd, void *data); ++extern void kill_off_processes_tt(void); ++ ++#endif ++ ++/* ++ * Overrides for Emacs so that we follow Linus's tabbing style. ++ * Emacs will notice this stuff at the end of the file and automatically ++ * adjust the settings for this buffer only. This must remain at the end ++ * of the file. ++ * --------------------------------------------------------------------------- ++ * Local variables: ++ * c-file-style: "linux" ++ * End: ++ */ ++/* ++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) ++ * Licensed under the GPL + */ + -+int logging = 1; -+int logging_fd = -1; ++#ifndef __MODE_TT_H__ ++#define __MODE_TT_H__ + -+int logging_line = 0; -+char logging_buf[512]; ++#include "sysdep/ptrace.h" + -+void log(char *fmt, ...) -+{ -+ va_list ap; -+ struct timeval tv; -+ struct openflags flags; ++enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; + -+ if(logging == 0) return; -+ if(logging_fd < 0){ -+ flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); -+ logging_fd = os_open_file("log", flags, 0644); -+ } -+ gettimeofday(&tv, NULL); -+ sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, -+ tv.tv_usec); -+ va_start(ap, fmt); -+ vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); -+ va_end(ap); -+ write(logging_fd, logging_buf, strlen(logging_buf)); -+} -+#endif ++extern int tracing_pid; + - /* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically -Index: linux-2.6.10/arch/um/kernel/time.c ++extern int tracer(int (*init_proc)(void *), void *sp); ++extern void user_time_init_tt(void); + extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data); + extern int copy_sc_to_user_tt(void *to_ptr, void *fp, void *from_ptr, + void *data); +Index: linux-2.6.10/arch/um/kernel/tt/include/tt.h =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/time.c 2004-12-25 05:34:26.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/time.c 2005-04-05 12:40:36.046908208 +0800 -@@ -60,6 +60,9 @@ - (setitimer(ITIMER_REAL, &disable, NULL) < 0)) - printk("disnable_timer - setitimer failed, errno = %d\n", - errno); -+ /* If there are signals already queued, after unblocking ignore them */ -+ set_handler(SIGALRM, SIG_IGN, 0, -1); -+ set_handler(SIGVTALRM, SIG_IGN, 0, -1); - } +--- linux-2.6.10.orig/arch/um/kernel/tt/include/tt.h 2004-12-25 05:34:58.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/tt/include/tt.h 2005-04-06 23:44:30.273020392 +0800 +@@ -26,7 +26,8 @@ + extern int is_tracing(void *task); + extern void syscall_handler(int sig, union uml_pt_regs *regs); + extern void exit_kernel(int pid, void *task); +-extern int do_syscall(void *task, int pid, int local_using_sysemu); ++extern void do_syscall(void *task, int pid, int local_using_sysemu); ++extern void do_sigtrap(void *task); + extern int is_valid_pid(int pid); + extern void remap_data(void *segment_start, void *segment_end, int w); - void switch_timers(int to_real) -Index: linux-2.6.10/arch/um/kernel/ksyms.c +Index: linux-2.6.10/arch/um/kernel/ptrace.c =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/ksyms.c 2004-12-25 05:33:50.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/ksyms.c 2005-04-05 12:40:36.049907752 +0800 -@@ -48,6 +48,7 @@ - EXPORT_SYMBOL(mode_tt); - EXPORT_SYMBOL(handle_page_fault); - EXPORT_SYMBOL(find_iomem); -+EXPORT_SYMBOL(end_iomem); +--- linux-2.6.10.orig/arch/um/kernel/ptrace.c 2004-12-25 05:35:50.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/ptrace.c 2005-04-06 23:44:30.254023280 +0800 +@@ -16,6 +16,7 @@ + #include "asm/uaccess.h" + #include "kern_util.h" + #include "ptrace_user.h" ++#include "signal_user.h" - #ifdef CONFIG_MODE_TT - EXPORT_SYMBOL(strncpy_from_user_tt); + /* + * Called by kernel/ptrace.c when detaching.. +@@ -328,8 +329,10 @@ + /* the 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + tracesysgood = (current->ptrace & PT_TRACESYSGOOD) && !is_singlestep; +- ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); +- ++ ptrace_notify(SIGTRAP | (tracesysgood ? SYSCALL_TRAP : 0)); ++ if ( entryexit ) /* force do_signal() --> is_syscall() */ ++ set_thread_flag(TIF_SIGPENDING); ++ + /* force do_signal() --> is_syscall() */ + set_thread_flag(TIF_SIGPENDING); + +Index: linux-2.6.10/arch/um/kernel/dyn.lds.S +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/dyn.lds.S 2004-12-25 05:34:48.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/dyn.lds.S 2005-04-06 23:44:30.253023432 +0800 +@@ -7,8 +7,11 @@ + + SECTIONS + { ++ PROVIDE (__executable_start = START); + . = START + SIZEOF_HEADERS; + .interp : { *(.interp) } ++ /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start ++ * is remapped.*/ + __binary_start = .; + . = ALIGN(4096); /* Init code and data */ + _stext = .; Index: linux-2.6.10/arch/um/kernel/um_arch.c =================================================================== --- linux-2.6.10.orig/arch/um/kernel/um_arch.c 2004-12-25 05:35:24.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/um_arch.c 2005-04-05 12:40:36.045908360 +0800 ++++ linux-2.6.10/arch/um/kernel/um_arch.c 2005-04-06 23:44:30.239025560 +0800 @@ -44,11 +44,6 @@ .ipi_pipe = { -1, -1 } }; @@ -2092,43 +2152,24 @@ Index: linux-2.6.10/arch/um/kernel/um_arch.c brk_start = (unsigned long) sbrk(0); CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); /* Increase physical memory size for exec-shield users -Index: linux-2.6.10/arch/um/kernel/process.c +Index: linux-2.6.10/arch/um/kernel/time.c =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/process.c 2004-12-25 05:35:25.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/process.c 2005-04-05 12:40:36.025911400 +0800 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -285,6 +286,9 @@ - printk("Checking that ptrace can change system call numbers..."); - pid = start_ptraced_child(&stack); +--- linux-2.6.10.orig/arch/um/kernel/time.c 2004-12-25 05:34:26.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/time.c 2005-04-06 23:44:30.237025864 +0800 +@@ -60,6 +60,9 @@ + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) + printk("disnable_timer - setitimer failed, errno = %d\n", + errno); ++ /* If there are signals already queued, after unblocking ignore them */ ++ set_handler(SIGALRM, SIG_IGN, 0, -1); ++ set_handler(SIGVTALRM, SIG_IGN, 0, -1); + } -+ if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) -+ panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno); -+ - while(1){ - if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) - panic("check_ptrace : ptrace failed, errno = %d", -@@ -292,8 +296,8 @@ - CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); - if(n < 0) - panic("check_ptrace : wait failed, errno = %d", errno); -- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) -- panic("check_ptrace : expected SIGTRAP, " -+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP))) -+ panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), " - "got status = %d", status); - - syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, + void switch_timers(int to_real) Index: linux-2.6.10/arch/um/kernel/process_kern.c =================================================================== --- linux-2.6.10.orig/arch/um/kernel/process_kern.c 2004-12-25 05:34:57.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/process_kern.c 2005-04-05 12:40:36.047908056 +0800 ++++ linux-2.6.10/arch/um/kernel/process_kern.c 2005-04-06 23:44:30.240025408 +0800 @@ -291,8 +291,6 @@ EXPORT_SYMBOL(disable_hlt); @@ -2138,79 +2179,80 @@ Index: linux-2.6.10/arch/um/kernel/process_kern.c void *um_kmalloc(int size) { return(kmalloc(size, GFP_KERNEL)); -Index: linux-2.6.10/arch/um/kernel/signal_user.c +Index: linux-2.6.10/arch/um/kernel/trap_user.c =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/signal_user.c 2004-12-25 05:35:23.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/signal_user.c 2005-04-05 12:40:36.050907600 +0800 -@@ -61,6 +61,10 @@ - * disable profiling; it's safe because the profiling code does not interact - * with the kernel code at all.*/ - -+/* Both here and in set/get_signal we don't touch SIGPROF, because we must not -+ * disable profiling; it's safe because the profiling code does not interact -+ * with the kernel code at all.*/ -+ - static void change_signals(int type) - { - sigset_t mask; -Index: linux-2.6.10/arch/um/kernel/initrd_user.c +--- linux-2.6.10.orig/arch/um/kernel/trap_user.c 2004-12-25 05:34:44.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/trap_user.c 2005-04-06 23:44:30.277019784 +0800 +@@ -18,7 +18,6 @@ + #include "sigcontext.h" + #include "sysdep/sigcontext.h" + #include "irq_user.h" +-#include "frame_user.h" + #include "signal_user.h" + #include "time_user.h" + #include "task.h" +Index: linux-2.6.10/arch/um/kernel/signal_kern.c =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/initrd_user.c 2004-12-25 05:34:26.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/initrd_user.c 2005-04-05 12:40:36.026911248 +0800 -@@ -29,6 +29,8 @@ - filename, -n); - return(-1); - } -+ -+ os_close_file(fd); - return(0); +--- linux-2.6.10.orig/arch/um/kernel/signal_kern.c 2004-12-25 05:34:58.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/signal_kern.c 2005-04-06 23:44:30.264021760 +0800 +@@ -230,53 +230,6 @@ + return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤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 @@ -2239,367 +2281,551 @@ Index: linux-2.6.10/arch/um/kernel/uml.lds.S _stext = .; __init_begin = .; .init.text : { -Index: linux-2.6.10/arch/um/kernel/main.c +Index: linux-2.6.10/arch/um/kernel/ksyms.c =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/main.c 2004-12-25 05:35:24.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/main.c 2005-04-05 12:40:36.024911552 +0800 -@@ -81,6 +81,8 @@ +--- linux-2.6.10.orig/arch/um/kernel/ksyms.c 2004-12-25 05:33:50.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/ksyms.c 2005-04-06 23:44:30.238025712 +0800 +@@ -48,6 +48,7 @@ + EXPORT_SYMBOL(mode_tt); + EXPORT_SYMBOL(handle_page_fault); + EXPORT_SYMBOL(find_iomem); ++EXPORT_SYMBOL(end_iomem); - extern int uml_exitcode; + #ifdef CONFIG_MODE_TT + EXPORT_SYMBOL(strncpy_from_user_tt); +Index: linux-2.6.10/arch/um/kernel/signal_user.c +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/signal_user.c 2004-12-25 05:35:23.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/signal_user.c 2005-04-06 23:44:30.252023584 +0800 +@@ -61,6 +61,10 @@ + * disable profiling; it's safe because the profiling code does not interact + * with the kernel code at all.*/ -+extern void scan_elf_aux( char **envp); ++/* Both here and in set/get_signal we don't touch SIGPROF, because we must not ++ * disable profiling; it's safe because the profiling code does not interact ++ * with the kernel code at all.*/ + - int main(int argc, char **argv, char **envp) + static void change_signals(int type) { - char **new_argv; -@@ -147,6 +149,8 @@ - set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); - set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); - -+ scan_elf_aux( envp); + sigset_t mask; +Index: linux-2.6.10/arch/um/kernel/mem_user.c +=================================================================== +--- linux-2.6.10.orig/arch/um/kernel/mem_user.c 2004-12-25 05:34:57.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/mem_user.c 2005-04-06 23:44:30.237025864 +0800 +@@ -101,6 +101,8 @@ + } + printf("OK\n"); + munmap(addr, UM_KERN_PAGE_SIZE); + - do_uml_initcalls(); - ret = linux_main(argc, argv); - -@@ -155,18 +159,20 @@ - int err; ++ os_close_file(fd); + } - printf("\n"); -- -- /* Let any pending signals fire, then disable them. This -- * ensures that they won't be delivered after the exec, when -- * they are definitely not expected. -- */ -- unblock_signals(); -+ /* stop timers and set SIG*ALRM to be ignored */ - disable_timer(); -+ /* disable SIGIO for the fds and set SIGIO to be ignored */ - err = deactivate_all_fds(); - if(err) - printf("deactivate_all_fds failed, errno = %d\n", - -err); + static int have_devanon = 0; +@@ -261,6 +263,39 @@ + } + #endif -+ /* Let any pending signals fire now. This ensures -+ * that they won't be delivered after the exec, when -+ * they are definitely not expected. -+ */ -+ unblock_signals(); ++#if 0 ++/* Debugging facility for dumping stuff out to the host, avoiding the timing ++ * problems that come with printf and breakpoints. ++ * Enable in case of emergency. ++ */ + - execvp(new_argv[0], new_argv); - perror("Failed to exec kernel"); - ret = 1; -Index: linux-2.6.10/arch/um/kernel/irq_user.c ++int logging = 1; ++int logging_fd = -1; ++ ++int logging_line = 0; ++char logging_buf[512]; ++ ++void log(char *fmt, ...) ++{ ++ va_list ap; ++ struct timeval tv; ++ struct openflags flags; ++ ++ if(logging == 0) return; ++ if(logging_fd < 0){ ++ flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); ++ logging_fd = os_open_file("log", flags, 0644); ++ } ++ gettimeofday(&tv, NULL); ++ sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, ++ tv.tv_usec); ++ va_start(ap, fmt); ++ vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); ++ va_end(ap); ++ write(logging_fd, logging_buf, strlen(logging_buf)); ++} ++#endif ++ + /* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically +Index: linux-2.6.10/arch/um/kernel/Makefile =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/irq_user.c 2004-12-25 05:34:32.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/irq_user.c 2005-04-05 12:40:36.028910944 +0800 -@@ -374,6 +374,8 @@ - if(err) - return(err); - } -+ /* If there is a signal already queued, after unblocking ignore it */ -+ set_handler(SIGIO, SIG_IGN, 0, -1); +--- linux-2.6.10.orig/arch/um/kernel/Makefile 2004-12-25 05:35:01.000000000 +0800 ++++ linux-2.6.10/arch/um/kernel/Makefile 2005-04-06 23:44:30.278019632 +0800 +@@ -6,7 +6,7 @@ + extra-y := vmlinux.lds + clean-files := vmlinux.lds.S - return(0); - } -Index: linux-2.6.10/arch/um/kernel/signal_kern.c +-obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \ ++obj-y = checksum.o config.o exec_kern.o exitcode.o \ + helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ + physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \ + sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \ +Index: linux-2.6.10/arch/um/Kconfig =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/signal_kern.c 2004-12-25 05:34:58.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/signal_kern.c 2005-04-05 12:40:36.048907904 +0800 -@@ -230,53 +230,6 @@ - return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤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 . 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 + * 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 -+ -+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 --#include --#include --#include --#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 +-#include "sysdep/frame.h" +- +-/* This stuff is to calculate the size of the fp state struct at runtime +- * because it has changed between 2.2 and 2.4 and it would be good for a +- * UML compiled on one to work on the other. +- * So, setup_arch_frame_raw fills in the arch struct with the raw data, which +- * just contains the address of the end of the sigcontext. This is invoked +- * from the signal handler. +- * setup_arch_frame uses that data to figure out what +- * arch_frame_data.fpstate_size should be. It really has no idea, since it's +- * not allowed to do sizeof(struct fpstate) but it's safe to consider that it's +- * everything from the end of the sigcontext up to the top of the stack. So, +- * it masks off the page number to get the offset within the page and subtracts +- * that from the page size, and that's how big the fpstate struct will be +- * considered to be. +- */ +- +-static inline void setup_arch_frame_raw(struct arch_frame_data_raw *data, +- void *end, unsigned long srp) +-{ +- unsigned long sr = *((unsigned long *) srp); +- +- data->fp_start = (unsigned long) end; +- if((sr & PAGE_MASK) == ((unsigned long) end & PAGE_MASK)) +- data->sr = sr; +- else data->sr = 0; +-} +- +-static inline void setup_arch_frame(struct arch_frame_data_raw *in, +- struct arch_frame_data *out) +-{ +- unsigned long fpstate_start = in->fp_start; +- +- if(in->sr == 0){ +- fpstate_start &= ~PAGE_MASK; +- out->fpstate_size = PAGE_SIZE - fpstate_start; +- } +- else { +- out->fpstate_size = in->sr - fpstate_start; +- } +-} +- +-/* This figures out where on the stack the SA_RESTORER function address +- * is stored. For i386, it's the signal handler return address, so it's +- * located next to the frame pointer. +- * This is inlined, so __builtin_frame_address(0) is correct. Otherwise, +- * it would have to be __builtin_frame_address(1). +- */ +- +-#define frame_restorer() \ +-({ \ +- unsigned long *fp; \ +-\ +- fp = __builtin_frame_address(0); \ +- ((unsigned long) (fp + 1)); \ +-}) - -- err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs); -- if(err < 0){ -- printk("copy_sc_to_user - PTRACE_GETFPREGS failed, " -- "errno = %d\n", errno); -- return(1); -- } -- to_fp = (struct _fpstate *) -- (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to))); -- sc.fpstate = to_fp; +-/* Similarly, this returns the value of sp when the handler was first +- * entered. This is used to calculate the proper sp when delivering +- * signals. +- */ - -- if(err) -- return(err); +-#define frame_sp() \ +-({ \ +- unsigned long *fp; \ +-\ +- fp = __builtin_frame_address(0); \ +- ((unsigned long) (fp + 1)); \ +-}) - -- return(copy_to_user_proc(to, &sc, sizeof(sc)) || -- copy_to_user_proc(to_fp, fpregs, sizeof(fpregs))); --} +-#endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. @@ -2611,1136 +2837,897 @@ Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c - * c-file-style: "linux" - * End: - */ -Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile +Index: linux-2.6.10/arch/um/include/frame_user.h =================================================================== ---- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/Makefile 2004-12-25 05:35:27.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile 2005-04-05 19:01:49.158500672 +0800 -@@ -1,12 +0,0 @@ --# --# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) --# Licensed under the GPL --# +--- linux-2.6.10.orig/arch/um/include/frame_user.h 2004-12-25 05:33:50.000000000 +0800 ++++ linux-2.6.10/arch/um/include/frame_user.h 2005-04-07 06:37:43.373923992 +0800 +@@ -1,23 +0,0 @@ +-/* +- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +- * Licensed under the GPL +- */ - --obj-y = sigcontext.o +-#ifndef __FRAME_USER_H_ +-#define __FRAME_USER_H_ - --USER_OBJS = sigcontext.o --USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) +-#include "sysdep/frame_user.h" +-#include "frame.h" - --$(USER_OBJS) : %.o: %.c -- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< -Index: linux-2.6.10/arch/um/kernel/skas/process.c -=================================================================== ---- linux-2.6.10.orig/arch/um/kernel/skas/process.c 2004-12-25 05:35:39.000000000 +0800 -+++ linux-2.6.10/arch/um/kernel/skas/process.c 2005-04-05 12:40:36.030910640 +0800 -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -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 + #include + #include ++#include -+ 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 + #include +@@ -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 + #include + #include ++#include + + #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 - #include - #include -+#include - #include - #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 --#include --#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 - #include - #include -+#include - #include - #include - #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 -+#include -+#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 + #include ++#include -- 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<. 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 + #include + #include ++#include - 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