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.c72
1 files changed, 38 insertions, 34 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 6ae180703a63..2d22f1fcd8e2 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -12,13 +12,7 @@
12#include "as-layout.h" 12#include "as-layout.h"
13#include "kern_util.h" 13#include "kern_util.h"
14#include "os.h" 14#include "os.h"
15#include "process.h" 15#include "sysdep/mcontext.h"
16#include "sysdep/barrier.h"
17#include "sysdep/sigcontext.h"
18#include "user.h"
19
20/* Copied from linux/compiler-gcc.h since we can't include it directly */
21#define barrier() __asm__ __volatile__("": : :"memory")
22 16
23void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { 17void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
24 [SIGTRAP] = relay_signal, 18 [SIGTRAP] = relay_signal,
@@ -30,7 +24,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
30 [SIGIO] = sigio_handler, 24 [SIGIO] = sigio_handler,
31 [SIGVTALRM] = timer_handler }; 25 [SIGVTALRM] = timer_handler };
32 26
33static void sig_handler_common(int sig, struct sigcontext *sc) 27static void sig_handler_common(int sig, mcontext_t *mc)
34{ 28{
35 struct uml_pt_regs r; 29 struct uml_pt_regs r;
36 int save_errno = errno; 30 int save_errno = errno;
@@ -38,8 +32,8 @@ static void sig_handler_common(int sig, struct sigcontext *sc)
38 r.is_user = 0; 32 r.is_user = 0;
39 if (sig == SIGSEGV) { 33 if (sig == SIGSEGV) {
40 /* For segfaults, we want the data from the sigcontext. */ 34 /* For segfaults, we want the data from the sigcontext. */
41 copy_sc(&r, sc); 35 get_regs_from_mc(&r, mc);
42 GET_FAULTINFO_FROM_SC(r.faultinfo, sc); 36 GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
43 } 37 }
44 38
45 /* enable signals if sig isn't IRQ signal */ 39 /* enable signals if sig isn't IRQ signal */
@@ -66,7 +60,7 @@ static void sig_handler_common(int sig, struct sigcontext *sc)
66static int signals_enabled; 60static int signals_enabled;
67static unsigned int signals_pending; 61static unsigned int signals_pending;
68 62
69void sig_handler(int sig, struct sigcontext *sc) 63void sig_handler(int sig, mcontext_t *mc)
70{ 64{
71 int enabled; 65 int enabled;
72 66
@@ -78,23 +72,23 @@ void sig_handler(int sig, struct sigcontext *sc)
78 72
79 block_signals(); 73 block_signals();
80 74
81 sig_handler_common(sig, sc); 75 sig_handler_common(sig, mc);
82 76
83 set_signals(enabled); 77 set_signals(enabled);
84} 78}
85 79
86static void real_alarm_handler(struct sigcontext *sc) 80static void real_alarm_handler(mcontext_t *mc)
87{ 81{
88 struct uml_pt_regs regs; 82 struct uml_pt_regs regs;
89 83
90 if (sc != NULL) 84 if (mc != NULL)
91 copy_sc(&regs, sc); 85 get_regs_from_mc(&regs, mc);
92 regs.is_user = 0; 86 regs.is_user = 0;
93 unblock_signals(); 87 unblock_signals();
94 timer_handler(SIGVTALRM, &regs); 88 timer_handler(SIGVTALRM, &regs);
95} 89}
96 90
97void alarm_handler(int sig, struct sigcontext *sc) 91void alarm_handler(int sig, mcontext_t *mc)
98{ 92{
99 int enabled; 93 int enabled;
100 94
@@ -106,14 +100,13 @@ void alarm_handler(int sig, struct sigcontext *sc)
106 100
107 block_signals(); 101 block_signals();
108 102
109 real_alarm_handler(sc); 103 real_alarm_handler(mc);
110 set_signals(enabled); 104 set_signals(enabled);
111} 105}
112 106
113void timer_init(void) 107void timer_init(void)
114{ 108{
115 set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, 109 set_handler(SIGVTALRM);
116 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
117} 110}
118 111
119void set_sigstack(void *sig_stack, int size) 112void set_sigstack(void *sig_stack, int size)
@@ -126,10 +119,23 @@ void set_sigstack(void *sig_stack, int size)
126 panic("enabling signal stack failed, errno = %d\n", errno); 119 panic("enabling signal stack failed, errno = %d\n", errno);
127} 120}
128 121
129static void (*handlers[_NSIG])(int sig, struct sigcontext *sc); 122static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = {
123 [SIGSEGV] = sig_handler,
124 [SIGBUS] = sig_handler,
125 [SIGILL] = sig_handler,
126 [SIGFPE] = sig_handler,
127 [SIGTRAP] = sig_handler,
128
129 [SIGIO] = sig_handler,
130 [SIGWINCH] = sig_handler,
131 [SIGVTALRM] = alarm_handler
132};
133
130 134
131void handle_signal(int sig, struct sigcontext *sc) 135static void hard_handler(int sig, siginfo_t *info, void *p)
132{ 136{
137 struct ucontext *uc = p;
138 mcontext_t *mc = &uc->uc_mcontext;
133 unsigned long pending = 1UL << sig; 139 unsigned long pending = 1UL << sig;
134 140
135 do { 141 do {
@@ -155,7 +161,7 @@ void handle_signal(int sig, struct sigcontext *sc)
155 while ((sig = ffs(pending)) != 0){ 161 while ((sig = ffs(pending)) != 0){
156 sig--; 162 sig--;
157 pending &= ~(1 << sig); 163 pending &= ~(1 << sig);
158 (*handlers[sig])(sig, sc); 164 (*handlers[sig])(sig, mc);
159 } 165 }
160 166
161 /* 167 /*
@@ -169,28 +175,26 @@ void handle_signal(int sig, struct sigcontext *sc)
169 } while (pending); 175 } while (pending);
170} 176}
171 177
172extern void hard_handler(int sig); 178void set_handler(int sig)
173
174void set_handler(int sig, void (*handler)(int), int flags, ...)
175{ 179{
176 struct sigaction action; 180 struct sigaction action;
177 va_list ap; 181 int flags = SA_SIGINFO | SA_ONSTACK;
178 sigset_t sig_mask; 182 sigset_t sig_mask;
179 int mask;
180 183
181 handlers[sig] = (void (*)(int, struct sigcontext *)) handler; 184 action.sa_sigaction = hard_handler;
182 action.sa_handler = hard_handler;
183 185
186 /* block irq ones */
184 sigemptyset(&action.sa_mask); 187 sigemptyset(&action.sa_mask);
185 188 sigaddset(&action.sa_mask, SIGVTALRM);
186 va_start(ap, flags); 189 sigaddset(&action.sa_mask, SIGIO);
187 while ((mask = va_arg(ap, int)) != -1) 190 sigaddset(&action.sa_mask, SIGWINCH);
188 sigaddset(&action.sa_mask, mask);
189 va_end(ap);
190 191
191 if (sig == SIGSEGV) 192 if (sig == SIGSEGV)
192 flags |= SA_NODEFER; 193 flags |= SA_NODEFER;
193 194
195 if (sigismember(&action.sa_mask, sig))
196 flags |= SA_RESTART; /* if it's an irq signal */
197
194 action.sa_flags = flags; 198 action.sa_flags = flags;
195 action.sa_restorer = NULL; 199 action.sa_restorer = NULL;
196 if (sigaction(sig, &action, NULL) < 0) 200 if (sigaction(sig, &action, NULL) < 0)