uml: fix irqstack crash
[sfrench/cifs-2.6.git] / arch / um / os-Linux / signal.c
1 /*
2  * Copyright (C) 2004 PathScale, Inc
3  * Licensed under the GPL
4  */
5
6 #include <signal.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <sys/mman.h>
14 #include "user.h"
15 #include "signal_kern.h"
16 #include "sysdep/sigcontext.h"
17 #include "sysdep/barrier.h"
18 #include "sigcontext.h"
19 #include "mode.h"
20 #include "os.h"
21
22 /* These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
23  * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
24  * be able to profile all of UML, not just the non-critical sections.  If
25  * profiling is not thread-safe, then that is not my problem.  We can disable
26  * profiling when SMP is enabled in that case.
27  */
28 #define SIGIO_BIT 0
29 #define SIGIO_MASK (1 << SIGIO_BIT)
30
31 #define SIGVTALRM_BIT 1
32 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
33
34 #define SIGALRM_BIT 2
35 #define SIGALRM_MASK (1 << SIGALRM_BIT)
36
37 /* These are used by both the signal handlers and
38  * block/unblock_signals.  I don't want modifications cached in a
39  * register - they must go straight to memory.
40  */
41 static volatile int signals_enabled = 1;
42 static volatile int pending = 0;
43
44 void sig_handler(int sig, struct sigcontext *sc)
45 {
46         int enabled;
47
48         enabled = signals_enabled;
49         if(!enabled && (sig == SIGIO)){
50                 pending |= SIGIO_MASK;
51                 return;
52         }
53
54         block_signals();
55
56         CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
57                          sig, sc);
58
59         set_signals(enabled);
60 }
61
62 static void real_alarm_handler(int sig, struct sigcontext *sc)
63 {
64         union uml_pt_regs regs;
65
66         if(sig == SIGALRM)
67                 switch_timers(0);
68
69         if(sc != NULL)
70                 copy_sc(&regs, sc);
71         regs.skas.is_user = 0;
72         unblock_signals();
73         timer_handler(sig, &regs);
74
75         if(sig == SIGALRM)
76                 switch_timers(1);
77 }
78
79 void alarm_handler(int sig, struct sigcontext *sc)
80 {
81         int enabled;
82
83         enabled = signals_enabled;
84         if(!signals_enabled){
85                 if(sig == SIGVTALRM)
86                         pending |= SIGVTALRM_MASK;
87                 else pending |= SIGALRM_MASK;
88
89                 return;
90         }
91
92         block_signals();
93
94         real_alarm_handler(sig, sc);
95         set_signals(enabled);
96 }
97
98 void set_sigstack(void *sig_stack, int size)
99 {
100         stack_t stack = ((stack_t) { .ss_flags  = 0,
101                                      .ss_sp     = (__ptr_t) sig_stack,
102                                      .ss_size   = size - sizeof(void *) });
103
104         if(sigaltstack(&stack, NULL) != 0)
105                 panic("enabling signal stack failed, errno = %d\n", errno);
106 }
107
108 void remove_sigstack(void)
109 {
110         stack_t stack = ((stack_t) { .ss_flags  = SS_DISABLE,
111                                      .ss_sp     = NULL,
112                                      .ss_size   = 0 });
113
114         if(sigaltstack(&stack, NULL) != 0)
115                 panic("disabling signal stack failed, errno = %d\n", errno);
116 }
117
118 void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
119
120 void handle_signal(int sig, struct sigcontext *sc)
121 {
122         unsigned long pending = 1UL << sig;
123
124         do {
125                 int nested, bail;
126
127                 /*
128                  * pending comes back with one bit set for each
129                  * interrupt that arrived while setting up the stack,
130                  * plus a bit for this interrupt, plus the zero bit is
131                  * set if this is a nested interrupt.
132                  * If bail is true, then we interrupted another
133                  * handler setting up the stack.  In this case, we
134                  * have to return, and the upper handler will deal
135                  * with this interrupt.
136                  */
137                 bail = to_irq_stack(&pending);
138                 if(bail)
139                         return;
140
141                 nested = pending & 1;
142                 pending &= ~1;
143
144                 while((sig = ffs(pending)) != 0){
145                         sig--;
146                         pending &= ~(1 << sig);
147                         (*handlers[sig])(sig, sc);
148                 }
149
150                 /* Again, pending comes back with a mask of signals
151                  * that arrived while tearing down the stack.  If this
152                  * is non-zero, we just go back, set up the stack
153                  * again, and handle the new interrupts.
154                  */
155                 if(!nested)
156                         pending = from_irq_stack(nested);
157         } while(pending);
158 }
159
160 extern void hard_handler(int sig);
161
162 void set_handler(int sig, void (*handler)(int), int flags, ...)
163 {
164         struct sigaction action;
165         va_list ap;
166         sigset_t sig_mask;
167         int mask;
168
169         handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
170         action.sa_handler = hard_handler;
171
172         sigemptyset(&action.sa_mask);
173
174         va_start(ap, flags);
175         while((mask = va_arg(ap, int)) != -1)
176                 sigaddset(&action.sa_mask, mask);
177         va_end(ap);
178
179         action.sa_flags = flags;
180         action.sa_restorer = NULL;
181         if(sigaction(sig, &action, NULL) < 0)
182                 panic("sigaction failed - errno = %d\n", errno);
183
184         sigemptyset(&sig_mask);
185         sigaddset(&sig_mask, sig);
186         if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
187                 panic("sigprocmask failed - errno = %d\n", errno);
188 }
189
190 int change_sig(int signal, int on)
191 {
192         sigset_t sigset, old;
193
194         sigemptyset(&sigset);
195         sigaddset(&sigset, signal);
196         sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
197         return(!sigismember(&old, signal));
198 }
199
200 void block_signals(void)
201 {
202         signals_enabled = 0;
203         /* This must return with signals disabled, so this barrier
204          * ensures that writes are flushed out before the return.
205          * This might matter if gcc figures out how to inline this and
206          * decides to shuffle this code into the caller.
207          */
208         mb();
209 }
210
211 void unblock_signals(void)
212 {
213         int save_pending;
214
215         if(signals_enabled == 1)
216                 return;
217
218         /* We loop because the IRQ handler returns with interrupts off.  So,
219          * interrupts may have arrived and we need to re-enable them and
220          * recheck pending.
221          */
222         while(1){
223                 /* Save and reset save_pending after enabling signals.  This
224                  * way, pending won't be changed while we're reading it.
225                  */
226                 signals_enabled = 1;
227
228                 /* Setting signals_enabled and reading pending must
229                  * happen in this order.
230                  */
231                 mb();
232
233                 save_pending = pending;
234                 if(save_pending == 0){
235                         /* This must return with signals enabled, so
236                          * this barrier ensures that writes are
237                          * flushed out before the return.  This might
238                          * matter if gcc figures out how to inline
239                          * this (unlikely, given its size) and decides
240                          * to shuffle this code into the caller.
241                          */
242                         mb();
243                         return;
244                 }
245
246                 pending = 0;
247
248                 /* We have pending interrupts, so disable signals, as the
249                  * handlers expect them off when they are called.  They will
250                  * be enabled again above.
251                  */
252
253                 signals_enabled = 0;
254
255                 /* Deal with SIGIO first because the alarm handler might
256                  * schedule, leaving the pending SIGIO stranded until we come
257                  * back here.
258                  */
259                 if(save_pending & SIGIO_MASK)
260                         CHOOSE_MODE_PROC(sig_handler_common_tt,
261                                          sig_handler_common_skas, SIGIO, NULL);
262
263                 if(save_pending & SIGALRM_MASK)
264                         real_alarm_handler(SIGALRM, NULL);
265
266                 if(save_pending & SIGVTALRM_MASK)
267                         real_alarm_handler(SIGVTALRM, NULL);
268         }
269 }
270
271 int get_signals(void)
272 {
273         return signals_enabled;
274 }
275
276 int set_signals(int enable)
277 {
278         int ret;
279         if(signals_enabled == enable)
280                 return enable;
281
282         ret = signals_enabled;
283         if(enable)
284                 unblock_signals();
285         else block_signals();
286
287         return ret;
288 }