summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/arm/at91/uart_dev_at91usart.c15
-rw-r--r--sys/dev/dcons/dcons_os.c34
-rw-r--r--sys/dev/ofw/ofw_console.c19
-rw-r--r--sys/dev/sio/sio.c26
-rw-r--r--sys/dev/uart/uart_core.c20
-rw-r--r--sys/kern/subr_kdb.c46
-rw-r--r--sys/pc98/cbus/sio.c27
-rw-r--r--sys/sun4v/sun4v/hvcons.c18
-rw-r--r--sys/sys/kdb.h7
9 files changed, 175 insertions, 37 deletions
diff --git a/sys/arm/at91/uart_dev_at91usart.c b/sys/arm/at91/uart_dev_at91usart.c
index f87dcaa..8a7644f 100644
--- a/sys/arm/at91/uart_dev_at91usart.c
+++ b/sys/arm/at91/uart_dev_at91usart.c
@@ -506,9 +506,20 @@ static __inline void
at91_rx_put(struct uart_softc *sc, int key)
{
#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+ int kdb_brk;
+
if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
- if (kdb_alt_break(key, &sc->sc_altbrk))
- kdb_enter(KDB_WHY_BREAK, "Break sequence to console");
+ if ((kdb_brk = kdb_alt_break(key, &sc->sc_altbrk)) != 0) {
+ case KDB_REQ_DEBUGGER:
+ kdb_enter(KDB_WHY_BREAK, "Break sequence on console");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("Panic sequence on console");
+ break;
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
}
#endif
uart_rx_put(sc, key);
diff --git a/sys/dev/dcons/dcons_os.c b/sys/dev/dcons/dcons_os.c
index 7eb89aa..5715343 100644
--- a/sys/dev/dcons/dcons_os.c
+++ b/sys/dev/dcons/dcons_os.c
@@ -198,22 +198,36 @@ extern struct gdb_dbgport *gdb_cur;
static int
dcons_check_break(struct dcons_softc *dc, int c)
{
+#if __FreeBSD_version >= 502122
+ int kdb_brk;
+#endif
if (c < 0)
return (c);
#if __FreeBSD_version >= 502122
- if (kdb_alt_break(c, &dc->brk_state)) {
- if ((dc->flags & DC_GDB) != 0) {
+ if ((kdb_brk = kdb_alt_break(c, &dc->brk_state)) != 0) {
+ switch (kdb_brk) {
+ case KDB_REQ_DEBUGGER:
+
+ if ((dc->flags & DC_GDB) != 0) {
#ifdef GDB
- if (gdb_cur == &dcons_gdb_dbgport) {
- kdb_dbbe_select("gdb");
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on dcons gdb port");
- }
+ if (gdb_cur == &dcons_gdb_dbgport) {
+ kdb_dbbe_select("gdb");
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on dcons gdb port");
+ }
#endif
- } else
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on dcons console port");
+ } else
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on dcons console port");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("Panic sequence on dcons console port");
+ break;
+ case KDB_REQ_BREAK:
+ kdb_reboot();
+ break;
+ }
}
#else
switch (dc->brk_state) {
diff --git a/sys/dev/ofw/ofw_console.c b/sys/dev/ofw/ofw_console.c
index 154bcc5..156f121 100644
--- a/sys/dev/ofw/ofw_console.c
+++ b/sys/dev/ofw/ofw_console.c
@@ -281,8 +281,23 @@ ofw_cngetc(struct consdev *cp)
if (OF_read(stdin, &ch, 1) > 0) {
#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- if (kdb_alt_break(ch, &alt_break_state))
- kdb_enter(KDB_WHY_BREAK, "Break sequence on console");
+ int kdb_brk;
+
+ if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) {
+ switch (kdb_brk) {
+ case KDB_REQ_DEBUGGER:
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on console");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("Panic sequence on console");
+ break;
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+
+ }
+ }
#endif
return (ch);
}
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index a62b411..a4cca4d 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -1469,6 +1469,11 @@ siointr1(com)
u_char modem_status;
u_char *ioptr;
u_char recv_data;
+#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+ int kdb_brk;
+
+again:
+#endif
if (COM_IIR_TXRDYBUG(com->flags)) {
int_ctl = inb(com->int_ctl_port);
@@ -1501,9 +1506,24 @@ siointr1(com)
#ifdef KDB
#ifdef ALT_BREAK_TO_DEBUGGER
if (com->unit == comconsole &&
- kdb_alt_break(recv_data, &com->alt_brk_state) != 0)
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
+ (kdb_brk = kdb_alt_break(recv_data,
+ &com->alt_brk_state)) != 0) {
+ mtx_unlock_spin(&sio_lock);
+ switch (kdb_brk) {
+ case KDB_REQ_DEBUGGER:
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on console");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("panic on console");
+ break;
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
+ mtx_lock_spin(&sio_lock);
+ goto again;
+ }
#endif /* ALT_BREAK_TO_DEBUGGER */
#endif /* KDB */
if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index b4730418..3b0d64c 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -175,9 +175,23 @@ uart_intr_rxready(void *arg)
#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
while (rxp != sc->sc_rxput) {
- if (kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk))
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
+ int kdb_brk;
+
+ if ((kdb_brk = kdb_alt_break(sc->sc_rxbuf[rxp++],
+ &sc->sc_altbrk)) != 0) {
+ switch (kdb_brk) {
+ case KDB_REQ_DEBUGGER:
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on console");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("Panic sequence on console");
+ break;
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
+ }
if (rxp == sc->sc_rxbufsz)
rxp = 0;
}
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index 8b66a58..602093b 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -221,6 +221,25 @@ kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS)
return (0);
}
+void
+kdb_panic(const char *msg)
+{
+
+#ifdef SMP
+ stop_cpus(PCPU_GET(other_cpus));
+#endif
+ printf("KDB: panic\n");
+ panic(msg);
+}
+
+void
+kdb_reboot(void)
+{
+
+ printf("KDB: reboot requested\n");
+ shutdown_nice(0);
+}
+
/*
* Solaris implements a new BREAK which is initiated by a character sequence
* CR ~ ^b which is similar to a familiar pattern used on Sun servers by the
@@ -235,6 +254,8 @@ kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS)
#define KEY_CR 13 /* CR '\r' */
#define KEY_TILDE 126 /* ~ */
#define KEY_CRTLB 2 /* ^B */
+#define KEY_CRTLP 16 /* ^P */
+#define KEY_CRTLR 18 /* ^R */
int
kdb_alt_break(int key, int *state)
@@ -242,20 +263,23 @@ kdb_alt_break(int key, int *state)
int brk;
brk = 0;
- switch (key) {
- case KEY_CR:
- *state = KEY_TILDE;
+ switch (*state) {
+ case 0:
+ if (key == KEY_CR)
+ *state = 1;
break;
- case KEY_TILDE:
- *state = (*state == KEY_TILDE) ? KEY_CRTLB : 0;
+ case 1:
+ if (key == KEY_TILDE)
+ *state = 2;
break;
- case KEY_CRTLB:
- if (*state == KEY_CRTLB)
- brk = 1;
- /* FALLTHROUGH */
- default:
+ case 2:
+ if (key == KEY_CRTLB)
+ brk = KDB_REQ_DEBUGGER;
+ else if (key == KEY_CRTLP)
+ brk = KDB_REQ_PANIC;
+ else if (key == KEY_CRTLR)
+ brk = KDB_REQ_REBOOT;
*state = 0;
- break;
}
return (brk);
}
diff --git a/sys/pc98/cbus/sio.c b/sys/pc98/cbus/sio.c
index d0173af..7089578 100644
--- a/sys/pc98/cbus/sio.c
+++ b/sys/pc98/cbus/sio.c
@@ -2268,12 +2268,16 @@ siointr1(com)
u_char modem_status;
u_char *ioptr;
u_char recv_data;
-
#ifdef PC98
u_char tmp = 0;
u_char rsa_buf_status = 0;
int rsa_tx_fifo_size = 0;
#endif /* PC98 */
+#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+ int kdb_brk;
+
+again:
+#endif
if (COM_IIR_TXRDYBUG(com->flags)) {
int_ctl = inb(com->int_ctl_port);
@@ -2368,9 +2372,24 @@ more_intr:
#ifdef KDB
#ifdef ALT_BREAK_TO_DEBUGGER
if (com->unit == comconsole &&
- kdb_alt_break(recv_data, &com->alt_brk_state) != 0)
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
+ (kdb_brk = kdb_alt_break(recv_data,
+ &com->alt_brk_state)) != 0) {
+ mtx_unlock_spin(&sio_lock);
+ switch (kdb_brk) {
+ case KDB_REQ_DEBUGGER:
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on console");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("panic on console");
+ break;
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
+ mtx_lock_spin(&sio_lock);
+ goto again;
+ }
#endif /* ALT_BREAK_TO_DEBUGGER */
#endif /* KDB */
if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
diff --git a/sys/sun4v/sun4v/hvcons.c b/sys/sun4v/sun4v/hvcons.c
index 3329d05..0217a85 100644
--- a/sys/sun4v/sun4v/hvcons.c
+++ b/sys/sun4v/sun4v/hvcons.c
@@ -223,11 +223,25 @@ hvcn_cngetc(struct consdev *cp)
while ((l = hv_cons_getchar(&ch)) != H_EOK) {
#if defined(KDB)
+ int kdb_brk;
+
if (l == H_BREAK || l == H_HUP)
kdb_enter(KDB_WHY_BREAK, "Break sequence on console");
- if (kdb_alt_break(ch, &alt_break_state))
- kdb_enter(KDB_WHY_BREAK, "Break sequence on console");
+ if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) {
+ switch (kdb_brk) {
+ case KDB_REQ_DEBUGGER:
+ kdb_enter(KDB_WHY_BREAK,
+ "Break sequence on console");
+ break;
+ case KDB_REQ_PANIC:
+ kdb_panic("Panic sequence on console");
+ break;
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
+ }
#endif
if (l != -2 && l != 0) {
return (-1);
diff --git a/sys/sys/kdb.h b/sys/sys/kdb.h
index 0f989f5..c162852 100644
--- a/sys/sys/kdb.h
+++ b/sys/sys/kdb.h
@@ -69,6 +69,8 @@ int kdb_dbbe_select(const char *);
void kdb_enter(const char *, const char *);
void kdb_init(void);
void * kdb_jmpbuf(jmp_buf);
+void kdb_panic(const char *);
+void kdb_reboot(void);
void kdb_reenter(void);
struct pcb *kdb_thr_ctx(struct thread *);
struct thread *kdb_thr_first(void);
@@ -105,4 +107,9 @@ extern const char * volatile kdb_why;
#define KDB_WHY_POWERPC "powerpc" /* Unhandled powerpc intr. */
#define KDB_WHY_UNIONFS "unionfs" /* Unionfs bug. */
+/* Return values for kdb_alt_break */
+#define KDB_REQ_DEBUGGER 1 /* User requested Debugger */
+#define KDB_REQ_PANIC 2 /* User requested a panic */
+#define KDB_REQ_REBOOT 3 /* User requested a clean reboot */
+
#endif /* !_SYS_KDB_H_ */
OpenPOWER on IntegriCloud