Merge tag 'printk-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/printk...
[linux-2.6-microblaze.git] / kernel / debug / kdb / kdb_main.c
index 315169d..1baa96a 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/kallsyms.h>
 #include <linux/kgdb.h>
 #include <linux/kdb.h>
+#include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -84,15 +85,8 @@ static unsigned int kdb_continue_catastrophic =
 static unsigned int kdb_continue_catastrophic;
 #endif
 
-/* kdb_commands describes the available commands. */
-static kdbtab_t *kdb_commands;
-#define KDB_BASE_CMD_MAX 50
-static int kdb_max_commands = KDB_BASE_CMD_MAX;
-static kdbtab_t kdb_base_commands[KDB_BASE_CMD_MAX];
-#define for_each_kdbcmd(cmd, num)                                      \
-       for ((cmd) = kdb_base_commands, (num) = 0;                      \
-            num < kdb_max_commands;                                    \
-            num++, num == KDB_BASE_CMD_MAX ? cmd = kdb_commands : cmd++)
+/* kdb_cmds_head describes the available commands. */
+static LIST_HEAD(kdb_cmds_head);
 
 typedef struct _kdbmsg {
        int     km_diag;        /* kdb diagnostic */
@@ -146,42 +140,18 @@ static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
  * KDB_ENVBUFSIZE if required).
  */
 
-static char *__env[] = {
+static char *__env[31] = {
 #if defined(CONFIG_SMP)
- "PROMPT=[%d]kdb> ",
      "PROMPT=[%d]kdb> ",
 #else
- "PROMPT=kdb> ",
      "PROMPT=kdb> ",
 #endif
- "MOREPROMPT=more> ",
- "RADIX=16",
- "MDCOUNT=8",                  /* lines of md output */
- KDB_PLATFORM_ENV,
- "DTABCOUNT=30",
- "NOSECT=1",
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
- (char *)0,
+       "MOREPROMPT=more> ",
+       "RADIX=16",
+       "MDCOUNT=8",            /* lines of md output */
+       KDB_PLATFORM_ENV,
+       "DTABCOUNT=30",
+       "NOSECT=1",
 };
 
 static const int __nenv = ARRAY_SIZE(__env);
@@ -323,6 +293,63 @@ int kdbgetintenv(const char *match, int *value)
        return diag;
 }
 
+/*
+ * kdb_setenv() - Alter an existing environment variable or create a new one.
+ * @var: Name of the variable
+ * @val: Value of the variable
+ *
+ * Return: Zero on success, a kdb diagnostic on failure.
+ */
+static int kdb_setenv(const char *var, const char *val)
+{
+       int i;
+       char *ep;
+       size_t varlen, vallen;
+
+       varlen = strlen(var);
+       vallen = strlen(val);
+       ep = kdballocenv(varlen + vallen + 2);
+       if (ep == (char *)0)
+               return KDB_ENVBUFFULL;
+
+       sprintf(ep, "%s=%s", var, val);
+
+       for (i = 0; i < __nenv; i++) {
+               if (__env[i]
+                && ((strncmp(__env[i], var, varlen) == 0)
+                  && ((__env[i][varlen] == '\0')
+                   || (__env[i][varlen] == '=')))) {
+                       __env[i] = ep;
+                       return 0;
+               }
+       }
+
+       /*
+        * Wasn't existing variable.  Fit into slot.
+        */
+       for (i = 0; i < __nenv-1; i++) {
+               if (__env[i] == (char *)0) {
+                       __env[i] = ep;
+                       return 0;
+               }
+       }
+
+       return KDB_ENVFULL;
+}
+
+/*
+ * kdb_printenv() - Display the current environment variables.
+ */
+static void kdb_printenv(void)
+{
+       int i;
+
+       for (i = 0; i < __nenv; i++) {
+               if (__env[i])
+                       kdb_printf("%s\n", __env[i]);
+       }
+}
+
 /*
  * kdbgetularg - This function will convert a numeric string into an
  *     unsigned long value.
@@ -380,10 +407,6 @@ int kdbgetu64arg(const char *arg, u64 *value)
  */
 int kdb_set(int argc, const char **argv)
 {
-       int i;
-       char *ep;
-       size_t varlen, vallen;
-
        /*
         * we can be invoked two ways:
         *   set var=value    argv[1]="var", argv[2]="value"
@@ -428,37 +451,7 @@ int kdb_set(int argc, const char **argv)
         * Tokenizer squashed the '=' sign.  argv[1] is variable
         * name, argv[2] = value.
         */
-       varlen = strlen(argv[1]);
-       vallen = strlen(argv[2]);
-       ep = kdballocenv(varlen + vallen + 2);
-       if (ep == (char *)0)
-               return KDB_ENVBUFFULL;
-
-       sprintf(ep, "%s=%s", argv[1], argv[2]);
-
-       ep[varlen+vallen+1] = '\0';
-
-       for (i = 0; i < __nenv; i++) {
-               if (__env[i]
-                && ((strncmp(__env[i], argv[1], varlen) == 0)
-                  && ((__env[i][varlen] == '\0')
-                   || (__env[i][varlen] == '=')))) {
-                       __env[i] = ep;
-                       return 0;
-               }
-       }
-
-       /*
-        * Wasn't existing variable.  Fit into slot.
-        */
-       for (i = 0; i < __nenv-1; i++) {
-               if (__env[i] == (char *)0) {
-                       __env[i] = ep;
-                       return 0;
-               }
-       }
-
-       return KDB_ENVFULL;
+       return kdb_setenv(argv[1], argv[2]);
 }
 
 static int kdb_check_regs(void)
@@ -921,7 +914,7 @@ int kdb_parse(const char *cmdstr)
        char *cp;
        char *cpp, quoted;
        kdbtab_t *tp;
-       int i, escaped, ignore_errors = 0, check_grep = 0;
+       int escaped, ignore_errors = 0, check_grep = 0;
 
        /*
         * First tokenize the command string.
@@ -1011,25 +1004,17 @@ int kdb_parse(const char *cmdstr)
                ++argv[0];
        }
 
-       for_each_kdbcmd(tp, i) {
-               if (tp->cmd_name) {
-                       /*
-                        * If this command is allowed to be abbreviated,
-                        * check to see if this is it.
-                        */
-
-                       if (tp->cmd_minlen
-                        && (strlen(argv[0]) <= tp->cmd_minlen)) {
-                               if (strncmp(argv[0],
-                                           tp->cmd_name,
-                                           tp->cmd_minlen) == 0) {
-                                       break;
-                               }
-                       }
+       list_for_each_entry(tp, &kdb_cmds_head, list_node) {
+               /*
+                * If this command is allowed to be abbreviated,
+                * check to see if this is it.
+                */
+               if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen) &&
+                   (strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0))
+                       break;
 
-                       if (strcmp(argv[0], tp->cmd_name) == 0)
-                               break;
-               }
+               if (strcmp(argv[0], tp->cmd_name) == 0)
+                       break;
        }
 
        /*
@@ -1037,19 +1022,15 @@ int kdb_parse(const char *cmdstr)
         * few characters of this match any of the known commands.
         * e.g., md1c20 should match md.
         */
-       if (i == kdb_max_commands) {
-               for_each_kdbcmd(tp, i) {
-                       if (tp->cmd_name) {
-                               if (strncmp(argv[0],
-                                           tp->cmd_name,
-                                           strlen(tp->cmd_name)) == 0) {
-                                       break;
-                               }
-                       }
+       if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
+               list_for_each_entry(tp, &kdb_cmds_head, list_node) {
+                       if (strncmp(argv[0], tp->cmd_name,
+                                   strlen(tp->cmd_name)) == 0)
+                               break;
                }
        }
 
-       if (i < kdb_max_commands) {
+       if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
                int result;
 
                if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
@@ -2073,12 +2054,7 @@ static int kdb_lsmod(int argc, const char **argv)
 
 static int kdb_env(int argc, const char **argv)
 {
-       int i;
-
-       for (i = 0; i < __nenv; i++) {
-               if (__env[i])
-                       kdb_printf("%s\n", __env[i]);
-       }
+       kdb_printenv();
 
        if (KDB_DEBUG(MASK))
                kdb_printf("KDBDEBUG=0x%x\n",
@@ -2101,7 +2077,7 @@ static int kdb_dmesg(int argc, const char **argv)
        int adjust = 0;
        int n = 0;
        int skip = 0;
-       struct kmsg_dumper dumper;
+       struct kmsg_dump_iter iter;
        size_t len;
        char buf[201];
 
@@ -2126,8 +2102,8 @@ static int kdb_dmesg(int argc, const char **argv)
                kdb_set(2, setargs);
        }
 
-       kmsg_dump_rewind_nolock(&dumper);
-       while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL))
+       kmsg_dump_rewind(&iter);
+       while (kmsg_dump_get_line(&iter, 1, NULL, 0, NULL))
                n++;
 
        if (lines < 0) {
@@ -2159,8 +2135,8 @@ static int kdb_dmesg(int argc, const char **argv)
        if (skip >= n || skip < 0)
                return 0;
 
-       kmsg_dump_rewind_nolock(&dumper);
-       while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) {
+       kmsg_dump_rewind(&iter);
+       while (kmsg_dump_get_line(&iter, 1, buf, sizeof(buf), &len)) {
                if (skip) {
                        skip--;
                        continue;
@@ -2428,17 +2404,14 @@ static int kdb_kgdb(int argc, const char **argv)
 static int kdb_help(int argc, const char **argv)
 {
        kdbtab_t *kt;
-       int i;
 
        kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
        kdb_printf("-----------------------------"
                   "-----------------------------\n");
-       for_each_kdbcmd(kt, i) {
+       list_for_each_entry(kt, &kdb_cmds_head, list_node) {
                char *space = "";
                if (KDB_FLAG(CMD_INTERRUPT))
                        return 0;
-               if (!kt->cmd_name)
-                       continue;
                if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
                        continue;
                if (strlen(kt->cmd_usage) > 20)
@@ -2659,7 +2632,6 @@ static int kdb_grep_help(int argc, const char **argv)
  * Returns:
  *     zero for success, one if a duplicate command.
  */
-#define kdb_command_extend 50  /* arbitrary */
 int kdb_register_flags(char *cmd,
                       kdb_func_t func,
                       char *usage,
@@ -2667,49 +2639,20 @@ int kdb_register_flags(char *cmd,
                       short minlen,
                       kdb_cmdflags_t flags)
 {
-       int i;
        kdbtab_t *kp;
 
-       /*
-        *  Brute force method to determine duplicates
-        */
-       for_each_kdbcmd(kp, i) {
-               if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
+       list_for_each_entry(kp, &kdb_cmds_head, list_node) {
+               if (strcmp(kp->cmd_name, cmd) == 0) {
                        kdb_printf("Duplicate kdb command registered: "
                                "%s, func %px help %s\n", cmd, func, help);
                        return 1;
                }
        }
 
-       /*
-        * Insert command into first available location in table
-        */
-       for_each_kdbcmd(kp, i) {
-               if (kp->cmd_name == NULL)
-                       break;
-       }
-
-       if (i >= kdb_max_commands) {
-               kdbtab_t *new = kmalloc_array(kdb_max_commands -
-                                               KDB_BASE_CMD_MAX +
-                                               kdb_command_extend,
-                                             sizeof(*new),
-                                             GFP_KDB);
-               if (!new) {
-                       kdb_printf("Could not allocate new kdb_command "
-                                  "table\n");
-                       return 1;
-               }
-               if (kdb_commands) {
-                       memcpy(new, kdb_commands,
-                         (kdb_max_commands - KDB_BASE_CMD_MAX) * sizeof(*new));
-                       kfree(kdb_commands);
-               }
-               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;
-               kdb_max_commands += kdb_command_extend;
+       kp = kmalloc(sizeof(*kp), GFP_KDB);
+       if (!kp) {
+               kdb_printf("Could not allocate new kdb_command table\n");
+               return 1;
        }
 
        kp->cmd_name   = cmd;
@@ -2718,11 +2661,27 @@ int kdb_register_flags(char *cmd,
        kp->cmd_help   = help;
        kp->cmd_minlen = minlen;
        kp->cmd_flags  = flags;
+       kp->is_dynamic = true;
+
+       list_add_tail(&kp->list_node, &kdb_cmds_head);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(kdb_register_flags);
 
+/*
+ * kdb_register_table() - This function is used to register a kdb command
+ *                        table.
+ * @kp: pointer to kdb command table
+ * @len: length of kdb command table
+ */
+void kdb_register_table(kdbtab_t *kp, size_t len)
+{
+       while (len--) {
+               list_add_tail(&kp->list_node, &kdb_cmds_head);
+               kp++;
+       }
+}
 
 /*
  * kdb_register - Compatibility register function for commands that do
@@ -2757,15 +2716,16 @@ EXPORT_SYMBOL_GPL(kdb_register);
  */
 int kdb_unregister(char *cmd)
 {
-       int i;
        kdbtab_t *kp;
 
        /*
         *  find the command.
         */
-       for_each_kdbcmd(kp, i) {
-               if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
-                       kp->cmd_name = NULL;
+       list_for_each_entry(kp, &kdb_cmds_head, list_node) {
+               if (strcmp(kp->cmd_name, cmd) == 0) {
+                       list_del(&kp->list_node);
+                       if (kp->is_dynamic)
+                               kfree(kp);
                        return 0;
                }
        }
@@ -2775,118 +2735,222 @@ int kdb_unregister(char *cmd)
 }
 EXPORT_SYMBOL_GPL(kdb_unregister);
 
-/* Initialize the kdb command table. */
-static void __init kdb_inittab(void)
-{
-       int i;
-       kdbtab_t *kp;
-
-       for_each_kdbcmd(kp, i)
-               kp->cmd_name = NULL;
-
-       kdb_register_flags("md", kdb_md, "<vaddr>",
-         "Display Memory Contents, also mdWcN, e.g. md8c1", 1,
-         KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
-       kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>",
-         "Display Raw Memory", 0,
-         KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
-       kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>",
-         "Display Physical Memory", 0,
-         KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
-       kdb_register_flags("mds", kdb_md, "<vaddr>",
-         "Display Memory Symbolically", 0,
-         KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
-       kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>",
-         "Modify Memory Contents", 0,
-         KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS);
-       kdb_register_flags("go", kdb_go, "[<vaddr>]",
-         "Continue Execution", 1,
-         KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
-       kdb_register_flags("rd", kdb_rd, "",
-         "Display Registers", 0,
-         KDB_ENABLE_REG_READ);
-       kdb_register_flags("rm", kdb_rm, "<reg> <contents>",
-         "Modify Registers", 0,
-         KDB_ENABLE_REG_WRITE);
-       kdb_register_flags("ef", kdb_ef, "<vaddr>",
-         "Display exception frame", 0,
-         KDB_ENABLE_MEM_READ);
-       kdb_register_flags("bt", kdb_bt, "[<vaddr>]",
-         "Stack traceback", 1,
-         KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
-       kdb_register_flags("btp", kdb_bt, "<pid>",
-         "Display stack for process <pid>", 0,
-         KDB_ENABLE_INSPECT);
-       kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
-         "Backtrace all processes matching state flag", 0,
-         KDB_ENABLE_INSPECT);
-       kdb_register_flags("btc", kdb_bt, "",
-         "Backtrace current process on each cpu", 0,
-         KDB_ENABLE_INSPECT);
-       kdb_register_flags("btt", kdb_bt, "<vaddr>",
-         "Backtrace process given its struct task address", 0,
-         KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
-       kdb_register_flags("env", kdb_env, "",
-         "Show environment variables", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
-       kdb_register_flags("set", kdb_set, "",
-         "Set environment variables", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
-       kdb_register_flags("help", kdb_help, "",
-         "Display Help Message", 1,
-         KDB_ENABLE_ALWAYS_SAFE);
-       kdb_register_flags("?", kdb_help, "",
-         "Display Help Message", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
-       kdb_register_flags("cpu", kdb_cpu, "<cpunum>",
-         "Switch to new cpu", 0,
-         KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
-       kdb_register_flags("kgdb", kdb_kgdb, "",
-         "Enter kgdb mode", 0, 0);
-       kdb_register_flags("ps", kdb_ps, "[<flags>|A]",
-         "Display active task list", 0,
-         KDB_ENABLE_INSPECT);
-       kdb_register_flags("pid", kdb_pid, "<pidnum>",
-         "Switch to another task", 0,
-         KDB_ENABLE_INSPECT);
-       kdb_register_flags("reboot", kdb_reboot, "",
-         "Reboot the machine immediately", 0,
-         KDB_ENABLE_REBOOT);
+static kdbtab_t maintab[] = {
+       {       .cmd_name = "md",
+               .cmd_func = kdb_md,
+               .cmd_usage = "<vaddr>",
+               .cmd_help = "Display Memory Contents, also mdWcN, e.g. md8c1",
+               .cmd_minlen = 1,
+               .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+       },
+       {       .cmd_name = "mdr",
+               .cmd_func = kdb_md,
+               .cmd_usage = "<vaddr> <bytes>",
+               .cmd_help = "Display Raw Memory",
+               .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+       },
+       {       .cmd_name = "mdp",
+               .cmd_func = kdb_md,
+               .cmd_usage = "<paddr> <bytes>",
+               .cmd_help = "Display Physical Memory",
+               .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+       },
+       {       .cmd_name = "mds",
+               .cmd_func = kdb_md,
+               .cmd_usage = "<vaddr>",
+               .cmd_help = "Display Memory Symbolically",
+               .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
+       },
+       {       .cmd_name = "mm",
+               .cmd_func = kdb_mm,
+               .cmd_usage = "<vaddr> <contents>",
+               .cmd_help = "Modify Memory Contents",
+               .cmd_flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS,
+       },
+       {       .cmd_name = "go",
+               .cmd_func = kdb_go,
+               .cmd_usage = "[<vaddr>]",
+               .cmd_help = "Continue Execution",
+               .cmd_minlen = 1,
+               .cmd_flags = KDB_ENABLE_REG_WRITE |
+                            KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
+       },
+       {       .cmd_name = "rd",
+               .cmd_func = kdb_rd,
+               .cmd_usage = "",
+               .cmd_help = "Display Registers",
+               .cmd_flags = KDB_ENABLE_REG_READ,
+       },
+       {       .cmd_name = "rm",
+               .cmd_func = kdb_rm,
+               .cmd_usage = "<reg> <contents>",
+               .cmd_help = "Modify Registers",
+               .cmd_flags = KDB_ENABLE_REG_WRITE,
+       },
+       {       .cmd_name = "ef",
+               .cmd_func = kdb_ef,
+               .cmd_usage = "<vaddr>",
+               .cmd_help = "Display exception frame",
+               .cmd_flags = KDB_ENABLE_MEM_READ,
+       },
+       {       .cmd_name = "bt",
+               .cmd_func = kdb_bt,
+               .cmd_usage = "[<vaddr>]",
+               .cmd_help = "Stack traceback",
+               .cmd_minlen = 1,
+               .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
+       },
+       {       .cmd_name = "btp",
+               .cmd_func = kdb_bt,
+               .cmd_usage = "<pid>",
+               .cmd_help = "Display stack for process <pid>",
+               .cmd_flags = KDB_ENABLE_INSPECT,
+       },
+       {       .cmd_name = "bta",
+               .cmd_func = kdb_bt,
+               .cmd_usage = "[D|R|S|T|C|Z|E|U|I|M|A]",
+               .cmd_help = "Backtrace all processes matching state flag",
+               .cmd_flags = KDB_ENABLE_INSPECT,
+       },
+       {       .cmd_name = "btc",
+               .cmd_func = kdb_bt,
+               .cmd_usage = "",
+               .cmd_help = "Backtrace current process on each cpu",
+               .cmd_flags = KDB_ENABLE_INSPECT,
+       },
+       {       .cmd_name = "btt",
+               .cmd_func = kdb_bt,
+               .cmd_usage = "<vaddr>",
+               .cmd_help = "Backtrace process given its struct task address",
+               .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
+       },
+       {       .cmd_name = "env",
+               .cmd_func = kdb_env,
+               .cmd_usage = "",
+               .cmd_help = "Show environment variables",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+       {       .cmd_name = "set",
+               .cmd_func = kdb_set,
+               .cmd_usage = "",
+               .cmd_help = "Set environment variables",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+       {       .cmd_name = "help",
+               .cmd_func = kdb_help,
+               .cmd_usage = "",
+               .cmd_help = "Display Help Message",
+               .cmd_minlen = 1,
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+       {       .cmd_name = "?",
+               .cmd_func = kdb_help,
+               .cmd_usage = "",
+               .cmd_help = "Display Help Message",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+       {       .cmd_name = "cpu",
+               .cmd_func = kdb_cpu,
+               .cmd_usage = "<cpunum>",
+               .cmd_help = "Switch to new cpu",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
+       },
+       {       .cmd_name = "kgdb",
+               .cmd_func = kdb_kgdb,
+               .cmd_usage = "",
+               .cmd_help = "Enter kgdb mode",
+               .cmd_flags = 0,
+       },
+       {       .cmd_name = "ps",
+               .cmd_func = kdb_ps,
+               .cmd_usage = "[<flags>|A]",
+               .cmd_help = "Display active task list",
+               .cmd_flags = KDB_ENABLE_INSPECT,
+       },
+       {       .cmd_name = "pid",
+               .cmd_func = kdb_pid,
+               .cmd_usage = "<pidnum>",
+               .cmd_help = "Switch to another task",
+               .cmd_flags = KDB_ENABLE_INSPECT,
+       },
+       {       .cmd_name = "reboot",
+               .cmd_func = kdb_reboot,
+               .cmd_usage = "",
+               .cmd_help = "Reboot the machine immediately",
+               .cmd_flags = KDB_ENABLE_REBOOT,
+       },
 #if defined(CONFIG_MODULES)
-       kdb_register_flags("lsmod", kdb_lsmod, "",
-         "List loaded kernel modules", 0,
-         KDB_ENABLE_INSPECT);
+       {       .cmd_name = "lsmod",
+               .cmd_func = kdb_lsmod,
+               .cmd_usage = "",
+               .cmd_help = "List loaded kernel modules",
+               .cmd_flags = KDB_ENABLE_INSPECT,
+       },
 #endif
 #if defined(CONFIG_MAGIC_SYSRQ)
-       kdb_register_flags("sr", kdb_sr, "<key>",
-         "Magic SysRq key", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
+       {       .cmd_name = "sr",
+               .cmd_func = kdb_sr,
+               .cmd_usage = "<key>",
+               .cmd_help = "Magic SysRq key",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
 #endif
 #if defined(CONFIG_PRINTK)
-       kdb_register_flags("dmesg", kdb_dmesg, "[lines]",
-         "Display syslog buffer", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
+       {       .cmd_name = "dmesg",
+               .cmd_func = kdb_dmesg,
+               .cmd_usage = "[lines]",
+               .cmd_help = "Display syslog buffer",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
 #endif
-       if (arch_kgdb_ops.enable_nmi) {
-               kdb_register_flags("disable_nmi", kdb_disable_nmi, "",
-                 "Disable NMI entry to KDB", 0,
-                 KDB_ENABLE_ALWAYS_SAFE);
-       }
-       kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
-         "Define a set of commands, down to endefcmd", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
-       kdb_register_flags("kill", kdb_kill, "<-signal> <pid>",
-         "Send a signal to a process", 0,
-         KDB_ENABLE_SIGNAL);
-       kdb_register_flags("summary", kdb_summary, "",
-         "Summarize the system", 4,
-         KDB_ENABLE_ALWAYS_SAFE);
-       kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
-         "Display per_cpu variables", 3,
-         KDB_ENABLE_MEM_READ);
-       kdb_register_flags("grephelp", kdb_grep_help, "",
-         "Display help on | grep", 0,
-         KDB_ENABLE_ALWAYS_SAFE);
+       {       .cmd_name = "defcmd",
+               .cmd_func = kdb_defcmd,
+               .cmd_usage = "name \"usage\" \"help\"",
+               .cmd_help = "Define a set of commands, down to endefcmd",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+       {       .cmd_name = "kill",
+               .cmd_func = kdb_kill,
+               .cmd_usage = "<-signal> <pid>",
+               .cmd_help = "Send a signal to a process",
+               .cmd_flags = KDB_ENABLE_SIGNAL,
+       },
+       {       .cmd_name = "summary",
+               .cmd_func = kdb_summary,
+               .cmd_usage = "",
+               .cmd_help = "Summarize the system",
+               .cmd_minlen = 4,
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+       {       .cmd_name = "per_cpu",
+               .cmd_func = kdb_per_cpu,
+               .cmd_usage = "<sym> [<bytes>] [<cpu>]",
+               .cmd_help = "Display per_cpu variables",
+               .cmd_minlen = 3,
+               .cmd_flags = KDB_ENABLE_MEM_READ,
+       },
+       {       .cmd_name = "grephelp",
+               .cmd_func = kdb_grep_help,
+               .cmd_usage = "",
+               .cmd_help = "Display help on | grep",
+               .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+       },
+};
+
+static kdbtab_t nmicmd = {
+       .cmd_name = "disable_nmi",
+       .cmd_func = kdb_disable_nmi,
+       .cmd_usage = "",
+       .cmd_help = "Disable NMI entry to KDB",
+       .cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
+};
+
+/* Initialize the kdb command table. */
+static void __init kdb_inittab(void)
+{
+       kdb_register_table(maintab, ARRAY_SIZE(maintab));
+       if (arch_kgdb_ops.enable_nmi)
+               kdb_register_table(&nmicmd, 1);
 }
 
 /* Execute any commands defined in kdb_cmds.  */