]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'for_linux-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 2 Mar 2013 16:31:39 +0000 (08:31 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 2 Mar 2013 16:31:39 +0000 (08:31 -0800)
Pull KGDB/KDB fixes and cleanups from Jason Wessel:
 "For a change we removed more code than we added.  If people aren't
  using it we shouldn't be carrying it.  :-)

  Cleanups:
   - Remove kdb ssb command - there is no in kernel disassembler to
     support it

   - Remove kdb ll command - Always caused a kernel oops and there were
     no bug reports so no one was using this command

   - Use kernel ARRAY_SIZE macro instead of array computations

  Fixes:
   - Stop oops in kdb if user executes kdb_defcmd with args

   - kdb help command truncated text

   - ppc64 support for kgdbts

   - Add missing kconfig option from original kdb port for dealing with
     catastrophic kernel crashes such that you can reboot automatically
     on continue from kdb"

* tag 'for_linux-3.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb:
  kdb: Remove unhandled ssb command
  kdb: Prevent kernel oops with kdb_defcmd
  kdb: Remove the ll command
  kdb_main: fix help print
  kdb: Fix overlap in buffers with strcpy
  Fixed dead ifdef block by adding missing Kconfig option.
  kdb: Setup basic kdb state before invoking commands via kgdb
  kdb: use ARRAY_SIZE where possible
  kgdb/kgdbts: support ppc64
  kdb: A fix for kdb command table expansion

drivers/misc/kgdbts.c
kernel/debug/debug_core.h
kernel/debug/gdbstub.c
kernel/debug/kdb/kdb_bp.c
kernel/debug/kdb/kdb_debugger.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_private.h
lib/Kconfig.kgdb

index 3aa9a969b373a4ffd102e35e2f5c804274675dab..36f5d52775a98a7b72602fd4d4f79ba731b48df2 100644 (file)
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
+#include <asm/sections.h>
 
 #define v1printk(a...) do { \
        if (verbose) \
@@ -222,6 +223,7 @@ static unsigned long lookup_addr(char *arg)
                addr = (unsigned long)do_fork;
        else if (!strcmp(arg, "hw_break_val"))
                addr = (unsigned long)&hw_break_val;
+       addr = (unsigned long) dereference_function_descriptor((void *)addr);
        return addr;
 }
 
index 3494c28a7e7ab85ce0fed8b9e46417df8e050833..2235967e78b0c8c6c181295269b2d7cc61e40232 100644 (file)
@@ -72,6 +72,8 @@ extern int dbg_kdb_mode;
 #ifdef CONFIG_KGDB_KDB
 extern int kdb_stub(struct kgdb_state *ks);
 extern int kdb_parse(const char *cmdstr);
+extern int kdb_common_init_state(struct kgdb_state *ks);
+extern int kdb_common_deinit_state(void);
 #else /* ! CONFIG_KGDB_KDB */
 static inline int kdb_stub(struct kgdb_state *ks)
 {
index 38573f35a5ad8acf12d55d52a3814daebde8a069..19d9a578c75316013d4acde0ac562d66d78794f3 100644 (file)
@@ -783,7 +783,10 @@ static void gdb_cmd_query(struct kgdb_state *ks)
                        len = len / 2;
                        remcom_out_buffer[len++] = 0;
 
+                       kdb_common_init_state(ks);
                        kdb_parse(remcom_out_buffer);
+                       kdb_common_deinit_state();
+
                        strcpy(remcom_out_buffer, "OK");
                }
                break;
index 8418c2f8ec5dd255d18794ca13cf895a3b588a76..70a504601dc3909c15c424b1d2b1afdf25b9b341 100644 (file)
@@ -486,11 +486,9 @@ static int kdb_bc(int argc, const char **argv)
 /*
  * kdb_ss
  *
- *     Process the 'ss' (Single Step) and 'ssb' (Single Step to Branch)
- *     commands.
+ *     Process the 'ss' (Single Step) command.
  *
  *     ss
- *     ssb
  *
  * Parameters:
  *     argc    Argument count
@@ -498,35 +496,23 @@ static int kdb_bc(int argc, const char **argv)
  * Outputs:
  *     None.
  * Returns:
- *     KDB_CMD_SS[B] for success, a kdb error if failure.
+ *     KDB_CMD_SS for success, a kdb error if failure.
  * Locking:
  *     None.
  * Remarks:
  *
  *     Set the arch specific option to trigger a debug trap after the next
  *     instruction.
- *
- *     For 'ssb', set the trace flag in the debug trap handler
- *     after printing the current insn and return directly without
- *     invoking the kdb command processor, until a branch instruction
- *     is encountered.
  */
 
 static int kdb_ss(int argc, const char **argv)
 {
-       int ssb = 0;
-
-       ssb = (strcmp(argv[0], "ssb") == 0);
        if (argc != 0)
                return KDB_ARGCOUNT;
        /*
         * Set trace flag and go.
         */
        KDB_STATE_SET(DOING_SS);
-       if (ssb) {
-               KDB_STATE_SET(DOING_SSB);
-               return KDB_CMD_SSB;
-       }
        return KDB_CMD_SS;
 }
 
@@ -561,8 +547,6 @@ void __init kdb_initbptab(void)
 
        kdb_register_repeat("ss", kdb_ss, "",
                "Single Step", 1, KDB_REPEAT_NO_ARGS);
-       kdb_register_repeat("ssb", kdb_ss, "",
-               "Single step to branch/call", 0, KDB_REPEAT_NO_ARGS);
        /*
         * Architecture dependent initialization.
         */
index be7b33b73d3001eef1b676ad1efde4f318824902..328d18ef31e4b4f02e7cde7aff71504ad8a0fb5e 100644 (file)
@@ -34,6 +34,22 @@ EXPORT_SYMBOL_GPL(kdb_poll_idx);
 
 static struct kgdb_state *kdb_ks;
 
+int kdb_common_init_state(struct kgdb_state *ks)
+{
+       kdb_initial_cpu = atomic_read(&kgdb_active);
+       kdb_current_task = kgdb_info[ks->cpu].task;
+       kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
+       return 0;
+}
+
+int kdb_common_deinit_state(void)
+{
+       kdb_initial_cpu = -1;
+       kdb_current_task = NULL;
+       kdb_current_regs = NULL;
+       return 0;
+}
+
 int kdb_stub(struct kgdb_state *ks)
 {
        int error = 0;
@@ -94,13 +110,10 @@ int kdb_stub(struct kgdb_state *ks)
        }
        /* Set initial kdb state variables */
        KDB_STATE_CLEAR(KGDB_TRANS);
-       kdb_initial_cpu = atomic_read(&kgdb_active);
-       kdb_current_task = kgdb_info[ks->cpu].task;
-       kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
+       kdb_common_init_state(ks);
        /* Remove any breakpoints as needed by kdb and clear single step */
        kdb_bp_remove();
        KDB_STATE_CLEAR(DOING_SS);
-       KDB_STATE_CLEAR(DOING_SSB);
        KDB_STATE_SET(PAGER);
        /* zero out any offline cpu data */
        for_each_present_cpu(i) {
@@ -125,9 +138,7 @@ int kdb_stub(struct kgdb_state *ks)
         * Upon exit from the kdb main loop setup break points and restart
         * the system based on the requested continue state
         */
-       kdb_initial_cpu = -1;
-       kdb_current_task = NULL;
-       kdb_current_regs = NULL;
+       kdb_common_deinit_state();
        KDB_STATE_CLEAR(PAGER);
        kdbnearsym_cleanup();
        if (error == KDB_CMD_KGDB) {
index 8875254120b66f9a0a6e784d83fc6a1e76f6f4c0..00eb8f7fbf41c49e1deb4b09e6858858064ae9e9 100644 (file)
@@ -124,7 +124,7 @@ static kdbmsg_t kdbmsgs[] = {
 };
 #undef KDBMSG
 
-static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t);
+static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
 
 
 /*
@@ -175,7 +175,7 @@ static char *__env[] = {
  (char *)0,
 };
 
-static const int __nenv = (sizeof(__env) / sizeof(char *));
+static const int __nenv = ARRAY_SIZE(__env);
 
 struct task_struct *kdb_curr_task(int cpu)
 {
@@ -681,34 +681,50 @@ static int kdb_defcmd(int argc, const char **argv)
        }
        if (argc != 3)
                return KDB_ARGCOUNT;
-       defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set),
-                            GFP_KDB);
-       if (!defcmd_set) {
-               kdb_printf("Could not allocate new defcmd_set entry for %s\n",
-                          argv[1]);
-               defcmd_set = save_defcmd_set;
+       if (in_dbg_master()) {
+               kdb_printf("Command only available during kdb_init()\n");
                return KDB_NOTIMP;
        }
+       defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set),
+                            GFP_KDB);
+       if (!defcmd_set)
+               goto fail_defcmd;
        memcpy(defcmd_set, save_defcmd_set,
               defcmd_set_count * sizeof(*defcmd_set));
-       kfree(save_defcmd_set);
        s = defcmd_set + defcmd_set_count;
        memset(s, 0, sizeof(*s));
        s->usable = 1;
        s->name = kdb_strdup(argv[1], GFP_KDB);
+       if (!s->name)
+               goto fail_name;
        s->usage = kdb_strdup(argv[2], GFP_KDB);
+       if (!s->usage)
+               goto fail_usage;
        s->help = kdb_strdup(argv[3], GFP_KDB);
+       if (!s->help)
+               goto fail_help;
        if (s->usage[0] == '"') {
-               strcpy(s->usage, s->usage+1);
+               strcpy(s->usage, argv[2]+1);
                s->usage[strlen(s->usage)-1] = '\0';
        }
        if (s->help[0] == '"') {
-               strcpy(s->help, s->help+1);
+               strcpy(s->help, argv[3]+1);
                s->help[strlen(s->help)-1] = '\0';
        }
        ++defcmd_set_count;
        defcmd_in_progress = 1;
+       kfree(save_defcmd_set);
        return 0;
+fail_help:
+       kfree(s->usage);
+fail_usage:
+       kfree(s->name);
+fail_name:
+       kfree(defcmd_set);
+fail_defcmd:
+       kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]);
+       defcmd_set = save_defcmd_set;
+       return KDB_NOTIMP;
 }
 
 /*
@@ -1112,7 +1128,6 @@ void kdb_set_current_task(struct task_struct *p)
  *     KDB_CMD_GO      User typed 'go'.
  *     KDB_CMD_CPU     User switched to another cpu.
  *     KDB_CMD_SS      Single step.
- *     KDB_CMD_SSB     Single step until branch.
  */
 static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
                     kdb_dbtrap_t db_result)
@@ -1151,14 +1166,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
                        kdb_printf("due to Debug @ " kdb_machreg_fmt "\n",
                                   instruction_pointer(regs));
                        break;
-               case KDB_DB_SSB:
-                       /*
-                        * In the midst of ssb command. Just return.
-                        */
-                       KDB_DEBUG_STATE("kdb_local 3", reason);
-                       return KDB_CMD_SSB;     /* Continue with SSB command */
-
-                       break;
                case KDB_DB_SS:
                        break;
                case KDB_DB_SSBPT:
@@ -1281,7 +1288,6 @@ do_full_getstr:
                if (diag == KDB_CMD_GO
                 || diag == KDB_CMD_CPU
                 || diag == KDB_CMD_SS
-                || diag == KDB_CMD_SSB
                 || diag == KDB_CMD_KGDB)
                        break;
 
@@ -1368,12 +1374,6 @@ int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
                        break;
                }
 
-               if (result == KDB_CMD_SSB) {
-                       KDB_STATE_SET(DOING_SS);
-                       KDB_STATE_SET(DOING_SSB);
-                       break;
-               }
-
                if (result == KDB_CMD_KGDB) {
                        if (!KDB_STATE(DOING_KGDB))
                                kdb_printf("Entering please attach debugger "
@@ -2350,69 +2350,6 @@ static int kdb_pid(int argc, const char **argv)
        return 0;
 }
 
-/*
- * kdb_ll - This function implements the 'll' command which follows a
- *     linked list and executes an arbitrary command for each
- *     element.
- */
-static int kdb_ll(int argc, const char **argv)
-{
-       int diag = 0;
-       unsigned long addr;
-       long offset = 0;
-       unsigned long va;
-       unsigned long linkoffset;
-       int nextarg;
-       const char *command;
-
-       if (argc != 3)
-               return KDB_ARGCOUNT;
-
-       nextarg = 1;
-       diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
-       if (diag)
-               return diag;
-
-       diag = kdbgetularg(argv[2], &linkoffset);
-       if (diag)
-               return diag;
-
-       /*
-        * Using the starting address as
-        * the first element in the list, and assuming that
-        * the list ends with a null pointer.
-        */
-
-       va = addr;
-       command = kdb_strdup(argv[3], GFP_KDB);
-       if (!command) {
-               kdb_printf("%s: cannot duplicate command\n", __func__);
-               return 0;
-       }
-       /* Recursive use of kdb_parse, do not use argv after this point */
-       argv = NULL;
-
-       while (va) {
-               char buf[80];
-
-               if (KDB_FLAG(CMD_INTERRUPT))
-                       goto out;
-
-               sprintf(buf, "%s " kdb_machreg_fmt "\n", command, va);
-               diag = kdb_parse(buf);
-               if (diag)
-                       goto out;
-
-               addr = va + linkoffset;
-               if (kdb_getword(&va, addr, sizeof(va)))
-                       goto out;
-       }
-
-out:
-       kfree(command);
-       return diag;
-}
-
 static int kdb_kgdb(int argc, const char **argv)
 {
        return KDB_CMD_KGDB;
@@ -2430,11 +2367,15 @@ static int kdb_help(int argc, const char **argv)
        kdb_printf("-----------------------------"
                   "-----------------------------\n");
        for_each_kdbcmd(kt, i) {
-               if (kt->cmd_name)
-                       kdb_printf("%-15.15s %-20.20s %s\n", kt->cmd_name,
-                                  kt->cmd_usage, kt->cmd_help);
+               char *space = "";
                if (KDB_FLAG(CMD_INTERRUPT))
                        return 0;
+               if (!kt->cmd_name)
+                       continue;
+               if (strlen(kt->cmd_usage) > 20)
+                       space = "\n                                    ";
+               kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,
+                          kt->cmd_usage, space, kt->cmd_help);
        }
        return 0;
 }
@@ -2739,7 +2680,7 @@ int kdb_register_repeat(char *cmd,
                          (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
                        kfree(kdb_commands);
                }
-               memset(new + kdb_max_commands, 0,
+               memset(new + kdb_max_commands - KDB_BASE_CMD_MAX, 0,
                       kdb_command_extend * sizeof(*new));
                kdb_commands = new;
                kp = kdb_commands + kdb_max_commands - KDB_BASE_CMD_MAX;
@@ -2843,15 +2784,13 @@ static void __init kdb_inittab(void)
          "Stack traceback", 1, KDB_REPEAT_NONE);
        kdb_register_repeat("btp", kdb_bt, "<pid>",
          "Display stack for process <pid>", 0, KDB_REPEAT_NONE);
-       kdb_register_repeat("bta", kdb_bt, "[DRSTCZEUIMA]",
-         "Display stack all processes", 0, KDB_REPEAT_NONE);
+       kdb_register_repeat("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
+         "Backtrace all processes matching state flag", 0, KDB_REPEAT_NONE);
        kdb_register_repeat("btc", kdb_bt, "",
          "Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
        kdb_register_repeat("btt", kdb_bt, "<vaddr>",
          "Backtrace process given its struct task address", 0,
                            KDB_REPEAT_NONE);
-       kdb_register_repeat("ll", kdb_ll, "<first-element> <linkoffset> <cmd>",
-         "Execute cmd for each element in linked list", 0, KDB_REPEAT_NONE);
        kdb_register_repeat("env", kdb_env, "",
          "Show environment variables", 0, KDB_REPEAT_NONE);
        kdb_register_repeat("set", kdb_set, "",
index 392ec6a25844c48f1242a649c0c58a1d22c0c783..7afd3c8c41d5d51f17a7a14566551bf2d731d068 100644 (file)
@@ -19,7 +19,6 @@
 #define KDB_CMD_GO     (-1001)
 #define KDB_CMD_CPU    (-1002)
 #define KDB_CMD_SS     (-1003)
-#define KDB_CMD_SSB    (-1004)
 #define KDB_CMD_KGDB (-1005)
 
 /* Internal debug flags */
@@ -125,8 +124,6 @@ extern int kdb_state;
                                                 * kdb control */
 #define KDB_STATE_HOLD_CPU     0x00000010      /* Hold this cpu inside kdb */
 #define KDB_STATE_DOING_SS     0x00000020      /* Doing ss command */
-#define KDB_STATE_DOING_SSB    0x00000040      /* Doing ssb command,
-                                                * DOING_SS is also set */
 #define KDB_STATE_SSBPT                0x00000080      /* Install breakpoint
                                                 * after one ss, independent of
                                                 * DOING_SS */
@@ -191,7 +188,6 @@ extern void kdb_bp_remove(void);
 typedef enum {
        KDB_DB_BPT,     /* Breakpoint */
        KDB_DB_SS,      /* Single-step trap */
-       KDB_DB_SSB,     /* Single step to branch */
        KDB_DB_SSBPT,   /* Single step over breakpoint */
        KDB_DB_NOBPT    /* Spurious breakpoint */
 } kdb_dbtrap_t;
index dbb58ae1b8e0c91060b3d8089bd5912d23a4c078..140e878241738ce9e2ba5a7b5369c14542e5d66d 100644 (file)
@@ -80,4 +80,22 @@ config KDB_KEYBOARD
        help
          KDB can use a PS/2 type keyboard for an input device
 
+config KDB_CONTINUE_CATASTROPHIC
+       int "KDB: continue after catastrophic errors"
+       depends on KGDB_KDB
+       default "0"
+       help
+         This integer controls the behaviour of kdb when the kernel gets a
+         catastrophic error, i.e. for a panic or oops.
+         When KDB is active and a catastrophic error occurs, nothing extra
+         will happen until you type 'go'.
+         CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default). The first time
+         you type 'go', you will be warned by kdb. The secend time you type
+         'go', KDB tries to continue. No guarantees that the
+         kernel is still usable in this situation.
+         CONFIG_KDB_CONTINUE_CATASTROPHIC == 1. KDB tries to continue.
+         No guarantees that the kernel is still usable in this situation.
+         CONFIG_KDB_CONTINUE_CATASTROPHIC == 2. KDB forces a reboot.
+         If you are not sure, say 0.
+
 endif # KGDB