.. | .. |
---|
| 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; |
---|