summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2019-08-23 07:16:23 -0400
committerRichard Weinberger <richard@nod.at>2019-09-15 15:37:11 -0400
commit0dafcbe128d2af48919619f79332ef219b5e5514 (patch)
tree2f95274135b2485bb13dea1dcbe6d86c31b206e7
parent276d75c4aff3ade04f0f78769dd895a78f03edd9 (diff)
um: Implement TRACE_IRQFLAGS_SUPPORT
UML enables TRACE_IRQFLAGS_SUPPORT but doesn't actually implement it. It seems to have been added for lockdep support, but that can't actually really work well without IRQ flags tracing, as is also very noisily reported when enabling CONFIG_DEBUG_LOCKDEP. Implement it now. Fixes: 711553efa5b8 ("[PATCH] uml: declare in Kconfig our partial LOCKDEP support") Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r--arch/um/include/shared/longjmp.h2
-rw-r--r--arch/um/include/shared/os.h7
-rw-r--r--arch/um/kernel/signal.c28
-rw-r--r--arch/um/kernel/skas/mmu.c4
-rw-r--r--arch/um/kernel/skas/process.c2
-rw-r--r--arch/um/os-Linux/main.c2
-rw-r--r--arch/um/os-Linux/sigio.c6
-rw-r--r--arch/um/os-Linux/signal.c44
-rw-r--r--arch/um/os-Linux/skas/process.c12
9 files changed, 81 insertions, 26 deletions
diff --git a/arch/um/include/shared/longjmp.h b/arch/um/include/shared/longjmp.h
index b3315c1f198b..85a1cc290ecb 100644
--- a/arch/um/include/shared/longjmp.h
+++ b/arch/um/include/shared/longjmp.h
@@ -18,7 +18,7 @@ extern void longjmp(jmp_buf, int);
18 enable = get_signals(); \ 18 enable = get_signals(); \
19 n = setjmp(*buf); \ 19 n = setjmp(*buf); \
20 if(n != 0) \ 20 if(n != 0) \
21 set_signals(enable); \ 21 set_signals_trace(enable); \
22 n; }) 22 n; })
23 23
24#endif 24#endif
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 4a62ac4251a5..fa1909365666 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -232,6 +232,7 @@ extern void block_signals(void);
232extern void unblock_signals(void); 232extern void unblock_signals(void);
233extern int get_signals(void); 233extern int get_signals(void);
234extern int set_signals(int enable); 234extern int set_signals(int enable);
235extern int set_signals_trace(int enable);
235extern int os_is_signal_stack(void); 236extern int os_is_signal_stack(void);
236extern void deliver_alarm(void); 237extern void deliver_alarm(void);
237 238
@@ -317,4 +318,10 @@ extern unsigned long os_get_top_address(void);
317 318
318long syscall(long number, ...); 319long syscall(long number, ...);
319 320
321/* irqflags tracing */
322extern void block_signals_trace(void);
323extern void unblock_signals_trace(void);
324extern void um_trace_signals_on(void);
325extern void um_trace_signals_off(void);
326
320#endif 327#endif
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 57acbd67d85d..3a8012520e22 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -6,15 +6,43 @@
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/ptrace.h> 7#include <linux/ptrace.h>
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/ftrace.h>
9#include <asm/siginfo.h> 10#include <asm/siginfo.h>
10#include <asm/signal.h> 11#include <asm/signal.h>
11#include <asm/unistd.h> 12#include <asm/unistd.h>
12#include <frame_kern.h> 13#include <frame_kern.h>
13#include <kern_util.h> 14#include <kern_util.h>
15#include <os.h>
14 16
15EXPORT_SYMBOL(block_signals); 17EXPORT_SYMBOL(block_signals);
16EXPORT_SYMBOL(unblock_signals); 18EXPORT_SYMBOL(unblock_signals);
17 19
20void block_signals_trace(void)
21{
22 block_signals();
23 if (current_thread_info())
24 trace_hardirqs_off();
25}
26
27void unblock_signals_trace(void)
28{
29 if (current_thread_info())
30 trace_hardirqs_on();
31 unblock_signals();
32}
33
34void um_trace_signals_on(void)
35{
36 if (current_thread_info())
37 trace_hardirqs_on();
38}
39
40void um_trace_signals_off(void)
41{
42 if (current_thread_info())
43 trace_hardirqs_off();
44}
45
18/* 46/*
19 * OK, we're invoking a handler 47 * OK, we're invoking a handler
20 */ 48 */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 29e7f5f9f188..ace71f805700 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -63,12 +63,12 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
63 if (current->mm != NULL && current->mm != &init_mm) 63 if (current->mm != NULL && current->mm != &init_mm)
64 from_mm = &current->mm->context; 64 from_mm = &current->mm->context;
65 65
66 block_signals(); 66 block_signals_trace();
67 if (from_mm) 67 if (from_mm)
68 to_mm->id.u.pid = copy_context_skas0(stack, 68 to_mm->id.u.pid = copy_context_skas0(stack,
69 from_mm->id.u.pid); 69 from_mm->id.u.pid);
70 else to_mm->id.u.pid = start_userspace(stack); 70 else to_mm->id.u.pid = start_userspace(stack);
71 unblock_signals(); 71 unblock_signals_trace();
72 72
73 if (to_mm->id.u.pid < 0) { 73 if (to_mm->id.u.pid < 0) {
74 ret = to_mm->id.u.pid; 74 ret = to_mm->id.u.pid;
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index d4dbf08722d6..404914627dd6 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -19,7 +19,7 @@ static int __init start_kernel_proc(void *unused)
19{ 19{
20 int pid; 20 int pid;
21 21
22 block_signals(); 22 block_signals_trace();
23 pid = os_getpid(); 23 pid = os_getpid();
24 24
25 cpu_tasks[0].pid = pid; 25 cpu_tasks[0].pid = pid;
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index f1fee2b91239..6d098e712839 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -170,7 +170,7 @@ int __init main(int argc, char **argv, char **envp)
170 * that they won't be delivered after the exec, when 170 * that they won't be delivered after the exec, when
171 * they are definitely not expected. 171 * they are definitely not expected.
172 */ 172 */
173 unblock_signals(); 173 unblock_signals_trace();
174 174
175 os_info("\n"); 175 os_info("\n");
176 /* Reboot */ 176 /* Reboot */
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 46e762f926eb..21b226aa1041 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -132,7 +132,7 @@ static void update_thread(void)
132 int n; 132 int n;
133 char c; 133 char c;
134 134
135 flags = set_signals(0); 135 flags = set_signals_trace(0);
136 CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c))); 136 CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
137 if (n != sizeof(c)) { 137 if (n != sizeof(c)) {
138 printk(UM_KERN_ERR "update_thread : write failed, err = %d\n", 138 printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
@@ -147,7 +147,7 @@ static void update_thread(void)
147 goto fail; 147 goto fail;
148 } 148 }
149 149
150 set_signals(flags); 150 set_signals_trace(flags);
151 return; 151 return;
152 fail: 152 fail:
153 /* Critical section start */ 153 /* Critical section start */
@@ -161,7 +161,7 @@ static void update_thread(void)
161 close(write_sigio_fds[0]); 161 close(write_sigio_fds[0]);
162 close(write_sigio_fds[1]); 162 close(write_sigio_fds[1]);
163 /* Critical section end */ 163 /* Critical section end */
164 set_signals(flags); 164 set_signals_trace(flags);
165} 165}
166 166
167int add_sigio_fd(int fd) 167int add_sigio_fd(int fd)
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 4cd88b5b9006..bde54c4a27da 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -43,7 +43,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
43 43
44 /* enable signals if sig isn't IRQ signal */ 44 /* enable signals if sig isn't IRQ signal */
45 if ((sig != SIGIO) && (sig != SIGWINCH)) 45 if ((sig != SIGIO) && (sig != SIGWINCH))
46 unblock_signals(); 46 unblock_signals_trace();
47 47
48 (*sig_info[sig])(sig, si, &r); 48 (*sig_info[sig])(sig, si, &r);
49 49
@@ -76,11 +76,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
76 return; 76 return;
77 } 77 }
78 78
79 block_signals(); 79 block_signals_trace();
80 80
81 sig_handler_common(sig, si, mc); 81 sig_handler_common(sig, si, mc);
82 82
83 set_signals(enabled); 83 set_signals_trace(enabled);
84} 84}
85 85
86static void timer_real_alarm_handler(mcontext_t *mc) 86static void timer_real_alarm_handler(mcontext_t *mc)
@@ -104,7 +104,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
104 return; 104 return;
105 } 105 }
106 106
107 block_signals(); 107 block_signals_trace();
108 108
109 signals_active |= SIGALRM_MASK; 109 signals_active |= SIGALRM_MASK;
110 110
@@ -112,7 +112,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
112 112
113 signals_active &= ~SIGALRM_MASK; 113 signals_active &= ~SIGALRM_MASK;
114 114
115 set_signals(enabled); 115 set_signals_trace(enabled);
116} 116}
117 117
118void deliver_alarm(void) { 118void deliver_alarm(void) {
@@ -253,6 +253,8 @@ void unblock_signals(void)
253 if (signals_enabled == 1) 253 if (signals_enabled == 1)
254 return; 254 return;
255 255
256 signals_enabled = 1;
257
256 /* 258 /*
257 * We loop because the IRQ handler returns with interrupts off. So, 259 * We loop because the IRQ handler returns with interrupts off. So,
258 * interrupts may have arrived and we need to re-enable them and 260 * interrupts may have arrived and we need to re-enable them and
@@ -262,12 +264,9 @@ void unblock_signals(void)
262 /* 264 /*
263 * Save and reset save_pending after enabling signals. This 265 * Save and reset save_pending after enabling signals. This
264 * way, signals_pending won't be changed while we're reading it. 266 * way, signals_pending won't be changed while we're reading it.
265 */ 267 *
266 signals_enabled = 1;
267
268 /*
269 * Setting signals_enabled and reading signals_pending must 268 * Setting signals_enabled and reading signals_pending must
270 * happen in this order. 269 * happen in this order, so have the barrier here.
271 */ 270 */
272 barrier(); 271 barrier();
273 272
@@ -280,10 +279,13 @@ void unblock_signals(void)
280 /* 279 /*
281 * We have pending interrupts, so disable signals, as the 280 * We have pending interrupts, so disable signals, as the
282 * handlers expect them off when they are called. They will 281 * handlers expect them off when they are called. They will
283 * be enabled again above. 282 * be enabled again above. We need to trace this, as we're
283 * expected to be enabling interrupts already, but any more
284 * tracing that happens inside the handlers we call for the
285 * pending signals will mess up the tracing state.
284 */ 286 */
285
286 signals_enabled = 0; 287 signals_enabled = 0;
288 um_trace_signals_off();
287 289
288 /* 290 /*
289 * Deal with SIGIO first because the alarm handler might 291 * Deal with SIGIO first because the alarm handler might
@@ -306,6 +308,9 @@ void unblock_signals(void)
306 if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK)) 308 if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
307 return; 309 return;
308 310
311 /* Re-enable signals and trace that we're doing so. */
312 um_trace_signals_on();
313 signals_enabled = 1;
309 } 314 }
310} 315}
311 316
@@ -328,6 +333,21 @@ int set_signals(int enable)
328 return ret; 333 return ret;
329} 334}
330 335
336int set_signals_trace(int enable)
337{
338 int ret;
339 if (signals_enabled == enable)
340 return enable;
341
342 ret = signals_enabled;
343 if (enable)
344 unblock_signals_trace();
345 else
346 block_signals_trace();
347
348 return ret;
349}
350
331int os_is_signal_stack(void) 351int os_is_signal_stack(void)
332{ 352{
333 stack_t ss; 353 stack_t ss;
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index df4a985716eb..095bff707bb3 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -425,9 +425,9 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
425 case SIGBUS: 425 case SIGBUS:
426 case SIGFPE: 426 case SIGFPE:
427 case SIGWINCH: 427 case SIGWINCH:
428 block_signals(); 428 block_signals_trace();
429 (*sig_info[sig])(sig, (struct siginfo *)&si, regs); 429 (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
430 unblock_signals(); 430 unblock_signals_trace();
431 break; 431 break;
432 default: 432 default:
433 printk(UM_KERN_ERR "userspace - child stopped " 433 printk(UM_KERN_ERR "userspace - child stopped "
@@ -625,10 +625,10 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
625 cb_arg = arg; 625 cb_arg = arg;
626 cb_back = &here; 626 cb_back = &here;
627 627
628 block_signals(); 628 block_signals_trace();
629 if (UML_SETJMP(&here) == 0) 629 if (UML_SETJMP(&here) == 0)
630 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); 630 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
631 unblock_signals(); 631 unblock_signals_trace();
632 632
633 cb_proc = NULL; 633 cb_proc = NULL;
634 cb_arg = NULL; 634 cb_arg = NULL;
@@ -637,13 +637,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
637 637
638void halt_skas(void) 638void halt_skas(void)
639{ 639{
640 block_signals(); 640 block_signals_trace();
641 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); 641 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
642} 642}
643 643
644void reboot_skas(void) 644void reboot_skas(void)
645{ 645{
646 block_signals(); 646 block_signals_trace();
647 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); 647 UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
648} 648}
649 649