++long sys_sigreturn(struct pt_regs regs)
++{
++ unsigned long __user sp = PT_REGS_SP(¤t->thread.regs);
++ struct sigframe __user *frame = (struct sigframe *)(sp - 8);
++ sigset_t set;
++ struct sigcontext __user *sc = &frame->sc;
++ unsigned long __user *oldmask = &sc->oldmask;
++ unsigned long __user *extramask = &frame->extramask;
++ int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
++
++ if(copy_from_user(&set.sig[0], oldmask, sizeof(&set.sig[0])) ||
++ copy_from_user(&set.sig[1], extramask, sig_size))
++ goto segfault;
++
++ sigdelsetmask(&set, ~_BLOCKABLE);
++
++ spin_lock_irq(¤t->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ if(copy_sc_from_user(¤t->thread.regs, sc))
++ goto segfault;
++
++ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; /* Avoid ERESTART handling */
++ return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
++
++ segfault:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++long sys_rt_sigreturn(struct pt_regs regs)
++{
++ unsigned long __user sp = PT_REGS_SP(¤t->thread.regs);
++ struct rt_sigframe __user *frame = (struct rt_sigframe *) (sp - 4);
++ sigset_t set;
++ struct ucontext __user *uc = &frame->uc;
++ int sig_size = _NSIG_WORDS * sizeof(unsigned long);
++
++ if(copy_from_user(&set, &uc->uc_sigmask, sig_size))
++ goto segfault;
++
++ sigdelsetmask(&set, ~_BLOCKABLE);
++
++ spin_lock_irq(¤t->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(¤t->sighand->siglock);
++
++ if(copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext))
++ goto segfault;
++
++ PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; /* Avoid ERESTART handling */
++ return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
++
++ segfault:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++/*
++ * Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+Index: linux-2.6.10/arch/um/sys-i386/ptrace_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/ptrace_user.c 2004-12-25 05:35:50.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/ptrace_user.c 2005-04-06 23:44:30.233026472 +0800
+@@ -17,17 +17,30 @@
+
+ int ptrace_getregs(long pid, unsigned long *regs_out)
+ {
+- return(ptrace(PTRACE_GETREGS, pid, 0, regs_out));
++ if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
++ return(-errno);
++ return(0);
+ }
+
+ int ptrace_setregs(long pid, unsigned long *regs)
+ {
+- return(ptrace(PTRACE_SETREGS, pid, 0, regs));
++ if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
++ return(-errno);
++ return(0);
+ }
+
+ int ptrace_getfpregs(long pid, unsigned long *regs)
+ {
+- return(ptrace(PTRACE_GETFPREGS, pid, 0, regs));
++ if(ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
++ return(-errno);
++ return(0);
++}
++
++int ptrace_setfpregs(long pid, unsigned long *regs)
++{
++ if(ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
++ return(-errno);
++ return(0);
+ }
+
+ static void write_debugregs(int pid, unsigned long *regs)
+Index: linux-2.6.10/arch/um/sys-i386/sysrq.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/sysrq.c 2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/sysrq.c 2005-04-06 23:44:30.234026320 +0800
+@@ -33,3 +33,13 @@
+
+ show_trace((unsigned long *) ®s);
+ }
++
++/* Overrides for Emacs so that we follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only. This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-file-style: "linux"
++ * End:
++ */
+Index: linux-2.6.10/arch/um/sys-i386/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/Makefile 2004-12-25 05:34:01.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/Makefile 2005-04-06 23:44:30.236026016 +0800
+@@ -1,5 +1,5 @@
+ obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
+- ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
++ ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o
+
+ obj-$(CONFIG_HIGHMEM) += highmem.o
+ obj-$(CONFIG_MODULES) += module.o
+Index: linux-2.6.10/arch/um/sys-i386/sigcontext.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/sys-i386/sigcontext.c 2004-12-25 05:33:49.000000000 +0800
++++ linux-2.6.10/arch/um/sys-i386/sigcontext.c 2005-04-06 23:44:30.233026472 +0800
+@@ -9,22 +9,14 @@
+ #include <asm/sigcontext.h>
+ #include "sysdep/ptrace.h"
+ #include "kern_util.h"
+-#include "frame_user.h"
+-
+-int sc_size(void *data)
+-{
+- struct arch_frame_data *arch = data;
+-
+- return(sizeof(struct sigcontext) + arch->fpstate_size);
+-}
+
+ void sc_to_sc(void *to_ptr, void *from_ptr)
+ {
+ struct sigcontext *to = to_ptr, *from = from_ptr;
+- int size = sizeof(*to) + signal_frame_sc.common.arch.fpstate_size;
+
+- memcpy(to, from, size);
+- if(from->fpstate != NULL) to->fpstate = (struct _fpstate *) (to + 1);
++ memcpy(to, from, sizeof(*to) + sizeof(struct _fpstate));
++ if(from->fpstate != NULL)
++ to->fpstate = (struct _fpstate *) (to + 1);
+ }
+
+ unsigned long *sc_sigmask(void *sc_ptr)
+Index: linux-2.6.10/arch/um/kernel/main.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/main.c 2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/main.c 2005-04-06 23:44:30.262022064 +0800
+@@ -81,6 +81,8 @@
+
+ extern int uml_exitcode;
+
++extern void scan_elf_aux( char **envp);
++
+ int main(int argc, char **argv, char **envp)
+ {
+ char **new_argv;
+@@ -147,6 +149,8 @@
+ set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+
++ scan_elf_aux( envp);
++
+ do_uml_initcalls();
+ ret = linux_main(argc, argv);
+
+@@ -155,18 +159,20 @@
+ int err;
+
+ printf("\n");
+-
+- /* Let any pending signals fire, then disable them. This
+- * ensures that they won't be delivered after the exec, when
+- * they are definitely not expected.
+- */
+- unblock_signals();
++ /* stop timers and set SIG*ALRM to be ignored */
+ disable_timer();
++ /* disable SIGIO for the fds and set SIGIO to be ignored */
+ err = deactivate_all_fds();
+ if(err)
+ printf("deactivate_all_fds failed, errno = %d\n",
+ -err);
+
++ /* Let any pending signals fire now. This ensures
++ * that they won't be delivered after the exec, when
++ * they are definitely not expected.
++ */
++ unblock_signals();
++
+ execvp(new_argv[0], new_argv);
+ perror("Failed to exec kernel");
+ ret = 1;
+Index: linux-2.6.10/arch/um/kernel/process.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/process.c 2004-12-25 05:35:25.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/process.c 2005-04-06 23:44:30.240025408 +0800
+@@ -13,6 +13,7 @@
+ #include <setjmp.h>
+ #include <sys/time.h>
+ #include <sys/ptrace.h>
++#include <linux/ptrace.h>
+ #include <sys/wait.h>
+ #include <sys/mman.h>
+ #include <asm/ptrace.h>
+@@ -285,6 +286,9 @@
+ printk("Checking that ptrace can change system call numbers...");
+ pid = start_ptraced_child(&stack);
+
++ if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
++ panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
++
+ while(1){
+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
+ panic("check_ptrace : ptrace failed, errno = %d",
+@@ -292,8 +296,8 @@
+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+ if(n < 0)
+ panic("check_ptrace : wait failed, errno = %d", errno);
+- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+- panic("check_ptrace : expected SIGTRAP, "
++ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP)))
++ panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
+ "got status = %d", status);
+
+ syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+Index: linux-2.6.10/arch/um/kernel/initrd_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/initrd_user.c 2004-12-25 05:34:26.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/initrd_user.c 2005-04-06 23:44:30.252023584 +0800
+@@ -29,6 +29,8 @@
+ filename, -n);
+ return(-1);
+ }
++
++ os_close_file(fd);
+ return(0);
+ }
+
+Index: linux-2.6.10/arch/um/kernel/time_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/time_kern.c 2004-12-25 05:35:00.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/time_kern.c 2005-04-06 23:44:30.271020696 +0800
+@@ -170,7 +170,7 @@
+ void timer_handler(int sig, union uml_pt_regs *regs)
+ {
+ local_irq_disable();
+- update_process_times(user_context(UPT_SP(regs)));
++ update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), (regs)->skas.is_user));
+ local_irq_enable();
+ if(current_thread->cpu == 0)
+ timer_irq(regs);
+Index: linux-2.6.10/arch/um/kernel/helper.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/helper.c 2004-12-25 05:34:45.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/helper.c 2005-04-06 23:44:30.271020696 +0800
+@@ -49,14 +49,14 @@
+ return(0);
+ }
+
+-/* XXX The alloc_stack here breaks if this is called in the tracing thread */
+-
++/* Returns either the pid of the child process we run or -E* on failure.
++ * XXX The alloc_stack here breaks if this is called in the tracing thread */
+ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
+ unsigned long *stack_out)
+ {
+ struct helper_data data;
+ unsigned long stack, sp;
+- int pid, fds[2], err, n;
++ int pid, fds[2], ret, n;
+
+ if((stack_out != NULL) && (*stack_out != 0))
+ stack = *stack_out;
+@@ -64,16 +64,16 @@
+ if(stack == 0)
+ return(-ENOMEM);
+
+- err = os_pipe(fds, 1, 0);
+- if(err < 0){
+- printk("run_helper : pipe failed, err = %d\n", -err);
++ ret = os_pipe(fds, 1, 0);
++ if(ret < 0){
++ printk("run_helper : pipe failed, ret = %d\n", -ret);
+ goto out_free;
+ }
+
+- err = os_set_exec_close(fds[1], 1);
+- if(err < 0){
+- printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
+- -err);
++ ret = os_set_exec_close(fds[1], 1);
++ if(ret < 0){
++ printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
++ -ret);
+ goto out_close;
+ }
+
+@@ -85,34 +85,36 @@
+ pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
+ if(pid < 0){
+ printk("run_helper : clone failed, errno = %d\n", errno);
+- err = -errno;
++ ret = -errno;
+ goto out_close;
+ }
+
+ os_close_file(fds[1]);
+- n = os_read_file(fds[0], &err, sizeof(err));
++ fds[1] = -1;
++
++ /*Read the errno value from the child.*/
++ n = os_read_file(fds[0], &ret, sizeof(ret));
+ if(n < 0){
+- printk("run_helper : read on pipe failed, err = %d\n", -n);
+- err = n;
+- goto out_kill;
++ printk("run_helper : read on pipe failed, ret = %d\n", -n);
++ ret = n;
++ os_kill_process(pid, 1);
+ }
+ else if(n != 0){
+ CATCH_EINTR(n = waitpid(pid, NULL, 0));
+- pid = -errno;
++ ret = -errno;
++ } else {
++ ret = pid;
+ }
+
+- if(stack_out == NULL) free_stack(stack, 0);
+- else *stack_out = stack;
+- return(pid);
+-
+- out_kill:
+- os_kill_process(pid, 1);
+ out_close:
++ if (fds[1] != -1)
++ os_close_file(fds[1]);
+ os_close_file(fds[0]);
+- os_close_file(fds[1]);
+ out_free:
+- free_stack(stack, 0);
+- return(err);
++ if(stack_out == NULL)
++ free_stack(stack, 0);
++ else *stack_out = stack;
++ return(ret);
+ }
+
+ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
+Index: linux-2.6.10/arch/um/kernel/irq_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/irq_user.c 2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/irq_user.c 2005-04-06 23:44:30.263021912 +0800
+@@ -374,6 +374,8 @@
+ if(err)
+ return(err);
+ }
++ /* If there is a signal already queued, after unblocking ignore it */
++ set_handler(SIGIO, SIG_IGN, 0, -1);
+
+ return(0);
+ }
+Index: linux-2.6.10/arch/um/kernel/mem.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/mem.c 2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/mem.c 2005-04-06 23:44:30.279019480 +0800
+@@ -175,6 +175,30 @@
+ }
+ #endif /* CONFIG_HIGHMEM */
+
++static void __init fixaddr_user_init( void)
++{
++ long size = FIXADDR_USER_END - FIXADDR_USER_START;
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
++ unsigned long paddr, vaddr = FIXADDR_USER_START;
++
++ if ( ! size )
++ return;
++
++ fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
++ paddr = (unsigned long)alloc_bootmem_low_pages( size);
++ memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
++ paddr = __pa(paddr);
++ for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE) {
++ pgd = swapper_pg_dir + pgd_index(vaddr);
++ pmd = pmd_offset(pgd, vaddr);
++ pte = pte_offset_kernel(pmd, vaddr);
++ /*pte_set_val( (*pte), paddr, PAGE_READONLY);*/
++ pte_val(*pte) = paddr | pgprot_val(PAGE_READONLY);
++ }
++}
++
+ void paging_init(void)
+ {
+ unsigned long zones_size[MAX_NR_ZONES], vaddr;
+@@ -195,6 +219,8 @@
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
+
++ fixaddr_user_init();
++
+ #ifdef CONFIG_HIGHMEM
+ init_highmem();
+ #endif
+Index: linux-2.6.10/arch/um/kernel/skas/process.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/process.c 2004-12-25 05:35:39.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/process.c 2005-04-06 23:44:30.268021152 +0800
+@@ -11,6 +11,7 @@
+ #include <sched.h>
+ #include <sys/wait.h>
+ #include <sys/ptrace.h>
++#include <linux/ptrace.h>
+ #include <sys/mman.h>
+ #include <sys/user.h>
+ #include <asm/unistd.h>
+@@ -60,15 +61,10 @@
+ /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
+ {
+- int err, syscall_nr, status;
+-
+- syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+- UPT_SYSCALL_NR(regs) = syscall_nr;
+- if(syscall_nr < 0){
+- relay_signal(SIGTRAP, regs);
+- return;
+- }
+
++ int err, status;
++
++ UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); /* Mark this as a syscall */
+ if (!local_using_sysemu)
+ {
+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+@@ -82,7 +78,8 @@
+ "errno = %d\n", errno);
+
+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+- if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
++ if((err < 0) || !WIFSTOPPED(status) ||
++ (WSTOPSIG(status) != (SIGTRAP|SYSCALL_TRAP)))
+ panic("handle_trap - failed to wait at end of syscall, "
+ "errno = %d, status = %d\n", errno, status);
+ }
+@@ -131,6 +128,10 @@
+ panic("start_userspace : expected SIGSTOP, got status = %d",
+ status);
+
++ if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
++ panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n",
++ errno);
++
+ if(munmap(stack, PAGE_SIZE) < 0)
+ panic("start_userspace : munmap failed, errno = %d\n", errno);
+
+@@ -160,15 +161,19 @@
+
+ regs->skas.is_user = 1;
+ save_registers(regs);
++ UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
+
+ if(WIFSTOPPED(status)){
+ switch(WSTOPSIG(status)){
+ case SIGSEGV:
+ handle_segv(pid);
+ break;
+- case SIGTRAP:
++ case (SIGTRAP|SYSCALL_TRAP):
+ handle_trap(pid, regs, local_using_sysemu);
+ break;
++ case SIGTRAP:
++ relay_signal(SIGTRAP, regs);
++ break;
+ case SIGIO:
+ case SIGVTALRM:
+ case SIGILL:
+@@ -222,9 +227,10 @@
+ block_signals();
+ if(sigsetjmp(fork_buf, 1) == 0)
+ new_thread_proc(stack, handler);
+- set_signals(flags);
+
+ remove_sigstack();
++
++ set_signals(flags);
+ }
+
+ void thread_wait(void *sw, void *fb)
+Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/Makefile 2004-12-25 05:35:27.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/sys-i386/Makefile 2005-04-07 06:37:43.373923992 +0800
+@@ -1,12 +0,0 @@
+-#
+-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+-# Licensed under the GPL
+-#
+-
+-obj-y = sigcontext.o
+-
+-USER_OBJS = sigcontext.o
+-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+-
+-$(USER_OBJS) : %.o: %.c
+- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+Index: linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/sys-i386/sigcontext.c 2004-12-25 05:33:51.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/sys-i386/sigcontext.c 2005-04-07 06:37:43.373923992 +0800
+@@ -1,114 +0,0 @@
+-/*
+- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#include <errno.h>
+-#include <asm/sigcontext.h>
+-#include <sys/ptrace.h>
+-#include <linux/ptrace.h>
+-#include "sysdep/ptrace.h"
+-#include "sysdep/ptrace_user.h"
+-#include "kern_util.h"
+-#include "user.h"
+-#include "sigcontext.h"
+-#include "mode.h"
+-
+-int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
+-{
+- struct sigcontext sc, *from = from_ptr;
+- unsigned long fpregs[FP_FRAME_SIZE];
+- int err;
+-
+- err = copy_from_user_proc(&sc, from, sizeof(sc));
+- err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs));
+- if(err)
+- return(err);
+-
+- regs->skas.regs[GS] = sc.gs;
+- regs->skas.regs[FS] = sc.fs;
+- regs->skas.regs[ES] = sc.es;
+- regs->skas.regs[DS] = sc.ds;
+- regs->skas.regs[EDI] = sc.edi;
+- regs->skas.regs[ESI] = sc.esi;
+- regs->skas.regs[EBP] = sc.ebp;
+- regs->skas.regs[UESP] = sc.esp;
+- regs->skas.regs[EBX] = sc.ebx;
+- regs->skas.regs[EDX] = sc.edx;
+- regs->skas.regs[ECX] = sc.ecx;
+- regs->skas.regs[EAX] = sc.eax;
+- regs->skas.regs[EIP] = sc.eip;
+- regs->skas.regs[CS] = sc.cs;
+- regs->skas.regs[EFL] = sc.eflags;
+- regs->skas.regs[SS] = sc.ss;
+- regs->skas.fault_addr = sc.cr2;
+- regs->skas.fault_type = FAULT_WRITE(sc.err);
+- regs->skas.trap_type = sc.trapno;
+-
+- err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
+- if(err < 0){
+- printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
+- "errno = %d\n", errno);
+- return(1);
+- }
+-
+- return(0);
+-}
+-
+-int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+- union uml_pt_regs *regs, unsigned long fault_addr,
+- int fault_type)
+-{
+- struct sigcontext sc, *to = to_ptr;
+- struct _fpstate *to_fp;
+- unsigned long fpregs[FP_FRAME_SIZE];
+- int err;
+-
+- sc.gs = regs->skas.regs[GS];
+- sc.fs = regs->skas.regs[FS];
+- sc.es = regs->skas.regs[ES];
+- sc.ds = regs->skas.regs[DS];
+- sc.edi = regs->skas.regs[EDI];
+- sc.esi = regs->skas.regs[ESI];
+- sc.ebp = regs->skas.regs[EBP];
+- sc.esp = regs->skas.regs[UESP];
+- sc.ebx = regs->skas.regs[EBX];
+- sc.edx = regs->skas.regs[EDX];
+- sc.ecx = regs->skas.regs[ECX];
+- sc.eax = regs->skas.regs[EAX];
+- sc.eip = regs->skas.regs[EIP];
+- sc.cs = regs->skas.regs[CS];
+- sc.eflags = regs->skas.regs[EFL];
+- sc.esp_at_signal = regs->skas.regs[UESP];
+- sc.ss = regs->skas.regs[SS];
+- sc.cr2 = fault_addr;
+- sc.err = TO_SC_ERR(fault_type);
+- sc.trapno = regs->skas.trap_type;
+-
+- err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
+- if(err < 0){
+- printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
+- "errno = %d\n", errno);
+- return(1);
+- }
+- to_fp = (struct _fpstate *)
+- (fp ? (unsigned long) fp : ((unsigned long) to + sizeof(*to)));
+- sc.fpstate = to_fp;
+-
+- if(err)
+- return(err);
+-
+- return(copy_to_user_proc(to, &sc, sizeof(sc)) ||
+- copy_to_user_proc(to_fp, fpregs, sizeof(fpregs)));
+-}
+-
+-/*
+- * Overrides for Emacs so that we follow Linus's tabbing style.
+- * Emacs will notice this stuff at the end of the file and automatically
+- * adjust the settings for this buffer only. This must remain at the end
+- * of the file.
+- * ---------------------------------------------------------------------------
+- * Local variables:
+- * c-file-style: "linux"
+- * End:
+- */
+Index: linux-2.6.10/arch/um/kernel/skas/process_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/process_kern.c 2004-12-25 05:35:50.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/process_kern.c 2005-04-06 23:44:30.268021152 +0800
+@@ -19,7 +19,6 @@
+ #include "os.h"
+ #include "user_util.h"
+ #include "tlb.h"
+-#include "frame.h"
+ #include "kern.h"
+ #include "mode.h"
+ #include "proc_mm.h"
+@@ -183,7 +182,6 @@
+ int start_uml_skas(void)
+ {
+ start_userspace(0);
+- capture_signal_stack();
+
+ init_new_thread_signals(1);
+ uml_idle_timer();
+Index: linux-2.6.10/arch/um/kernel/skas/trap_user.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/trap_user.c 2004-12-25 05:34:32.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/trap_user.c 2005-04-06 23:44:30.269021000 +0800
+@@ -21,6 +21,14 @@
+ int save_errno = errno;
+ int save_user;
+
++ /* This is done because to allow SIGSEGV to be delivered inside a SEGV
++ * handler. This can happen in copy_user, and if SEGV is disabled,
++ * the process will die.
++ * XXX Figure out why this is better than SA_NODEFER
++ */
++ if(sig == SIGSEGV)
++ change_sig(SIGSEGV, 1);
++
+ r = &TASK_REGS(get_current())->skas;
+ save_user = r->is_user;
+ r->is_user = 0;
+Index: linux-2.6.10/arch/um/kernel/skas/syscall_kern.c
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/syscall_kern.c 2004-12-25 05:35:00.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/syscall_kern.c 2005-04-06 23:44:30.269021000 +0800
+@@ -6,6 +6,7 @@
+ #include "linux/sys.h"
+ #include "linux/ptrace.h"
+ #include "asm/errno.h"
++#include "linux/ptrace.h"
+ #include "asm/unistd.h"
+ #include "asm/ptrace.h"
+ #include "asm/current.h"
+Index: linux-2.6.10/arch/um/kernel/skas/Makefile
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/Makefile 2004-12-25 05:34:30.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/Makefile 2005-04-06 23:44:30.270020848 +0800
+@@ -4,8 +4,7 @@
+ #
+
+ obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
+- syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
+- sys-$(SUBARCH)/
++ syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o
+
+ subdir-y := util
+
+Index: linux-2.6.10/arch/um/kernel/skas/include/mmu-skas.h
+===================================================================
+--- linux-2.6.10.orig/arch/um/kernel/skas/include/mmu-skas.h 2004-12-25 05:35:24.000000000 +0800
++++ linux-2.6.10/arch/um/kernel/skas/include/mmu-skas.h 2005-04-06 23:44:30.265021608 +0800
+@@ -22,3 +22,27 @@
+ * c-file-style: "linux"
+ * End:
+ */
++/*
++ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
++ * Licensed under the GPL
++ */
++
++#ifndef __SKAS_MMU_H
++#define __SKAS_MMU_H