aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/signal.c')
-rw-r--r--arch/um/os-Linux/signal.c63
1 files changed, 18 insertions, 45 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index cde9e766b5b4..91a35da5fe90 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -10,14 +10,15 @@
10#include <signal.h> 10#include <signal.h>
11#include <strings.h> 11#include <strings.h>
12#include "as-layout.h" 12#include "as-layout.h"
13#include "kern_constants.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "os.h" 14#include "os.h"
16#include "sysdep/barrier.h" 15#include "sysdep/barrier.h"
17#include "sysdep/sigcontext.h" 16#include "sysdep/sigcontext.h"
18#include "task.h"
19#include "user.h" 17#include "user.h"
20 18
19/* Copied from linux/compiler-gcc.h since we can't include it directly */
20#define barrier() __asm__ __volatile__("": : :"memory")
21
21void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { 22void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
22 [SIGTRAP] = relay_signal, 23 [SIGTRAP] = relay_signal,
23 [SIGFPE] = relay_signal, 24 [SIGFPE] = relay_signal,
@@ -28,58 +29,27 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
28 [SIGIO] = sigio_handler, 29 [SIGIO] = sigio_handler,
29 [SIGVTALRM] = timer_handler }; 30 [SIGVTALRM] = timer_handler };
30 31
31static struct uml_pt_regs ksig_regs[UM_NR_CPUS]; 32static void sig_handler_common(int sig, struct sigcontext *sc)
32
33void sig_handler_common_skas(int sig, void *sc_ptr)
34{ 33{
35 struct sigcontext *sc = sc_ptr; 34 struct uml_pt_regs r;
36 struct uml_pt_regs *r; 35 int save_errno = errno;
37 void (*handler)(int, struct uml_pt_regs *);
38 int save_user, save_errno = errno;
39 36
40 /* 37 r.is_user = 0;
41 * This is done because to allow SIGSEGV to be delivered inside a SEGV
42 * handler. This can happen in copy_user, and if SEGV is disabled,
43 * the process will die.
44 * XXX Figure out why this is better than SA_NODEFER
45 */
46 if (sig == SIGSEGV) { 38 if (sig == SIGSEGV) {
47 change_sig(SIGSEGV, 1); 39 /* For segfaults, we want the data from the sigcontext. */
48 /* 40 copy_sc(&r, sc);
49 * For segfaults, we want the data from the 41 GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
50 * sigcontext. In this case, we don't want to mangle 42 }
51 * the process registers, so use a static set of
52 * registers. For other signals, the process
53 * registers are OK.
54 */
55 r = &ksig_regs[cpu()];
56 copy_sc(r, sc_ptr);
57 } else
58 r = TASK_REGS(get_current());
59
60 save_user = r->is_user;
61 r->is_user = 0;
62 if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
63 (sig == SIGILL) || (sig == SIGTRAP))
64 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
65
66 change_sig(SIGUSR1, 1);
67
68 handler = sig_info[sig];
69 43
70 /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */ 44 /* enable signals if sig isn't IRQ signal */
71 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) 45 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
72 unblock_signals(); 46 unblock_signals();
73 47
74 handler(sig, r); 48 (*sig_info[sig])(sig, &r);
75 49
76 errno = save_errno; 50 errno = save_errno;
77 r->is_user = save_user;
78} 51}
79 52
80/* Copied from linux/compiler-gcc.h since we can't include it directly */
81#define barrier() __asm__ __volatile__("": : :"memory")
82
83/* 53/*
84 * These are the asynchronous signals. SIGPROF is excluded because we want to 54 * These are the asynchronous signals. SIGPROF is excluded because we want to
85 * be able to profile all of UML, not just the non-critical sections. If 55 * be able to profile all of UML, not just the non-critical sections. If
@@ -107,7 +77,7 @@ void sig_handler(int sig, struct sigcontext *sc)
107 77
108 block_signals(); 78 block_signals();
109 79
110 sig_handler_common_skas(sig, sc); 80 sig_handler_common(sig, sc);
111 81
112 set_signals(enabled); 82 set_signals(enabled);
113} 83}
@@ -227,6 +197,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
227 sigaddset(&action.sa_mask, mask); 197 sigaddset(&action.sa_mask, mask);
228 va_end(ap); 198 va_end(ap);
229 199
200 if (sig == SIGSEGV)
201 flags |= SA_NODEFER;
202
230 action.sa_flags = flags; 203 action.sa_flags = flags;
231 action.sa_restorer = NULL; 204 action.sa_restorer = NULL;
232 if (sigaction(sig, &action, NULL) < 0) 205 if (sigaction(sig, &action, NULL) < 0)
@@ -306,7 +279,7 @@ void unblock_signals(void)
306 * back here. 279 * back here.
307 */ 280 */
308 if (save_pending & SIGIO_MASK) 281 if (save_pending & SIGIO_MASK)
309 sig_handler_common_skas(SIGIO, NULL); 282 sig_handler_common(SIGIO, NULL);
310 283
311 if (save_pending & SIGVTALRM_MASK) 284 if (save_pending & SIGVTALRM_MASK)
312 real_alarm_handler(NULL); 285 real_alarm_handler(NULL);