]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
um: Implement TRACE_IRQFLAGS_SUPPORT
authorJohannes Berg <johannes.berg@intel.com>
Fri, 23 Aug 2019 11:16:23 +0000 (13:16 +0200)
committerRichard Weinberger <richard@nod.at>
Sun, 15 Sep 2019 19:37:11 +0000 (21:37 +0200)
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>
arch/um/include/shared/longjmp.h
arch/um/include/shared/os.h
arch/um/kernel/signal.c
arch/um/kernel/skas/mmu.c
arch/um/kernel/skas/process.c
arch/um/os-Linux/main.c
arch/um/os-Linux/sigio.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/skas/process.c

index b3315c1f198bede97a50bd8d9c9743d261710cd7..85a1cc290ecb93a5dcd4d4f4e037992f697121d5 100644 (file)
@@ -18,7 +18,7 @@ extern void longjmp(jmp_buf, int);
        enable = get_signals(); \
        n = setjmp(*buf); \
        if(n != 0) \
-               set_signals(enable); \
+               set_signals_trace(enable); \
        n; })
 
 #endif
index 4a62ac4251a53d4797cf8600c9c18aab6e602992..fa1909365666a8e5547f65722c8cf98da92ea7f0 100644 (file)
@@ -232,6 +232,7 @@ extern void block_signals(void);
 extern void unblock_signals(void);
 extern int get_signals(void);
 extern int set_signals(int enable);
+extern int set_signals_trace(int enable);
 extern int os_is_signal_stack(void);
 extern void deliver_alarm(void);
 
@@ -317,4 +318,10 @@ extern unsigned long os_get_top_address(void);
 
 long syscall(long number, ...);
 
+/* irqflags tracing */
+extern void block_signals_trace(void);
+extern void unblock_signals_trace(void);
+extern void um_trace_signals_on(void);
+extern void um_trace_signals_off(void);
+
 #endif
index 57acbd67d85dbd4051cd3c534ceff2a300ce9906..3a8012520e222c5525b00b49bb43fcade9c56580 100644 (file)
@@ -6,15 +6,43 @@
 #include <linux/module.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
+#include <linux/ftrace.h>
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 #include <asm/unistd.h>
 #include <frame_kern.h>
 #include <kern_util.h>
+#include <os.h>
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
 
+void block_signals_trace(void)
+{
+       block_signals();
+       if (current_thread_info())
+               trace_hardirqs_off();
+}
+
+void unblock_signals_trace(void)
+{
+       if (current_thread_info())
+               trace_hardirqs_on();
+       unblock_signals();
+}
+
+void um_trace_signals_on(void)
+{
+       if (current_thread_info())
+               trace_hardirqs_on();
+}
+
+void um_trace_signals_off(void)
+{
+       if (current_thread_info())
+               trace_hardirqs_off();
+}
+
 /*
  * OK, we're invoking a handler
  */
index 29e7f5f9f18852df86d8c04f2c2cec619ee7da78..ace71f805700da1e1ddd86cdec821f95e61f6254 100644 (file)
@@ -63,12 +63,12 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
        if (current->mm != NULL && current->mm != &init_mm)
                from_mm = &current->mm->context;
 
-       block_signals();
+       block_signals_trace();
        if (from_mm)
                to_mm->id.u.pid = copy_context_skas0(stack,
                                                     from_mm->id.u.pid);
        else to_mm->id.u.pid = start_userspace(stack);
-       unblock_signals();
+       unblock_signals_trace();
 
        if (to_mm->id.u.pid < 0) {
                ret = to_mm->id.u.pid;
index d4dbf08722d68c6da4cae14a02b3a6372603c8bb..404914627dd6150e13901bd1b73545dd2f0184a6 100644 (file)
@@ -19,7 +19,7 @@ static int __init start_kernel_proc(void *unused)
 {
        int pid;
 
-       block_signals();
+       block_signals_trace();
        pid = os_getpid();
 
        cpu_tasks[0].pid = pid;
index f1fee2b9123942c117ac1d498027da2f33f004b9..6d098e712839e1ec493dbfc8eb66681bf32263b3 100644 (file)
@@ -170,7 +170,7 @@ int __init main(int argc, char **argv, char **envp)
         * that they won't be delivered after the exec, when
         * they are definitely not expected.
         */
-       unblock_signals();
+       unblock_signals_trace();
 
        os_info("\n");
        /* Reboot */
index 46e762f926eb9def51ad29fbc8dc6ac17f7bc485..21b226aa1041b3196986789895a062b0fc0f9075 100644 (file)
@@ -132,7 +132,7 @@ static void update_thread(void)
        int n;
        char c;
 
-       flags = set_signals(0);
+       flags = set_signals_trace(0);
        CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
        if (n != sizeof(c)) {
                printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
@@ -147,7 +147,7 @@ static void update_thread(void)
                goto fail;
        }
 
-       set_signals(flags);
+       set_signals_trace(flags);
        return;
  fail:
        /* Critical section start */
@@ -161,7 +161,7 @@ static void update_thread(void)
        close(write_sigio_fds[0]);
        close(write_sigio_fds[1]);
        /* Critical section end */
-       set_signals(flags);
+       set_signals_trace(flags);
 }
 
 int add_sigio_fd(int fd)
index 4cd88b5b90066b2da22b1143b1908c342a931148..bde54c4a27da8c99b55505f1bb20bfef15d0c129 100644 (file)
@@ -43,7 +43,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
 
        /* enable signals if sig isn't IRQ signal */
        if ((sig != SIGIO) && (sig != SIGWINCH))
-               unblock_signals();
+               unblock_signals_trace();
 
        (*sig_info[sig])(sig, si, &r);
 
@@ -76,11 +76,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
                return;
        }
 
-       block_signals();
+       block_signals_trace();
 
        sig_handler_common(sig, si, mc);
 
-       set_signals(enabled);
+       set_signals_trace(enabled);
 }
 
 static 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)
                return;
        }
 
-       block_signals();
+       block_signals_trace();
 
        signals_active |= SIGALRM_MASK;
 
@@ -112,7 +112,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
 
        signals_active &= ~SIGALRM_MASK;
 
-       set_signals(enabled);
+       set_signals_trace(enabled);
 }
 
 void deliver_alarm(void) {
@@ -253,6 +253,8 @@ void unblock_signals(void)
        if (signals_enabled == 1)
                return;
 
+       signals_enabled = 1;
+
        /*
         * We loop because the IRQ handler returns with interrupts off.  So,
         * interrupts may have arrived and we need to re-enable them and
@@ -262,12 +264,9 @@ void unblock_signals(void)
                /*
                 * Save and reset save_pending after enabling signals.  This
                 * way, signals_pending won't be changed while we're reading it.
-                */
-               signals_enabled = 1;
-
-               /*
+                *
                 * Setting signals_enabled and reading signals_pending must
-                * happen in this order.
+                * happen in this order, so have the barrier here.
                 */
                barrier();
 
@@ -280,10 +279,13 @@ void unblock_signals(void)
                /*
                 * We have pending interrupts, so disable signals, as the
                 * handlers expect them off when they are called.  They will
-                * be enabled again above.
+                * be enabled again above. We need to trace this, as we're
+                * expected to be enabling interrupts already, but any more
+                * tracing that happens inside the handlers we call for the
+                * pending signals will mess up the tracing state.
                 */
-
                signals_enabled = 0;
+               um_trace_signals_off();
 
                /*
                 * Deal with SIGIO first because the alarm handler might
@@ -306,6 +308,9 @@ void unblock_signals(void)
                if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
                        return;
 
+               /* Re-enable signals and trace that we're doing so. */
+               um_trace_signals_on();
+               signals_enabled = 1;
        }
 }
 
@@ -328,6 +333,21 @@ int set_signals(int enable)
        return ret;
 }
 
+int set_signals_trace(int enable)
+{
+       int ret;
+       if (signals_enabled == enable)
+               return enable;
+
+       ret = signals_enabled;
+       if (enable)
+               unblock_signals_trace();
+       else
+               block_signals_trace();
+
+       return ret;
+}
+
 int os_is_signal_stack(void)
 {
        stack_t ss;
index df4a985716eba7047cb0873fcea7fb61a57d7a80..095bff707bb3d4a17f52dcf01078e2a9ba83a2ca 100644 (file)
@@ -425,9 +425,9 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
                        case SIGBUS:
                        case SIGFPE:
                        case SIGWINCH:
-                               block_signals();
+                               block_signals_trace();
                                (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
-                               unblock_signals();
+                               unblock_signals_trace();
                                break;
                        default:
                                printk(UM_KERN_ERR "userspace - child stopped "
@@ -625,10 +625,10 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
        cb_arg = arg;
        cb_back = &here;
 
-       block_signals();
+       block_signals_trace();
        if (UML_SETJMP(&here) == 0)
                UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
-       unblock_signals();
+       unblock_signals_trace();
 
        cb_proc = NULL;
        cb_arg = NULL;
@@ -637,13 +637,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 
 void halt_skas(void)
 {
-       block_signals();
+       block_signals_trace();
        UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
-       block_signals();
+       block_signals_trace();
        UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
 }