15d5314d6SJason Wessel /*
25d5314d6SJason Wessel * Kernel Debugger Architecture Independent Main Code
35d5314d6SJason Wessel *
45d5314d6SJason Wessel * This file is subject to the terms and conditions of the GNU General Public
55d5314d6SJason Wessel * License. See the file "COPYING" in the main directory of this archive
65d5314d6SJason Wessel * for more details.
75d5314d6SJason Wessel *
85d5314d6SJason Wessel * Copyright (C) 1999-2004 Silicon Graphics, Inc. All Rights Reserved.
95d5314d6SJason Wessel * Copyright (C) 2000 Stephane Eranian <[email protected]>
105d5314d6SJason Wessel * Xscale (R) modifications copyright (C) 2003 Intel Corporation.
115d5314d6SJason Wessel * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
125d5314d6SJason Wessel */
135d5314d6SJason Wessel
145d5314d6SJason Wessel #include <linux/ctype.h>
15420c2b1bSAnton Vorontsov #include <linux/types.h>
165d5314d6SJason Wessel #include <linux/string.h>
175d5314d6SJason Wessel #include <linux/kernel.h>
18bc792e61SAnton Vorontsov #include <linux/kmsg_dump.h>
195d5314d6SJason Wessel #include <linux/reboot.h>
205d5314d6SJason Wessel #include <linux/sched.h>
214f17722cSIngo Molnar #include <linux/sched/loadavg.h>
2203441a34SIngo Molnar #include <linux/sched/stat.h>
23b17b0153SIngo Molnar #include <linux/sched/debug.h>
245d5314d6SJason Wessel #include <linux/sysrq.h>
255d5314d6SJason Wessel #include <linux/smp.h>
265d5314d6SJason Wessel #include <linux/utsname.h>
275d5314d6SJason Wessel #include <linux/vmalloc.h>
28ad394f66SAnton Vorontsov #include <linux/moduleparam.h>
29420c2b1bSAnton Vorontsov #include <linux/mm.h>
305d5314d6SJason Wessel #include <linux/init.h>
315d5314d6SJason Wessel #include <linux/kallsyms.h>
325d5314d6SJason Wessel #include <linux/kgdb.h>
335d5314d6SJason Wessel #include <linux/kdb.h>
345d5314d6SJason Wessel #include <linux/notifier.h>
355d5314d6SJason Wessel #include <linux/interrupt.h>
365d5314d6SJason Wessel #include <linux/delay.h>
375d5314d6SJason Wessel #include <linux/nmi.h>
385d5314d6SJason Wessel #include <linux/time.h>
395d5314d6SJason Wessel #include <linux/ptrace.h>
405d5314d6SJason Wessel #include <linux/sysctl.h>
415d5314d6SJason Wessel #include <linux/cpu.h>
425d5314d6SJason Wessel #include <linux/kdebug.h>
435d5314d6SJason Wessel #include <linux/proc_fs.h>
445d5314d6SJason Wessel #include <linux/uaccess.h>
455d5314d6SJason Wessel #include <linux/slab.h>
465d5314d6SJason Wessel #include <linux/security.h>
47eadb2f47SDaniel Thompson #include "kdb_private.h"
485d5314d6SJason Wessel
495d5314d6SJason Wessel #undef MODULE_PARAM_PREFIX
50420c2b1bSAnton Vorontsov #define MODULE_PARAM_PREFIX "kdb."
51420c2b1bSAnton Vorontsov
52420c2b1bSAnton Vorontsov static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE;
53b8017177SDaniel Thompson module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
54420c2b1bSAnton Vorontsov
55420c2b1bSAnton Vorontsov char kdb_grep_string[KDB_GREP_STRLEN];
56fb6daa75SDaniel Thompson int kdb_grepping_flag;
575d5314d6SJason Wessel EXPORT_SYMBOL(kdb_grepping_flag);
585d5314d6SJason Wessel int kdb_grep_leading;
595d5314d6SJason Wessel int kdb_grep_trailing;
605d5314d6SJason Wessel
615d5314d6SJason Wessel /*
625d5314d6SJason Wessel * Kernel debugger state flags
635d5314d6SJason Wessel */
645d5314d6SJason Wessel unsigned int kdb_flags;
65c893de12SWei Li
665d5314d6SJason Wessel /*
675d5314d6SJason Wessel * kdb_lock protects updates to kdb_initial_cpu. Used to
685d5314d6SJason Wessel * single thread processors through the kernel debugger.
695d5314d6SJason Wessel */
705d5314d6SJason Wessel int kdb_initial_cpu = -1; /* cpu number that owns kdb */
715d5314d6SJason Wessel int kdb_nextline = 1;
725d5314d6SJason Wessel int kdb_state; /* General KDB state */
735d5314d6SJason Wessel
745d5314d6SJason Wessel struct task_struct *kdb_current_task;
755d5314d6SJason Wessel struct pt_regs *kdb_current_regs;
765d5314d6SJason Wessel
775d5314d6SJason Wessel const char *kdb_diemsg;
785d5314d6SJason Wessel static int kdb_go_count;
795d5314d6SJason Wessel #ifdef CONFIG_KDB_CONTINUE_CATASTROPHIC
805d5314d6SJason Wessel static unsigned int kdb_continue_catastrophic =
815d5314d6SJason Wessel CONFIG_KDB_CONTINUE_CATASTROPHIC;
825d5314d6SJason Wessel #else
835d5314d6SJason Wessel static unsigned int kdb_continue_catastrophic;
845d5314d6SJason Wessel #endif
855d5314d6SJason Wessel
865d5314d6SJason Wessel /* kdb_cmds_head describes the available commands. */
87e4f291b3SSumit Garg static LIST_HEAD(kdb_cmds_head);
88e4f291b3SSumit Garg
895d5314d6SJason Wessel typedef struct _kdbmsg {
905d5314d6SJason Wessel int km_diag; /* kdb diagnostic */
915d5314d6SJason Wessel char *km_msg; /* Corresponding message text */
925d5314d6SJason Wessel } kdbmsg_t;
935d5314d6SJason Wessel
945d5314d6SJason Wessel #define KDBMSG(msgnum, text) \
955d5314d6SJason Wessel { KDB_##msgnum, text }
965d5314d6SJason Wessel
975d5314d6SJason Wessel static kdbmsg_t kdbmsgs[] = {
985d5314d6SJason Wessel KDBMSG(NOTFOUND, "Command Not Found"),
995d5314d6SJason Wessel KDBMSG(ARGCOUNT, "Improper argument count, see usage."),
1005d5314d6SJason Wessel KDBMSG(BADWIDTH, "Illegal value for BYTESPERWORD use 1, 2, 4 or 8, "
1015d5314d6SJason Wessel "8 is only allowed on 64 bit systems"),
1025d5314d6SJason Wessel KDBMSG(BADRADIX, "Illegal value for RADIX use 8, 10 or 16"),
1035d5314d6SJason Wessel KDBMSG(NOTENV, "Cannot find environment variable"),
1045d5314d6SJason Wessel KDBMSG(NOENVVALUE, "Environment variable should have value"),
1055d5314d6SJason Wessel KDBMSG(NOTIMP, "Command not implemented"),
1065d5314d6SJason Wessel KDBMSG(ENVFULL, "Environment full"),
1075d5314d6SJason Wessel KDBMSG(KMALLOCFAILED, "Failed to allocate memory"),
108*a30d4ff8SNir Lichtman KDBMSG(TOOMANYBPT, "Too many breakpoints defined"),
1095d5314d6SJason Wessel #ifdef CONFIG_CPU_XSCALE
1105d5314d6SJason Wessel KDBMSG(TOOMANYDBREGS, "More breakpoints than ibcr registers defined"),
1115d5314d6SJason Wessel #else
1125d5314d6SJason Wessel KDBMSG(TOOMANYDBREGS, "More breakpoints than db registers defined"),
1135d5314d6SJason Wessel #endif
1145d5314d6SJason Wessel KDBMSG(DUPBPT, "Duplicate breakpoint address"),
1155d5314d6SJason Wessel KDBMSG(BPTNOTFOUND, "Breakpoint not found"),
1165d5314d6SJason Wessel KDBMSG(BADMODE, "Invalid IDMODE"),
1175d5314d6SJason Wessel KDBMSG(BADINT, "Illegal numeric value"),
1185d5314d6SJason Wessel KDBMSG(INVADDRFMT, "Invalid symbolic address format"),
1195d5314d6SJason Wessel KDBMSG(BADREG, "Invalid register name"),
1205d5314d6SJason Wessel KDBMSG(BADCPUNUM, "Invalid cpu number"),
1215d5314d6SJason Wessel KDBMSG(BADLENGTH, "Invalid length field"),
1225d5314d6SJason Wessel KDBMSG(NOBP, "No Breakpoint exists"),
1235d5314d6SJason Wessel KDBMSG(BADADDR, "Invalid address"),
1245d5314d6SJason Wessel KDBMSG(NOPERM, "Permission denied"),
125420c2b1bSAnton Vorontsov };
1265d5314d6SJason Wessel #undef KDBMSG
1275d5314d6SJason Wessel
1285d5314d6SJason Wessel static const int __nkdb_err = ARRAY_SIZE(kdbmsgs);
1295f784f79SSasha Levin
1305d5314d6SJason Wessel
1315d5314d6SJason Wessel /*
1325d5314d6SJason Wessel * Initial environment. This is all kept static and local to this file.
133*a30d4ff8SNir Lichtman * The entire environment is limited to a fixed number of entries
134*a30d4ff8SNir Lichtman * (add more to __env[] if required)
135*a30d4ff8SNir Lichtman */
1365d5314d6SJason Wessel
1375d5314d6SJason Wessel static char *__env[31] = {
13883fa2d13SSumit Garg #if defined(CONFIG_SMP)
1395d5314d6SJason Wessel "PROMPT=[%d]kdb> ",
1405d5314d6SJason Wessel #else
1415d5314d6SJason Wessel "PROMPT=kdb> ",
1425d5314d6SJason Wessel #endif
1435d5314d6SJason Wessel "MOREPROMPT=more> ",
1440f26d0e0SJason Wessel "RADIX=16",
1455d5314d6SJason Wessel "MDCOUNT=8", /* lines of md output */
1465d5314d6SJason Wessel KDB_PLATFORM_ENV,
1475d5314d6SJason Wessel "DTABCOUNT=30",
1485d5314d6SJason Wessel "NOSECT=1",
1495d5314d6SJason Wessel };
1505d5314d6SJason Wessel
1515d5314d6SJason Wessel static const int __nenv = ARRAY_SIZE(__env);
1525f784f79SSasha Levin
1535d5314d6SJason Wessel /*
1545d5314d6SJason Wessel * Update the permissions flags (kdb_cmd_enabled) to match the
155eadb2f47SDaniel Thompson * current lockdown state.
156eadb2f47SDaniel Thompson *
157eadb2f47SDaniel Thompson * Within this function the calls to security_locked_down() are "lazy". We
158eadb2f47SDaniel Thompson * avoid calling them if the current value of kdb_cmd_enabled already excludes
159eadb2f47SDaniel Thompson * flags that might be subject to lockdown. Additionally we deliberately check
160eadb2f47SDaniel Thompson * the lockdown flags independently (even though read lockdown implies write
161eadb2f47SDaniel Thompson * lockdown) since that results in both simpler code and clearer messages to
162eadb2f47SDaniel Thompson * the user on first-time debugger entry.
163eadb2f47SDaniel Thompson *
164eadb2f47SDaniel Thompson * The permission masks during a read+write lockdown permits the following
165eadb2f47SDaniel Thompson * flags: INSPECT, SIGNAL, REBOOT (and ALWAYS_SAFE).
166eadb2f47SDaniel Thompson *
167eadb2f47SDaniel Thompson * The INSPECT commands are not blocked during lockdown because they are
168eadb2f47SDaniel Thompson * not arbitrary memory reads. INSPECT covers the backtrace family (sometimes
169eadb2f47SDaniel Thompson * forcing them to have no arguments) and lsmod. These commands do expose
170eadb2f47SDaniel Thompson * some kernel state but do not allow the developer seated at the console to
171eadb2f47SDaniel Thompson * choose what state is reported. SIGNAL and REBOOT should not be controversial,
172eadb2f47SDaniel Thompson * given these are allowed for root during lockdown already.
173eadb2f47SDaniel Thompson */
kdb_check_for_lockdown(void)1749452e977SDaniel Thompson static void kdb_check_for_lockdown(void)
175eadb2f47SDaniel Thompson {
176eadb2f47SDaniel Thompson const int write_flags = KDB_ENABLE_MEM_WRITE |
177eadb2f47SDaniel Thompson KDB_ENABLE_REG_WRITE |
178eadb2f47SDaniel Thompson KDB_ENABLE_FLOW_CTRL;
179eadb2f47SDaniel Thompson const int read_flags = KDB_ENABLE_MEM_READ |
180eadb2f47SDaniel Thompson KDB_ENABLE_REG_READ;
181eadb2f47SDaniel Thompson
182eadb2f47SDaniel Thompson bool need_to_lockdown_write = false;
183eadb2f47SDaniel Thompson bool need_to_lockdown_read = false;
184eadb2f47SDaniel Thompson
185eadb2f47SDaniel Thompson if (kdb_cmd_enabled & (KDB_ENABLE_ALL | write_flags))
186eadb2f47SDaniel Thompson need_to_lockdown_write =
187eadb2f47SDaniel Thompson security_locked_down(LOCKDOWN_DBG_WRITE_KERNEL);
188eadb2f47SDaniel Thompson
189eadb2f47SDaniel Thompson if (kdb_cmd_enabled & (KDB_ENABLE_ALL | read_flags))
190eadb2f47SDaniel Thompson need_to_lockdown_read =
191eadb2f47SDaniel Thompson security_locked_down(LOCKDOWN_DBG_READ_KERNEL);
192eadb2f47SDaniel Thompson
193eadb2f47SDaniel Thompson /* De-compose KDB_ENABLE_ALL if required */
194eadb2f47SDaniel Thompson if (need_to_lockdown_write || need_to_lockdown_read)
195eadb2f47SDaniel Thompson if (kdb_cmd_enabled & KDB_ENABLE_ALL)
196eadb2f47SDaniel Thompson kdb_cmd_enabled = KDB_ENABLE_MASK & ~KDB_ENABLE_ALL;
197eadb2f47SDaniel Thompson
198eadb2f47SDaniel Thompson if (need_to_lockdown_write)
199eadb2f47SDaniel Thompson kdb_cmd_enabled &= ~write_flags;
200eadb2f47SDaniel Thompson
201eadb2f47SDaniel Thompson if (need_to_lockdown_read)
202eadb2f47SDaniel Thompson kdb_cmd_enabled &= ~read_flags;
203eadb2f47SDaniel Thompson }
204eadb2f47SDaniel Thompson
205eadb2f47SDaniel Thompson /*
206eadb2f47SDaniel Thompson * Check whether the flags of the current command, the permissions of the kdb
207eadb2f47SDaniel Thompson * console and the lockdown state allow a command to be run.
208eadb2f47SDaniel Thompson */
kdb_check_flags(kdb_cmdflags_t flags,int permissions,bool no_args)209eadb2f47SDaniel Thompson static bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
210eadb2f47SDaniel Thompson bool no_args)
2119452e977SDaniel Thompson {
2129452e977SDaniel Thompson /* permissions comes from userspace so needs massaging slightly */
2139452e977SDaniel Thompson permissions &= KDB_ENABLE_MASK;
2149452e977SDaniel Thompson permissions |= KDB_ENABLE_ALWAYS_SAFE;
2159452e977SDaniel Thompson
2169452e977SDaniel Thompson /* some commands change group when launched with no arguments */
2179452e977SDaniel Thompson if (no_args)
2189452e977SDaniel Thompson permissions |= permissions << KDB_ENABLE_NO_ARGS_SHIFT;
2199452e977SDaniel Thompson
2209452e977SDaniel Thompson flags |= KDB_ENABLE_ALL;
2219452e977SDaniel Thompson
2229452e977SDaniel Thompson return permissions & flags;
2239452e977SDaniel Thompson }
2249452e977SDaniel Thompson
2259452e977SDaniel Thompson /*
2269452e977SDaniel Thompson * kdbgetenv - This function will return the character string value of
2275d5314d6SJason Wessel * an environment variable.
2285d5314d6SJason Wessel * Parameters:
2295d5314d6SJason Wessel * match A character string representing an environment variable.
2305d5314d6SJason Wessel * Returns:
2315d5314d6SJason Wessel * NULL No environment variable matches 'match'
2325d5314d6SJason Wessel * char* Pointer to string value of environment variable.
2335d5314d6SJason Wessel */
kdbgetenv(const char * match)2345d5314d6SJason Wessel char *kdbgetenv(const char *match)
2355d5314d6SJason Wessel {
2365d5314d6SJason Wessel char **ep = __env;
2375d5314d6SJason Wessel int matchlen = strlen(match);
2385d5314d6SJason Wessel int i;
2395d5314d6SJason Wessel
2405d5314d6SJason Wessel for (i = 0; i < __nenv; i++) {
2415d5314d6SJason Wessel char *e = *ep++;
2425d5314d6SJason Wessel
2435d5314d6SJason Wessel if (!e)
2445d5314d6SJason Wessel continue;
2455d5314d6SJason Wessel
2465d5314d6SJason Wessel if ((strncmp(match, e, matchlen) == 0)
2475d5314d6SJason Wessel && ((e[matchlen] == '\0')
2485d5314d6SJason Wessel || (e[matchlen] == '='))) {
2495d5314d6SJason Wessel char *cp = strchr(e, '=');
2505d5314d6SJason Wessel return cp ? ++cp : "";
2515d5314d6SJason Wessel }
2525d5314d6SJason Wessel }
2535d5314d6SJason Wessel return NULL;
2545d5314d6SJason Wessel }
2555d5314d6SJason Wessel
2565d5314d6SJason Wessel /*
2575d5314d6SJason Wessel * kdbgetulenv - This function will return the value of an unsigned
2585d5314d6SJason Wessel * long-valued environment variable.
2595d5314d6SJason Wessel * Parameters:
2605d5314d6SJason Wessel * match A character string representing a numeric value
2615d5314d6SJason Wessel * Outputs:
2625d5314d6SJason Wessel * *value the unsigned long representation of the env variable 'match'
263220a31b0SZhen Lei * Returns:
2645d5314d6SJason Wessel * Zero on success, a kdb diagnostic on failure.
2655d5314d6SJason Wessel */
kdbgetulenv(const char * match,unsigned long * value)2665d5314d6SJason Wessel static int kdbgetulenv(const char *match, unsigned long *value)
2675d5314d6SJason Wessel {
2685d5314d6SJason Wessel char *ep;
2695d5314d6SJason Wessel
2705d5314d6SJason Wessel ep = kdbgetenv(match);
2715d5314d6SJason Wessel if (!ep)
2725d5314d6SJason Wessel return KDB_NOTENV;
2735d5314d6SJason Wessel if (strlen(ep) == 0)
2745d5314d6SJason Wessel return KDB_NOENVVALUE;
2755d5314d6SJason Wessel if (kstrtoul(ep, 0, value))
276120fb87cSYuran Pereira return KDB_BADINT;
277120fb87cSYuran Pereira
2785d5314d6SJason Wessel return 0;
2795d5314d6SJason Wessel }
2805d5314d6SJason Wessel
2815d5314d6SJason Wessel /*
2825d5314d6SJason Wessel * kdbgetintenv - This function will return the value of an
2835d5314d6SJason Wessel * integer-valued environment variable.
2845d5314d6SJason Wessel * Parameters:
2855d5314d6SJason Wessel * match A character string representing an integer-valued env variable
2865d5314d6SJason Wessel * Outputs:
2875d5314d6SJason Wessel * *value the integer representation of the environment variable 'match'
2885d5314d6SJason Wessel * Returns:
2895d5314d6SJason Wessel * Zero on success, a kdb diagnostic on failure.
2905d5314d6SJason Wessel */
kdbgetintenv(const char * match,int * value)2915d5314d6SJason Wessel int kdbgetintenv(const char *match, int *value)
2925d5314d6SJason Wessel {
2935d5314d6SJason Wessel unsigned long val;
2945d5314d6SJason Wessel int diag;
2955d5314d6SJason Wessel
2965d5314d6SJason Wessel diag = kdbgetulenv(match, &val);
2975d5314d6SJason Wessel if (!diag)
2985d5314d6SJason Wessel *value = (int) val;
2995d5314d6SJason Wessel return diag;
3005d5314d6SJason Wessel }
3015d5314d6SJason Wessel
3025d5314d6SJason Wessel /*
3035d5314d6SJason Wessel * kdb_setenv() - Alter an existing environment variable or create a new one.
30483fa2d13SSumit Garg * @var: Name of the variable
30583fa2d13SSumit Garg * @val: Value of the variable
30683fa2d13SSumit Garg *
30783fa2d13SSumit Garg * Return: Zero on success, a kdb diagnostic on failure.
30883fa2d13SSumit Garg */
kdb_setenv(const char * var,const char * val)30983fa2d13SSumit Garg static int kdb_setenv(const char *var, const char *val)
31083fa2d13SSumit Garg {
31183fa2d13SSumit Garg int i;
31283fa2d13SSumit Garg char *ep;
31383fa2d13SSumit Garg size_t varlen, vallen;
31483fa2d13SSumit Garg
31583fa2d13SSumit Garg varlen = strlen(var);
31683fa2d13SSumit Garg vallen = strlen(val);
31783fa2d13SSumit Garg ep = kmalloc(varlen + vallen + 2, GFP_KDB);
318*a30d4ff8SNir Lichtman if (!ep)
319*a30d4ff8SNir Lichtman return KDB_KMALLOCFAILED;
320*a30d4ff8SNir Lichtman
32183fa2d13SSumit Garg sprintf(ep, "%s=%s", var, val);
32283fa2d13SSumit Garg
32383fa2d13SSumit Garg for (i = 0; i < __nenv; i++) {
32483fa2d13SSumit Garg if (__env[i]
32583fa2d13SSumit Garg && ((strncmp(__env[i], var, varlen) == 0)
32683fa2d13SSumit Garg && ((__env[i][varlen] == '\0')
32783fa2d13SSumit Garg || (__env[i][varlen] == '=')))) {
32883fa2d13SSumit Garg kfree_const(__env[i]);
329*a30d4ff8SNir Lichtman __env[i] = ep;
33083fa2d13SSumit Garg return 0;
33183fa2d13SSumit Garg }
33283fa2d13SSumit Garg }
33383fa2d13SSumit Garg
33483fa2d13SSumit Garg /*
33583fa2d13SSumit Garg * Wasn't existing variable. Fit into slot.
33683fa2d13SSumit Garg */
33783fa2d13SSumit Garg for (i = 0; i < __nenv-1; i++) {
33883fa2d13SSumit Garg if (__env[i] == (char *)0) {
33983fa2d13SSumit Garg __env[i] = ep;
34083fa2d13SSumit Garg return 0;
34183fa2d13SSumit Garg }
34283fa2d13SSumit Garg }
34383fa2d13SSumit Garg
34483fa2d13SSumit Garg return KDB_ENVFULL;
34583fa2d13SSumit Garg }
34683fa2d13SSumit Garg
34783fa2d13SSumit Garg /*
34883fa2d13SSumit Garg * kdb_printenv() - Display the current environment variables.
34983fa2d13SSumit Garg */
kdb_printenv(void)35083fa2d13SSumit Garg static void kdb_printenv(void)
35183fa2d13SSumit Garg {
35283fa2d13SSumit Garg int i;
35383fa2d13SSumit Garg
35483fa2d13SSumit Garg for (i = 0; i < __nenv; i++) {
35583fa2d13SSumit Garg if (__env[i])
35683fa2d13SSumit Garg kdb_printf("%s\n", __env[i]);
35783fa2d13SSumit Garg }
35883fa2d13SSumit Garg }
35983fa2d13SSumit Garg
36083fa2d13SSumit Garg /*
36183fa2d13SSumit Garg * kdbgetularg - This function will convert a numeric string into an
3625d5314d6SJason Wessel * unsigned long value.
3635d5314d6SJason Wessel * Parameters:
3645d5314d6SJason Wessel * arg A character string representing a numeric value
3655d5314d6SJason Wessel * Outputs:
3665d5314d6SJason Wessel * *value the unsigned long representation of arg.
367220a31b0SZhen Lei * Returns:
3685d5314d6SJason Wessel * Zero on success, a kdb diagnostic on failure.
3695d5314d6SJason Wessel */
kdbgetularg(const char * arg,unsigned long * value)3705d5314d6SJason Wessel int kdbgetularg(const char *arg, unsigned long *value)
3715d5314d6SJason Wessel {
3725d5314d6SJason Wessel if (kstrtoul(arg, 0, value))
3739131d6a7SNir Lichtman return KDB_BADINT;
3745d5314d6SJason Wessel return 0;
3755d5314d6SJason Wessel }
3765d5314d6SJason Wessel
kdbgetu64arg(const char * arg,u64 * value)3775d5314d6SJason Wessel int kdbgetu64arg(const char *arg, u64 *value)
378534af108SJason Wessel {
379534af108SJason Wessel if (kstrtou64(arg, 0, value))
3809131d6a7SNir Lichtman return KDB_BADINT;
381534af108SJason Wessel return 0;
382534af108SJason Wessel }
383534af108SJason Wessel
384534af108SJason Wessel /*
3855d5314d6SJason Wessel * kdb_set - This function implements the 'set' command. Alter an
3865d5314d6SJason Wessel * existing environment variable or create a new one.
3875d5314d6SJason Wessel */
kdb_set(int argc,const char ** argv)3885d5314d6SJason Wessel int kdb_set(int argc, const char **argv)
3895d5314d6SJason Wessel {
3905d5314d6SJason Wessel /*
3915d5314d6SJason Wessel * we can be invoked two ways:
3925d5314d6SJason Wessel * set var=value argv[1]="var", argv[2]="value"
3935d5314d6SJason Wessel * set var = value argv[1]="var", argv[2]="=", argv[3]="value"
3945d5314d6SJason Wessel * - if the latter, shift 'em down.
3955d5314d6SJason Wessel */
3965d5314d6SJason Wessel if (argc == 3) {
3975d5314d6SJason Wessel argv[2] = argv[3];
3985d5314d6SJason Wessel argc--;
3995d5314d6SJason Wessel }
4005d5314d6SJason Wessel
4015d5314d6SJason Wessel if (argc != 2)
4025d5314d6SJason Wessel return KDB_ARGCOUNT;
4035d5314d6SJason Wessel
4045d5314d6SJason Wessel /*
4055d5314d6SJason Wessel * Censor sensitive variables
406ad99b510SDaniel Thompson */
407ad99b510SDaniel Thompson if (strcmp(argv[1], "PROMPT") == 0 &&
408ad99b510SDaniel Thompson !kdb_check_flags(KDB_ENABLE_MEM_READ, kdb_cmd_enabled, false))
409ad99b510SDaniel Thompson return KDB_NOPERM;
410ad99b510SDaniel Thompson
411ad99b510SDaniel Thompson /*
412ad99b510SDaniel Thompson * Check for internal variables
4135d5314d6SJason Wessel */
4145d5314d6SJason Wessel if (strcmp(argv[1], "KDBDEBUG") == 0) {
4155d5314d6SJason Wessel unsigned int debugflags;
4165d5314d6SJason Wessel int ret;
417120fb87cSYuran Pereira
4185d5314d6SJason Wessel ret = kstrtouint(argv[2], 0, &debugflags);
419120fb87cSYuran Pereira if (ret || debugflags & ~KDB_DEBUG_FLAG_MASK) {
420120fb87cSYuran Pereira kdb_printf("kdb: illegal debug flags '%s'\n",
4215d5314d6SJason Wessel argv[2]);
4225d5314d6SJason Wessel return 0;
4235d5314d6SJason Wessel }
4245d5314d6SJason Wessel kdb_flags = (kdb_flags & ~KDB_DEBUG(MASK))
425c893de12SWei Li | (debugflags << KDB_DEBUG_FLAG_SHIFT);
4265d5314d6SJason Wessel
4275d5314d6SJason Wessel return 0;
4285d5314d6SJason Wessel }
4295d5314d6SJason Wessel
4305d5314d6SJason Wessel /*
4315d5314d6SJason Wessel * Tokenizer squashed the '=' sign. argv[1] is variable
4325d5314d6SJason Wessel * name, argv[2] = value.
4335d5314d6SJason Wessel */
4345d5314d6SJason Wessel return kdb_setenv(argv[1], argv[2]);
43583fa2d13SSumit Garg }
4365d5314d6SJason Wessel
kdb_check_regs(void)4375d5314d6SJason Wessel static int kdb_check_regs(void)
4385d5314d6SJason Wessel {
4395d5314d6SJason Wessel if (!kdb_current_regs) {
4405d5314d6SJason Wessel kdb_printf("No current kdb registers."
4415d5314d6SJason Wessel " You may need to select another task\n");
4425d5314d6SJason Wessel return KDB_BADREG;
4435d5314d6SJason Wessel }
4445d5314d6SJason Wessel return 0;
4455d5314d6SJason Wessel }
4465d5314d6SJason Wessel
4475d5314d6SJason Wessel /*
4485d5314d6SJason Wessel * kdbgetaddrarg - This function is responsible for parsing an
4495d5314d6SJason Wessel * address-expression and returning the value of the expression,
4505d5314d6SJason Wessel * symbol name, and offset to the caller.
4515d5314d6SJason Wessel *
4525d5314d6SJason Wessel * The argument may consist of a numeric value (decimal or
4535d5314d6SJason Wessel * hexadecimal), a symbol name, a register name (preceded by the
454220a31b0SZhen Lei * percent sign), an environment variable with a numeric value
4555d5314d6SJason Wessel * (preceded by a dollar sign) or a simple arithmetic expression
45625985edcSLucas De Marchi * consisting of a symbol name, +/-, and a numeric constant value
4575d5314d6SJason Wessel * (offset).
4585d5314d6SJason Wessel * Parameters:
4595d5314d6SJason Wessel * argc - count of arguments in argv
4605d5314d6SJason Wessel * argv - argument vector
4615d5314d6SJason Wessel * *nextarg - index to next unparsed argument in argv[]
4625d5314d6SJason Wessel * regs - Register state at time of KDB entry
4635d5314d6SJason Wessel * Outputs:
4645d5314d6SJason Wessel * *value - receives the value of the address-expression
4655d5314d6SJason Wessel * *offset - receives the offset specified, if any
4665d5314d6SJason Wessel * *name - receives the symbol name, if any
4675d5314d6SJason Wessel * *nextarg - index to next unparsed argument in argv[]
4685d5314d6SJason Wessel * Returns:
4695d5314d6SJason Wessel * zero is returned on success, a kdb diagnostic code is
4705d5314d6SJason Wessel * returned on error.
4715d5314d6SJason Wessel */
kdbgetaddrarg(int argc,const char ** argv,int * nextarg,unsigned long * value,long * offset,char ** name)4725d5314d6SJason Wessel int kdbgetaddrarg(int argc, const char **argv, int *nextarg,
4735d5314d6SJason Wessel unsigned long *value, long *offset,
4745d5314d6SJason Wessel char **name)
4755d5314d6SJason Wessel {
4765d5314d6SJason Wessel unsigned long addr;
4775d5314d6SJason Wessel unsigned long off = 0;
4785d5314d6SJason Wessel int positive;
4795d5314d6SJason Wessel int diag;
4805d5314d6SJason Wessel int found = 0;
4815d5314d6SJason Wessel char *symname;
4825d5314d6SJason Wessel char symbol = '\0';
4835d5314d6SJason Wessel char *cp;
4845d5314d6SJason Wessel kdb_symtab_t symtab;
4855d5314d6SJason Wessel
4865d5314d6SJason Wessel /*
4875d5314d6SJason Wessel * If the enable flags prohibit both arbitrary memory access
488420c2b1bSAnton Vorontsov * and flow control then there are no reasonable grounds to
489420c2b1bSAnton Vorontsov * provide symbol lookup.
490420c2b1bSAnton Vorontsov */
491420c2b1bSAnton Vorontsov if (!kdb_check_flags(KDB_ENABLE_MEM_READ | KDB_ENABLE_FLOW_CTRL,
492420c2b1bSAnton Vorontsov kdb_cmd_enabled, false))
493420c2b1bSAnton Vorontsov return KDB_NOPERM;
494420c2b1bSAnton Vorontsov
495420c2b1bSAnton Vorontsov /*
496420c2b1bSAnton Vorontsov * Process arguments which follow the following syntax:
4975d5314d6SJason Wessel *
4985d5314d6SJason Wessel * symbol | numeric-address [+/- numeric-offset]
4995d5314d6SJason Wessel * %register
5005d5314d6SJason Wessel * $environment-variable
5015d5314d6SJason Wessel */
5025d5314d6SJason Wessel
5035d5314d6SJason Wessel if (*nextarg > argc)
5045d5314d6SJason Wessel return KDB_ARGCOUNT;
5055d5314d6SJason Wessel
5065d5314d6SJason Wessel symname = (char *)argv[*nextarg];
5075d5314d6SJason Wessel
5085d5314d6SJason Wessel /*
5095d5314d6SJason Wessel * If there is no whitespace between the symbol
5105d5314d6SJason Wessel * or address and the '+' or '-' symbols, we
5115d5314d6SJason Wessel * remember the character and replace it with a
5125d5314d6SJason Wessel * null so the symbol/value can be properly parsed
5135d5314d6SJason Wessel */
5145d5314d6SJason Wessel cp = strpbrk(symname, "+-");
5155d5314d6SJason Wessel if (cp != NULL) {
5165d5314d6SJason Wessel symbol = *cp;
5175d5314d6SJason Wessel *cp++ = '\0';
5185d5314d6SJason Wessel }
5195d5314d6SJason Wessel
5205d5314d6SJason Wessel if (symname[0] == '$') {
5215d5314d6SJason Wessel diag = kdbgetulenv(&symname[1], &addr);
5225d5314d6SJason Wessel if (diag)
5235d5314d6SJason Wessel return diag;
5245d5314d6SJason Wessel } else if (symname[0] == '%') {
5255d5314d6SJason Wessel diag = kdb_check_regs();
526fcf2736cSDaniel Thompson if (diag)
527fcf2736cSDaniel Thompson return diag;
528fcf2736cSDaniel Thompson /* Implement register values with % at a later time as it is
5295d5314d6SJason Wessel * arch optional.
5305d5314d6SJason Wessel */
5315d5314d6SJason Wessel return KDB_NOTIMP;
5325d5314d6SJason Wessel } else {
5335d5314d6SJason Wessel found = kdbgetsymval(symname, &symtab);
5345d5314d6SJason Wessel if (found) {
5355d5314d6SJason Wessel addr = symtab.sym_start;
5365d5314d6SJason Wessel } else {
5375d5314d6SJason Wessel diag = kdbgetularg(argv[*nextarg], &addr);
5385d5314d6SJason Wessel if (diag)
5395d5314d6SJason Wessel return diag;
5405d5314d6SJason Wessel }
5415d5314d6SJason Wessel }
5425d5314d6SJason Wessel
5435d5314d6SJason Wessel if (!found)
5445d5314d6SJason Wessel found = kdbnearsym(addr, &symtab);
5455d5314d6SJason Wessel
5465d5314d6SJason Wessel (*nextarg)++;
5475d5314d6SJason Wessel
5485d5314d6SJason Wessel if (name)
5495d5314d6SJason Wessel *name = symname;
5505d5314d6SJason Wessel if (value)
5515d5314d6SJason Wessel *value = addr;
5525d5314d6SJason Wessel if (offset && name && *name)
5535d5314d6SJason Wessel *offset = addr - symtab.sym_start;
5545d5314d6SJason Wessel
5555d5314d6SJason Wessel if ((*nextarg > argc)
5565d5314d6SJason Wessel && (symbol == '\0'))
5575d5314d6SJason Wessel return 0;
5585d5314d6SJason Wessel
5595d5314d6SJason Wessel /*
5605d5314d6SJason Wessel * check for +/- and offset
5615d5314d6SJason Wessel */
5625d5314d6SJason Wessel
5635d5314d6SJason Wessel if (symbol == '\0') {
5645d5314d6SJason Wessel if ((argv[*nextarg][0] != '+')
5655d5314d6SJason Wessel && (argv[*nextarg][0] != '-')) {
5665d5314d6SJason Wessel /*
5675d5314d6SJason Wessel * Not our argument. Return.
5685d5314d6SJason Wessel */
5695d5314d6SJason Wessel return 0;
5705d5314d6SJason Wessel } else {
5715d5314d6SJason Wessel positive = (argv[*nextarg][0] == '+');
5725d5314d6SJason Wessel (*nextarg)++;
5735d5314d6SJason Wessel }
5745d5314d6SJason Wessel } else
5755d5314d6SJason Wessel positive = (symbol == '+');
5765d5314d6SJason Wessel
5775d5314d6SJason Wessel /*
5785d5314d6SJason Wessel * Now there must be an offset!
5795d5314d6SJason Wessel */
5805d5314d6SJason Wessel if ((*nextarg > argc)
5815d5314d6SJason Wessel && (symbol == '\0')) {
5825d5314d6SJason Wessel return KDB_INVADDRFMT;
5835d5314d6SJason Wessel }
5845d5314d6SJason Wessel
5855d5314d6SJason Wessel if (!symbol) {
5865d5314d6SJason Wessel cp = (char *)argv[*nextarg];
5875d5314d6SJason Wessel (*nextarg)++;
5885d5314d6SJason Wessel }
5895d5314d6SJason Wessel
5905d5314d6SJason Wessel diag = kdbgetularg(cp, &off);
5915d5314d6SJason Wessel if (diag)
5925d5314d6SJason Wessel return diag;
5935d5314d6SJason Wessel
5945d5314d6SJason Wessel if (!positive)
5955d5314d6SJason Wessel off = -off;
5965d5314d6SJason Wessel
5975d5314d6SJason Wessel if (offset)
5985d5314d6SJason Wessel *offset += off;
5995d5314d6SJason Wessel
6005d5314d6SJason Wessel if (value)
6015d5314d6SJason Wessel *value += off;
6025d5314d6SJason Wessel
6035d5314d6SJason Wessel return 0;
6045d5314d6SJason Wessel }
6055d5314d6SJason Wessel
kdb_cmderror(int diag)6065d5314d6SJason Wessel static void kdb_cmderror(int diag)
6075d5314d6SJason Wessel {
6085d5314d6SJason Wessel int i;
6095d5314d6SJason Wessel
6105d5314d6SJason Wessel if (diag >= 0) {
6115d5314d6SJason Wessel kdb_printf("no error detected (diagnostic is %d)\n", diag);
6125d5314d6SJason Wessel return;
6135d5314d6SJason Wessel }
6145d5314d6SJason Wessel
6155d5314d6SJason Wessel for (i = 0; i < __nkdb_err; i++) {
6165d5314d6SJason Wessel if (kdbmsgs[i].km_diag == diag) {
6175d5314d6SJason Wessel kdb_printf("diag: %d: %s\n", diag, kdbmsgs[i].km_msg);
6185d5314d6SJason Wessel return;
6195d5314d6SJason Wessel }
6205d5314d6SJason Wessel }
6215d5314d6SJason Wessel
6225d5314d6SJason Wessel kdb_printf("Unknown diag %d\n", -diag);
6235d5314d6SJason Wessel }
6245d5314d6SJason Wessel
6255d5314d6SJason Wessel /*
6265d5314d6SJason Wessel * kdb_defcmd, kdb_defcmd2 - This function implements the 'defcmd'
6275d5314d6SJason Wessel * command which defines one command as a set of other commands,
6285d5314d6SJason Wessel * terminated by endefcmd. kdb_defcmd processes the initial
6295d5314d6SJason Wessel * 'defcmd' command, kdb_defcmd2 is invoked from kdb_parse for
6305d5314d6SJason Wessel * the following commands until 'endefcmd'.
6315d5314d6SJason Wessel * Inputs:
6325d5314d6SJason Wessel * argc argument count
6335d5314d6SJason Wessel * argv argument vector
6345d5314d6SJason Wessel * Returns:
6355d5314d6SJason Wessel * zero for success, a kdb diagnostic if error
6365d5314d6SJason Wessel */
6375d5314d6SJason Wessel struct kdb_macro {
638b39cded8SSumit Garg kdbtab_t cmd; /* Macro command */
6399a5db530SSumit Garg struct list_head statements; /* Associated statement list */
6409a5db530SSumit Garg };
6415d5314d6SJason Wessel
6429a5db530SSumit Garg struct kdb_macro_statement {
6439a5db530SSumit Garg char *statement; /* Statement text */
6449a5db530SSumit Garg struct list_head list_node; /* Statement list node */
6459a5db530SSumit Garg };
6469a5db530SSumit Garg
6479a5db530SSumit Garg static struct kdb_macro *kdb_macro;
648b39cded8SSumit Garg static bool defcmd_in_progress;
6497faedcd4SNicholas Mc Guire
6505d5314d6SJason Wessel /* Forward references */
6515d5314d6SJason Wessel static int kdb_exec_defcmd(int argc, const char **argv);
6525d5314d6SJason Wessel
kdb_defcmd2(const char * cmdstr,const char * argv0)6535d5314d6SJason Wessel static int kdb_defcmd2(const char *cmdstr, const char *argv0)
6545d5314d6SJason Wessel {
6555d5314d6SJason Wessel struct kdb_macro_statement *kms;
6569a5db530SSumit Garg
6579a5db530SSumit Garg if (!kdb_macro)
6589a5db530SSumit Garg return KDB_NOTIMP;
6599a5db530SSumit Garg
6609a5db530SSumit Garg if (strcmp(argv0, "endefcmd") == 0) {
6615d5314d6SJason Wessel defcmd_in_progress = false;
6627faedcd4SNicholas Mc Guire if (!list_empty(&kdb_macro->statements))
6639a5db530SSumit Garg kdb_register(&kdb_macro->cmd);
6649a5db530SSumit Garg return 0;
6655d5314d6SJason Wessel }
6665d5314d6SJason Wessel
6679a5db530SSumit Garg kms = kmalloc(sizeof(*kms), GFP_KDB);
6689a5db530SSumit Garg if (!kms) {
6699a5db530SSumit Garg kdb_printf("Could not allocate new kdb macro command: %s\n",
6709a5db530SSumit Garg cmdstr);
6715d5314d6SJason Wessel return KDB_NOTIMP;
6725d5314d6SJason Wessel }
6735d5314d6SJason Wessel
6749a5db530SSumit Garg kms->statement = kdb_strdup(cmdstr, GFP_KDB);
6759a5db530SSumit Garg list_add_tail(&kms->list_node, &kdb_macro->statements);
6769a5db530SSumit Garg
6779a5db530SSumit Garg return 0;
6785d5314d6SJason Wessel }
6795d5314d6SJason Wessel
kdb_defcmd(int argc,const char ** argv)6805d5314d6SJason Wessel static int kdb_defcmd(int argc, const char **argv)
6815d5314d6SJason Wessel {
6825d5314d6SJason Wessel kdbtab_t *mp;
683c25abcd6SSumit Garg
684c25abcd6SSumit Garg if (defcmd_in_progress) {
6855d5314d6SJason Wessel kdb_printf("kdb: nested defcmd detected, assuming missing "
6865d5314d6SJason Wessel "endefcmd\n");
6875d5314d6SJason Wessel kdb_defcmd2("endefcmd", "endefcmd");
6885d5314d6SJason Wessel }
6895d5314d6SJason Wessel if (argc == 0) {
6905d5314d6SJason Wessel kdbtab_t *kp;
6919a5db530SSumit Garg struct kdb_macro *kmp;
6929a5db530SSumit Garg struct kdb_macro_statement *kms;
6939a5db530SSumit Garg
6949a5db530SSumit Garg list_for_each_entry(kp, &kdb_cmds_head, list_node) {
6959a5db530SSumit Garg if (kp->func == kdb_exec_defcmd) {
696e868f0a3SSumit Garg kdb_printf("defcmd %s \"%s\" \"%s\"\n",
6979a5db530SSumit Garg kp->name, kp->usage, kp->help);
698e868f0a3SSumit Garg kmp = container_of(kp, struct kdb_macro, cmd);
6999a5db530SSumit Garg list_for_each_entry(kms, &kmp->statements,
7009a5db530SSumit Garg list_node)
7019a5db530SSumit Garg kdb_printf("%s", kms->statement);
7029a5db530SSumit Garg kdb_printf("endefcmd\n");
7035d5314d6SJason Wessel }
7045d5314d6SJason Wessel }
7059a5db530SSumit Garg return 0;
7065d5314d6SJason Wessel }
7075d5314d6SJason Wessel if (argc != 3)
7085d5314d6SJason Wessel return KDB_ARGCOUNT;
7095d5314d6SJason Wessel if (in_dbg_master()) {
710a37372f6SJason Wessel kdb_printf("Command only available during kdb_init()\n");
711a37372f6SJason Wessel return KDB_NOTIMP;
712a37372f6SJason Wessel }
713a37372f6SJason Wessel kdb_macro = kzalloc(sizeof(*kdb_macro), GFP_KDB);
7149a5db530SSumit Garg if (!kdb_macro)
715b39cded8SSumit Garg goto fail_defcmd;
7164eb7a66dSJason Wessel
717c25abcd6SSumit Garg mp = &kdb_macro->cmd;
7189a5db530SSumit Garg mp->func = kdb_exec_defcmd;
719e868f0a3SSumit Garg mp->minlen = 0;
720e868f0a3SSumit Garg mp->flags = KDB_ENABLE_ALWAYS_SAFE;
721e868f0a3SSumit Garg mp->name = kdb_strdup(argv[1], GFP_KDB);
722e868f0a3SSumit Garg if (!mp->name)
723e868f0a3SSumit Garg goto fail_name;
7244eb7a66dSJason Wessel mp->usage = kdb_strdup(argv[2], GFP_KDB);
725e868f0a3SSumit Garg if (!mp->usage)
726e868f0a3SSumit Garg goto fail_usage;
7274eb7a66dSJason Wessel mp->help = kdb_strdup(argv[3], GFP_KDB);
728e868f0a3SSumit Garg if (!mp->help)
729e868f0a3SSumit Garg goto fail_help;
7304eb7a66dSJason Wessel if (mp->usage[0] == '"') {
731e868f0a3SSumit Garg strcpy(mp->usage, argv[2]+1);
732e868f0a3SSumit Garg mp->usage[strlen(mp->usage)-1] = '\0';
733e868f0a3SSumit Garg }
7345d5314d6SJason Wessel if (mp->help[0] == '"') {
735e868f0a3SSumit Garg strcpy(mp->help, argv[3]+1);
736e868f0a3SSumit Garg mp->help[strlen(mp->help)-1] = '\0';
737e868f0a3SSumit Garg }
7385d5314d6SJason Wessel
7399a5db530SSumit Garg INIT_LIST_HEAD(&kdb_macro->statements);
7409a5db530SSumit Garg defcmd_in_progress = true;
7417faedcd4SNicholas Mc Guire return 0;
7425d5314d6SJason Wessel fail_help:
7434eb7a66dSJason Wessel kfree(mp->usage);
744e868f0a3SSumit Garg fail_usage:
7454eb7a66dSJason Wessel kfree(mp->name);
746e868f0a3SSumit Garg fail_name:
7474eb7a66dSJason Wessel kfree(kdb_macro);
748b39cded8SSumit Garg fail_defcmd:
7494eb7a66dSJason Wessel kdb_printf("Could not allocate new kdb_macro entry for %s\n", argv[1]);
750b39cded8SSumit Garg return KDB_NOTIMP;
7514eb7a66dSJason Wessel }
7525d5314d6SJason Wessel
7535d5314d6SJason Wessel /*
7545d5314d6SJason Wessel * kdb_exec_defcmd - Execute the set of commands associated with this
7555d5314d6SJason Wessel * defcmd name.
7565d5314d6SJason Wessel * Inputs:
7575d5314d6SJason Wessel * argc argument count
7585d5314d6SJason Wessel * argv argument vector
7595d5314d6SJason Wessel * Returns:
7605d5314d6SJason Wessel * zero for success, a kdb diagnostic if error
7615d5314d6SJason Wessel */
kdb_exec_defcmd(int argc,const char ** argv)7625d5314d6SJason Wessel static int kdb_exec_defcmd(int argc, const char **argv)
7635d5314d6SJason Wessel {
7645d5314d6SJason Wessel int ret;
7659a5db530SSumit Garg kdbtab_t *kp;
7669a5db530SSumit Garg struct kdb_macro *kmp;
7679a5db530SSumit Garg struct kdb_macro_statement *kms;
7689a5db530SSumit Garg
7699a5db530SSumit Garg if (argc != 0)
7705d5314d6SJason Wessel return KDB_ARGCOUNT;
7715d5314d6SJason Wessel
7729a5db530SSumit Garg list_for_each_entry(kp, &kdb_cmds_head, list_node) {
7739a5db530SSumit Garg if (strcmp(kp->name, argv[0]) == 0)
774e868f0a3SSumit Garg break;
7755d5314d6SJason Wessel }
7765d5314d6SJason Wessel if (list_entry_is_head(kp, &kdb_cmds_head, list_node)) {
7779a5db530SSumit Garg kdb_printf("kdb_exec_defcmd: could not find commands for %s\n",
7785d5314d6SJason Wessel argv[0]);
7795d5314d6SJason Wessel return KDB_NOTIMP;
7805d5314d6SJason Wessel }
7815d5314d6SJason Wessel kmp = container_of(kp, struct kdb_macro, cmd);
7829a5db530SSumit Garg list_for_each_entry(kms, &kmp->statements, list_node) {
7839a5db530SSumit Garg /*
7849a5db530SSumit Garg * Recursive use of kdb_parse, do not use argv after this point.
7859a5db530SSumit Garg */
7869a5db530SSumit Garg argv = NULL;
7875d5314d6SJason Wessel kdb_printf("[%s]kdb> %s\n", kmp->cmd.name, kms->statement);
788e868f0a3SSumit Garg ret = kdb_parse(kms->statement);
7899a5db530SSumit Garg if (ret)
7905d5314d6SJason Wessel return ret;
7915d5314d6SJason Wessel }
7925d5314d6SJason Wessel return 0;
7935d5314d6SJason Wessel }
7945d5314d6SJason Wessel
7955d5314d6SJason Wessel /* Command history */
7965d5314d6SJason Wessel #define KDB_CMD_HISTORY_COUNT 32
7975d5314d6SJason Wessel #define CMD_BUFLEN 200 /* kdb_printf: max printline
7985d5314d6SJason Wessel * size == 256 */
7995d5314d6SJason Wessel static unsigned int cmd_head, cmd_tail;
8005d5314d6SJason Wessel static unsigned int cmdptr;
8015d5314d6SJason Wessel static char cmd_hist[KDB_CMD_HISTORY_COUNT][CMD_BUFLEN];
8025d5314d6SJason Wessel static char cmd_cur[CMD_BUFLEN];
8035d5314d6SJason Wessel
8045d5314d6SJason Wessel /*
8055d5314d6SJason Wessel * The "str" argument may point to something like | grep xyz
8065d5314d6SJason Wessel */
parse_grep(const char * str)8075d5314d6SJason Wessel static void parse_grep(const char *str)
8085d5314d6SJason Wessel {
8095d5314d6SJason Wessel int len;
8105d5314d6SJason Wessel char *cp = (char *)str, *cp2;
8115d5314d6SJason Wessel
8125d5314d6SJason Wessel /* sanity check: we should have been called with the \ first */
8135d5314d6SJason Wessel if (*cp != '|')
8145d5314d6SJason Wessel return;
8155d5314d6SJason Wessel cp++;
8165d5314d6SJason Wessel while (isspace(*cp))
8175d5314d6SJason Wessel cp++;
8185d5314d6SJason Wessel if (!str_has_prefix(cp, "grep ")) {
81963571431SChuhong Yuan kdb_printf("invalid 'pipe', see grephelp\n");
8205d5314d6SJason Wessel return;
8215d5314d6SJason Wessel }
8225d5314d6SJason Wessel cp += 5;
8235d5314d6SJason Wessel while (isspace(*cp))
8245d5314d6SJason Wessel cp++;
8255d5314d6SJason Wessel cp2 = strchr(cp, '\n');
8265d5314d6SJason Wessel if (cp2)
8275d5314d6SJason Wessel *cp2 = '\0'; /* remove the trailing newline */
8285d5314d6SJason Wessel len = strlen(cp);
8295d5314d6SJason Wessel if (len == 0) {
8305d5314d6SJason Wessel kdb_printf("invalid 'pipe', see grephelp\n");
8315d5314d6SJason Wessel return;
8325d5314d6SJason Wessel }
8335d5314d6SJason Wessel /* now cp points to a nonzero length search string */
8345d5314d6SJason Wessel if (*cp == '"') {
8355d5314d6SJason Wessel /* allow it be "x y z" by removing the "'s - there must
8365d5314d6SJason Wessel be two of them */
8375d5314d6SJason Wessel cp++;
8385d5314d6SJason Wessel cp2 = strchr(cp, '"');
8395d5314d6SJason Wessel if (!cp2) {
8405d5314d6SJason Wessel kdb_printf("invalid quoted string, see grephelp\n");
8415d5314d6SJason Wessel return;
8425d5314d6SJason Wessel }
8435d5314d6SJason Wessel *cp2 = '\0'; /* end the string where the 2nd " was */
8445d5314d6SJason Wessel }
8455d5314d6SJason Wessel kdb_grep_leading = 0;
8465d5314d6SJason Wessel if (*cp == '^') {
8475d5314d6SJason Wessel kdb_grep_leading = 1;
8485d5314d6SJason Wessel cp++;
8495d5314d6SJason Wessel }
8505d5314d6SJason Wessel len = strlen(cp);
8515d5314d6SJason Wessel kdb_grep_trailing = 0;
8525d5314d6SJason Wessel if (*(cp+len-1) == '$') {
8535d5314d6SJason Wessel kdb_grep_trailing = 1;
8545d5314d6SJason Wessel *(cp+len-1) = '\0';
8555d5314d6SJason Wessel }
8565d5314d6SJason Wessel len = strlen(cp);
8575d5314d6SJason Wessel if (!len)
8585d5314d6SJason Wessel return;
8595d5314d6SJason Wessel if (len >= KDB_GREP_STRLEN) {
860fb6daa75SDaniel Thompson kdb_printf("search string too long\n");
8615d5314d6SJason Wessel return;
8625d5314d6SJason Wessel }
8635d5314d6SJason Wessel strcpy(kdb_grep_string, cp);
8645d5314d6SJason Wessel kdb_grepping_flag++;
8655d5314d6SJason Wessel return;
8665d5314d6SJason Wessel }
8675d5314d6SJason Wessel
8685d5314d6SJason Wessel /*
8695d5314d6SJason Wessel * kdb_parse - Parse the command line, search the command table for a
8705d5314d6SJason Wessel * matching command and invoke the command function. This
8715d5314d6SJason Wessel * function may be called recursively, if it is, the second call
8725d5314d6SJason Wessel * will overwrite argv and cbuf. It is the caller's
8735d5314d6SJason Wessel * responsibility to save their argv if they recursively call
8745d5314d6SJason Wessel * kdb_parse().
8755d5314d6SJason Wessel * Parameters:
8765d5314d6SJason Wessel * cmdstr The input command line to be parsed.
8775d5314d6SJason Wessel * regs The registers at the time kdb was entered.
8785d5314d6SJason Wessel * Returns:
8795d5314d6SJason Wessel * Zero for success, a kdb diagnostic if failure.
8805d5314d6SJason Wessel * Remarks:
8815d5314d6SJason Wessel * Limited to 20 tokens.
8825d5314d6SJason Wessel *
8835d5314d6SJason Wessel * Real rudimentary tokenization. Basically only whitespace
8845d5314d6SJason Wessel * is considered a token delimiter (but special consideration
885220a31b0SZhen Lei * is taken of the '=' sign as used by the 'set' command).
8865d5314d6SJason Wessel *
8875d5314d6SJason Wessel * The algorithm used to tokenize the input string relies on
8885d5314d6SJason Wessel * there being at least one whitespace (or otherwise useless)
8895d5314d6SJason Wessel * character between tokens as the character immediately following
8905d5314d6SJason Wessel * the token is altered in-place to a null-byte to terminate the
8915d5314d6SJason Wessel * token string.
8925d5314d6SJason Wessel */
8935d5314d6SJason Wessel
8945d5314d6SJason Wessel #define MAXARGC 20
8955d5314d6SJason Wessel
kdb_parse(const char * cmdstr)8965d5314d6SJason Wessel int kdb_parse(const char *cmdstr)
8975d5314d6SJason Wessel {
8985d5314d6SJason Wessel static char *argv[MAXARGC];
8995d5314d6SJason Wessel static int argc;
9005d5314d6SJason Wessel static char cbuf[CMD_BUFLEN+2];
9015d5314d6SJason Wessel char *cp;
9025d5314d6SJason Wessel char *cpp, quoted;
9035d5314d6SJason Wessel kdbtab_t *tp;
9045d5314d6SJason Wessel int escaped, ignore_errors = 0, check_grep = 0;
905e4f291b3SSumit Garg
9065d5314d6SJason Wessel /*
9075d5314d6SJason Wessel * First tokenize the command string.
9085d5314d6SJason Wessel */
9095d5314d6SJason Wessel cp = (char *)cmdstr;
9105d5314d6SJason Wessel
9115d5314d6SJason Wessel if (KDB_FLAG(CMD_INTERRUPT)) {
9125d5314d6SJason Wessel /* Previous command was interrupted, newline must not
9135d5314d6SJason Wessel * repeat the command */
9145d5314d6SJason Wessel KDB_FLAG_CLEAR(CMD_INTERRUPT);
9155d5314d6SJason Wessel KDB_STATE_SET(PAGER);
9165d5314d6SJason Wessel argc = 0; /* no repeat */
9175d5314d6SJason Wessel }
9185d5314d6SJason Wessel
9195d5314d6SJason Wessel if (*cp != '\n' && *cp != '\0') {
9205d5314d6SJason Wessel argc = 0;
9215d5314d6SJason Wessel cpp = cbuf;
9225d5314d6SJason Wessel while (*cp) {
9235d5314d6SJason Wessel /* skip whitespace */
9245d5314d6SJason Wessel while (isspace(*cp))
9255d5314d6SJason Wessel cp++;
9265d5314d6SJason Wessel if ((*cp == '\0') || (*cp == '\n') ||
9275d5314d6SJason Wessel (*cp == '#' && !defcmd_in_progress))
9285d5314d6SJason Wessel break;
9295d5314d6SJason Wessel /* special case: check for | grep pattern */
9305d5314d6SJason Wessel if (*cp == '|') {
9315d5314d6SJason Wessel check_grep++;
9325d5314d6SJason Wessel break;
9335d5314d6SJason Wessel }
9345d5314d6SJason Wessel if (cpp >= cbuf + CMD_BUFLEN) {
9355d5314d6SJason Wessel kdb_printf("kdb_parse: command buffer "
9365d5314d6SJason Wessel "overflow, command ignored\n%s\n",
9375d5314d6SJason Wessel cmdstr);
9385d5314d6SJason Wessel return KDB_NOTFOUND;
9395d5314d6SJason Wessel }
9405d5314d6SJason Wessel if (argc >= MAXARGC - 1) {
9415d5314d6SJason Wessel kdb_printf("kdb_parse: too many arguments, "
9425d5314d6SJason Wessel "command ignored\n%s\n", cmdstr);
9435d5314d6SJason Wessel return KDB_NOTFOUND;
9445d5314d6SJason Wessel }
9455d5314d6SJason Wessel argv[argc++] = cpp;
9465d5314d6SJason Wessel escaped = 0;
9475d5314d6SJason Wessel quoted = '\0';
9485d5314d6SJason Wessel /* Copy to next unquoted and unescaped
9495d5314d6SJason Wessel * whitespace or '=' */
9505d5314d6SJason Wessel while (*cp && *cp != '\n' &&
9515d5314d6SJason Wessel (escaped || quoted || !isspace(*cp))) {
9525d5314d6SJason Wessel if (cpp >= cbuf + CMD_BUFLEN)
9535d5314d6SJason Wessel break;
9545d5314d6SJason Wessel if (escaped) {
9555d5314d6SJason Wessel escaped = 0;
9565d5314d6SJason Wessel *cpp++ = *cp++;
9575d5314d6SJason Wessel continue;
9585d5314d6SJason Wessel }
9595d5314d6SJason Wessel if (*cp == '\\') {
9605d5314d6SJason Wessel escaped = 1;
9615d5314d6SJason Wessel ++cp;
9625d5314d6SJason Wessel continue;
9635d5314d6SJason Wessel }
9645d5314d6SJason Wessel if (*cp == quoted)
9655d5314d6SJason Wessel quoted = '\0';
9665d5314d6SJason Wessel else if (*cp == '\'' || *cp == '"')
9675d5314d6SJason Wessel quoted = *cp;
9685d5314d6SJason Wessel *cpp = *cp++;
9695d5314d6SJason Wessel if (*cpp == '=' && !quoted)
9705d5314d6SJason Wessel break;
9715d5314d6SJason Wessel ++cpp;
9725d5314d6SJason Wessel }
9735d5314d6SJason Wessel *cpp++ = '\0'; /* Squash a ws or '=' character */
9745d5314d6SJason Wessel }
9755d5314d6SJason Wessel }
9765d5314d6SJason Wessel if (!argc)
9775d5314d6SJason Wessel return 0;
9785d5314d6SJason Wessel if (check_grep)
9795d5314d6SJason Wessel parse_grep(cp);
9805d5314d6SJason Wessel if (defcmd_in_progress) {
9815d5314d6SJason Wessel int result = kdb_defcmd2(cmdstr, argv[0]);
9825d5314d6SJason Wessel if (!defcmd_in_progress) {
9835d5314d6SJason Wessel argc = 0; /* avoid repeat on endefcmd */
9845d5314d6SJason Wessel *(argv[0]) = '\0';
9855d5314d6SJason Wessel }
9865d5314d6SJason Wessel return result;
9875d5314d6SJason Wessel }
9885d5314d6SJason Wessel if (argv[0][0] == '-' && argv[0][1] &&
9895d5314d6SJason Wessel (argv[0][1] < '0' || argv[0][1] > '9')) {
9905d5314d6SJason Wessel ignore_errors = 1;
9915d5314d6SJason Wessel ++argv[0];
9925d5314d6SJason Wessel }
9935d5314d6SJason Wessel
9945d5314d6SJason Wessel list_for_each_entry(tp, &kdb_cmds_head, list_node) {
995e4f291b3SSumit Garg /*
9965d5314d6SJason Wessel * If this command is allowed to be abbreviated,
9975d5314d6SJason Wessel * check to see if this is it.
9985d5314d6SJason Wessel */
9995d5314d6SJason Wessel if (tp->minlen && (strlen(argv[0]) <= tp->minlen) &&
1000e868f0a3SSumit Garg (strncmp(argv[0], tp->name, tp->minlen) == 0))
1001e868f0a3SSumit Garg break;
10025d5314d6SJason Wessel
10035d5314d6SJason Wessel if (strcmp(argv[0], tp->name) == 0)
1004e868f0a3SSumit Garg break;
10055d5314d6SJason Wessel }
10065d5314d6SJason Wessel
10075d5314d6SJason Wessel /*
10085d5314d6SJason Wessel * If we don't find a command by this name, see if the first
10095d5314d6SJason Wessel * few characters of this match any of the known commands.
10105d5314d6SJason Wessel * e.g., md1c20 should match md.
10115d5314d6SJason Wessel */
10125d5314d6SJason Wessel if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
1013e4f291b3SSumit Garg list_for_each_entry(tp, &kdb_cmds_head, list_node) {
1014e4f291b3SSumit Garg if (strncmp(argv[0], tp->name, strlen(tp->name)) == 0)
1015e868f0a3SSumit Garg break;
10165d5314d6SJason Wessel }
10175d5314d6SJason Wessel }
10185d5314d6SJason Wessel
10195d5314d6SJason Wessel if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) {
1020e4f291b3SSumit Garg int result;
10215d5314d6SJason Wessel
1022420c2b1bSAnton Vorontsov if (!kdb_check_flags(tp->flags, kdb_cmd_enabled, argc <= 1))
1023e868f0a3SSumit Garg return KDB_NOPERM;
1024420c2b1bSAnton Vorontsov
1025420c2b1bSAnton Vorontsov KDB_STATE_SET(CMD);
10265d5314d6SJason Wessel result = (*tp->func)(argc-1, (const char **)argv);
1027e868f0a3SSumit Garg if (result && ignore_errors && result > KDB_CMD_GO)
10285d5314d6SJason Wessel result = 0;
10295d5314d6SJason Wessel KDB_STATE_CLEAR(CMD);
10305d5314d6SJason Wessel
103104bb171eSAnton Vorontsov if (tp->flags & KDB_REPEAT_WITH_ARGS)
1032e868f0a3SSumit Garg return result;
103304bb171eSAnton Vorontsov
103404bb171eSAnton Vorontsov argc = tp->flags & KDB_REPEAT_NO_ARGS ? 1 : 0;
1035e868f0a3SSumit Garg if (argv[argc])
103604bb171eSAnton Vorontsov *(argv[argc]) = '\0';
103704bb171eSAnton Vorontsov return result;
10385d5314d6SJason Wessel }
10395d5314d6SJason Wessel
10405d5314d6SJason Wessel /*
10415d5314d6SJason Wessel * If the input with which we were presented does not
10425d5314d6SJason Wessel * map to an existing command, attempt to parse it as an
10435d5314d6SJason Wessel * address argument and display the result. Useful for
10445d5314d6SJason Wessel * obtaining the address of a variable, or the nearest symbol
10455d5314d6SJason Wessel * to an address contained in a register.
10465d5314d6SJason Wessel */
10475d5314d6SJason Wessel {
10485d5314d6SJason Wessel unsigned long value;
10495d5314d6SJason Wessel char *name = NULL;
10505d5314d6SJason Wessel long offset;
10515d5314d6SJason Wessel int nextarg = 0;
10525d5314d6SJason Wessel
10535d5314d6SJason Wessel if (kdbgetaddrarg(0, (const char **)argv, &nextarg,
10545d5314d6SJason Wessel &value, &offset, &name)) {
10555d5314d6SJason Wessel return KDB_NOTFOUND;
10565d5314d6SJason Wessel }
10575d5314d6SJason Wessel
10585d5314d6SJason Wessel kdb_printf("%s = ", argv[0]);
10595d5314d6SJason Wessel kdb_symbol_print(value, NULL, KDB_SP_DEFAULT);
10605d5314d6SJason Wessel kdb_printf("\n");
10615d5314d6SJason Wessel return 0;
10625d5314d6SJason Wessel }
10635d5314d6SJason Wessel }
10645d5314d6SJason Wessel
10655d5314d6SJason Wessel
handle_ctrl_cmd(char * cmd)10665d5314d6SJason Wessel static int handle_ctrl_cmd(char *cmd)
10675d5314d6SJason Wessel {
10685d5314d6SJason Wessel #define CTRL_P 16
10695d5314d6SJason Wessel #define CTRL_N 14
10705d5314d6SJason Wessel
10715d5314d6SJason Wessel /* initial situation */
10725d5314d6SJason Wessel if (cmd_head == cmd_tail)
10735d5314d6SJason Wessel return 0;
10745d5314d6SJason Wessel switch (*cmd) {
10755d5314d6SJason Wessel case CTRL_P:
10765d5314d6SJason Wessel if (cmdptr != cmd_tail)
10775d5314d6SJason Wessel cmdptr = (cmdptr + KDB_CMD_HISTORY_COUNT - 1) %
10781b310030SDouglas Anderson KDB_CMD_HISTORY_COUNT;
10791b310030SDouglas Anderson strscpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
1080d228bee8SDaniel Thompson return 1;
10815d5314d6SJason Wessel case CTRL_N:
10825d5314d6SJason Wessel if (cmdptr != cmd_head)
10835d5314d6SJason Wessel cmdptr = (cmdptr+1) % KDB_CMD_HISTORY_COUNT;
10845d5314d6SJason Wessel strscpy(cmd_cur, cmd_hist[cmdptr], CMD_BUFLEN);
1085d228bee8SDaniel Thompson return 1;
10865d5314d6SJason Wessel }
10875d5314d6SJason Wessel return 0;
10885d5314d6SJason Wessel }
10895d5314d6SJason Wessel
10905d5314d6SJason Wessel /*
10915d5314d6SJason Wessel * kdb_reboot - This function implements the 'reboot' command. Reboot
10925d5314d6SJason Wessel * the system immediately, or loop for ever on failure.
10935d5314d6SJason Wessel */
kdb_reboot(int argc,const char ** argv)10945d5314d6SJason Wessel static int kdb_reboot(int argc, const char **argv)
10955d5314d6SJason Wessel {
10965d5314d6SJason Wessel emergency_restart();
10975d5314d6SJason Wessel kdb_printf("Hmm, kdb_reboot did not reboot, spinning here\n");
10985d5314d6SJason Wessel while (1)
10995d5314d6SJason Wessel cpu_relax();
11005d5314d6SJason Wessel /* NOTREACHED */
11015d5314d6SJason Wessel return 0;
11025d5314d6SJason Wessel }
11035d5314d6SJason Wessel
kdb_dumpregs(struct pt_regs * regs)11045d5314d6SJason Wessel static void kdb_dumpregs(struct pt_regs *regs)
11055d5314d6SJason Wessel {
11065d5314d6SJason Wessel int old_lvl = console_loglevel;
11075d5314d6SJason Wessel console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
1108a8fe19ebSBorislav Petkov kdb_trap_printk++;
1109d37d39aeSJason Wessel show_regs(regs);
11105d5314d6SJason Wessel kdb_trap_printk--;
1111d37d39aeSJason Wessel kdb_printf("\n");
11125d5314d6SJason Wessel console_loglevel = old_lvl;
11135d5314d6SJason Wessel }
11145d5314d6SJason Wessel
kdb_set_current_task(struct task_struct * p)11155d5314d6SJason Wessel static void kdb_set_current_task(struct task_struct *p)
11169441d5f6SDouglas Anderson {
11175d5314d6SJason Wessel kdb_current_task = p;
11185d5314d6SJason Wessel
11195d5314d6SJason Wessel if (kdb_task_has_cpu(p)) {
11205d5314d6SJason Wessel kdb_current_regs = KDB_TSKREGS(kdb_process_cpu(p));
11215d5314d6SJason Wessel return;
11225d5314d6SJason Wessel }
11235d5314d6SJason Wessel kdb_current_regs = NULL;
11245d5314d6SJason Wessel }
11255d5314d6SJason Wessel
drop_newline(char * buf)11265d5314d6SJason Wessel static void drop_newline(char *buf)
1127b0f73bc7SRandy Dunlap {
1128b0f73bc7SRandy Dunlap size_t len = strlen(buf);
1129b0f73bc7SRandy Dunlap
1130b0f73bc7SRandy Dunlap if (len == 0)
1131b0f73bc7SRandy Dunlap return;
1132b0f73bc7SRandy Dunlap if (*(buf + len - 1) == '\n')
1133b0f73bc7SRandy Dunlap *(buf + len - 1) = '\0';
1134b0f73bc7SRandy Dunlap }
1135b0f73bc7SRandy Dunlap
1136b0f73bc7SRandy Dunlap /*
11375d5314d6SJason Wessel * kdb_local - The main code for kdb. This routine is invoked on a
11385d5314d6SJason Wessel * specific processor, it is not global. The main kdb() routine
11395d5314d6SJason Wessel * ensures that only one processor at a time is in this routine.
11405d5314d6SJason Wessel * This code is called with the real reason code on the first
11415d5314d6SJason Wessel * entry to a kdb session, thereafter it is called with reason
11425d5314d6SJason Wessel * SWITCH, even if the user goes back to the original cpu.
11435d5314d6SJason Wessel * Inputs:
11445d5314d6SJason Wessel * reason The reason KDB was invoked
11455d5314d6SJason Wessel * error The hardware-defined error code
11465d5314d6SJason Wessel * regs The exception frame at time of fault/breakpoint.
11475d5314d6SJason Wessel * db_result Result code from the break or debug point.
11485d5314d6SJason Wessel * Returns:
11495d5314d6SJason Wessel * 0 KDB was invoked for an event which it wasn't responsible
11505d5314d6SJason Wessel * 1 KDB handled the event for which it was invoked.
11515d5314d6SJason Wessel * KDB_CMD_GO User typed 'go'.
11525d5314d6SJason Wessel * KDB_CMD_CPU User switched to another cpu.
11535d5314d6SJason Wessel * KDB_CMD_SS Single step.
11545d5314d6SJason Wessel */
kdb_local(kdb_reason_t reason,int error,struct pt_regs * regs,kdb_dbtrap_t db_result)11555d5314d6SJason Wessel static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
11565d5314d6SJason Wessel kdb_dbtrap_t db_result)
11575d5314d6SJason Wessel {
11585d5314d6SJason Wessel char *cmdbuf;
11595d5314d6SJason Wessel int diag;
11605d5314d6SJason Wessel struct task_struct *kdb_current =
11615d5314d6SJason Wessel curr_task(raw_smp_processor_id());
11629bccbe7bSZheng Zengkai
11635d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_local 1", reason);
11645d5314d6SJason Wessel
1165eadb2f47SDaniel Thompson kdb_check_for_lockdown();
1166eadb2f47SDaniel Thompson
1167eadb2f47SDaniel Thompson kdb_go_count = 0;
11685d5314d6SJason Wessel if (reason == KDB_REASON_DEBUG) {
11695d5314d6SJason Wessel /* special case below */
11705d5314d6SJason Wessel } else {
11715d5314d6SJason Wessel kdb_printf("\nEntering kdb (current=0x%px, pid %d) ",
1172568fb6f4SChristophe Leroy kdb_current, kdb_current ? kdb_current->pid : 0);
1173578bd4dfSJason Wessel #if defined(CONFIG_SMP)
11745d5314d6SJason Wessel kdb_printf("on processor %d ", raw_smp_processor_id());
11755d5314d6SJason Wessel #endif
11765d5314d6SJason Wessel }
11775d5314d6SJason Wessel
11785d5314d6SJason Wessel switch (reason) {
11795d5314d6SJason Wessel case KDB_REASON_DEBUG:
11805d5314d6SJason Wessel {
11815d5314d6SJason Wessel /*
11825d5314d6SJason Wessel * If re-entering kdb after a single step
11835d5314d6SJason Wessel * command, don't print the message.
11845d5314d6SJason Wessel */
11855d5314d6SJason Wessel switch (db_result) {
11865d5314d6SJason Wessel case KDB_DB_BPT:
11875d5314d6SJason Wessel kdb_printf("\nEntering kdb (0x%px, pid %d) ",
1188568fb6f4SChristophe Leroy kdb_current, kdb_current->pid);
11895d5314d6SJason Wessel #if defined(CONFIG_SMP)
11905d5314d6SJason Wessel kdb_printf("on processor %d ", raw_smp_processor_id());
11915d5314d6SJason Wessel #endif
11925d5314d6SJason Wessel kdb_printf("due to Debug @ " kdb_machreg_fmt "\n",
11935d5314d6SJason Wessel instruction_pointer(regs));
11945d5314d6SJason Wessel break;
11955d5314d6SJason Wessel case KDB_DB_SS:
11965d5314d6SJason Wessel break;
11975d5314d6SJason Wessel case KDB_DB_SSBPT:
11985d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_local 4", reason);
11995d5314d6SJason Wessel return 1; /* kdba_db_trap did the work */
12005d5314d6SJason Wessel default:
12015d5314d6SJason Wessel kdb_printf("kdb: Bad result from kdba_db_trap: %d\n",
12025d5314d6SJason Wessel db_result);
12035d5314d6SJason Wessel break;
12045d5314d6SJason Wessel }
12055d5314d6SJason Wessel
12065d5314d6SJason Wessel }
12075d5314d6SJason Wessel break;
12085d5314d6SJason Wessel case KDB_REASON_ENTER:
12095d5314d6SJason Wessel if (KDB_STATE(KEYBOARD))
12105d5314d6SJason Wessel kdb_printf("due to Keyboard Entry\n");
12115d5314d6SJason Wessel else
12125d5314d6SJason Wessel kdb_printf("due to KDB_ENTER()\n");
12135d5314d6SJason Wessel break;
12145d5314d6SJason Wessel case KDB_REASON_KEYBOARD:
12155d5314d6SJason Wessel KDB_STATE_SET(KEYBOARD);
12165d5314d6SJason Wessel kdb_printf("due to Keyboard Entry\n");
12175d5314d6SJason Wessel break;
12185d5314d6SJason Wessel case KDB_REASON_ENTER_SLAVE:
12195d5314d6SJason Wessel /* drop through, slaves only get released via cpu switch */
12205d5314d6SJason Wessel case KDB_REASON_SWITCH:
12215d5314d6SJason Wessel kdb_printf("due to cpu switch\n");
12225d5314d6SJason Wessel break;
12235d5314d6SJason Wessel case KDB_REASON_OOPS:
12245d5314d6SJason Wessel kdb_printf("Oops: %s\n", kdb_diemsg);
12255d5314d6SJason Wessel kdb_printf("due to oops @ " kdb_machreg_fmt "\n",
12265d5314d6SJason Wessel instruction_pointer(regs));
12275d5314d6SJason Wessel kdb_dumpregs(regs);
12285d5314d6SJason Wessel break;
12295d5314d6SJason Wessel case KDB_REASON_SYSTEM_NMI:
12308daaa5f8SMike Travis kdb_printf("due to System NonMaskable Interrupt\n");
12318daaa5f8SMike Travis break;
12328daaa5f8SMike Travis case KDB_REASON_NMI:
12335d5314d6SJason Wessel kdb_printf("due to NonMaskable Interrupt @ "
12345d5314d6SJason Wessel kdb_machreg_fmt "\n",
12355d5314d6SJason Wessel instruction_pointer(regs));
12365d5314d6SJason Wessel break;
12375d5314d6SJason Wessel case KDB_REASON_SSTEP:
12385d5314d6SJason Wessel case KDB_REASON_BREAK:
12395d5314d6SJason Wessel kdb_printf("due to %s @ " kdb_machreg_fmt "\n",
12405d5314d6SJason Wessel reason == KDB_REASON_BREAK ?
12415d5314d6SJason Wessel "Breakpoint" : "SS trap", instruction_pointer(regs));
12425d5314d6SJason Wessel /*
12435d5314d6SJason Wessel * Determine if this breakpoint is one that we
12445d5314d6SJason Wessel * are interested in.
12455d5314d6SJason Wessel */
12465d5314d6SJason Wessel if (db_result != KDB_DB_BPT) {
12475d5314d6SJason Wessel kdb_printf("kdb: error return from kdba_bp_trap: %d\n",
12485d5314d6SJason Wessel db_result);
12495d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_local 6", reason);
12505d5314d6SJason Wessel return 0; /* Not for us, dismiss it */
12515d5314d6SJason Wessel }
12525d5314d6SJason Wessel break;
12535d5314d6SJason Wessel case KDB_REASON_RECURSE:
12545d5314d6SJason Wessel kdb_printf("due to Recursion @ " kdb_machreg_fmt "\n",
12555d5314d6SJason Wessel instruction_pointer(regs));
12565d5314d6SJason Wessel break;
12575d5314d6SJason Wessel default:
12585d5314d6SJason Wessel kdb_printf("kdb: unexpected reason code: %d\n", reason);
12595d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_local 8", reason);
12605d5314d6SJason Wessel return 0; /* Not for us, dismiss it */
12615d5314d6SJason Wessel }
12625d5314d6SJason Wessel
12635d5314d6SJason Wessel while (1) {
12645d5314d6SJason Wessel /*
12655d5314d6SJason Wessel * Initialize pager context.
12665d5314d6SJason Wessel */
12675d5314d6SJason Wessel kdb_nextline = 1;
12685d5314d6SJason Wessel KDB_STATE_CLEAR(SUPPRESS);
12695d5314d6SJason Wessel kdb_grepping_flag = 0;
1270ab08e464SDaniel Thompson /* ensure the old search does not leak into '/' commands */
1271fb6daa75SDaniel Thompson kdb_grep_string[0] = '\0';
1272fb6daa75SDaniel Thompson
12735d5314d6SJason Wessel cmdbuf = cmd_cur;
12745d5314d6SJason Wessel *cmdbuf = '\0';
12755d5314d6SJason Wessel *(cmd_hist[cmd_head]) = '\0';
12765d5314d6SJason Wessel
12775d5314d6SJason Wessel do_full_getstr:
12785d5314d6SJason Wessel /* PROMPT can only be set if we have MEM_READ permission. */
1279ad99b510SDaniel Thompson snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"),
12805d5314d6SJason Wessel raw_smp_processor_id());
12815d5314d6SJason Wessel
12825d5314d6SJason Wessel /*
12835d5314d6SJason Wessel * Fetch command from keyboard
12845d5314d6SJason Wessel */
12855d5314d6SJason Wessel cmdbuf = kdb_getstr(cmdbuf, CMD_BUFLEN, kdb_prompt_str);
12865d5314d6SJason Wessel if (*cmdbuf != '\n') {
12875d5314d6SJason Wessel if (*cmdbuf < 32) {
12885d5314d6SJason Wessel if (cmdptr == cmd_head) {
12895d5314d6SJason Wessel strscpy(cmd_hist[cmd_head], cmd_cur,
1290d228bee8SDaniel Thompson CMD_BUFLEN);
12915d5314d6SJason Wessel *(cmd_hist[cmd_head] +
12925d5314d6SJason Wessel strlen(cmd_hist[cmd_head])-1) = '\0';
12935d5314d6SJason Wessel }
12945d5314d6SJason Wessel if (!handle_ctrl_cmd(cmdbuf))
12955d5314d6SJason Wessel *(cmd_cur+strlen(cmd_cur)-1) = '\0';
12965d5314d6SJason Wessel cmdbuf = cmd_cur;
12975d5314d6SJason Wessel goto do_full_getstr;
12985d5314d6SJason Wessel } else {
12995d5314d6SJason Wessel strscpy(cmd_hist[cmd_head], cmd_cur,
1300d228bee8SDaniel Thompson CMD_BUFLEN);
13015d5314d6SJason Wessel }
13025d5314d6SJason Wessel
13035d5314d6SJason Wessel cmd_head = (cmd_head+1) % KDB_CMD_HISTORY_COUNT;
13045d5314d6SJason Wessel if (cmd_head == cmd_tail)
13055d5314d6SJason Wessel cmd_tail = (cmd_tail+1) % KDB_CMD_HISTORY_COUNT;
13065d5314d6SJason Wessel }
13075d5314d6SJason Wessel
13085d5314d6SJason Wessel cmdptr = cmd_head;
13095d5314d6SJason Wessel diag = kdb_parse(cmdbuf);
13105d5314d6SJason Wessel if (diag == KDB_NOTFOUND) {
13115d5314d6SJason Wessel drop_newline(cmdbuf);
1312b0f73bc7SRandy Dunlap kdb_printf("Unknown kdb command: '%s'\n", cmdbuf);
13135d5314d6SJason Wessel diag = 0;
13145d5314d6SJason Wessel }
13155d5314d6SJason Wessel if (diag == KDB_CMD_GO
13165d5314d6SJason Wessel || diag == KDB_CMD_CPU
13175d5314d6SJason Wessel || diag == KDB_CMD_SS
13185d5314d6SJason Wessel || diag == KDB_CMD_KGDB)
13195d5314d6SJason Wessel break;
13205d5314d6SJason Wessel
13215d5314d6SJason Wessel if (diag)
13225d5314d6SJason Wessel kdb_cmderror(diag);
13235d5314d6SJason Wessel }
13245d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_local 9", diag);
13255d5314d6SJason Wessel return diag;
13265d5314d6SJason Wessel }
13275d5314d6SJason Wessel
13285d5314d6SJason Wessel
13295d5314d6SJason Wessel /*
13305d5314d6SJason Wessel * kdb_print_state - Print the state data for the current processor
13315d5314d6SJason Wessel * for debugging.
13325d5314d6SJason Wessel * Inputs:
13335d5314d6SJason Wessel * text Identifies the debug point
13345d5314d6SJason Wessel * value Any integer value to be printed, e.g. reason code.
13355d5314d6SJason Wessel */
kdb_print_state(const char * text,int value)13365d5314d6SJason Wessel void kdb_print_state(const char *text, int value)
13375d5314d6SJason Wessel {
13385d5314d6SJason Wessel kdb_printf("state: %s cpu %d value %d initial %d state %x\n",
13395d5314d6SJason Wessel text, raw_smp_processor_id(), value, kdb_initial_cpu,
13405d5314d6SJason Wessel kdb_state);
13415d5314d6SJason Wessel }
13425d5314d6SJason Wessel
13435d5314d6SJason Wessel /*
13445d5314d6SJason Wessel * kdb_main_loop - After initial setup and assignment of the
13455d5314d6SJason Wessel * controlling cpu, all cpus are in this loop. One cpu is in
13465d5314d6SJason Wessel * control and will issue the kdb prompt, the others will spin
13475d5314d6SJason Wessel * until 'go' or cpu switch.
13485d5314d6SJason Wessel *
13495d5314d6SJason Wessel * To get a consistent view of the kernel stacks for all
13505d5314d6SJason Wessel * processes, this routine is invoked from the main kdb code via
13515d5314d6SJason Wessel * an architecture specific routine. kdba_main_loop is
13525d5314d6SJason Wessel * responsible for making the kernel stacks consistent for all
13535d5314d6SJason Wessel * processes, there should be no difference between a blocked
13545d5314d6SJason Wessel * process and a running process as far as kdb is concerned.
13555d5314d6SJason Wessel * Inputs:
13565d5314d6SJason Wessel * reason The reason KDB was invoked
13575d5314d6SJason Wessel * error The hardware-defined error code
13585d5314d6SJason Wessel * reason2 kdb's current reason code.
13595d5314d6SJason Wessel * Initially error but can change
13605d5314d6SJason Wessel * according to kdb state.
136125985edcSLucas De Marchi * db_result Result code from break or debug point.
13625d5314d6SJason Wessel * regs The exception frame at time of fault/breakpoint.
13635d5314d6SJason Wessel * should always be valid.
13645d5314d6SJason Wessel * Returns:
13655d5314d6SJason Wessel * 0 KDB was invoked for an event which it wasn't responsible
13665d5314d6SJason Wessel * 1 KDB handled the event for which it was invoked.
13675d5314d6SJason Wessel */
kdb_main_loop(kdb_reason_t reason,kdb_reason_t reason2,int error,kdb_dbtrap_t db_result,struct pt_regs * regs)13685d5314d6SJason Wessel int kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,
13695d5314d6SJason Wessel kdb_dbtrap_t db_result, struct pt_regs *regs)
13705d5314d6SJason Wessel {
13715d5314d6SJason Wessel int result = 1;
13725d5314d6SJason Wessel /* Stay in kdb() until 'go', 'ss[b]' or an error */
13735d5314d6SJason Wessel while (1) {
13745d5314d6SJason Wessel /*
13755d5314d6SJason Wessel * All processors except the one that is in control
13765d5314d6SJason Wessel * will spin here.
13775d5314d6SJason Wessel */
13785d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_main_loop 1", reason);
13795d5314d6SJason Wessel while (KDB_STATE(HOLD_CPU)) {
13805d5314d6SJason Wessel /* state KDB is turned off by kdb_cpu to see if the
13815d5314d6SJason Wessel * other cpus are still live, each cpu in this loop
13825d5314d6SJason Wessel * turns it back on.
13835d5314d6SJason Wessel */
13845d5314d6SJason Wessel if (!KDB_STATE(KDB))
13855d5314d6SJason Wessel KDB_STATE_SET(KDB);
13865d5314d6SJason Wessel }
13875d5314d6SJason Wessel
13885d5314d6SJason Wessel KDB_STATE_CLEAR(SUPPRESS);
13895d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_main_loop 2", reason);
13905d5314d6SJason Wessel if (KDB_STATE(LEAVING))
13915d5314d6SJason Wessel break; /* Another cpu said 'go' */
13925d5314d6SJason Wessel /* Still using kdb, this processor is in control */
13935d5314d6SJason Wessel result = kdb_local(reason2, error, regs, db_result);
13945d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_main_loop 3", result);
13955d5314d6SJason Wessel
13965d5314d6SJason Wessel if (result == KDB_CMD_CPU)
13975d5314d6SJason Wessel break;
13985d5314d6SJason Wessel
13995d5314d6SJason Wessel if (result == KDB_CMD_SS) {
14005d5314d6SJason Wessel KDB_STATE_SET(DOING_SS);
14015d5314d6SJason Wessel break;
14025d5314d6SJason Wessel }
14035d5314d6SJason Wessel
14045d5314d6SJason Wessel if (result == KDB_CMD_KGDB) {
14055d5314d6SJason Wessel if (!KDB_STATE(DOING_KGDB))
1406d613d828SJason Wessel kdb_printf("Entering please attach debugger "
14075d5314d6SJason Wessel "or use $D#44+ or $3#33\n");
14085d5314d6SJason Wessel break;
14095d5314d6SJason Wessel }
14105d5314d6SJason Wessel if (result && result != 1 && result != KDB_CMD_GO)
14115d5314d6SJason Wessel kdb_printf("\nUnexpected kdb_local return code %d\n",
14125d5314d6SJason Wessel result);
14135d5314d6SJason Wessel KDB_DEBUG_STATE("kdb_main_loop 4", reason);
14145d5314d6SJason Wessel break;
14155d5314d6SJason Wessel }
14165d5314d6SJason Wessel if (KDB_STATE(DOING_SS))
14175d5314d6SJason Wessel KDB_STATE_CLEAR(SSBPT);
14185d5314d6SJason Wessel
14195d5314d6SJason Wessel /* Clean up any keyboard devices before leaving */
14208f30d411SAndrei Warkentin kdb_kbd_cleanup_state();
14218f30d411SAndrei Warkentin
14228f30d411SAndrei Warkentin return result;
14235d5314d6SJason Wessel }
14245d5314d6SJason Wessel
14255d5314d6SJason Wessel /*
14265d5314d6SJason Wessel * kdb_mdr - This function implements the guts of the 'mdr', memory
14275d5314d6SJason Wessel * read command.
14285d5314d6SJason Wessel * mdr <addr arg>,<byte count>
14295d5314d6SJason Wessel * Inputs:
14305d5314d6SJason Wessel * addr Start address
14315d5314d6SJason Wessel * count Number of bytes
14325d5314d6SJason Wessel * Returns:
14335d5314d6SJason Wessel * Always 0. Any errors are detected and printed by kdb_getarea.
14345d5314d6SJason Wessel */
kdb_mdr(unsigned long addr,unsigned int count)14355d5314d6SJason Wessel static int kdb_mdr(unsigned long addr, unsigned int count)
14365d5314d6SJason Wessel {
14375d5314d6SJason Wessel unsigned char c;
14385d5314d6SJason Wessel while (count--) {
14395d5314d6SJason Wessel if (kdb_getarea(c, addr))
14405d5314d6SJason Wessel return 0;
14415d5314d6SJason Wessel kdb_printf("%02x", c);
14425d5314d6SJason Wessel addr++;
14435d5314d6SJason Wessel }
14445d5314d6SJason Wessel kdb_printf("\n");
14455d5314d6SJason Wessel return 0;
14465d5314d6SJason Wessel }
14475d5314d6SJason Wessel
14485d5314d6SJason Wessel /*
14495d5314d6SJason Wessel * kdb_md - This function implements the 'md', 'md1', 'md2', 'md4',
14505d5314d6SJason Wessel * 'md8' 'mdr' and 'mds' commands.
14515d5314d6SJason Wessel *
14525d5314d6SJason Wessel * md|mds [<addr arg> [<line count> [<radix>]]]
14535d5314d6SJason Wessel * mdWcN [<addr arg> [<line count> [<radix>]]]
14545d5314d6SJason Wessel * where W = is the width (1, 2, 4 or 8) and N is the count.
14555d5314d6SJason Wessel * for eg., md1c20 reads 20 bytes, 1 at a time.
14565d5314d6SJason Wessel * mdr <addr arg>,<byte count>
14575d5314d6SJason Wessel */
kdb_md_line(const char * fmtstr,unsigned long addr,int symbolic,int nosect,int bytesperword,int num,int repeat,int phys)14585d5314d6SJason Wessel static void kdb_md_line(const char *fmtstr, unsigned long addr,
14595d5314d6SJason Wessel int symbolic, int nosect, int bytesperword,
14605d5314d6SJason Wessel int num, int repeat, int phys)
14615d5314d6SJason Wessel {
14625d5314d6SJason Wessel /* print just one line of data */
14635d5314d6SJason Wessel kdb_symtab_t symtab;
14645d5314d6SJason Wessel char cbuf[32];
14655d5314d6SJason Wessel char *c = cbuf;
14665d5314d6SJason Wessel int i;
14675d5314d6SJason Wessel int j;
14689eb62f0eSGustavo A. R. Silva unsigned long word;
14695d5314d6SJason Wessel
14705d5314d6SJason Wessel memset(cbuf, '\0', sizeof(cbuf));
14715d5314d6SJason Wessel if (phys)
14725d5314d6SJason Wessel kdb_printf("phys " kdb_machreg_fmt0 " ", addr);
14735d5314d6SJason Wessel else
14745d5314d6SJason Wessel kdb_printf(kdb_machreg_fmt0 " ", addr);
14755d5314d6SJason Wessel
14765d5314d6SJason Wessel for (i = 0; i < num && repeat--; i++) {
14775d5314d6SJason Wessel if (phys) {
14785d5314d6SJason Wessel if (kdb_getphysword(&word, addr, bytesperword))
14795d5314d6SJason Wessel break;
14805d5314d6SJason Wessel } else if (kdb_getword(&word, addr, bytesperword))
14815d5314d6SJason Wessel break;
14825d5314d6SJason Wessel kdb_printf(fmtstr, word);
14835d5314d6SJason Wessel if (symbolic)
14845d5314d6SJason Wessel kdbnearsym(word, &symtab);
14855d5314d6SJason Wessel else
14865d5314d6SJason Wessel memset(&symtab, 0, sizeof(symtab));
14875d5314d6SJason Wessel if (symtab.sym_name) {
14885d5314d6SJason Wessel kdb_symbol_print(word, &symtab, 0);
14895d5314d6SJason Wessel if (!nosect) {
14905d5314d6SJason Wessel kdb_printf("\n");
14915d5314d6SJason Wessel kdb_printf(" %s %s "
14925d5314d6SJason Wessel kdb_machreg_fmt " "
14935d5314d6SJason Wessel kdb_machreg_fmt " "
14945d5314d6SJason Wessel kdb_machreg_fmt, symtab.mod_name,
14955d5314d6SJason Wessel symtab.sec_name, symtab.sec_start,
14965d5314d6SJason Wessel symtab.sym_start, symtab.sym_end);
14975d5314d6SJason Wessel }
14985d5314d6SJason Wessel addr += bytesperword;
14995d5314d6SJason Wessel } else {
15005d5314d6SJason Wessel union {
15015d5314d6SJason Wessel u64 word;
15025d5314d6SJason Wessel unsigned char c[8];
15035d5314d6SJason Wessel } wc;
15045d5314d6SJason Wessel unsigned char *cp;
15055d5314d6SJason Wessel #ifdef __BIG_ENDIAN
15065d5314d6SJason Wessel cp = wc.c + 8 - bytesperword;
15075d5314d6SJason Wessel #else
15085d5314d6SJason Wessel cp = wc.c;
15095d5314d6SJason Wessel #endif
15105d5314d6SJason Wessel wc.word = word;
15115d5314d6SJason Wessel #define printable_char(c) \
15125d5314d6SJason Wessel ({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.'; })
15135d5314d6SJason Wessel for (j = 0; j < bytesperword; j++)
15149eb62f0eSGustavo A. R. Silva *c++ = printable_char(*cp++);
15155d5314d6SJason Wessel addr += bytesperword;
15169eb62f0eSGustavo A. R. Silva #undef printable_char
15175d5314d6SJason Wessel }
15185d5314d6SJason Wessel }
15195d5314d6SJason Wessel kdb_printf("%*s %s\n", (int)((num-i)*(2*bytesperword + 1)+1),
15205d5314d6SJason Wessel " ", cbuf);
15215d5314d6SJason Wessel }
15225d5314d6SJason Wessel
kdb_md(int argc,const char ** argv)15235d5314d6SJason Wessel static int kdb_md(int argc, const char **argv)
15245d5314d6SJason Wessel {
15255d5314d6SJason Wessel static unsigned long last_addr;
15265d5314d6SJason Wessel static int last_radix, last_bytesperword, last_repeat;
15275d5314d6SJason Wessel int radix = 16, mdcount = 8, bytesperword = KDB_WORD_SIZE, repeat;
15285d5314d6SJason Wessel int nosect = 0;
15295d5314d6SJason Wessel char fmtchar, fmtstr[64];
15305d5314d6SJason Wessel unsigned long addr;
15315d5314d6SJason Wessel unsigned long word;
15325d5314d6SJason Wessel long offset = 0;
15335d5314d6SJason Wessel int symbolic = 0;
15345d5314d6SJason Wessel int valid = 0;
15355d5314d6SJason Wessel int phys = 0;
15365d5314d6SJason Wessel int raw = 0;
15371e0ce03bSRandy Dunlap
15385d5314d6SJason Wessel kdbgetintenv("MDCOUNT", &mdcount);
15395d5314d6SJason Wessel kdbgetintenv("RADIX", &radix);
15405d5314d6SJason Wessel kdbgetintenv("BYTESPERWORD", &bytesperword);
15415d5314d6SJason Wessel
15425d5314d6SJason Wessel /* Assume 'md <addr>' and start with environment values */
15435d5314d6SJason Wessel repeat = mdcount * 16 / bytesperword;
15445d5314d6SJason Wessel
15455d5314d6SJason Wessel if (strcmp(argv[0], "mdr") == 0) {
15465d5314d6SJason Wessel if (argc == 2 || (argc == 0 && last_addr != 0))
15471e0ce03bSRandy Dunlap valid = raw = 1;
15481e0ce03bSRandy Dunlap else
15491e0ce03bSRandy Dunlap return KDB_ARGCOUNT;
15505d5314d6SJason Wessel } else if (isdigit(argv[0][2])) {
15515d5314d6SJason Wessel bytesperword = (int)(argv[0][2] - '0');
15525d5314d6SJason Wessel if (bytesperword == 0) {
15535d5314d6SJason Wessel bytesperword = last_bytesperword;
15545d5314d6SJason Wessel if (bytesperword == 0)
15555d5314d6SJason Wessel bytesperword = 4;
15565d5314d6SJason Wessel }
15575d5314d6SJason Wessel last_bytesperword = bytesperword;
15585d5314d6SJason Wessel repeat = mdcount * 16 / bytesperword;
15595d5314d6SJason Wessel if (!argv[0][3])
15605d5314d6SJason Wessel valid = 1;
15615d5314d6SJason Wessel else if (argv[0][3] == 'c' && argv[0][4]) {
15625d5314d6SJason Wessel if (kstrtouint(argv[0] + 4, 10, &repeat))
1563120fb87cSYuran Pereira return KDB_BADINT;
1564120fb87cSYuran Pereira mdcount = ((repeat * bytesperword) + 15) / 16;
15655d5314d6SJason Wessel valid = 1;
1566120fb87cSYuran Pereira }
15675d5314d6SJason Wessel last_repeat = repeat;
15685d5314d6SJason Wessel } else if (strcmp(argv[0], "md") == 0)
15695d5314d6SJason Wessel valid = 1;
15705d5314d6SJason Wessel else if (strcmp(argv[0], "mds") == 0)
15715d5314d6SJason Wessel valid = 1;
15725d5314d6SJason Wessel else if (strcmp(argv[0], "mdp") == 0) {
15735d5314d6SJason Wessel phys = valid = 1;
15745d5314d6SJason Wessel }
15755d5314d6SJason Wessel if (!valid)
15765d5314d6SJason Wessel return KDB_NOTFOUND;
15775d5314d6SJason Wessel
15785d5314d6SJason Wessel if (argc == 0) {
15795d5314d6SJason Wessel if (last_addr == 0)
15805d5314d6SJason Wessel return KDB_ARGCOUNT;
15815d5314d6SJason Wessel addr = last_addr;
15825d5314d6SJason Wessel radix = last_radix;
15835d5314d6SJason Wessel bytesperword = last_bytesperword;
15845d5314d6SJason Wessel repeat = last_repeat;
15855d5314d6SJason Wessel if (raw)
15861e0ce03bSRandy Dunlap mdcount = repeat;
15871e0ce03bSRandy Dunlap else
15881e0ce03bSRandy Dunlap mdcount = ((repeat * bytesperword) + 15) / 16;
15895d5314d6SJason Wessel }
15905d5314d6SJason Wessel
15915d5314d6SJason Wessel if (argc) {
15925d5314d6SJason Wessel unsigned long val;
15935d5314d6SJason Wessel int diag, nextarg = 1;
15945d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg, &addr,
15955d5314d6SJason Wessel &offset, NULL);
15965d5314d6SJason Wessel if (diag)
15975d5314d6SJason Wessel return diag;
15985d5314d6SJason Wessel if (argc > nextarg+2)
15995d5314d6SJason Wessel return KDB_ARGCOUNT;
16005d5314d6SJason Wessel
16015d5314d6SJason Wessel if (argc >= nextarg) {
16025d5314d6SJason Wessel diag = kdbgetularg(argv[nextarg], &val);
16035d5314d6SJason Wessel if (!diag) {
16045d5314d6SJason Wessel mdcount = (int) val;
16055d5314d6SJason Wessel if (raw)
16061e0ce03bSRandy Dunlap repeat = mdcount;
16071e0ce03bSRandy Dunlap else
16081e0ce03bSRandy Dunlap repeat = mdcount * 16 / bytesperword;
16095d5314d6SJason Wessel }
16105d5314d6SJason Wessel }
16115d5314d6SJason Wessel if (argc >= nextarg+1) {
16125d5314d6SJason Wessel diag = kdbgetularg(argv[nextarg+1], &val);
16135d5314d6SJason Wessel if (!diag)
16145d5314d6SJason Wessel radix = (int) val;
16155d5314d6SJason Wessel }
16165d5314d6SJason Wessel }
16175d5314d6SJason Wessel
16185d5314d6SJason Wessel if (strcmp(argv[0], "mdr") == 0) {
16191e0ce03bSRandy Dunlap int ret;
16201e0ce03bSRandy Dunlap last_addr = addr;
16211e0ce03bSRandy Dunlap ret = kdb_mdr(addr, mdcount);
16221e0ce03bSRandy Dunlap last_addr += mdcount;
16231e0ce03bSRandy Dunlap last_repeat = mdcount;
16241e0ce03bSRandy Dunlap last_bytesperword = bytesperword; // to make REPEAT happy
16251e0ce03bSRandy Dunlap return ret;
16261e0ce03bSRandy Dunlap }
16271e0ce03bSRandy Dunlap
16285d5314d6SJason Wessel switch (radix) {
16295d5314d6SJason Wessel case 10:
16305d5314d6SJason Wessel fmtchar = 'd';
16315d5314d6SJason Wessel break;
16325d5314d6SJason Wessel case 16:
16335d5314d6SJason Wessel fmtchar = 'x';
16345d5314d6SJason Wessel break;
16355d5314d6SJason Wessel case 8:
16365d5314d6SJason Wessel fmtchar = 'o';
16375d5314d6SJason Wessel break;
16385d5314d6SJason Wessel default:
16395d5314d6SJason Wessel return KDB_BADRADIX;
16405d5314d6SJason Wessel }
16415d5314d6SJason Wessel
16425d5314d6SJason Wessel last_radix = radix;
16435d5314d6SJason Wessel
16445d5314d6SJason Wessel if (bytesperword > KDB_WORD_SIZE)
16455d5314d6SJason Wessel return KDB_BADWIDTH;
16465d5314d6SJason Wessel
16475d5314d6SJason Wessel switch (bytesperword) {
16485d5314d6SJason Wessel case 8:
16495d5314d6SJason Wessel sprintf(fmtstr, "%%16.16l%c ", fmtchar);
16505d5314d6SJason Wessel break;
16515d5314d6SJason Wessel case 4:
16525d5314d6SJason Wessel sprintf(fmtstr, "%%8.8l%c ", fmtchar);
16535d5314d6SJason Wessel break;
16545d5314d6SJason Wessel case 2:
16555d5314d6SJason Wessel sprintf(fmtstr, "%%4.4l%c ", fmtchar);
16565d5314d6SJason Wessel break;
16575d5314d6SJason Wessel case 1:
16585d5314d6SJason Wessel sprintf(fmtstr, "%%2.2l%c ", fmtchar);
16595d5314d6SJason Wessel break;
16605d5314d6SJason Wessel default:
16615d5314d6SJason Wessel return KDB_BADWIDTH;
16625d5314d6SJason Wessel }
16635d5314d6SJason Wessel
16645d5314d6SJason Wessel last_repeat = repeat;
16655d5314d6SJason Wessel last_bytesperword = bytesperword;
16665d5314d6SJason Wessel
16675d5314d6SJason Wessel if (strcmp(argv[0], "mds") == 0) {
16685d5314d6SJason Wessel symbolic = 1;
16695d5314d6SJason Wessel /* Do not save these changes as last_*, they are temporary mds
16705d5314d6SJason Wessel * overrides.
16715d5314d6SJason Wessel */
16725d5314d6SJason Wessel bytesperword = KDB_WORD_SIZE;
16735d5314d6SJason Wessel repeat = mdcount;
16745d5314d6SJason Wessel kdbgetintenv("NOSECT", &nosect);
16755d5314d6SJason Wessel }
16765d5314d6SJason Wessel
16775d5314d6SJason Wessel /* Round address down modulo BYTESPERWORD */
16785d5314d6SJason Wessel
16795d5314d6SJason Wessel addr &= ~(bytesperword-1);
16805d5314d6SJason Wessel
16815d5314d6SJason Wessel while (repeat > 0) {
16825d5314d6SJason Wessel unsigned long a;
16835d5314d6SJason Wessel int n, z, num = (symbolic ? 1 : (16 / bytesperword));
16845d5314d6SJason Wessel
16855d5314d6SJason Wessel if (KDB_FLAG(CMD_INTERRUPT))
16865d5314d6SJason Wessel return 0;
16875d5314d6SJason Wessel for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) {
16885d5314d6SJason Wessel if (phys) {
16895d5314d6SJason Wessel if (kdb_getphysword(&word, a, bytesperword)
16905d5314d6SJason Wessel || word)
16915d5314d6SJason Wessel break;
16925d5314d6SJason Wessel } else if (kdb_getword(&word, a, bytesperword) || word)
16935d5314d6SJason Wessel break;
16945d5314d6SJason Wessel }
16955d5314d6SJason Wessel n = min(num, repeat);
16965d5314d6SJason Wessel kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword,
16975d5314d6SJason Wessel num, repeat, phys);
16985d5314d6SJason Wessel addr += bytesperword * n;
16995d5314d6SJason Wessel repeat -= n;
17005d5314d6SJason Wessel z = (z + num - 1) / num;
17015d5314d6SJason Wessel if (z > 2) {
17025d5314d6SJason Wessel int s = num * (z-2);
17035d5314d6SJason Wessel kdb_printf(kdb_machreg_fmt0 "-" kdb_machreg_fmt0
17045d5314d6SJason Wessel " zero suppressed\n",
17055d5314d6SJason Wessel addr, addr + bytesperword * s - 1);
17065d5314d6SJason Wessel addr += bytesperword * s;
17075d5314d6SJason Wessel repeat -= s;
17085d5314d6SJason Wessel }
17095d5314d6SJason Wessel }
17105d5314d6SJason Wessel last_addr = addr;
17115d5314d6SJason Wessel
17125d5314d6SJason Wessel return 0;
17135d5314d6SJason Wessel }
17145d5314d6SJason Wessel
17155d5314d6SJason Wessel /*
17165d5314d6SJason Wessel * kdb_mm - This function implements the 'mm' command.
17175d5314d6SJason Wessel * mm address-expression new-value
17185d5314d6SJason Wessel * Remarks:
17195d5314d6SJason Wessel * mm works on machine words, mmW works on bytes.
17205d5314d6SJason Wessel */
kdb_mm(int argc,const char ** argv)17215d5314d6SJason Wessel static int kdb_mm(int argc, const char **argv)
17225d5314d6SJason Wessel {
17235d5314d6SJason Wessel int diag;
17245d5314d6SJason Wessel unsigned long addr;
17255d5314d6SJason Wessel long offset = 0;
17265d5314d6SJason Wessel unsigned long contents;
17275d5314d6SJason Wessel int nextarg;
17285d5314d6SJason Wessel int width;
17295d5314d6SJason Wessel
17305d5314d6SJason Wessel if (argv[0][2] && !isdigit(argv[0][2]))
17315d5314d6SJason Wessel return KDB_NOTFOUND;
17325d5314d6SJason Wessel
17335d5314d6SJason Wessel if (argc < 2)
17345d5314d6SJason Wessel return KDB_ARGCOUNT;
17355d5314d6SJason Wessel
17365d5314d6SJason Wessel nextarg = 1;
17375d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
17385d5314d6SJason Wessel if (diag)
17395d5314d6SJason Wessel return diag;
17405d5314d6SJason Wessel
17415d5314d6SJason Wessel if (nextarg > argc)
17425d5314d6SJason Wessel return KDB_ARGCOUNT;
17435d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL);
17445d5314d6SJason Wessel if (diag)
17455d5314d6SJason Wessel return diag;
17465d5314d6SJason Wessel
17475d5314d6SJason Wessel if (nextarg != argc + 1)
17485d5314d6SJason Wessel return KDB_ARGCOUNT;
17495d5314d6SJason Wessel
17505d5314d6SJason Wessel width = argv[0][2] ? (argv[0][2] - '0') : (KDB_WORD_SIZE);
17515d5314d6SJason Wessel diag = kdb_putword(addr, contents, width);
17525d5314d6SJason Wessel if (diag)
17535d5314d6SJason Wessel return diag;
17545d5314d6SJason Wessel
17555d5314d6SJason Wessel kdb_printf(kdb_machreg_fmt " = " kdb_machreg_fmt "\n", addr, contents);
17565d5314d6SJason Wessel
17575d5314d6SJason Wessel return 0;
17585d5314d6SJason Wessel }
17595d5314d6SJason Wessel
17605d5314d6SJason Wessel /*
17615d5314d6SJason Wessel * kdb_go - This function implements the 'go' command.
17625d5314d6SJason Wessel * go [address-expression]
17635d5314d6SJason Wessel */
kdb_go(int argc,const char ** argv)17645d5314d6SJason Wessel static int kdb_go(int argc, const char **argv)
17655d5314d6SJason Wessel {
17665d5314d6SJason Wessel unsigned long addr;
17675d5314d6SJason Wessel int diag;
17685d5314d6SJason Wessel int nextarg;
17695d5314d6SJason Wessel long offset;
17705d5314d6SJason Wessel
17715d5314d6SJason Wessel if (raw_smp_processor_id() != kdb_initial_cpu) {
17725d5314d6SJason Wessel kdb_printf("go must execute on the entry cpu, "
1773495363d3SJason Wessel "please use \"cpu %d\" and then execute go\n",
1774495363d3SJason Wessel kdb_initial_cpu);
17755d5314d6SJason Wessel return KDB_BADCPUNUM;
1776495363d3SJason Wessel }
17775d5314d6SJason Wessel if (argc == 1) {
1778495363d3SJason Wessel nextarg = 1;
17795d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg,
17805d5314d6SJason Wessel &addr, &offset, NULL);
17815d5314d6SJason Wessel if (diag)
17825d5314d6SJason Wessel return diag;
17835d5314d6SJason Wessel } else if (argc) {
17845d5314d6SJason Wessel return KDB_ARGCOUNT;
17855d5314d6SJason Wessel }
17865d5314d6SJason Wessel
17875d5314d6SJason Wessel diag = KDB_CMD_GO;
17885d5314d6SJason Wessel if (KDB_FLAG(CATASTROPHIC)) {
17895d5314d6SJason Wessel kdb_printf("Catastrophic error detected\n");
17905d5314d6SJason Wessel kdb_printf("kdb_continue_catastrophic=%d, ",
17915d5314d6SJason Wessel kdb_continue_catastrophic);
17925d5314d6SJason Wessel if (kdb_continue_catastrophic == 0 && kdb_go_count++ == 0) {
17935d5314d6SJason Wessel kdb_printf("type go a second time if you really want "
17945d5314d6SJason Wessel "to continue\n");
17955d5314d6SJason Wessel return 0;
17965d5314d6SJason Wessel }
17975d5314d6SJason Wessel if (kdb_continue_catastrophic == 2) {
17985d5314d6SJason Wessel kdb_printf("forcing reboot\n");
17995d5314d6SJason Wessel kdb_reboot(0, NULL);
18005d5314d6SJason Wessel }
18015d5314d6SJason Wessel kdb_printf("attempting to continue\n");
18025d5314d6SJason Wessel }
18035d5314d6SJason Wessel return diag;
18045d5314d6SJason Wessel }
18055d5314d6SJason Wessel
18065d5314d6SJason Wessel /*
18075d5314d6SJason Wessel * kdb_rd - This function implements the 'rd' command.
18085d5314d6SJason Wessel */
kdb_rd(int argc,const char ** argv)18095d5314d6SJason Wessel static int kdb_rd(int argc, const char **argv)
18105d5314d6SJason Wessel {
18115d5314d6SJason Wessel int len = kdb_check_regs();
1812fcf2736cSDaniel Thompson #if DBG_MAX_REG_NUM > 0
1813fcf2736cSDaniel Thompson int i;
1814534af108SJason Wessel char *rname;
1815534af108SJason Wessel int rsize;
1816534af108SJason Wessel u64 reg64;
1817534af108SJason Wessel u32 reg32;
1818534af108SJason Wessel u16 reg16;
1819534af108SJason Wessel u8 reg8;
1820534af108SJason Wessel
1821534af108SJason Wessel if (len)
1822fcf2736cSDaniel Thompson return len;
1823fcf2736cSDaniel Thompson
1824534af108SJason Wessel for (i = 0; i < DBG_MAX_REG_NUM; i++) {
1825534af108SJason Wessel rsize = dbg_reg_def[i].size * 2;
1826534af108SJason Wessel if (rsize > 16)
1827534af108SJason Wessel rsize = 2;
1828534af108SJason Wessel if (len + strlen(dbg_reg_def[i].name) + 4 + rsize > 80) {
1829534af108SJason Wessel len = 0;
1830534af108SJason Wessel kdb_printf("\n");
1831534af108SJason Wessel }
1832534af108SJason Wessel if (len)
1833534af108SJason Wessel len += kdb_printf(" ");
1834534af108SJason Wessel switch(dbg_reg_def[i].size * 8) {
1835534af108SJason Wessel case 8:
1836534af108SJason Wessel rname = dbg_get_reg(i, ®8, kdb_current_regs);
1837534af108SJason Wessel if (!rname)
1838534af108SJason Wessel break;
1839534af108SJason Wessel len += kdb_printf("%s: %02x", rname, reg8);
1840534af108SJason Wessel break;
1841534af108SJason Wessel case 16:
1842534af108SJason Wessel rname = dbg_get_reg(i, ®16, kdb_current_regs);
1843534af108SJason Wessel if (!rname)
1844534af108SJason Wessel break;
1845534af108SJason Wessel len += kdb_printf("%s: %04x", rname, reg16);
1846534af108SJason Wessel break;
1847534af108SJason Wessel case 32:
1848534af108SJason Wessel rname = dbg_get_reg(i, ®32, kdb_current_regs);
1849534af108SJason Wessel if (!rname)
1850534af108SJason Wessel break;
1851534af108SJason Wessel len += kdb_printf("%s: %08x", rname, reg32);
1852534af108SJason Wessel break;
1853534af108SJason Wessel case 64:
1854534af108SJason Wessel rname = dbg_get_reg(i, ®64, kdb_current_regs);
1855534af108SJason Wessel if (!rname)
1856534af108SJason Wessel break;
1857534af108SJason Wessel len += kdb_printf("%s: %016llx", rname, reg64);
1858534af108SJason Wessel break;
1859534af108SJason Wessel default:
1860534af108SJason Wessel len += kdb_printf("%s: ??", dbg_reg_def[i].name);
1861534af108SJason Wessel }
1862534af108SJason Wessel }
1863534af108SJason Wessel kdb_printf("\n");
1864534af108SJason Wessel #else
1865fcf2736cSDaniel Thompson if (len)
1866fcf2736cSDaniel Thompson return len;
1867fcf2736cSDaniel Thompson
18685d5314d6SJason Wessel kdb_dumpregs(kdb_current_regs);
1869fcf2736cSDaniel Thompson #endif
1870fcf2736cSDaniel Thompson return 0;
18715d5314d6SJason Wessel }
18725d5314d6SJason Wessel
18735d5314d6SJason Wessel /*
18745d5314d6SJason Wessel * kdb_rm - This function implements the 'rm' (register modify) command.
18755d5314d6SJason Wessel * rm register-name new-contents
18765d5314d6SJason Wessel * Remarks:
18775d5314d6SJason Wessel * Allows register modification with the same restrictions as gdb
1878534af108SJason Wessel */
kdb_rm(int argc,const char ** argv)18795d5314d6SJason Wessel static int kdb_rm(int argc, const char **argv)
18805d5314d6SJason Wessel {
18815d5314d6SJason Wessel #if DBG_MAX_REG_NUM > 0
1882534af108SJason Wessel int diag;
18835d5314d6SJason Wessel const char *rname;
1884534af108SJason Wessel int i;
1885534af108SJason Wessel u64 reg64;
1886534af108SJason Wessel u32 reg32;
1887534af108SJason Wessel u16 reg16;
1888534af108SJason Wessel u8 reg8;
1889534af108SJason Wessel
18905d5314d6SJason Wessel if (argc != 2)
18915d5314d6SJason Wessel return KDB_ARGCOUNT;
18925d5314d6SJason Wessel /*
18935d5314d6SJason Wessel * Allow presence or absence of leading '%' symbol.
18945d5314d6SJason Wessel */
18955d5314d6SJason Wessel rname = argv[1];
1896534af108SJason Wessel if (*rname == '%')
1897534af108SJason Wessel rname++;
1898534af108SJason Wessel
18995d5314d6SJason Wessel diag = kdbgetu64arg(argv[2], ®64);
1900534af108SJason Wessel if (diag)
19015d5314d6SJason Wessel return diag;
19025d5314d6SJason Wessel
19035d5314d6SJason Wessel diag = kdb_check_regs();
1904fcf2736cSDaniel Thompson if (diag)
1905fcf2736cSDaniel Thompson return diag;
1906fcf2736cSDaniel Thompson
1907534af108SJason Wessel diag = KDB_BADREG;
1908534af108SJason Wessel for (i = 0; i < DBG_MAX_REG_NUM; i++) {
1909534af108SJason Wessel if (strcmp(rname, dbg_reg_def[i].name) == 0) {
1910534af108SJason Wessel diag = 0;
1911534af108SJason Wessel break;
1912534af108SJason Wessel }
1913534af108SJason Wessel }
1914534af108SJason Wessel if (!diag) {
1915534af108SJason Wessel switch(dbg_reg_def[i].size * 8) {
1916534af108SJason Wessel case 8:
1917534af108SJason Wessel reg8 = reg64;
1918534af108SJason Wessel dbg_set_reg(i, ®8, kdb_current_regs);
1919534af108SJason Wessel break;
1920534af108SJason Wessel case 16:
1921534af108SJason Wessel reg16 = reg64;
1922534af108SJason Wessel dbg_set_reg(i, ®16, kdb_current_regs);
1923534af108SJason Wessel break;
1924534af108SJason Wessel case 32:
1925534af108SJason Wessel reg32 = reg64;
1926534af108SJason Wessel dbg_set_reg(i, ®32, kdb_current_regs);
1927534af108SJason Wessel break;
1928534af108SJason Wessel case 64:
1929534af108SJason Wessel dbg_set_reg(i, ®64, kdb_current_regs);
1930534af108SJason Wessel break;
1931534af108SJason Wessel }
1932534af108SJason Wessel }
1933534af108SJason Wessel return diag;
1934534af108SJason Wessel #else
1935534af108SJason Wessel kdb_printf("ERROR: Register set currently not implemented\n");
19365d5314d6SJason Wessel return 0;
19375d5314d6SJason Wessel #endif
1938534af108SJason Wessel }
19395d5314d6SJason Wessel
19405d5314d6SJason Wessel #if defined(CONFIG_MAGIC_SYSRQ)
19415d5314d6SJason Wessel /*
19425d5314d6SJason Wessel * kdb_sr - This function implements the 'sr' (SYSRQ key) command
19435d5314d6SJason Wessel * which interfaces to the soi-disant MAGIC SYSRQ functionality.
19445d5314d6SJason Wessel * sr <magic-sysrq-code>
19455d5314d6SJason Wessel */
kdb_sr(int argc,const char ** argv)19465d5314d6SJason Wessel static int kdb_sr(int argc, const char **argv)
19475d5314d6SJason Wessel {
19485d5314d6SJason Wessel bool check_mask =
1949420c2b1bSAnton Vorontsov !kdb_check_flags(KDB_ENABLE_ALL, kdb_cmd_enabled, false);
1950420c2b1bSAnton Vorontsov
1951420c2b1bSAnton Vorontsov if (argc != 1)
19525d5314d6SJason Wessel return KDB_ARGCOUNT;
19535d5314d6SJason Wessel
1954420c2b1bSAnton Vorontsov kdb_trap_printk++;
1955d37d39aeSJason Wessel __handle_sysrq(*argv[1], check_mask);
1956420c2b1bSAnton Vorontsov kdb_trap_printk--;
1957d37d39aeSJason Wessel
19585d5314d6SJason Wessel return 0;
19595d5314d6SJason Wessel }
19605d5314d6SJason Wessel #endif /* CONFIG_MAGIC_SYSRQ */
19615d5314d6SJason Wessel
19625d5314d6SJason Wessel /*
19635d5314d6SJason Wessel * kdb_ef - This function implements the 'regs' (display exception
19645d5314d6SJason Wessel * frame) command. This command takes an address and expects to
19655d5314d6SJason Wessel * find an exception frame at that address, formats and prints
19665d5314d6SJason Wessel * it.
19675d5314d6SJason Wessel * regs address-expression
19685d5314d6SJason Wessel * Remarks:
19695d5314d6SJason Wessel * Not done yet.
19705d5314d6SJason Wessel */
kdb_ef(int argc,const char ** argv)19715d5314d6SJason Wessel static int kdb_ef(int argc, const char **argv)
19725d5314d6SJason Wessel {
19735d5314d6SJason Wessel int diag;
19745d5314d6SJason Wessel unsigned long addr;
19755d5314d6SJason Wessel long offset;
19765d5314d6SJason Wessel int nextarg;
19775d5314d6SJason Wessel
19785d5314d6SJason Wessel if (argc != 1)
19795d5314d6SJason Wessel return KDB_ARGCOUNT;
19805d5314d6SJason Wessel
19815d5314d6SJason Wessel nextarg = 1;
19825d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL);
19835d5314d6SJason Wessel if (diag)
19845d5314d6SJason Wessel return diag;
19855d5314d6SJason Wessel show_regs((struct pt_regs *)addr);
19865d5314d6SJason Wessel return 0;
19875d5314d6SJason Wessel }
19885d5314d6SJason Wessel
19895d5314d6SJason Wessel /*
19905d5314d6SJason Wessel * kdb_env - This function implements the 'env' command. Display the
19915d5314d6SJason Wessel * current environment variables.
19925d5314d6SJason Wessel */
19935d5314d6SJason Wessel
kdb_env(int argc,const char ** argv)19945d5314d6SJason Wessel static int kdb_env(int argc, const char **argv)
19955d5314d6SJason Wessel {
19965d5314d6SJason Wessel kdb_printenv();
199783fa2d13SSumit Garg
19985d5314d6SJason Wessel if (KDB_DEBUG(MASK))
19995d5314d6SJason Wessel kdb_printf("KDBDEBUG=0x%x\n",
2000c893de12SWei Li (kdb_flags & KDB_DEBUG(MASK)) >> KDB_DEBUG_FLAG_SHIFT);
2001c893de12SWei Li
20025d5314d6SJason Wessel return 0;
20035d5314d6SJason Wessel }
20045d5314d6SJason Wessel
20055d5314d6SJason Wessel #ifdef CONFIG_PRINTK
20065d5314d6SJason Wessel /*
20075d5314d6SJason Wessel * kdb_dmesg - This function implements the 'dmesg' command to display
20085d5314d6SJason Wessel * the contents of the syslog buffer.
20095d5314d6SJason Wessel * dmesg [lines] [adjust]
20105d5314d6SJason Wessel */
kdb_dmesg(int argc,const char ** argv)20115d5314d6SJason Wessel static int kdb_dmesg(int argc, const char **argv)
20125d5314d6SJason Wessel {
20135d5314d6SJason Wessel int diag;
2014bc792e61SAnton Vorontsov int logging;
2015bc792e61SAnton Vorontsov int lines = 0;
2016bc792e61SAnton Vorontsov int adjust = 0;
2017bc792e61SAnton Vorontsov int n = 0;
2018bc792e61SAnton Vorontsov int skip = 0;
2019bc792e61SAnton Vorontsov struct kmsg_dump_iter iter;
2020f9f3f02dSJohn Ogness size_t len;
2021bc792e61SAnton Vorontsov char buf[201];
2022bc792e61SAnton Vorontsov
20235d5314d6SJason Wessel if (argc > 2)
20245d5314d6SJason Wessel return KDB_ARGCOUNT;
20255d5314d6SJason Wessel if (argc) {
20265d5314d6SJason Wessel if (kstrtoint(argv[1], 0, &lines))
2027120fb87cSYuran Pereira lines = 0;
20285d5314d6SJason Wessel if (argc > 1 && (kstrtoint(argv[2], 0, &adjust) || adjust < 0))
2029120fb87cSYuran Pereira adjust = 0;
20305d5314d6SJason Wessel }
20315d5314d6SJason Wessel
20325d5314d6SJason Wessel /* disable LOGGING if set */
20335d5314d6SJason Wessel diag = kdbgetintenv("LOGGING", &logging);
20345d5314d6SJason Wessel if (!diag && logging) {
20355d5314d6SJason Wessel const char *setargs[] = { "set", "LOGGING", "0" };
20365d5314d6SJason Wessel kdb_set(2, setargs);
20375d5314d6SJason Wessel }
20385d5314d6SJason Wessel
20395d5314d6SJason Wessel kmsg_dump_rewind(&iter);
2040a4f98765SJohn Ogness while (kmsg_dump_get_line(&iter, 1, NULL, 0, NULL))
2041a4f98765SJohn Ogness n++;
2042bc792e61SAnton Vorontsov
2043bc792e61SAnton Vorontsov if (lines < 0) {
20445d5314d6SJason Wessel if (adjust >= n)
20455d5314d6SJason Wessel kdb_printf("buffer only contains %d lines, nothing "
20465d5314d6SJason Wessel "printed\n", n);
20475d5314d6SJason Wessel else if (adjust - lines >= n)
20485d5314d6SJason Wessel kdb_printf("buffer only contains %d lines, last %d "
20495d5314d6SJason Wessel "lines printed\n", n, n - adjust);
20505d5314d6SJason Wessel skip = adjust;
2051bc792e61SAnton Vorontsov lines = abs(lines);
2052bc792e61SAnton Vorontsov } else if (lines > 0) {
20535d5314d6SJason Wessel skip = n - lines - adjust;
2054bc792e61SAnton Vorontsov lines = abs(lines);
2055bc792e61SAnton Vorontsov if (adjust >= n) {
20565d5314d6SJason Wessel kdb_printf("buffer only contains %d lines, "
20575d5314d6SJason Wessel "nothing printed\n", n);
20585d5314d6SJason Wessel skip = n;
20595d5314d6SJason Wessel } else if (skip < 0) {
20605d5314d6SJason Wessel lines += skip;
20615d5314d6SJason Wessel skip = 0;
20625d5314d6SJason Wessel kdb_printf("buffer only contains %d lines, first "
20635d5314d6SJason Wessel "%d lines printed\n", n, lines);
20645d5314d6SJason Wessel }
20655d5314d6SJason Wessel } else {
2066bc792e61SAnton Vorontsov lines = n;
2067bc792e61SAnton Vorontsov }
20685d5314d6SJason Wessel
2069bc792e61SAnton Vorontsov if (skip >= n || skip < 0)
2070bc792e61SAnton Vorontsov return 0;
20715d5314d6SJason Wessel
2072bc792e61SAnton Vorontsov kmsg_dump_rewind(&iter);
2073a4f98765SJohn Ogness while (kmsg_dump_get_line(&iter, 1, buf, sizeof(buf), &len)) {
2074a4f98765SJohn Ogness if (skip) {
2075bc792e61SAnton Vorontsov skip--;
2076bc792e61SAnton Vorontsov continue;
2077bc792e61SAnton Vorontsov }
2078bc792e61SAnton Vorontsov if (!lines--)
2079bc792e61SAnton Vorontsov break;
20805d5314d6SJason Wessel if (KDB_FLAG(CMD_INTERRUPT))
2081d1871b38SJason Wessel return 0;
2082d1871b38SJason Wessel
2083bc792e61SAnton Vorontsov kdb_printf("%.*s\n", (int)len - 1, buf);
2084bc792e61SAnton Vorontsov }
20855d5314d6SJason Wessel
20865d5314d6SJason Wessel return 0;
20875d5314d6SJason Wessel }
20885d5314d6SJason Wessel #endif /* CONFIG_PRINTK */
20895d5314d6SJason Wessel /*
2090ad394f66SAnton Vorontsov * kdb_cpu - This function implements the 'cpu' command.
2091ad394f66SAnton Vorontsov * cpu [<cpunum>]
2092ad394f66SAnton Vorontsov * Returns:
2093ad394f66SAnton Vorontsov * KDB_CMD_CPU for success, a kdb diagnostic if error
2094ad394f66SAnton Vorontsov */
kdb_cpu_status(void)2095ad394f66SAnton Vorontsov static void kdb_cpu_status(void)
2096ad394f66SAnton Vorontsov {
2097ad394f66SAnton Vorontsov int i, start_cpu, first_print = 1;
2098ad394f66SAnton Vorontsov char state, prev_state = '?';
2099ad394f66SAnton Vorontsov
2100ad394f66SAnton Vorontsov kdb_printf("Currently on cpu %d\n", raw_smp_processor_id());
2101ad394f66SAnton Vorontsov kdb_printf("Available cpus: ");
2102ad394f66SAnton Vorontsov for (start_cpu = -1, i = 0; i < NR_CPUS; i++) {
2103ad394f66SAnton Vorontsov if (!cpu_online(i)) {
2104ad394f66SAnton Vorontsov state = 'F'; /* cpu is offline */
2105ad394f66SAnton Vorontsov } else if (!kgdb_info[i].enter_kgdb) {
2106ad394f66SAnton Vorontsov state = 'D'; /* cpu is online but unresponsive */
2107ad394f66SAnton Vorontsov } else {
2108ad394f66SAnton Vorontsov state = ' '; /* cpu is responding to kdb */
2109ad394f66SAnton Vorontsov if (kdb_task_state_char(KDB_TSK(i)) == '-')
2110ad394f66SAnton Vorontsov state = '-'; /* idle task */
2111ad394f66SAnton Vorontsov }
2112ad394f66SAnton Vorontsov if (state != prev_state) {
2113ad394f66SAnton Vorontsov if (prev_state != '?') {
2114ad394f66SAnton Vorontsov if (!first_print)
2115ad394f66SAnton Vorontsov kdb_printf(", ");
21165d5314d6SJason Wessel first_print = 0;
21175d5314d6SJason Wessel kdb_printf("%d", start_cpu);
21185d5314d6SJason Wessel if (start_cpu < i-1)
21195d5314d6SJason Wessel kdb_printf("-%d", i-1);
21205d5314d6SJason Wessel if (prev_state != ' ')
21215d5314d6SJason Wessel kdb_printf("(%c)", prev_state);
21225d5314d6SJason Wessel }
21235d5314d6SJason Wessel prev_state = state;
21245d5314d6SJason Wessel start_cpu = i;
21255d5314d6SJason Wessel }
21265d5314d6SJason Wessel }
21275d5314d6SJason Wessel /* print the trailing cpus, ignoring them if they are all offline */
21285d5314d6SJason Wessel if (prev_state != 'F') {
21295d5314d6SJason Wessel if (!first_print)
21305d5314d6SJason Wessel kdb_printf(", ");
21315d5314d6SJason Wessel kdb_printf("%d", start_cpu);
2132a1465d2fSDaniel Thompson if (start_cpu < i-1)
2133a1465d2fSDaniel Thompson kdb_printf("-%d", i-1);
21345d5314d6SJason Wessel if (prev_state != ' ')
21355d5314d6SJason Wessel kdb_printf("(%c)", prev_state);
2136b77dbc86SDaniel Thompson }
2137b77dbc86SDaniel Thompson kdb_printf("\n");
21385d5314d6SJason Wessel }
21395d5314d6SJason Wessel
kdb_cpu(int argc,const char ** argv)21405d5314d6SJason Wessel static int kdb_cpu(int argc, const char **argv)
21415d5314d6SJason Wessel {
21425d5314d6SJason Wessel unsigned long cpunum;
21435d5314d6SJason Wessel int diag;
21445d5314d6SJason Wessel
21455d5314d6SJason Wessel if (argc == 0) {
21465d5314d6SJason Wessel kdb_cpu_status();
21475d5314d6SJason Wessel return 0;
21485d5314d6SJason Wessel }
21495d5314d6SJason Wessel
21505d5314d6SJason Wessel if (argc != 1)
21515d5314d6SJason Wessel return KDB_ARGCOUNT;
21525d5314d6SJason Wessel
21535d5314d6SJason Wessel diag = kdbgetularg(argv[1], &cpunum);
21545d5314d6SJason Wessel if (diag)
21555d5314d6SJason Wessel return diag;
21565d5314d6SJason Wessel
21575d5314d6SJason Wessel /*
21585d5314d6SJason Wessel * Validate cpunum
21595d5314d6SJason Wessel */
21605d5314d6SJason Wessel if ((cpunum >= CONFIG_NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
21615d5314d6SJason Wessel return KDB_BADCPUNUM;
21625d5314d6SJason Wessel
21635d5314d6SJason Wessel dbg_switch_cpu = cpunum;
21645d5314d6SJason Wessel
21655d5314d6SJason Wessel /*
21665d5314d6SJason Wessel * Switch to other cpu
21675d5314d6SJason Wessel */
21685d5314d6SJason Wessel return KDB_CMD_CPU;
21695d5314d6SJason Wessel }
21705d5314d6SJason Wessel
21715d5314d6SJason Wessel /* The user may not realize that ps/bta with no parameters does not print idle
21725d5314d6SJason Wessel * or sleeping system daemon processes, so tell them how many were suppressed.
21735d5314d6SJason Wessel */
kdb_ps_suppressed(void)21745d5314d6SJason Wessel void kdb_ps_suppressed(void)
21755d5314d6SJason Wessel {
21765d5314d6SJason Wessel int idle = 0, daemon = 0;
21775d5314d6SJason Wessel unsigned long cpu;
21785d5314d6SJason Wessel const struct task_struct *p, *g;
21795d5314d6SJason Wessel for_each_online_cpu(cpu) {
21805d5314d6SJason Wessel p = curr_task(cpu);
21815d5314d6SJason Wessel if (kdb_task_state(p, "-"))
21825d5314d6SJason Wessel ++idle;
21835d5314d6SJason Wessel }
21845d5314d6SJason Wessel for_each_process_thread(g, p) {
21855d5314d6SJason Wessel if (kdb_task_state(p, "ims"))
21865d5314d6SJason Wessel ++daemon;
2187df0036d1SJason Wessel }
21885d5314d6SJason Wessel if (idle || daemon) {
21895d5314d6SJason Wessel if (idle)
21905d5314d6SJason Wessel kdb_printf("%d idle process%s (state -)%s\n",
21915d5314d6SJason Wessel idle, idle == 1 ? "" : "es",
21925d5314d6SJason Wessel daemon ? " and " : "");
21935d5314d6SJason Wessel if (daemon)
21945d5314d6SJason Wessel kdb_printf("%d sleeping system daemon (state [ims]) "
21955d5314d6SJason Wessel "process%s", daemon,
21965d5314d6SJason Wessel daemon == 1 ? "" : "es");
21975d5314d6SJason Wessel kdb_printf(" suppressed,\nuse 'ps A' to see all.\n");
21985d5314d6SJason Wessel }
21995d5314d6SJason Wessel }
22005d5314d6SJason Wessel
kdb_ps1(const struct task_struct * p)22015d5314d6SJason Wessel void kdb_ps1(const struct task_struct *p)
22025d5314d6SJason Wessel {
22035d5314d6SJason Wessel int cpu;
22045d5314d6SJason Wessel unsigned long tmp;
22055d5314d6SJason Wessel
22065d5314d6SJason Wessel if (!p ||
22079bccbe7bSZheng Zengkai copy_from_kernel_nofault(&tmp, (char *)p, sizeof(unsigned long)))
2208b77dbc86SDaniel Thompson return;
22095d5314d6SJason Wessel
22105d5314d6SJason Wessel cpu = kdb_process_cpu(p);
2211ece4ceafSDavidlohr Bueso kdb_printf("0x%px %8d %8d %d %4d %c 0x%px %c%s\n",
2212b77dbc86SDaniel Thompson (void *)p, p->pid, p->parent->pid,
22135d5314d6SJason Wessel kdb_task_has_cpu(p), kdb_process_cpu(p),
2214ece4ceafSDavidlohr Bueso kdb_task_state_char(p),
22155d5314d6SJason Wessel (void *)(&p->thread),
22165d5314d6SJason Wessel p == curr_task(raw_smp_processor_id()) ? '*' : ' ',
2217b77dbc86SDaniel Thompson p->comm);
22185d5314d6SJason Wessel if (kdb_task_has_cpu(p)) {
22195d5314d6SJason Wessel if (!KDB_TSK(cpu)) {
22205d5314d6SJason Wessel kdb_printf(" Error: no saved data for this cpu\n");
2221b77dbc86SDaniel Thompson } else {
22225d5314d6SJason Wessel if (KDB_TSK(cpu) != p)
22235d5314d6SJason Wessel kdb_printf(" Error: does not match running "
22245d5314d6SJason Wessel "process table (0x%px)\n", KDB_TSK(cpu));
22255d5314d6SJason Wessel }
22265d5314d6SJason Wessel }
22275d5314d6SJason Wessel }
22285d5314d6SJason Wessel
22295d5314d6SJason Wessel /*
22305d5314d6SJason Wessel * kdb_ps - This function implements the 'ps' command which shows a
22315d5314d6SJason Wessel * list of the active processes.
22325d5314d6SJason Wessel *
2233fe557319SChristoph Hellwig * ps [<state_chars>] Show processes, optionally selecting only those whose
2234fe557319SChristoph Hellwig * state character is found in <state_chars>.
22355d5314d6SJason Wessel */
kdb_ps(int argc,const char ** argv)22365d5314d6SJason Wessel static int kdb_ps(int argc, const char **argv)
22375d5314d6SJason Wessel {
2238568fb6f4SChristophe Leroy struct task_struct *g, *p;
22395d5314d6SJason Wessel const char *mask;
22405d5314d6SJason Wessel unsigned long cpu;
22415d5314d6SJason Wessel
22425d5314d6SJason Wessel if (argc == 0)
22439bccbe7bSZheng Zengkai kdb_ps_suppressed();
22445d5314d6SJason Wessel kdb_printf("%-*s Pid Parent [*] cpu State %-*s Command\n",
22455d5314d6SJason Wessel (int)(2*sizeof(void *))+2, "Task Addr",
22465d5314d6SJason Wessel (int)(2*sizeof(void *))+2, "Thread");
22475d5314d6SJason Wessel mask = argc ? argv[1] : kdbgetenv("PS");
22485d5314d6SJason Wessel /* Run the active tasks first */
22495d5314d6SJason Wessel for_each_online_cpu(cpu) {
22505d5314d6SJason Wessel if (KDB_FLAG(CMD_INTERRUPT))
2251568fb6f4SChristophe Leroy return 0;
22525d5314d6SJason Wessel p = curr_task(cpu);
22535d5314d6SJason Wessel if (kdb_task_state(p, mask))
22545d5314d6SJason Wessel kdb_ps1(p);
22555d5314d6SJason Wessel }
2256b77dbc86SDaniel Thompson kdb_printf("\n");
2257b77dbc86SDaniel Thompson /* Now the real tasks */
2258b77dbc86SDaniel Thompson for_each_process_thread(g, p) {
2259b77dbc86SDaniel Thompson if (KDB_FLAG(CMD_INTERRUPT))
2260b77dbc86SDaniel Thompson return 0;
2261b77dbc86SDaniel Thompson if (kdb_task_state(p, mask))
2262b77dbc86SDaniel Thompson kdb_ps1(p);
22635d5314d6SJason Wessel }
22645d5314d6SJason Wessel
22655d5314d6SJason Wessel return 0;
2266b77dbc86SDaniel Thompson }
2267b77dbc86SDaniel Thompson
22685d5314d6SJason Wessel /*
22695d5314d6SJason Wessel * kdb_pid - This function implements the 'pid' command which switches
22705d5314d6SJason Wessel * the currently active process.
22715d5314d6SJason Wessel * pid [<pid> | R]
22725d5314d6SJason Wessel */
kdb_pid(int argc,const char ** argv)22735d5314d6SJason Wessel static int kdb_pid(int argc, const char **argv)
2274b77dbc86SDaniel Thompson {
22755d5314d6SJason Wessel struct task_struct *p;
22765d5314d6SJason Wessel unsigned long val;
22775d5314d6SJason Wessel int diag;
22785d5314d6SJason Wessel
22799bccbe7bSZheng Zengkai if (argc > 1)
22805d5314d6SJason Wessel return KDB_ARGCOUNT;
22815d5314d6SJason Wessel
22825d5314d6SJason Wessel if (argc) {
22835d5314d6SJason Wessel if (strcmp(argv[1], "R") == 0) {
22845d5314d6SJason Wessel p = KDB_TSK(kdb_initial_cpu);
2285ece4ceafSDavidlohr Bueso } else {
22865d5314d6SJason Wessel diag = kdbgetularg(argv[1], &val);
22875d5314d6SJason Wessel if (diag)
22885d5314d6SJason Wessel return KDB_BADINT;
22895d5314d6SJason Wessel
2290ece4ceafSDavidlohr Bueso p = find_task_by_pid_ns((pid_t)val, &init_pid_ns);
22915d5314d6SJason Wessel if (!p) {
22925d5314d6SJason Wessel kdb_printf("No task with pid=%d\n", (pid_t)val);
22935d5314d6SJason Wessel return 0;
22945d5314d6SJason Wessel }
22955d5314d6SJason Wessel }
22965d5314d6SJason Wessel kdb_set_current_task(p);
22975d5314d6SJason Wessel }
22985d5314d6SJason Wessel kdb_printf("KDB current process is %s(pid=%d)\n",
22995d5314d6SJason Wessel kdb_current_task->comm,
23005d5314d6SJason Wessel kdb_current_task->pid);
23015d5314d6SJason Wessel
23025d5314d6SJason Wessel return 0;
23035d5314d6SJason Wessel }
23045d5314d6SJason Wessel
kdb_kgdb(int argc,const char ** argv)23055d5314d6SJason Wessel static int kdb_kgdb(int argc, const char **argv)
23065d5314d6SJason Wessel {
23075d5314d6SJason Wessel return KDB_CMD_KGDB;
23085d5314d6SJason Wessel }
23095d5314d6SJason Wessel
23105d5314d6SJason Wessel /*
23115d5314d6SJason Wessel * kdb_help - This function implements the 'help' and '?' commands.
23125d5314d6SJason Wessel */
kdb_help(int argc,const char ** argv)23135d5314d6SJason Wessel static int kdb_help(int argc, const char **argv)
23145d5314d6SJason Wessel {
23155d5314d6SJason Wessel kdbtab_t *kt;
23165d5314d6SJason Wessel
23175d5314d6SJason Wessel kdb_printf("%-15.15s %-20.20s %s\n", "Command", "Usage", "Description");
23185d5314d6SJason Wessel kdb_printf("-----------------------------"
23195d5314d6SJason Wessel "-----------------------------\n");
23205d5314d6SJason Wessel list_for_each_entry(kt, &kdb_cmds_head, list_node) {
23215d5314d6SJason Wessel char *space = "";
23225d5314d6SJason Wessel if (KDB_FLAG(CMD_INTERRUPT))
23235d5314d6SJason Wessel return 0;
23245d5314d6SJason Wessel if (!kdb_check_flags(kt->flags, kdb_cmd_enabled, true))
23255d5314d6SJason Wessel continue;
23265d5314d6SJason Wessel if (strlen(kt->usage) > 20)
23275d5314d6SJason Wessel space = "\n ";
23285d5314d6SJason Wessel kdb_printf("%-15.15s %-20s%s%s\n", kt->name,
23295d5314d6SJason Wessel kt->usage, space, kt->help);
23305d5314d6SJason Wessel }
23315d5314d6SJason Wessel return 0;
23325d5314d6SJason Wessel }
23335d5314d6SJason Wessel
23345d5314d6SJason Wessel /*
23355d5314d6SJason Wessel * kdb_kill - This function implements the 'kill' commands.
23365d5314d6SJason Wessel */
kdb_kill(int argc,const char ** argv)23375d5314d6SJason Wessel static int kdb_kill(int argc, const char **argv)
23385d5314d6SJason Wessel {
23395d5314d6SJason Wessel long sig, pid;
23405d5314d6SJason Wessel struct task_struct *p;
23415d5314d6SJason Wessel
23425d5314d6SJason Wessel if (argc != 2)
23435d5314d6SJason Wessel return KDB_ARGCOUNT;
23445d5314d6SJason Wessel
23455d5314d6SJason Wessel if (kstrtol(argv[1], 0, &sig))
23465d5314d6SJason Wessel return KDB_BADINT;
2347e4f291b3SSumit Garg if ((sig >= 0) || !valid_signal(-sig)) {
2348074604afSJason Wessel kdb_printf("Invalid signal parameter.<-signal>\n");
23495d5314d6SJason Wessel return 0;
23505d5314d6SJason Wessel }
2351e868f0a3SSumit Garg sig = -sig;
2352420c2b1bSAnton Vorontsov
2353e868f0a3SSumit Garg if (kstrtol(argv[2], 0, &pid))
2354074604afSJason Wessel return KDB_BADINT;
2355e868f0a3SSumit Garg if (pid <= 0) {
2356e868f0a3SSumit Garg kdb_printf("Process ID must be large than 0.\n");
23575d5314d6SJason Wessel return 0;
23585d5314d6SJason Wessel }
23595d5314d6SJason Wessel
23605d5314d6SJason Wessel /* Find the process. */
23615d5314d6SJason Wessel p = find_task_by_pid_ns(pid, &init_pid_ns);
23625d5314d6SJason Wessel if (!p) {
23635d5314d6SJason Wessel kdb_printf("The specified process isn't found.\n");
23645d5314d6SJason Wessel return 0;
23655d5314d6SJason Wessel }
23665d5314d6SJason Wessel p = p->group_leader;
23675d5314d6SJason Wessel kdb_send_sig(p, sig);
23685d5314d6SJason Wessel return 0;
23695d5314d6SJason Wessel }
23705d5314d6SJason Wessel
23715d5314d6SJason Wessel /*
2372120fb87cSYuran Pereira * Most of this code has been lifted from kernel/timer.c::sys_sysinfo().
23735d5314d6SJason Wessel * I cannot call that code directly from kdb, it has an unconditional
23740b44bf9aSEric W. Biederman * cli()/sti() and calls routines that take locks which can stop the debugger.
23755d5314d6SJason Wessel */
kdb_sysinfo(struct sysinfo * val)23765d5314d6SJason Wessel static void kdb_sysinfo(struct sysinfo *val)
23775d5314d6SJason Wessel {
23785d5314d6SJason Wessel u64 uptime = ktime_get_mono_fast_ns();
23795d5314d6SJason Wessel
2380120fb87cSYuran Pereira memset(val, 0, sizeof(*val));
23815d5314d6SJason Wessel val->uptime = div_u64(uptime, NSEC_PER_SEC);
23825d5314d6SJason Wessel val->loads[0] = avenrun[0];
23835d5314d6SJason Wessel val->loads[1] = avenrun[1];
23845d5314d6SJason Wessel val->loads[2] = avenrun[2];
23855d5314d6SJason Wessel val->procs = nr_threads-1;
23865d5314d6SJason Wessel si_meminfo(val);
23875d5314d6SJason Wessel
23885d5314d6SJason Wessel return;
23895d5314d6SJason Wessel }
23905d5314d6SJason Wessel
23915d5314d6SJason Wessel /*
23925d5314d6SJason Wessel * kdb_summary - This function implements the 'summary' command.
23935d5314d6SJason Wessel */
kdb_summary(int argc,const char ** argv)23940b44bf9aSEric W. Biederman static int kdb_summary(int argc, const char **argv)
23955d5314d6SJason Wessel {
23965d5314d6SJason Wessel time64_t now;
23975d5314d6SJason Wessel struct sysinfo val;
23985d5314d6SJason Wessel
23995d5314d6SJason Wessel if (argc)
24005d5314d6SJason Wessel return KDB_ARGCOUNT;
24015d5314d6SJason Wessel
24025d5314d6SJason Wessel kdb_printf("sysname %s\n", init_uts_ns.name.sysname);
24035d5314d6SJason Wessel kdb_printf("release %s\n", init_uts_ns.name.release);
24045d5314d6SJason Wessel kdb_printf("version %s\n", init_uts_ns.name.version);
240540b90efeSBaolin Wang kdb_printf("machine %s\n", init_uts_ns.name.machine);
240640b90efeSBaolin Wang kdb_printf("nodename %s\n", init_uts_ns.name.nodename);
24075d5314d6SJason Wessel kdb_printf("domainname %s\n", init_uts_ns.name.domainname);
240840b90efeSBaolin Wang
24095d5314d6SJason Wessel now = __ktime_get_real_seconds();
24105d5314d6SJason Wessel kdb_printf("date %ptTs tz_minuteswest %d\n", &now, sys_tz.tz_minuteswest);
24115d5314d6SJason Wessel kdb_sysinfo(&val);
24125d5314d6SJason Wessel kdb_printf("uptime ");
24135d5314d6SJason Wessel if (val.uptime > (24*60*60)) {
24145d5314d6SJason Wessel int days = val.uptime / (24*60*60);
24155d5314d6SJason Wessel val.uptime %= (24*60*60);
24165d5314d6SJason Wessel kdb_printf("%d day%s ", days, str_plural(days));
24175d5314d6SJason Wessel }
24185d5314d6SJason Wessel kdb_printf("%02ld:%02ld\n", val.uptime/(60*60), (val.uptime/60)%60);
24195d5314d6SJason Wessel
24205d5314d6SJason Wessel kdb_printf("load avg %ld.%02ld %ld.%02ld %ld.%02ld\n",
24215d5314d6SJason Wessel LOAD_INT(val.loads[0]), LOAD_FRAC(val.loads[0]),
24225d5314d6SJason Wessel LOAD_INT(val.loads[1]), LOAD_FRAC(val.loads[1]),
24236909e29fSArnd Bergmann LOAD_INT(val.loads[2]), LOAD_FRAC(val.loads[2]));
24245d5314d6SJason Wessel
24255d5314d6SJason Wessel /* Display in kilobytes */
24265d5314d6SJason Wessel #define K(x) ((x) << (PAGE_SHIFT - 10))
24275d5314d6SJason Wessel kdb_printf("\nMemTotal: %8lu kB\nMemFree: %8lu kB\n"
24285d5314d6SJason Wessel "Buffers: %8lu kB\n",
24295d5314d6SJason Wessel K(val.totalram), K(val.freeram), K(val.bufferram));
24305d5314d6SJason Wessel return 0;
24315d5314d6SJason Wessel }
24325d5314d6SJason Wessel
24335d5314d6SJason Wessel /*
24345d5314d6SJason Wessel * kdb_per_cpu - This function implements the 'per_cpu' command.
24355d5314d6SJason Wessel */
kdb_per_cpu(int argc,const char ** argv)24366909e29fSArnd Bergmann static int kdb_per_cpu(int argc, const char **argv)
2437126ac4d6SAndy Shevchenko {
24385d5314d6SJason Wessel char fmtstr[64];
24395d5314d6SJason Wessel int cpu, diag, nextarg = 1;
24405d5314d6SJason Wessel unsigned long addr, symaddr, val, bytesperword = 0, whichcpu = ~0UL;
24415d5314d6SJason Wessel
24425d5314d6SJason Wessel if (argc < 1 || argc > 3)
24435b6d8ef6SThorsten Blum return KDB_ARGCOUNT;
24445d5314d6SJason Wessel
24455d5314d6SJason Wessel diag = kdbgetaddrarg(argc, argv, &nextarg, &symaddr, NULL, NULL);
24465d5314d6SJason Wessel if (diag)
24475d5314d6SJason Wessel return diag;
24485d5314d6SJason Wessel
24495d5314d6SJason Wessel if (argc >= 2) {
24505d5314d6SJason Wessel diag = kdbgetularg(argv[2], &bytesperword);
24518508cf3fSJohannes Weiner if (diag)
24525d5314d6SJason Wessel return diag;
24535d5314d6SJason Wessel }
24545d5314d6SJason Wessel if (!bytesperword)
24555d5314d6SJason Wessel bytesperword = KDB_WORD_SIZE;
245614675592SJay Lan else if (bytesperword > KDB_WORD_SIZE)
24575d5314d6SJason Wessel return KDB_BADWIDTH;
24585d5314d6SJason Wessel sprintf(fmtstr, "%%0%dlx ", (int)(2*bytesperword));
24595d5314d6SJason Wessel if (argc >= 3) {
24605d5314d6SJason Wessel diag = kdbgetularg(argv[3], &whichcpu);
24615d5314d6SJason Wessel if (diag)
24625d5314d6SJason Wessel return diag;
24635d5314d6SJason Wessel if (whichcpu >= nr_cpu_ids || !cpu_online(whichcpu)) {
24645d5314d6SJason Wessel kdb_printf("cpu %ld is not online\n", whichcpu);
2465931ea248SJason Wessel return KDB_BADCPUNUM;
2466931ea248SJason Wessel }
2467931ea248SJason Wessel }
24685d5314d6SJason Wessel
24695d5314d6SJason Wessel /* Most architectures use __per_cpu_offset[cpu], some use
24705d5314d6SJason Wessel * __per_cpu_offset(cpu), smp has no __per_cpu_offset.
24715d5314d6SJason Wessel */
2472931ea248SJason Wessel #ifdef __per_cpu_offset
2473931ea248SJason Wessel #define KDB_PCU(cpu) __per_cpu_offset(cpu)
2474931ea248SJason Wessel #else
2475931ea248SJason Wessel #ifdef CONFIG_SMP
24765d5314d6SJason Wessel #define KDB_PCU(cpu) __per_cpu_offset[cpu]
24775d5314d6SJason Wessel #else
24785d5314d6SJason Wessel #define KDB_PCU(cpu) 0
24795d5314d6SJason Wessel #endif
24805d5314d6SJason Wessel #endif
24815d5314d6SJason Wessel for_each_online_cpu(cpu) {
24825d5314d6SJason Wessel if (KDB_FLAG(CMD_INTERRUPT))
24835d5314d6SJason Wessel return 0;
24845d5314d6SJason Wessel
24855d5314d6SJason Wessel if (whichcpu != ~0UL && whichcpu != cpu)
24865d5314d6SJason Wessel continue;
24875d5314d6SJason Wessel addr = symaddr + KDB_PCU(cpu);
24885d5314d6SJason Wessel diag = kdb_getword(&val, addr, bytesperword);
24895d5314d6SJason Wessel if (diag) {
2490b586627eSDan Carpenter kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to "
24915d5314d6SJason Wessel "read, diag=%d\n", cpu, addr, diag);
24925d5314d6SJason Wessel continue;
24935d5314d6SJason Wessel }
24945d5314d6SJason Wessel kdb_printf("%5d ", cpu);
24955d5314d6SJason Wessel kdb_md_line(fmtstr, addr,
24965d5314d6SJason Wessel bytesperword == KDB_WORD_SIZE,
24975d5314d6SJason Wessel 1, bytesperword, 1, 1, 0);
24985d5314d6SJason Wessel }
24995d5314d6SJason Wessel #undef KDB_PCU
25005d5314d6SJason Wessel return 0;
25015d5314d6SJason Wessel }
25025d5314d6SJason Wessel
25035d5314d6SJason Wessel /*
25045d5314d6SJason Wessel * display help for the use of cmd | grep pattern
25055d5314d6SJason Wessel */
kdb_grep_help(int argc,const char ** argv)25065d5314d6SJason Wessel static int kdb_grep_help(int argc, const char **argv)
25075d5314d6SJason Wessel {
25085d5314d6SJason Wessel kdb_printf("Usage of cmd args | grep pattern:\n");
2509931ea248SJason Wessel kdb_printf(" Any command's output may be filtered through an ");
2510931ea248SJason Wessel kdb_printf("emulated 'pipe'.\n");
2511931ea248SJason Wessel kdb_printf(" 'grep' is just a key word.\n");
25125d5314d6SJason Wessel kdb_printf(" The pattern may include a very limited set of "
25135d5314d6SJason Wessel "metacharacters:\n");
2514931ea248SJason Wessel kdb_printf(" pattern or ^pattern or pattern$ or ^pattern$\n");
25155d5314d6SJason Wessel kdb_printf(" And if there are spaces in the pattern, you may "
25165d5314d6SJason Wessel "quote it:\n");
25175d5314d6SJason Wessel kdb_printf(" \"pat tern\" or \"^pat tern\" or \"pat tern$\""
25185d5314d6SJason Wessel " or \"^pat tern$\"\n");
25195d5314d6SJason Wessel return 0;
25205d5314d6SJason Wessel }
25215d5314d6SJason Wessel
25225d5314d6SJason Wessel /**
25235d5314d6SJason Wessel * kdb_register() - This function is used to register a kernel debugger
25245d5314d6SJason Wessel * command.
25255d5314d6SJason Wessel * @cmd: pointer to kdb command
25265d5314d6SJason Wessel *
25275d5314d6SJason Wessel * Note that it's the job of the caller to keep the memory for the cmd
25285d5314d6SJason Wessel * allocated until unregister is called.
25295d5314d6SJason Wessel */
kdb_register(kdbtab_t * cmd)25305d5314d6SJason Wessel int kdb_register(kdbtab_t *cmd)
25315d5314d6SJason Wessel {
25325d5314d6SJason Wessel kdbtab_t *kp;
25335d5314d6SJason Wessel
25345d5314d6SJason Wessel list_for_each_entry(kp, &kdb_cmds_head, list_node) {
25355d5314d6SJason Wessel if (strcmp(kp->name, cmd->name) == 0) {
25365d5314d6SJason Wessel kdb_printf("Duplicate kdb cmd: %s, func %p help %s\n",
25375d5314d6SJason Wessel cmd->name, cmd->func, cmd->help);
25385d5314d6SJason Wessel return 1;
25395d5314d6SJason Wessel }
25405d5314d6SJason Wessel }
25415d5314d6SJason Wessel
25425d5314d6SJason Wessel list_add_tail(&cmd->list_node, &kdb_cmds_head);
25435d5314d6SJason Wessel return 0;
25445d5314d6SJason Wessel }
25455d5314d6SJason Wessel EXPORT_SYMBOL_GPL(kdb_register);
25465d5314d6SJason Wessel
25475d5314d6SJason Wessel /**
25485d5314d6SJason Wessel * kdb_register_table() - This function is used to register a kdb command
2549c25abcd6SSumit Garg * table.
2550c25abcd6SSumit Garg * @kp: pointer to kdb command table
2551c25abcd6SSumit Garg * @len: length of kdb command table
2552c25abcd6SSumit Garg */
kdb_register_table(kdbtab_t * kp,size_t len)2553c25abcd6SSumit Garg void kdb_register_table(kdbtab_t *kp, size_t len)
2554c25abcd6SSumit Garg {
2555c25abcd6SSumit Garg while (len--) {
25565d5314d6SJason Wessel list_add_tail(&kp->list_node, &kdb_cmds_head);
2557c25abcd6SSumit Garg kp++;
25585d5314d6SJason Wessel }
25595d5314d6SJason Wessel }
25605d5314d6SJason Wessel
2561e4f291b3SSumit Garg /**
2562e868f0a3SSumit Garg * kdb_unregister() - This function is used to unregister a kernel debugger
2563c25abcd6SSumit Garg * command. It is generally called when a module which
2564e868f0a3SSumit Garg * implements kdb command is unloaded.
25655d5314d6SJason Wessel * @cmd: pointer to kdb command
25665d5314d6SJason Wessel */
kdb_unregister(kdbtab_t * cmd)25675d5314d6SJason Wessel void kdb_unregister(kdbtab_t *cmd)
25685d5314d6SJason Wessel {
2569c25abcd6SSumit Garg list_del(&cmd->list_node);
25705d5314d6SJason Wessel }
25715d5314d6SJason Wessel EXPORT_SYMBOL_GPL(kdb_unregister);
2572c25abcd6SSumit Garg
2573f7030bbcSJason Wessel static kdbtab_t maintab[] = {
2574c25abcd6SSumit Garg { .name = "md",
2575e4f291b3SSumit Garg .func = kdb_md,
2576e4f291b3SSumit Garg .usage = "<vaddr>",
2577e4f291b3SSumit Garg .help = "Display Memory Contents, also mdWcN, e.g. md8c1",
2578e4f291b3SSumit Garg .minlen = 1,
2579e4f291b3SSumit Garg .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
2580e4f291b3SSumit Garg },
2581e4f291b3SSumit Garg { .name = "mdr",
2582e4f291b3SSumit Garg .func = kdb_md,
2583e4f291b3SSumit Garg .usage = "<vaddr> <bytes>",
2584e4f291b3SSumit Garg .help = "Display Raw Memory",
2585e4f291b3SSumit Garg .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
2586e4f291b3SSumit Garg },
25875d5314d6SJason Wessel { .name = "mdp",
2588c25abcd6SSumit Garg .func = kdb_md,
2589c25abcd6SSumit Garg .usage = "<paddr> <bytes>",
2590c25abcd6SSumit Garg .help = "Display Physical Memory",
2591c25abcd6SSumit Garg .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
2592c25abcd6SSumit Garg },
25935d5314d6SJason Wessel { .name = "mds",
2594c25abcd6SSumit Garg .func = kdb_md,
25955d5314d6SJason Wessel .usage = "<vaddr>",
2596c25abcd6SSumit Garg .help = "Display Memory Symbolically",
25975d5314d6SJason Wessel .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS,
2598f7030bbcSJason Wessel },
25995d5314d6SJason Wessel { .name = "mm",
2600e4f291b3SSumit Garg .func = kdb_mm,
2601e868f0a3SSumit Garg .usage = "<vaddr> <contents>",
2602e868f0a3SSumit Garg .help = "Modify Memory Contents",
2603e868f0a3SSumit Garg .flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS,
2604e868f0a3SSumit Garg },
2605e868f0a3SSumit Garg { .name = "go",
2606e868f0a3SSumit Garg .func = kdb_go,
2607e4f291b3SSumit Garg .usage = "[<vaddr>]",
2608e868f0a3SSumit Garg .help = "Continue Execution",
2609e868f0a3SSumit Garg .minlen = 1,
2610e868f0a3SSumit Garg .flags = KDB_ENABLE_REG_WRITE |
2611e868f0a3SSumit Garg KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
2612e868f0a3SSumit Garg },
2613e4f291b3SSumit Garg { .name = "rd",
2614e868f0a3SSumit Garg .func = kdb_rd,
2615e868f0a3SSumit Garg .usage = "",
2616e868f0a3SSumit Garg .help = "Display Registers",
2617e868f0a3SSumit Garg .flags = KDB_ENABLE_REG_READ,
2618e868f0a3SSumit Garg },
2619e4f291b3SSumit Garg { .name = "rm",
2620e868f0a3SSumit Garg .func = kdb_rm,
2621e868f0a3SSumit Garg .usage = "<reg> <contents>",
2622e868f0a3SSumit Garg .help = "Modify Registers",
2623e868f0a3SSumit Garg .flags = KDB_ENABLE_REG_WRITE,
2624e868f0a3SSumit Garg },
2625e4f291b3SSumit Garg { .name = "ef",
2626e868f0a3SSumit Garg .func = kdb_ef,
2627e868f0a3SSumit Garg .usage = "<vaddr>",
2628e868f0a3SSumit Garg .help = "Display exception frame",
2629e868f0a3SSumit Garg .flags = KDB_ENABLE_MEM_READ,
2630e868f0a3SSumit Garg },
2631e4f291b3SSumit Garg { .name = "bt",
2632e868f0a3SSumit Garg .func = kdb_bt,
2633e868f0a3SSumit Garg .usage = "[<vaddr>]",
2634e868f0a3SSumit Garg .help = "Stack traceback",
2635e868f0a3SSumit Garg .minlen = 1,
2636e868f0a3SSumit Garg .flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
2637e868f0a3SSumit Garg },
2638e4f291b3SSumit Garg { .name = "btp",
2639e4f291b3SSumit Garg .func = kdb_bt,
2640e868f0a3SSumit Garg .usage = "<pid>",
2641e868f0a3SSumit Garg .help = "Display stack for process <pid>",
2642e868f0a3SSumit Garg .flags = KDB_ENABLE_INSPECT,
2643e868f0a3SSumit Garg },
2644e868f0a3SSumit Garg { .name = "bta",
2645e4f291b3SSumit Garg .func = kdb_bt,
2646e868f0a3SSumit Garg .usage = "[<state_chars>|A]",
2647e868f0a3SSumit Garg .help = "Backtrace all processes whose state matches",
2648e868f0a3SSumit Garg .flags = KDB_ENABLE_INSPECT,
2649e868f0a3SSumit Garg },
2650e868f0a3SSumit Garg { .name = "btc",
2651e4f291b3SSumit Garg .func = kdb_bt,
2652e868f0a3SSumit Garg .usage = "",
2653e868f0a3SSumit Garg .help = "Backtrace current process on each cpu",
2654e868f0a3SSumit Garg .flags = KDB_ENABLE_INSPECT,
2655e868f0a3SSumit Garg },
2656e868f0a3SSumit Garg { .name = "btt",
2657e4f291b3SSumit Garg .func = kdb_bt,
2658e868f0a3SSumit Garg .usage = "<vaddr>",
2659e868f0a3SSumit Garg .help = "Backtrace process given its struct task address",
2660e868f0a3SSumit Garg .flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS,
2661e868f0a3SSumit Garg },
2662e868f0a3SSumit Garg { .name = "env",
2663e868f0a3SSumit Garg .func = kdb_env,
2664e4f291b3SSumit Garg .usage = "",
2665e868f0a3SSumit Garg .help = "Show environment variables",
2666e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2667e868f0a3SSumit Garg },
2668e868f0a3SSumit Garg { .name = "set",
2669e868f0a3SSumit Garg .func = kdb_set,
2670e4f291b3SSumit Garg .usage = "",
2671e868f0a3SSumit Garg .help = "Set environment variables",
2672e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2673b77dbc86SDaniel Thompson },
2674b77dbc86SDaniel Thompson { .name = "help",
2675e868f0a3SSumit Garg .func = kdb_help,
2676e4f291b3SSumit Garg .usage = "",
2677e868f0a3SSumit Garg .help = "Display Help Message",
2678e868f0a3SSumit Garg .minlen = 1,
2679e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2680e868f0a3SSumit Garg },
2681e868f0a3SSumit Garg { .name = "?",
2682e4f291b3SSumit Garg .func = kdb_help,
2683e868f0a3SSumit Garg .usage = "",
2684e868f0a3SSumit Garg .help = "Display Help Message",
2685e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2686e868f0a3SSumit Garg },
2687e868f0a3SSumit Garg { .name = "cpu",
2688e4f291b3SSumit Garg .func = kdb_cpu,
2689e868f0a3SSumit Garg .usage = "<cpunum>",
2690e868f0a3SSumit Garg .help = "Switch to new cpu",
2691e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS,
2692e868f0a3SSumit Garg },
2693e868f0a3SSumit Garg { .name = "kgdb",
2694e4f291b3SSumit Garg .func = kdb_kgdb,
2695e868f0a3SSumit Garg .usage = "",
2696e868f0a3SSumit Garg .help = "Enter kgdb mode",
2697e868f0a3SSumit Garg .flags = 0,
2698e868f0a3SSumit Garg },
2699e868f0a3SSumit Garg { .name = "ps",
2700e4f291b3SSumit Garg .func = kdb_ps,
2701e868f0a3SSumit Garg .usage = "[<state_chars>|A]",
2702e868f0a3SSumit Garg .help = "Display active task list",
2703e868f0a3SSumit Garg .flags = KDB_ENABLE_INSPECT,
2704e868f0a3SSumit Garg },
2705e868f0a3SSumit Garg { .name = "pid",
2706e868f0a3SSumit Garg .func = kdb_pid,
2707e4f291b3SSumit Garg .usage = "<pidnum>",
2708e868f0a3SSumit Garg .help = "Switch to another task",
2709e868f0a3SSumit Garg .flags = KDB_ENABLE_INSPECT,
2710e868f0a3SSumit Garg },
2711e868f0a3SSumit Garg { .name = "reboot",
2712e868f0a3SSumit Garg .func = kdb_reboot,
2713e4f291b3SSumit Garg .usage = "",
2714e868f0a3SSumit Garg .help = "Reboot the machine immediately",
2715e868f0a3SSumit Garg .flags = KDB_ENABLE_REBOOT,
2716e868f0a3SSumit Garg },
2717e868f0a3SSumit Garg #if defined(CONFIG_MODULES)
2718e868f0a3SSumit Garg { .name = "lsmod",
2719e4f291b3SSumit Garg .func = kdb_lsmod,
2720e868f0a3SSumit Garg .usage = "",
2721e868f0a3SSumit Garg .help = "List loaded kernel modules",
2722e868f0a3SSumit Garg .flags = KDB_ENABLE_INSPECT,
2723e868f0a3SSumit Garg },
2724e868f0a3SSumit Garg #endif
2725e4f291b3SSumit Garg #if defined(CONFIG_MAGIC_SYSRQ)
2726e868f0a3SSumit Garg { .name = "sr",
2727e868f0a3SSumit Garg .func = kdb_sr,
2728b77dbc86SDaniel Thompson .usage = "<key>",
2729e868f0a3SSumit Garg .help = "Magic SysRq key",
2730e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2731e4f291b3SSumit Garg },
2732e868f0a3SSumit Garg #endif
2733e868f0a3SSumit Garg #if defined(CONFIG_PRINTK)
2734e868f0a3SSumit Garg { .name = "dmesg",
2735e868f0a3SSumit Garg .func = kdb_dmesg,
2736e868f0a3SSumit Garg .usage = "[lines]",
2737e4f291b3SSumit Garg .help = "Display syslog buffer",
2738e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2739e868f0a3SSumit Garg },
2740e868f0a3SSumit Garg #endif
2741e868f0a3SSumit Garg { .name = "defcmd",
2742e868f0a3SSumit Garg .func = kdb_defcmd,
2743e4f291b3SSumit Garg .usage = "name \"usage\" \"help\"",
2744e4f291b3SSumit Garg .help = "Define a set of commands, down to endefcmd",
2745e868f0a3SSumit Garg /*
2746e868f0a3SSumit Garg * Macros are always safe because when executed each
2747e868f0a3SSumit Garg * internal command re-enters kdb_parse() and is safety
2748e868f0a3SSumit Garg * checked individually.
2749e868f0a3SSumit Garg */
2750e4f291b3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2751e4f291b3SSumit Garg },
2752e4f291b3SSumit Garg { .name = "kill",
2753e868f0a3SSumit Garg .func = kdb_kill,
2754e868f0a3SSumit Garg .usage = "<-signal> <pid>",
2755e868f0a3SSumit Garg .help = "Send a signal to a process",
2756e868f0a3SSumit Garg .flags = KDB_ENABLE_SIGNAL,
2757e868f0a3SSumit Garg },
2758e4f291b3SSumit Garg { .name = "summary",
2759e4f291b3SSumit Garg .func = kdb_summary,
2760e4f291b3SSumit Garg .usage = "",
2761e868f0a3SSumit Garg .help = "Summarize the system",
2762e868f0a3SSumit Garg .minlen = 4,
2763e868f0a3SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2764e868f0a3SSumit Garg },
2765e868f0a3SSumit Garg { .name = "per_cpu",
2766e4f291b3SSumit Garg .func = kdb_per_cpu,
2767e4f291b3SSumit Garg .usage = "<sym> [<bytes>] [<cpu>]",
2768e868f0a3SSumit Garg .help = "Display per_cpu variables",
2769e868f0a3SSumit Garg .minlen = 3,
2770e868f0a3SSumit Garg .flags = KDB_ENABLE_MEM_READ,
2771e868f0a3SSumit Garg },
2772c25abcd6SSumit Garg { .name = "grephelp",
2773c25abcd6SSumit Garg .func = kdb_grep_help,
2774c25abcd6SSumit Garg .usage = "",
2775c25abcd6SSumit Garg .help = "Display help on | grep",
2776c25abcd6SSumit Garg .flags = KDB_ENABLE_ALWAYS_SAFE,
2777e868f0a3SSumit Garg },
2778e4f291b3SSumit Garg };
2779e868f0a3SSumit Garg
2780e868f0a3SSumit Garg /* Initialize the kdb command table. */
kdb_inittab(void)2781e868f0a3SSumit Garg static void __init kdb_inittab(void)
2782e868f0a3SSumit Garg {
2783e868f0a3SSumit Garg kdb_register_table(maintab, ARRAY_SIZE(maintab));
2784e4f291b3SSumit Garg }
2785e868f0a3SSumit Garg
2786e868f0a3SSumit Garg /* Execute any commands defined in kdb_cmds. */
kdb_cmd_init(void)2787e868f0a3SSumit Garg static void __init kdb_cmd_init(void)
2788e868f0a3SSumit Garg {
2789e868f0a3SSumit Garg int i, diag;
2790e868f0a3SSumit Garg for (i = 0; kdb_cmds[i]; ++i) {
2791e4f291b3SSumit Garg diag = kdb_parse(kdb_cmds[i]);
2792e868f0a3SSumit Garg if (diag)
2793e868f0a3SSumit Garg kdb_printf("kdb command %s failed, kdb diag %d\n",
2794e868f0a3SSumit Garg kdb_cmds[i], diag);
2795e868f0a3SSumit Garg }
2796e868f0a3SSumit Garg if (defcmd_in_progress) {
2797e868f0a3SSumit Garg kdb_printf("Incomplete 'defcmd' set, forcing endefcmd\n");
2798e4f291b3SSumit Garg kdb_parse("endefcmd");
2799e868f0a3SSumit Garg }
2800e868f0a3SSumit Garg }
2801e868f0a3SSumit Garg
2802e868f0a3SSumit Garg /* Initialize kdb_printf, breakpoint tables and kdb state */
kdb_init(int lvl)2803e868f0a3SSumit Garg void __init kdb_init(int lvl)
2804e4f291b3SSumit Garg {
2805e4f291b3SSumit Garg static int kdb_init_lvl = KDB_NOT_INITIALIZED;
2806e4f291b3SSumit Garg int i;
2807e4f291b3SSumit Garg
2808e868f0a3SSumit Garg if (kdb_init_lvl == KDB_INIT_FULL || lvl <= kdb_init_lvl)
2809e868f0a3SSumit Garg return;
2810e868f0a3SSumit Garg for (i = kdb_init_lvl; i < lvl; i++) {
2811e868f0a3SSumit Garg switch (i) {
2812e868f0a3SSumit Garg case KDB_NOT_INITIALIZED:
2813e4f291b3SSumit Garg kdb_inittab(); /* Initialize Command Table */
2814e4f291b3SSumit Garg kdb_initbptab(); /* Initialize Breakpoints */
28155d5314d6SJason Wessel break;
28165d5314d6SJason Wessel case KDB_INIT_EARLY:
28175d5314d6SJason Wessel kdb_cmd_init(); /* Build kdb_cmds tables */
2818e4f291b3SSumit Garg break;
2819e4f291b3SSumit Garg }
2820e4f291b3SSumit Garg }
28215d5314d6SJason Wessel kdb_init_lvl = lvl;
28225d5314d6SJason Wessel }
28235d5314d6SJason Wessel