signal.c 7.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
 * Copyright (C) 2004 PathScale, Inc
J
Jeff Dike 已提交
3
 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
L
Linus Torvalds 已提交
4 5 6
 * Licensed under the GPL
 */

7 8
#include <stdlib.h>
#include <stdarg.h>
J
Jeff Dike 已提交
9 10 11
#include <errno.h>
#include <signal.h>
#include <strings.h>
J
Jeff Dike 已提交
12 13
#include "as-layout.h"
#include "kern_constants.h"
J
Jeff Dike 已提交
14
#include "kern_util.h"
15
#include "os.h"
J
Jeff Dike 已提交
16 17
#include "sysdep/barrier.h"
#include "sysdep/sigcontext.h"
J
Jeff Dike 已提交
18
#include "task.h"
J
Jeff Dike 已提交
19
#include "user.h"
L
Linus Torvalds 已提交
20

J
Jeff Dike 已提交
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
	[SIGTRAP]	= relay_signal,
	[SIGFPE]	= relay_signal,
	[SIGILL]	= relay_signal,
	[SIGWINCH]	= winch,
	[SIGBUS]	= bus_handler,
	[SIGSEGV]	= segv_handler,
	[SIGIO]		= sigio_handler,
	[SIGVTALRM]	= timer_handler };

static struct uml_pt_regs ksig_regs[UM_NR_CPUS];

void sig_handler_common_skas(int sig, void *sc_ptr)
{
	struct sigcontext *sc = sc_ptr;
	struct uml_pt_regs *r;
	void (*handler)(int, struct uml_pt_regs *);
	int save_user, save_errno = errno;

	/*
	 * 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);
		/*
		 * For segfaults, we want the data from the
		 * sigcontext.  In this case, we don't want to mangle
		 * the process registers, so use a static set of
		 * registers.  For other signals, the process
		 * registers are OK.
		 */
		r = &ksig_regs[cpu()];
		copy_sc(r, sc_ptr);
	} else
		r = TASK_REGS(get_current());

	save_user = r->is_user;
	r->is_user = 0;
	if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
	    (sig == SIGILL) || (sig == SIGTRAP))
		GET_FAULTINFO_FROM_SC(r->faultinfo, sc);

	change_sig(SIGUSR1, 1);

	handler = sig_info[sig];

	/* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
	if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
		unblock_signals();

	handler(sig, r);

	errno = save_errno;
	r->is_user = save_user;
}

J
Jeff Dike 已提交
80 81 82
/* Copied from linux/compiler-gcc.h since we can't include it directly */
#define barrier() __asm__ __volatile__("": : :"memory")

J
Jeff Dike 已提交
83
/*
J
Jeff Dike 已提交
84
 * These are the asynchronous signals.  SIGPROF is excluded because we want to
85 86 87 88 89 90 91 92 93 94
 * be able to profile all of UML, not just the non-critical sections.  If
 * profiling is not thread-safe, then that is not my problem.  We can disable
 * profiling when SMP is enabled in that case.
 */
#define SIGIO_BIT 0
#define SIGIO_MASK (1 << SIGIO_BIT)

#define SIGVTALRM_BIT 1
#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)

J
Jeff Dike 已提交
95 96
static int signals_enabled;
static unsigned int pending;
97

98
void sig_handler(int sig, struct sigcontext *sc)
L
Linus Torvalds 已提交
99
{
100 101 102
	int enabled;

	enabled = signals_enabled;
J
Jeff Dike 已提交
103
	if (!enabled && (sig == SIGIO)) {
104 105 106 107 108 109
		pending |= SIGIO_MASK;
		return;
	}

	block_signals();

J
Jeff Dike 已提交
110
	sig_handler_common_skas(sig, sc);
111 112

	set_signals(enabled);
L
Linus Torvalds 已提交
113 114
}

J
Jeff Dike 已提交
115
static void real_alarm_handler(struct sigcontext *sc)
L
Linus Torvalds 已提交
116
{
117
	struct uml_pt_regs regs;
J
Jeff Dike 已提交
118

J
Jeff Dike 已提交
119
	if (sc != NULL)
J
Jeff Dike 已提交
120
		copy_sc(&regs, sc);
121
	regs.is_user = 0;
J
Jeff Dike 已提交
122
	unblock_signals();
J
Jeff Dike 已提交
123
	timer_handler(SIGVTALRM, &regs);
124 125
}

126
void alarm_handler(int sig, struct sigcontext *sc)
127 128 129 130
{
	int enabled;

	enabled = signals_enabled;
J
Jeff Dike 已提交
131
	if (!signals_enabled) {
J
Jeff Dike 已提交
132
		pending |= SIGVTALRM_MASK;
133 134 135 136 137
		return;
	}

	block_signals();

J
Jeff Dike 已提交
138
	real_alarm_handler(sc);
139
	set_signals(enabled);
L
Linus Torvalds 已提交
140 141
}

J
Jeff Dike 已提交
142 143 144
void timer_init(void)
{
	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
J
Jeff Dike 已提交
145
		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
J
Jeff Dike 已提交
146 147
}

148 149 150 151 152 153
void set_sigstack(void *sig_stack, int size)
{
	stack_t stack = ((stack_t) { .ss_flags	= 0,
				     .ss_sp	= (__ptr_t) sig_stack,
				     .ss_size 	= size - sizeof(void *) });

J
Jeff Dike 已提交
154
	if (sigaltstack(&stack, NULL) != 0)
155 156 157 158 159 160 161 162 163
		panic("enabling signal stack failed, errno = %d\n", errno);
}

void remove_sigstack(void)
{
	stack_t stack = ((stack_t) { .ss_flags	= SS_DISABLE,
				     .ss_sp	= NULL,
				     .ss_size	= 0 });

J
Jeff Dike 已提交
164
	if (sigaltstack(&stack, NULL) != 0)
165 166 167
		panic("disabling signal stack failed, errno = %d\n", errno);
}

168 169
void (*handlers[_NSIG])(int sig, struct sigcontext *sc);

J
Jeff Dike 已提交
170 171
void handle_signal(int sig, struct sigcontext *sc)
{
J
Jeff Dike 已提交
172
	unsigned long pending = 1UL << sig;
J
Jeff Dike 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186

	do {
		int nested, bail;

		/*
		 * pending comes back with one bit set for each
		 * interrupt that arrived while setting up the stack,
		 * plus a bit for this interrupt, plus the zero bit is
		 * set if this is a nested interrupt.
		 * If bail is true, then we interrupted another
		 * handler setting up the stack.  In this case, we
		 * have to return, and the upper handler will deal
		 * with this interrupt.
		 */
J
Jeff Dike 已提交
187
		bail = to_irq_stack(&pending);
J
Jeff Dike 已提交
188
		if (bail)
J
Jeff Dike 已提交
189 190 191 192 193
			return;

		nested = pending & 1;
		pending &= ~1;

J
Jeff Dike 已提交
194
		while ((sig = ffs(pending)) != 0){
J
Jeff Dike 已提交
195 196 197 198 199
			sig--;
			pending &= ~(1 << sig);
			(*handlers[sig])(sig, sc);
		}

J
Jeff Dike 已提交
200 201
		/*
		 * Again, pending comes back with a mask of signals
J
Jeff Dike 已提交
202 203 204 205
		 * that arrived while tearing down the stack.  If this
		 * is non-zero, we just go back, set up the stack
		 * again, and handle the new interrupts.
		 */
J
Jeff Dike 已提交
206
		if (!nested)
J
Jeff Dike 已提交
207
			pending = from_irq_stack(nested);
J
Jeff Dike 已提交
208
	} while (pending);
J
Jeff Dike 已提交
209 210
}

211 212
extern void hard_handler(int sig);

213 214 215 216
void set_handler(int sig, void (*handler)(int), int flags, ...)
{
	struct sigaction action;
	va_list ap;
217
	sigset_t sig_mask;
218 219
	int mask;

220 221 222
	handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
	action.sa_handler = hard_handler;

223
	sigemptyset(&action.sa_mask);
224 225

	va_start(ap, flags);
J
Jeff Dike 已提交
226
	while ((mask = va_arg(ap, int)) != -1)
227 228
		sigaddset(&action.sa_mask, mask);
	va_end(ap);
229

230 231
	action.sa_flags = flags;
	action.sa_restorer = NULL;
J
Jeff Dike 已提交
232
	if (sigaction(sig, &action, NULL) < 0)
233 234 235 236
		panic("sigaction failed - errno = %d\n", errno);

	sigemptyset(&sig_mask);
	sigaddset(&sig_mask, sig);
J
Jeff Dike 已提交
237
	if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
238
		panic("sigprocmask failed - errno = %d\n", errno);
239 240 241 242 243 244 245 246
}

int change_sig(int signal, int on)
{
	sigset_t sigset, old;

	sigemptyset(&sigset);
	sigaddset(&sigset, signal);
247 248
	if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old) < 0)
		return -errno;
J
Jeff Dike 已提交
249
	return !sigismember(&old, signal);
250 251 252 253
}

void block_signals(void)
{
254
	signals_enabled = 0;
J
Jeff Dike 已提交
255 256
	/*
	 * This must return with signals disabled, so this barrier
J
Jeff Dike 已提交
257 258 259 260
	 * ensures that writes are flushed out before the return.
	 * This might matter if gcc figures out how to inline this and
	 * decides to shuffle this code into the caller.
	 */
J
Jeff Dike 已提交
261
	barrier();
262 263 264 265
}

void unblock_signals(void)
{
266
	int save_pending;
267

J
Jeff Dike 已提交
268
	if (signals_enabled == 1)
269
		return;
270

J
Jeff Dike 已提交
271 272
	/*
	 * We loop because the IRQ handler returns with interrupts off.  So,
273 274 275
	 * interrupts may have arrived and we need to re-enable them and
	 * recheck pending.
	 */
J
Jeff Dike 已提交
276 277 278
	while(1) {
		/*
		 * Save and reset save_pending after enabling signals.  This
279 280 281 282
		 * way, pending won't be changed while we're reading it.
		 */
		signals_enabled = 1;

J
Jeff Dike 已提交
283 284
		/*
		 * Setting signals_enabled and reading pending must
J
Jeff Dike 已提交
285 286
		 * happen in this order.
		 */
J
Jeff Dike 已提交
287
		barrier();
J
Jeff Dike 已提交
288

289
		save_pending = pending;
J
Jeff Dike 已提交
290
		if (save_pending == 0)
291 292 293 294
			return;

		pending = 0;

J
Jeff Dike 已提交
295 296
		/*
		 * We have pending interrupts, so disable signals, as the
297 298 299 300 301 302
		 * handlers expect them off when they are called.  They will
		 * be enabled again above.
		 */

		signals_enabled = 0;

J
Jeff Dike 已提交
303 304
		/*
		 * Deal with SIGIO first because the alarm handler might
305 306 307
		 * schedule, leaving the pending SIGIO stranded until we come
		 * back here.
		 */
J
Jeff Dike 已提交
308
		if (save_pending & SIGIO_MASK)
J
Jeff Dike 已提交
309
			sig_handler_common_skas(SIGIO, NULL);
310

J
Jeff Dike 已提交
311
		if (save_pending & SIGVTALRM_MASK)
J
Jeff Dike 已提交
312
			real_alarm_handler(NULL);
313
	}
314 315 316 317
}

int get_signals(void)
{
318
	return signals_enabled;
319 320 321 322 323
}

int set_signals(int enable)
{
	int ret;
J
Jeff Dike 已提交
324
	if (signals_enabled == enable)
325
		return enable;
326

327
	ret = signals_enabled;
J
Jeff Dike 已提交
328
	if (enable)
329 330
		unblock_signals();
	else block_signals();
331

332
	return ret;
333
}