|
|
|
|
@@ -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.
|
|
|
|
|
*/
|
|
|
|
|
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 (tp->cmd_minlen
|
|
|
|
|
&& (strlen(argv[0]) <= tp->cmd_minlen)) {
|
|
|
|
|
if (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",
|
|
|
|
|
@@ -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);
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{ .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)
|
|
|
|
|
{ .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)
|
|
|
|
|
{ .cmd_name = "dmesg",
|
|
|
|
|
.cmd_func = kdb_dmesg,
|
|
|
|
|
.cmd_usage = "[lines]",
|
|
|
|
|
.cmd_help = "Display syslog buffer",
|
|
|
|
|
.cmd_flags = KDB_ENABLE_ALWAYS_SAFE,
|
|
|
|
|
},
|
|
|
|
|
#endif
|
|
|
|
|
{ .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)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
#if defined(CONFIG_MODULES)
|
|
|
|
|
kdb_register_flags("lsmod", kdb_lsmod, "",
|
|
|
|
|
"List loaded kernel modules", 0,
|
|
|
|
|
KDB_ENABLE_INSPECT);
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(CONFIG_MAGIC_SYSRQ)
|
|
|
|
|
kdb_register_flags("sr", kdb_sr, "<key>",
|
|
|
|
|
"Magic SysRq key", 0,
|
|
|
|
|
KDB_ENABLE_ALWAYS_SAFE);
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(CONFIG_PRINTK)
|
|
|
|
|
kdb_register_flags("dmesg", kdb_dmesg, "[lines]",
|
|
|
|
|
"Display syslog buffer", 0,
|
|
|
|
|
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);
|
|
|
|
|
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. */
|
|
|
|
|
|