| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk}) |
|---|
| 3 | 4 | * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de) |
|---|
| 4 | 5 | * Copyright (C) 2004 PathScale, Inc |
|---|
| 5 | 6 | * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
|---|
| 6 | | - * Licensed under the GPL |
|---|
| 7 | 7 | */ |
|---|
| 8 | 8 | |
|---|
| 9 | 9 | #include <stdlib.h> |
|---|
| 10 | 10 | #include <stdarg.h> |
|---|
| 11 | 11 | #include <errno.h> |
|---|
| 12 | 12 | #include <signal.h> |
|---|
| 13 | +#include <string.h> |
|---|
| 13 | 14 | #include <strings.h> |
|---|
| 14 | 15 | #include <as-layout.h> |
|---|
| 15 | 16 | #include <kern_util.h> |
|---|
| .. | .. |
|---|
| 26 | 27 | [SIGBUS] = bus_handler, |
|---|
| 27 | 28 | [SIGSEGV] = segv_handler, |
|---|
| 28 | 29 | [SIGIO] = sigio_handler, |
|---|
| 29 | | - [SIGALRM] = timer_handler |
|---|
| 30 | 30 | }; |
|---|
| 31 | 31 | |
|---|
| 32 | 32 | static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) |
|---|
| 33 | 33 | { |
|---|
| 34 | | - struct uml_pt_regs *r; |
|---|
| 34 | + struct uml_pt_regs r; |
|---|
| 35 | 35 | int save_errno = errno; |
|---|
| 36 | 36 | |
|---|
| 37 | | - r = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC); |
|---|
| 38 | | - if (!r) |
|---|
| 39 | | - panic("out of memory"); |
|---|
| 40 | | - |
|---|
| 41 | | - r->is_user = 0; |
|---|
| 37 | + r.is_user = 0; |
|---|
| 42 | 38 | if (sig == SIGSEGV) { |
|---|
| 43 | 39 | /* For segfaults, we want the data from the sigcontext. */ |
|---|
| 44 | | - get_regs_from_mc(r, mc); |
|---|
| 45 | | - GET_FAULTINFO_FROM_MC(r->faultinfo, mc); |
|---|
| 40 | + get_regs_from_mc(&r, mc); |
|---|
| 41 | + GET_FAULTINFO_FROM_MC(r.faultinfo, mc); |
|---|
| 46 | 42 | } |
|---|
| 47 | 43 | |
|---|
| 48 | 44 | /* enable signals if sig isn't IRQ signal */ |
|---|
| 49 | | - if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM)) |
|---|
| 50 | | - unblock_signals(); |
|---|
| 45 | + if ((sig != SIGIO) && (sig != SIGWINCH)) |
|---|
| 46 | + unblock_signals_trace(); |
|---|
| 51 | 47 | |
|---|
| 52 | | - (*sig_info[sig])(sig, si, r); |
|---|
| 48 | + (*sig_info[sig])(sig, si, &r); |
|---|
| 53 | 49 | |
|---|
| 54 | 50 | errno = save_errno; |
|---|
| 55 | | - |
|---|
| 56 | | - free(r); |
|---|
| 57 | 51 | } |
|---|
| 58 | 52 | |
|---|
| 59 | 53 | /* |
|---|
| .. | .. |
|---|
| 82 | 76 | return; |
|---|
| 83 | 77 | } |
|---|
| 84 | 78 | |
|---|
| 85 | | - block_signals(); |
|---|
| 79 | + block_signals_trace(); |
|---|
| 86 | 80 | |
|---|
| 87 | 81 | sig_handler_common(sig, si, mc); |
|---|
| 88 | 82 | |
|---|
| 89 | | - set_signals(enabled); |
|---|
| 83 | + set_signals_trace(enabled); |
|---|
| 90 | 84 | } |
|---|
| 91 | 85 | |
|---|
| 92 | 86 | static void timer_real_alarm_handler(mcontext_t *mc) |
|---|
| 93 | 87 | { |
|---|
| 94 | | - struct uml_pt_regs *regs; |
|---|
| 95 | | - |
|---|
| 96 | | - regs = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC); |
|---|
| 97 | | - if (!regs) |
|---|
| 98 | | - panic("out of memory"); |
|---|
| 88 | + struct uml_pt_regs regs; |
|---|
| 99 | 89 | |
|---|
| 100 | 90 | if (mc != NULL) |
|---|
| 101 | | - get_regs_from_mc(regs, mc); |
|---|
| 102 | | - timer_handler(SIGALRM, NULL, regs); |
|---|
| 103 | | - |
|---|
| 104 | | - free(regs); |
|---|
| 91 | + get_regs_from_mc(®s, mc); |
|---|
| 92 | + else |
|---|
| 93 | + memset(®s, 0, sizeof(regs)); |
|---|
| 94 | + timer_handler(SIGALRM, NULL, ®s); |
|---|
| 105 | 95 | } |
|---|
| 106 | 96 | |
|---|
| 107 | 97 | void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) |
|---|
| .. | .. |
|---|
| 114 | 104 | return; |
|---|
| 115 | 105 | } |
|---|
| 116 | 106 | |
|---|
| 117 | | - block_signals(); |
|---|
| 107 | + block_signals_trace(); |
|---|
| 118 | 108 | |
|---|
| 119 | 109 | signals_active |= SIGALRM_MASK; |
|---|
| 120 | 110 | |
|---|
| .. | .. |
|---|
| 122 | 112 | |
|---|
| 123 | 113 | signals_active &= ~SIGALRM_MASK; |
|---|
| 124 | 114 | |
|---|
| 125 | | - set_signals(enabled); |
|---|
| 115 | + set_signals_trace(enabled); |
|---|
| 126 | 116 | } |
|---|
| 127 | 117 | |
|---|
| 128 | 118 | void deliver_alarm(void) { |
|---|
| .. | .. |
|---|
| 146 | 136 | panic("enabling signal stack failed, errno = %d\n", errno); |
|---|
| 147 | 137 | } |
|---|
| 148 | 138 | |
|---|
| 139 | +static void sigusr1_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) |
|---|
| 140 | +{ |
|---|
| 141 | + uml_pm_wake(); |
|---|
| 142 | +} |
|---|
| 143 | + |
|---|
| 144 | +void register_pm_wake_signal(void) |
|---|
| 145 | +{ |
|---|
| 146 | + set_handler(SIGUSR1); |
|---|
| 147 | +} |
|---|
| 148 | + |
|---|
| 149 | 149 | static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = { |
|---|
| 150 | 150 | [SIGSEGV] = sig_handler, |
|---|
| 151 | 151 | [SIGBUS] = sig_handler, |
|---|
| .. | .. |
|---|
| 155 | 155 | |
|---|
| 156 | 156 | [SIGIO] = sig_handler, |
|---|
| 157 | 157 | [SIGWINCH] = sig_handler, |
|---|
| 158 | | - [SIGALRM] = timer_alarm_handler |
|---|
| 158 | + [SIGALRM] = timer_alarm_handler, |
|---|
| 159 | + |
|---|
| 160 | + [SIGUSR1] = sigusr1_handler, |
|---|
| 159 | 161 | }; |
|---|
| 160 | 162 | |
|---|
| 161 | 163 | static void hard_handler(int sig, siginfo_t *si, void *p) |
|---|
| .. | .. |
|---|
| 263 | 265 | if (signals_enabled == 1) |
|---|
| 264 | 266 | return; |
|---|
| 265 | 267 | |
|---|
| 268 | + signals_enabled = 1; |
|---|
| 269 | + |
|---|
| 266 | 270 | /* |
|---|
| 267 | 271 | * We loop because the IRQ handler returns with interrupts off. So, |
|---|
| 268 | 272 | * interrupts may have arrived and we need to re-enable them and |
|---|
| .. | .. |
|---|
| 272 | 276 | /* |
|---|
| 273 | 277 | * Save and reset save_pending after enabling signals. This |
|---|
| 274 | 278 | * way, signals_pending won't be changed while we're reading it. |
|---|
| 275 | | - */ |
|---|
| 276 | | - signals_enabled = 1; |
|---|
| 277 | | - |
|---|
| 278 | | - /* |
|---|
| 279 | + * |
|---|
| 279 | 280 | * Setting signals_enabled and reading signals_pending must |
|---|
| 280 | | - * happen in this order. |
|---|
| 281 | + * happen in this order, so have the barrier here. |
|---|
| 281 | 282 | */ |
|---|
| 282 | 283 | barrier(); |
|---|
| 283 | 284 | |
|---|
| .. | .. |
|---|
| 290 | 291 | /* |
|---|
| 291 | 292 | * We have pending interrupts, so disable signals, as the |
|---|
| 292 | 293 | * handlers expect them off when they are called. They will |
|---|
| 293 | | - * be enabled again above. |
|---|
| 294 | + * be enabled again above. We need to trace this, as we're |
|---|
| 295 | + * expected to be enabling interrupts already, but any more |
|---|
| 296 | + * tracing that happens inside the handlers we call for the |
|---|
| 297 | + * pending signals will mess up the tracing state. |
|---|
| 294 | 298 | */ |
|---|
| 295 | | - |
|---|
| 296 | 299 | signals_enabled = 0; |
|---|
| 300 | + um_trace_signals_off(); |
|---|
| 297 | 301 | |
|---|
| 298 | 302 | /* |
|---|
| 299 | 303 | * Deal with SIGIO first because the alarm handler might |
|---|
| .. | .. |
|---|
| 316 | 320 | if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK)) |
|---|
| 317 | 321 | return; |
|---|
| 318 | 322 | |
|---|
| 323 | + /* Re-enable signals and trace that we're doing so. */ |
|---|
| 324 | + um_trace_signals_on(); |
|---|
| 325 | + signals_enabled = 1; |
|---|
| 319 | 326 | } |
|---|
| 320 | 327 | } |
|---|
| 321 | 328 | |
|---|
| .. | .. |
|---|
| 338 | 345 | return ret; |
|---|
| 339 | 346 | } |
|---|
| 340 | 347 | |
|---|
| 348 | +int set_signals_trace(int enable) |
|---|
| 349 | +{ |
|---|
| 350 | + int ret; |
|---|
| 351 | + if (signals_enabled == enable) |
|---|
| 352 | + return enable; |
|---|
| 353 | + |
|---|
| 354 | + ret = signals_enabled; |
|---|
| 355 | + if (enable) |
|---|
| 356 | + unblock_signals_trace(); |
|---|
| 357 | + else |
|---|
| 358 | + block_signals_trace(); |
|---|
| 359 | + |
|---|
| 360 | + return ret; |
|---|
| 361 | +} |
|---|
| 362 | + |
|---|
| 341 | 363 | int os_is_signal_stack(void) |
|---|
| 342 | 364 | { |
|---|
| 343 | 365 | stack_t ss; |
|---|