diff options
author | peter <peter@FreeBSD.org> | 2008-05-04 23:29:38 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2008-05-04 23:29:38 +0000 |
commit | 5a3c5f632b4461dbf60ab538e16453104b937231 (patch) | |
tree | dec162871c2e0c2defef809d28858069fac12065 /sys | |
parent | 40ba3f0b054237aea1c061c7ae1d4a9b1b5dd800 (diff) | |
download | FreeBSD-src-5a3c5f632b4461dbf60ab538e16453104b937231.zip FreeBSD-src-5a3c5f632b4461dbf60ab538e16453104b937231.tar.gz |
Expand kdb_alt_break a little, most commonly used with the option
ALT_BREAK_TO_DEBUGGER. In addition to "Enter ~ ctrl-B" (to enter the
debugger), there is now "Enter ~ ctrl-P" (force panic) and
"Enter ~ ctrl-R" (request clean reboot, ala ctrl-alt-del on syscons).
We've used variations of this at work. The force panic sequence is
best used with KDB_UNATTENDED for when you just want it to dump and
get on with it.
The reboot request is a safer way of getting into single user than
a power cycle. eg: you've hosed the ability to log in (pam, rtld, etc).
It gives init the reboot signal, which causes an orderly reboot.
I've taken my best guess at what the !x86 and non-sio code changes
should be.
This also makes sio release its spinlock before calling KDB/DDB.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arm/at91/uart_dev_at91usart.c | 15 | ||||
-rw-r--r-- | sys/dev/dcons/dcons_os.c | 34 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_console.c | 19 | ||||
-rw-r--r-- | sys/dev/sio/sio.c | 26 | ||||
-rw-r--r-- | sys/dev/uart/uart_core.c | 20 | ||||
-rw-r--r-- | sys/kern/subr_kdb.c | 46 | ||||
-rw-r--r-- | sys/pc98/cbus/sio.c | 27 | ||||
-rw-r--r-- | sys/sun4v/sun4v/hvcons.c | 18 | ||||
-rw-r--r-- | sys/sys/kdb.h | 7 |
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_ */ |