]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/debug/debug_core.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux.git] / kernel / debug / debug_core.c
index f76d6f77dd5e5301f40406c928e79420b4f308cf..2b7c9b67931d6818d85d5066544172f2df8693ac 100644 (file)
@@ -441,6 +441,37 @@ int dbg_remove_all_break(void)
        return 0;
 }
 
+#ifdef CONFIG_KGDB_KDB
+void kdb_dump_stack_on_cpu(int cpu)
+{
+       if (cpu == raw_smp_processor_id() || !IS_ENABLED(CONFIG_SMP)) {
+               dump_stack();
+               return;
+       }
+
+       if (!(kgdb_info[cpu].exception_state & DCPU_IS_SLAVE)) {
+               kdb_printf("ERROR: Task on cpu %d didn't stop in the debugger\n",
+                          cpu);
+               return;
+       }
+
+       /*
+        * In general, architectures don't support dumping the stack of a
+        * "running" process that's not the current one.  From the point of
+        * view of the Linux, kernel processes that are looping in the kgdb
+        * slave loop are still "running".  There's also no API (that actually
+        * works across all architectures) that can do a stack crawl based
+        * on registers passed as a parameter.
+        *
+        * Solve this conundrum by asking slave CPUs to do the backtrace
+        * themselves.
+        */
+       kgdb_info[cpu].exception_state |= DCPU_WANT_BT;
+       while (kgdb_info[cpu].exception_state & DCPU_WANT_BT)
+               cpu_relax();
+}
+#endif
+
 /*
  * Return true if there is a valid kgdb I/O module.  Also if no
  * debugger is attached a message can be printed to the console about
@@ -580,6 +611,9 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
                                atomic_xchg(&kgdb_active, cpu);
                                break;
                        }
+               } else if (kgdb_info[cpu].exception_state & DCPU_WANT_BT) {
+                       dump_stack();
+                       kgdb_info[cpu].exception_state &= ~DCPU_WANT_BT;
                } else if (kgdb_info[cpu].exception_state & DCPU_IS_SLAVE) {
                        if (!raw_spin_is_locked(&dbg_slave_lock))
                                goto return_normal;