aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_kdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_kdb.c')
-rw-r--r--sys/kern/subr_kdb.c83
1 files changed, 82 insertions, 1 deletions
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index f5cb31e71dd6..76b37a9ce7c0 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -57,6 +57,21 @@ struct pcb *kdb_thrctx = NULL;
struct thread *kdb_thread = NULL;
struct trapframe *kdb_frame = NULL;
+#ifdef BREAK_TO_DEBUGGER
+#define KDB_BREAK_TO_DEBUGGER 1
+#else
+#define KDB_BREAK_TO_DEBUGGER 0
+#endif
+
+#ifdef ALT_BREAK_TO_DEBUGGER
+#define KDB_ALT_BREAK_TO_DEBUGGER 1
+#else
+#define KDB_ALT_BREAK_TO_DEBUGGER 0
+#endif
+
+static int kdb_break_to_debugger = KDB_BREAK_TO_DEBUGGER;
+static int kdb_alt_break_to_debugger = KDB_ALT_BREAK_TO_DEBUGGER;
+
KDB_BACKEND(null, NULL, NULL, NULL);
SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe);
@@ -87,6 +102,15 @@ SYSCTL_PROC(_debug_kdb, OID_AUTO, trap, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
SYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
kdb_sysctl_trap_code, "I", "set to cause a page fault via code access");
+SYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger, CTLTYPE_INT | CTLFLAG_RW |
+ CTLFLAG_TUN, &kdb_break_to_debugger, 0, "Enable break to debugger");
+TUNABLE_INT("debug.kdb.break_to_debugger", &kdb_break_to_debugger);
+
+SYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger, CTLTYPE_INT |
+ CTLFLAG_RW | CTLFLAG_TUN, &kdb_alt_break_to_debugger, 0,
+ "Enable alternative break to debugger");
+TUNABLE_INT("debug.kdb.alt_break_to_debugger", &kdb_alt_break_to_debugger);
+
/*
* Flag to indicate to debuggers why the debugger was entered.
*/
@@ -241,7 +265,17 @@ enum {
};
int
-kdb_alt_break(int key, int *state)
+kdb_break(void)
+{
+
+ if (!kdb_break_to_debugger)
+ return (0);
+ kdb_enter(KDB_WHY_BREAK, "Break to debugger");
+ return (KDB_REQ_DEBUGGER);
+}
+
+static int
+kdb_alt_break_state(int key, int *state)
{
int brk;
@@ -275,6 +309,53 @@ kdb_alt_break(int key, int *state)
return (brk);
}
+static int
+kdb_alt_break_internal(int key, int *state, int force_gdb)
+{
+ int brk;
+
+ if (!kdb_alt_break_to_debugger)
+ return (0);
+ brk = kdb_alt_break_state(key, state);
+ switch (brk) {
+ case KDB_REQ_DEBUGGER:
+ if (force_gdb)
+ kdb_dbbe_select("gdb");
+ kdb_enter(KDB_WHY_BREAK, "Break to debugger");
+ break;
+
+ case KDB_REQ_PANIC:
+ if (force_gdb)
+ kdb_dbbe_select("gdb");
+ kdb_panic("Panic sequence on console");
+ break;
+
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
+ return (0);
+}
+
+int
+kdb_alt_break(int key, int *state)
+{
+
+ return (kdb_alt_break_internal(key, state, 0));
+}
+
+/*
+ * This variation on kdb_alt_break() is used only by dcons, which has its own
+ * configuration flag to force GDB use regardless of the global KDB
+ * configuration.
+ */
+int
+kdb_alt_break_gdb(int key, int *state)
+{
+
+ return (kdb_alt_break_internal(key, state, 1));
+}
+
/*
* Print a backtrace of the calling thread. The backtrace is generated by
* the selected debugger, provided it supports backtraces. If no debugger