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.
This commit is contained in:
parent
40ba3f0b05
commit
5a3c5f632b
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user