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