summaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/tt/trap_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/tt/trap_user.c')
-rw-r--r--arch/um/kernel/tt/trap_user.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
new file mode 100644
index 000000000000..92a3820ca543
--- /dev/null
+++ b/arch/um/kernel/tt/trap_user.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include "sysdep/ptrace.h"
+#include "signal_user.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "task.h"
+#include "tt.h"
+
+void sig_handler_common_tt(int sig, void *sc_ptr)
+{
+ struct sigcontext *sc = sc_ptr;
+ struct tt_regs save_regs, *r;
+ struct signal_info *info;
+ int save_errno = errno, is_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.
+ */
+ if(sig == SIGSEGV)
+ change_sig(SIGSEGV, 1);
+
+ r = &TASK_REGS(get_current())->tt;
+ save_regs = *r;
+ is_user = user_context(SC_SP(sc));
+ r->sc = sc;
+ if(sig != SIGUSR2)
+ r->syscall = -1;
+
+ info = &sig_info[sig];
+ if(!info->is_irq) unblock_signals();
+
+ (*info->handler)(sig, (union uml_pt_regs *) r);
+
+ if(is_user){
+ interrupt_end();
+ block_signals();
+ set_user_mode(NULL);
+ }
+ *r = save_regs;
+ errno = save_errno;
+}
+
+/*
+ * 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:
+ */