xref: /linux-6.15/kernel/debug/kdb/kdb_main.c (revision a30d4ff8)
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, &reg8, 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, &reg16, 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, &reg32, 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, &reg64, 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], &reg64);
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, &reg8, kdb_current_regs);
1919534af108SJason Wessel 			break;
1920534af108SJason Wessel 		case 16:
1921534af108SJason Wessel 			reg16 = reg64;
1922534af108SJason Wessel 			dbg_set_reg(i, &reg16, kdb_current_regs);
1923534af108SJason Wessel 			break;
1924534af108SJason Wessel 		case 32:
1925534af108SJason Wessel 			reg32 = reg64;
1926534af108SJason Wessel 			dbg_set_reg(i, &reg32, kdb_current_regs);
1927534af108SJason Wessel 			break;
1928534af108SJason Wessel 		case 64:
1929534af108SJason Wessel 			dbg_set_reg(i, &reg64, 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