linux/arch/um/os-Linux/signal.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004 PathScale, Inc
   3 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4 * Licensed under the GPL
   5 */
   6
   7#include <stdlib.h>
   8#include <stdarg.h>
   9#include <errno.h>
  10#include <signal.h>
  11#include <strings.h>
  12#include <as-layout.h>
  13#include <kern_util.h>
  14#include <os.h>
  15#include <sysdep/mcontext.h>
  16#include "internal.h"
  17
  18void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
  19        [SIGTRAP]       = relay_signal,
  20        [SIGFPE]        = relay_signal,
  21        [SIGILL]        = relay_signal,
  22        [SIGWINCH]      = winch,
  23        [SIGBUS]        = bus_handler,
  24        [SIGSEGV]       = segv_handler,
  25        [SIGIO]         = sigio_handler,
  26        [SIGVTALRM]     = timer_handler };
  27
  28static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc)
  29{
  30        struct uml_pt_regs r;
  31        int save_errno = errno;
  32
  33        r.is_user = 0;
  34        if (sig == SIGSEGV) {
  35                /* For segfaults, we want the data from the sigcontext. */
  36                get_regs_from_mc(&r, mc);
  37                GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
  38        }
  39
  40        /* enable signals if sig isn't IRQ signal */
  41        if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
  42                unblock_signals();
  43
  44        (*sig_info[sig])(sig, si, &r);
  45
  46        errno = save_errno;
  47}
  48
  49/*
  50 * These are the asynchronous signals.  SIGPROF is excluded because we want to
  51 * be able to profile all of UML, not just the non-critical sections.  If
  52 * profiling is not thread-safe, then that is not my problem.  We can disable
  53 * profiling when SMP is enabled in that case.
  54 */
  55#define SIGIO_BIT 0
  56#define SIGIO_MASK (1 << SIGIO_BIT)
  57
  58#define SIGVTALRM_BIT 1
  59#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
  60
  61static int signals_enabled;
  62static unsigned int signals_pending;
  63
  64void sig_handler(int sig, siginfo_t *si, mcontext_t *mc)
  65{
  66        int enabled;
  67
  68        enabled = signals_enabled;
  69        if (!enabled && (sig == SIGIO)) {
  70                signals_pending |= SIGIO_MASK;
  71                return;
  72        }
  73
  74        block_signals();
  75
  76        sig_handler_common(sig, si, mc);
  77
  78        set_signals(enabled);
  79}
  80
  81static void real_alarm_handler(mcontext_t *mc)
  82{
  83        struct uml_pt_regs regs;
  84
  85        if (mc != NULL)
  86                get_regs_from_mc(&regs, mc);
  87        regs.is_user = 0;
  88        unblock_signals();
  89        timer_handler(SIGVTALRM, NULL, &regs);
  90}
  91
  92void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
  93{
  94        int enabled;
  95
  96        enabled = signals_enabled;
  97        if (!signals_enabled) {
  98                signals_pending |= SIGVTALRM_MASK;
  99                return;
 100        }
 101
 102        block_signals();
 103
 104        real_alarm_handler(mc);
 105        set_signals(enabled);
 106}
 107
 108void timer_init(void)
 109{
 110        set_handler(SIGVTALRM);
 111}
 112
 113void set_sigstack(void *sig_stack, int size)
 114{
 115        stack_t stack = ((stack_t) { .ss_flags  = 0,
 116                                     .ss_sp     = (__ptr_t) sig_stack,
 117                                     .ss_size   = size - sizeof(void *) });
 118
 119        if (sigaltstack(&stack, NULL) != 0)
 120                panic("enabling signal stack failed, errno = %d\n", errno);
 121}
 122
 123static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = {
 124        [SIGSEGV] = sig_handler,
 125        [SIGBUS] = sig_handler,
 126        [SIGILL] = sig_handler,
 127        [SIGFPE] = sig_handler,
 128        [SIGTRAP] = sig_handler,
 129
 130        [SIGIO] = sig_handler,
 131        [SIGWINCH] = sig_handler,
 132        [SIGVTALRM] = alarm_handler
 133};
 134
 135
 136static void hard_handler(int sig, siginfo_t *si, void *p)
 137{
 138        struct ucontext *uc = p;
 139        mcontext_t *mc = &uc->uc_mcontext;
 140        unsigned long pending = 1UL << sig;
 141
 142        do {
 143                int nested, bail;
 144
 145                /*
 146                 * pending comes back with one bit set for each
 147                 * interrupt that arrived while setting up the stack,
 148                 * plus a bit for this interrupt, plus the zero bit is
 149                 * set if this is a nested interrupt.
 150                 * If bail is true, then we interrupted another
 151                 * handler setting up the stack.  In this case, we
 152                 * have to return, and the upper handler will deal
 153                 * with this interrupt.
 154                 */
 155                bail = to_irq_stack(&pending);
 156                if (bail)
 157                        return;
 158
 159                nested = pending & 1;
 160                pending &= ~1;
 161
 162                while ((sig = ffs(pending)) != 0){
 163                        sig--;
 164                        pending &= ~(1 << sig);
 165                        (*handlers[sig])(sig, si, mc);
 166                }
 167
 168                /*
 169                 * Again, pending comes back with a mask of signals
 170                 * that arrived while tearing down the stack.  If this
 171                 * is non-zero, we just go back, set up the stack
 172                 * again, and handle the new interrupts.
 173                 */
 174                if (!nested)
 175                        pending = from_irq_stack(nested);
 176        } while (pending);
 177}
 178
 179void set_handler(int sig)
 180{
 181        struct sigaction action;
 182        int flags = SA_SIGINFO | SA_ONSTACK;
 183        sigset_t sig_mask;
 184
 185        action.sa_sigaction = hard_handler;
 186
 187        /* block irq ones */
 188        sigemptyset(&action.sa_mask);
 189        sigaddset(&action.sa_mask, SIGVTALRM);
 190        sigaddset(&action.sa_mask, SIGIO);
 191        sigaddset(&action.sa_mask, SIGWINCH);
 192
 193        if (sig == SIGSEGV)
 194                flags |= SA_NODEFER;
 195
 196        if (sigismember(&action.sa_mask, sig))
 197                flags |= SA_RESTART; /* if it's an irq signal */
 198
 199        action.sa_flags = flags;
 200        action.sa_restorer = NULL;
 201        if (sigaction(sig, &action, NULL) < 0)
 202                panic("sigaction failed - errno = %d\n", errno);
 203
 204        sigemptyset(&sig_mask);
 205        sigaddset(&sig_mask, sig);
 206        if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
 207                panic("sigprocmask failed - errno = %d\n", errno);
 208}
 209
 210int change_sig(int signal, int on)
 211{
 212        sigset_t sigset;
 213
 214        sigemptyset(&sigset);
 215        sigaddset(&sigset, signal);
 216        if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
 217                return -errno;
 218
 219        return 0;
 220}
 221
 222void block_signals(void)
 223{
 224        signals_enabled = 0;
 225        /*
 226         * This must return with signals disabled, so this barrier
 227         * ensures that writes are flushed out before the return.
 228         * This might matter if gcc figures out how to inline this and
 229         * decides to shuffle this code into the caller.
 230         */
 231        barrier();
 232}
 233
 234void unblock_signals(void)
 235{
 236        int save_pending;
 237
 238        if (signals_enabled == 1)
 239                return;
 240
 241        /*
 242         * We loop because the IRQ handler returns with interrupts off.  So,
 243         * interrupts may have arrived and we need to re-enable them and
 244         * recheck signals_pending.
 245         */
 246        while (1) {
 247                /*
 248                 * Save and reset save_pending after enabling signals.  This
 249                 * way, signals_pending won't be changed while we're reading it.
 250                 */
 251                signals_enabled = 1;
 252
 253                /*
 254                 * Setting signals_enabled and reading signals_pending must
 255                 * happen in this order.
 256                 */
 257                barrier();
 258
 259                save_pending = signals_pending;
 260                if (save_pending == 0)
 261                        return;
 262
 263                signals_pending = 0;
 264
 265                /*
 266                 * We have pending interrupts, so disable signals, as the
 267                 * handlers expect them off when they are called.  They will
 268                 * be enabled again above.
 269                 */
 270
 271                signals_enabled = 0;
 272
 273                /*
 274                 * Deal with SIGIO first because the alarm handler might
 275                 * schedule, leaving the pending SIGIO stranded until we come
 276                 * back here.
 277                 *
 278                 * SIGIO's handler doesn't use siginfo or mcontext,
 279                 * so they can be NULL.
 280                 */
 281                if (save_pending & SIGIO_MASK)
 282                        sig_handler_common(SIGIO, NULL, NULL);
 283
 284                if (save_pending & SIGVTALRM_MASK)
 285                        real_alarm_handler(NULL);
 286        }
 287}
 288
 289int get_signals(void)
 290{
 291        return signals_enabled;
 292}
 293
 294int set_signals(int enable)
 295{
 296        int ret;
 297        if (signals_enabled == enable)
 298                return enable;
 299
 300        ret = signals_enabled;
 301        if (enable)
 302                unblock_signals();
 303        else block_signals();
 304
 305        return ret;
 306}
 307