kdb
[Top] [All Lists]

Re: can't enter KDB after panic?

To: Ken Preslan <kpreslan@xxxxxxxxxxx>
Subject: Re: can't enter KDB after panic?
From: Keith Owens <kaos@xxxxxxxxxxxxxxxxx>
Date: Fri, 23 Feb 2001 15:12:43 +1100
Cc: kdb@xxxxxxxxxxx
In-reply-to: Your message of "Thu, 22 Feb 2001 17:31:22 MDT." <20010222173122.A8980@xxxxxxxxxxx>
Sender: owner-kdb@xxxxxxxxxxx
On Thu, 22 Feb 2001 17:31:22 -0600, 
Ken Preslan <kpreslan@xxxxxxxxxxx> wrote:
>No version of KDB I've ever used has automaticaly dropped into KDB
>on a panic() call.  An oops, yes, but not a panic.

True.  See patch below.

>Is there something I should be doing to set up the NMI watchdog on a SMP box?

panic() disables the APICs which turns off all interrupts, including
the NMI watchdog.  panic() also disables all the other cpus.

This patch renames the existing kdb panic to oops and adds panic.
Because of the way that kdb is entered from the panic() routine, it has
no valid exception frame.  kdb tries to synthesise an exception frame
but that is tricky and does not always work.  If backtrace from panic
says "not in kernel" then get the pid from the earlier message and do
"btp pid" instead.  You can also get invalid kernel addresses due to
the incorrect exception frame, ignore those messages.

Patch against kernel 2.4.2 + kdb-v1.7-2.4.2.

Index: 2.2/include/linux/kdb.h
--- 2.2/include/linux/kdb.h Mon, 29 Jan 2001 17:02:23 +1100 kaos 
(linux-2.4/b/d/39_kdb.h 1.3 644)
+++ 2.2(w)/include/linux/kdb.h Fri, 23 Feb 2001 14:31:41 +1100 kaos 
(linux-2.4/b/d/39_kdb.h 1.3 644)
@@ -136,7 +136,7 @@ typedef enum {
        KDB_REASON_FAULT,               /* Kernel fault - regs valid */
        KDB_REASON_BREAK,               /* Breakpoint inst. - regs valid */
        KDB_REASON_DEBUG,               /* Debug Fault - regs valid */
-       KDB_REASON_PANIC,               /* Kernel Panic - regs valid */
+       KDB_REASON_OOPS,                /* Kernel Oops - regs valid */
        KDB_REASON_SWITCH,              /* CPU switch - regs valid*/
        KDB_REASON_ENTER,               /* KDB_ENTER() trap/fault - regs valid 
*/
        KDB_REASON_KEYBOARD,            /* Keyboard entry - regs valid */
@@ -144,6 +144,7 @@ typedef enum {
        KDB_REASON_WATCHDOG,            /* Watchdog interrupt; regs valid */
        KDB_REASON_RECURSE,             /* Recursive entry to kdb; regs 
probably valid */
        KDB_REASON_SILENT,              /* Silent entry/exit to kdb; regs 
invalid */
+       KDB_REASON_PANIC,               /* From panic() routine; regs invalid */
 } kdb_reason_t;
 
 
Index: 2.2/arch/i386/kdb/kdbasupport.c
--- 2.2/arch/i386/kdb/kdbasupport.c Sun, 21 Jan 2001 15:29:07 +1100 kaos 
(linux-2.4/b/d/48_kdbasuppor 1.2 644)
+++ 2.2(w)/arch/i386/kdb/kdbasupport.c Fri, 23 Feb 2001 13:01:28 +1100 kaos 
(linux-2.4/b/d/48_kdbasuppor 1.2 644)
@@ -1497,7 +1497,7 @@ kdba_callback_die(struct pt_regs *regs, 
         */
        kdb_diemsg = (char *)vp;
 
-       return kdb(KDB_REASON_PANIC, error_code, (kdb_eframe_t) regs);
+       return kdb(KDB_REASON_OOPS, error_code, (kdb_eframe_t) regs);
 }
 
 /*
Index: 2.2/kdb/kdbmain.c
--- 2.2/kdb/kdbmain.c Tue, 30 Jan 2001 17:15:54 +1100 kaos 
(linux-2.4/b/d/49_kdbmain.c 1.1.1.4 644)
+++ 2.2(w)/kdb/kdbmain.c Fri, 23 Feb 2001 14:53:39 +1100 kaos 
(linux-2.4/b/d/49_kdbmain.c 1.1.1.4 644)
@@ -734,6 +734,7 @@ kdb_local(kdb_reason_t reason, int error
        char            cmd[CMD_BUFLEN];
        int             diag;
        int             parsed_once=0;  /* if false don't repeat last cmd on CR 
*/
+       typeof (*ef)    local_ef;
 
        if (reason != KDB_REASON_DEBUG &&
            reason != KDB_REASON_SILENT) {
@@ -788,18 +789,24 @@ kdb_local(kdb_reason_t reason, int error
        case KDB_REASON_SWITCH:
                kdb_printf("due to cpu switch\n");
                break;
-       case KDB_REASON_CALL:
-               kdb_printf("due to direct function call\n");
+       case KDB_REASON_CALL:   /* drop through */
+       case KDB_REASON_PANIC:
+               if (reason == KDB_REASON_CALL)
+                       kdb_printf("due to direct function call\n");
+               else
+                       kdb_printf("due to panic\n");
                /*
                 *  Get a set of registers that defines the current
                 * context (as of the call to kdb).
                 */
+               memset(&local_ef, 0, sizeof(local_ef));
+               ef = &local_ef;
                kdb_getcurrentframe(ef);
                kdba_setpc(ef, (kdb_machreg_t)(&kdb));  /* for traceback */
                break;
-       case KDB_REASON_PANIC:
-               kdb_printf("Panic: %s\n", kdb_diemsg);
-               kdb_printf("due to panic @ " kdb_machreg_fmt "\n", 
kdba_getpc(ef));
+       case KDB_REASON_OOPS:
+               kdb_printf("Oops: %s\n", kdb_diemsg);
+               kdb_printf("due to oops @ " kdb_machreg_fmt "\n", 
kdba_getpc(ef));
                kdba_dumpregs(ef, NULL, NULL);
                break;
        case KDB_REASON_NMI:
@@ -977,8 +984,8 @@ kdb_previous_event(void)
  *                     acording to kdb state.
  *     db_result       Result code from break or debug point.
  *     ef              The exception frame at time of fault/breakpoint.  If 
reason
- *                     is KDB_REASON_SILENT then ef is NULL, otherwise it 
should
- *                     always be valid.
+ *                     is KDB_REASON_SILENT or KDB_REASON_PANIC then ef is 
NULL,
+ *                     otherwise it should always be valid.
  * Returns:
  *     0       KDB was invoked for an event which it wasn't responsible
  *     1       KDB handled the event for which it was invoked.
@@ -1065,8 +1072,10 @@ kdb_main_loop(kdb_reason_t reason, kdb_r
  *     The breakpoint trap code should invoke this function with
  *     one of KDB_REASON_BREAK (int 03) or KDB_REASON_DEBUG (debug register)
  *
- *     the panic function should invoke this function with
- *     KDB_REASON_PANIC.
+ *     the die_if_kernel function should invoke this function with
+ *     KDB_REASON_OOPS.
+ *
+ *     the panic function should invoke this function with KDB_REASON_PANIC.
  *
  *     The kernel fault handler should invoke this function with
  *     reason == KDB_REASON_FAULT and error == trap vector #.
@@ -1080,8 +1089,8 @@ kdb_main_loop(kdb_reason_t reason, kdb_r
  *     reason          The reason KDB was invoked
  *     error           The hardware-defined error code
  *     ef              The exception frame at time of fault/breakpoint.  If 
reason
- *                     is KDB_REASON_SILENT then ef is NULL, otherwise it 
should
- *                     always be valid.
+ *                     is KDB_REASON_SILENT or KDB_REASON_PANIC then ef is 
NULL,
+ *                     otherwise it should always be valid.
  * Returns:
  *     0       KDB was invoked for an event which it wasn't responsible
  *     1       KDB handled the event for which it was invoked.
@@ -2698,6 +2707,34 @@ kdb_cmd_init(void)
 }
 
 /*
+ * kdb_panic
+ *
+ *     Invoked via the panic_notifier_list.
+ *
+ * Inputs:
+ *     None.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     Zero.
+ * Locking:
+ *     None.
+ * Remarks:
+ *     When this function is called from panic(), the other cpus have already
+ *     been stopped.
+ *
+ */
+
+static int
+kdb_panic(struct notifier_block *self, unsigned long command, void *ptr)
+{
+       kdb(KDB_REASON_PANIC, 0, NULL);
+       return(0);
+}
+
+static struct notifier_block kdb_block = { kdb_panic, NULL, 0 };
+
+/*
  * kdb_init
  *
  *     Initialize the kernel debugger environment.
@@ -2734,6 +2771,7 @@ kdb_init(void)
 
        kdb_cmd_init();         /* Preset commands from kdb_cmds */
        kdb(KDB_REASON_SILENT, 0, 0);   /* Activate any preset breakpoints on 
boot cpu */
+       notifier_chain_register(&panic_notifier_list, &kdb_block);
 }
 
 EXPORT_SYMBOL(kdb_register);


<Prev in Thread] Current Thread [Next in Thread>