* [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV
@ 2013-03-25 18:50 Mike Travis
2013-03-25 18:50 ` [PATCH 01/15] KDB: fix the interrupt of the KDB btc command Mike Travis
` (14 more replies)
0 siblings, 15 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel
These are kernel updates for the NMI/KDB handler on the SGI
Ultraviolet System.
* Fix problem where 'quit' to more> prompt doesn't stop output.
* Fix problem where reg dump shows letter 'd' in first column of
every line.
* Up the number of LINES so the entire entry message is displayed.
* Moves KDB header defines to externally visable header so external
KDB modules can be built.
* Exports some significant KDB functions for use by external modules.
* Consolidates the '| grep' support into new kdb_grep.c file.
* Updates kdb grep support to add some new options.
* Restablishes support for kdump from the kdb prompt.
* Adds back in the 'pshelp' command.
* Adds new entry into KGDB for systems with global NMI support.
* Adds new reason code to enter KDB that's not considered an error.
* Adds support for external 'uvtrace' module.
* Updates NMI support for new internal system (SMM) NMI handler.
* Adds back the capability of NMI entering KDB/KGDB.
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 01/15] KDB: fix the interrupt of the KDB btc command
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 21:11 ` Jason Wessel
2013-03-25 18:50 ` [PATCH 02/15] KDB: fix errant character in KDB show regs Mike Travis
` (13 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, David Howells
[-- Attachment #1: kdb-fix-bt-break.patch --]
[-- Type: text/plain, Size: 798 bytes --]
The KDB 'btc' (backtrace cpus) command ignores the 'quit' reply
to the 'more>' prompt. This is quite annoying when you have a
large number of processors and thousands of lines are being
printed. This fixes that problem.
Cc: David Howells <dhowells@redhat.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
kernel/debug/kdb/kdb_bt.c | 2 ++
1 file changed, 2 insertions(+)
--- linux.orig/kernel/debug/kdb/kdb_bt.c
+++ linux/kernel/debug/kdb/kdb_bt.c
@@ -123,6 +123,8 @@ kdb_bt(int argc, const char **argv)
kdb_ps_suppressed();
/* Run the active tasks first */
for_each_online_cpu(cpu) {
+ if (KDB_FLAG(CMD_INTERRUPT))
+ return 0;
p = kdb_curr_task(cpu);
if (kdb_bt1(p, mask, argcount, btaprompt))
return 0;
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 02/15] KDB: fix errant character in KDB show regs
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
2013-03-25 18:50 ` [PATCH 01/15] KDB: fix the interrupt of the KDB btc command Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 03/15] KDB: up the default LINES value Mike Travis
` (12 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird
[-- Attachment #1: kdb-fix-show-regs.patch --]
[-- Type: text/plain, Size: 2290 bytes --]
When KDB prints the process regs and backtrace, every line is preceeded
with the character 'd'. This is the level argument to printk which
is not interpreted when KDB is printing. Skip over this possible
printk level in the outgoing string to fix this.
Here is a small sample:
dRIP: 0010:[<ffffffff814e96ca>] [<ffffffff814e96ca>] poll_idle+0x4a/0x90
dRSP: 0018:ffff88081d5eddd8 EFLAGS: 00000246
dRAX: 0000000400000000 RBX: 00000216ae7fbf5d RCX: 0000021658a8e600
dRDX: ffff88081d5ec010 RSI: ffffffff819a7d20 RDI: ffffffff8193c140
Cc: Tim Bird <tim.bird@am.sony.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
kernel/debug/kdb/kdb_io.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
--- linux.orig/kernel/debug/kdb/kdb_io.c
+++ linux/kernel/debug/kdb/kdb_io.c
@@ -559,6 +559,7 @@ int vkdb_printf(const char *fmt, va_list
int retlen = 0;
int fnd, len;
char *cp, *cp2, *cphold = NULL, replaced_byte = ' ';
+ const char *ostring;
char *moreprompt = "more> ";
struct console *c = console_drivers;
static DEFINE_SPINLOCK(kdb_printf_lock);
@@ -690,20 +691,21 @@ kdb_printit:
/*
* Write to all consoles.
*/
- retlen = strlen(kdb_buffer);
+ ostring = printk_skip_level(kdb_buffer);
+ retlen = strlen(ostring);
if (!dbg_kdb_mode && kgdb_connected) {
- gdbstub_msg_write(kdb_buffer, retlen);
+ gdbstub_msg_write(ostring, retlen);
} else {
if (dbg_io_ops && !dbg_io_ops->is_console) {
len = retlen;
- cp = kdb_buffer;
+ cp = (char *)ostring;
while (len--) {
dbg_io_ops->write_char(*cp);
cp++;
}
}
while (c) {
- c->write(c, kdb_buffer, retlen);
+ c->write(c, ostring, retlen);
touch_nmi_watchdog();
c = c->next;
}
@@ -711,7 +713,7 @@ kdb_printit:
if (logging) {
saved_loglevel = console_loglevel;
console_loglevel = 0;
- printk(KERN_INFO "%s", kdb_buffer);
+ pr_info("%s", ostring);
}
if (KDB_STATE(PAGER)) {
@@ -723,10 +725,10 @@ kdb_printit:
int got = 0;
len = retlen;
while (len--) {
- if (kdb_buffer[len] == '\n') {
+ if (ostring[len] == '\n') {
kdb_nextline++;
got = 0;
- } else if (kdb_buffer[len] == '\r') {
+ } else if (ostring[len] == '\r') {
got = 0;
} else {
got++;
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 03/15] KDB: up the default LINES value
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
2013-03-25 18:50 ` [PATCH 01/15] KDB: fix the interrupt of the KDB btc command Mike Travis
2013-03-25 18:50 ` [PATCH 02/15] KDB: fix errant character in KDB show regs Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 21:22 ` Jason Wessel
2013-03-25 18:50 ` [PATCH 04/15] KDB: allow KDB modules to be external modules Mike Travis
` (11 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird
[-- Attachment #1: kdb-up-default-lines.patch --]
[-- Type: text/plain, Size: 760 bytes --]
Currently the default for the # of lines displayed by the KDB pager
is 24. This does not allow all of the lines for the entry messages,
reg dump and process trace. Increase it to something more reasonable.
Cc: Tim Bird <tim.bird@am.sony.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
kernel/debug/kdb/kdb_io.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- linux.orig/kernel/debug/kdb/kdb_io.c
+++ linux/kernel/debug/kdb/kdb_io.c
@@ -586,7 +586,7 @@ int vkdb_printf(const char *fmt, va_list
diag = kdbgetintenv("LINES", &linecount);
if (diag || linecount <= 1)
- linecount = 24;
+ linecount = 60;
diag = kdbgetintenv("COLUMNS", &colcount);
if (diag || colcount <= 1)
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 04/15] KDB: allow KDB modules to be external modules
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (2 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 03/15] KDB: up the default LINES value Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 05/15] KDB: add more exports for supporting KDB modules v2 Mike Travis
` (10 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Vincent Stehle,
Andrei Warkentin, Anton Vorontsov
[-- Attachment #1: kdb-allow-ext-modules.patch --]
[-- Type: text/plain, Size: 9335 bytes --]
Since KDB modules are not built within the Linux kernel build domain,
symbols needed by them must be available in a header file that is
accessible. This patch moves the significant routines used by KDB
modules to the external kdb.h header file.
Cc: Vincent Stehle <vincent.stehle@laposte.net>
Cc: Andrei Warkentin <andrey.warkentin@gmail.com>
Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
include/linux/kdb.h | 89 +++++++++++++++++++++++++++++++++++++++++
kernel/debug/debug_core.h | 1
kernel/debug/kdb/kdb_private.h | 79 ------------------------------------
3 files changed, 89 insertions(+), 80 deletions(-)
--- linux.orig/include/linux/kdb.h
+++ linux/include/linux/kdb.h
@@ -25,6 +25,7 @@ typedef int (*kdb_func_t)(int, const cha
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/atomic.h>
+#include <linux/hardirq.h>
#define KDB_POLL_FUNC_MAX 5
extern int kdb_poll_idx;
@@ -148,6 +149,93 @@ extern int kdb_register(char *, kdb_func
extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
short, kdb_repeat_t);
extern int kdb_unregister(char *);
+
+/*
+ * Exported Symbols for kernel loadable modules to use.
+ *
+ * (All of these need to be within an #ifdef CONFIG_KGDB_KDB domain)
+ */
+extern int kdb_parse(const char *cmdstr);
+extern int kdb_getarea_size(void *, unsigned long, size_t);
+extern int kdb_putarea_size(unsigned long, void *, size_t);
+
+/*
+ * Like get_user and put_user, kdb_getarea and kdb_putarea take variable
+ * names, not pointers. The underlying *_size functions take pointers.
+ */
+#define kdb_getarea(x, addr) kdb_getarea_size(&(x), addr, sizeof((x)))
+#define kdb_putarea(addr, x) kdb_putarea_size(addr, &(x), sizeof((x)))
+
+extern int kdb_getphysword(unsigned long *word,
+ unsigned long addr, size_t size);
+extern int kdb_getword(unsigned long *, unsigned long, size_t);
+extern int kdb_putword(unsigned long, unsigned long, size_t);
+
+extern int kdbgetularg(const char *, unsigned long *);
+extern int kdbgetu64arg(const char *, u64 *);
+extern char *kdbgetenv(const char *);
+extern int kdbgetaddrarg(int, const char **, int*, unsigned long *,
+ long *, char **);
+
+/* Symbol table format returned by kallsyms. */
+typedef struct __ksymtab {
+ unsigned long value; /* Address of symbol */
+ const char *mod_name; /* Module containing symbol or
+ * "kernel" */
+ unsigned long mod_start;
+ unsigned long mod_end;
+ const char *sec_name; /* Section containing symbol */
+ unsigned long sec_start;
+ unsigned long sec_end;
+ const char *sym_name; /* Full symbol name, including
+ * any version */
+ unsigned long sym_start;
+ unsigned long sym_end;
+} kdb_symtab_t;
+extern int kallsyms_symbol_next(char *prefix_name, int flag);
+extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
+
+extern int kdbgetsymval(const char *, kdb_symtab_t *);
+extern int kdbnearsym(unsigned long, kdb_symtab_t *);
+extern void kdbnearsym_cleanup(void);
+extern char *kdb_strdup(const char *str, gfp_t type);
+extern void kdb_symbol_print(unsigned long, const kdb_symtab_t *, unsigned int);
+
+extern void kdb_ps_suppressed(void);
+extern void kdb_ps1(const struct task_struct *p);
+extern void kdb_print_nameval(const char *name, unsigned long val);
+extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
+extern void kdb_meminfo_proc_show(void);
+extern char *kdb_getstr(char *, size_t, char *);
+
+/* Defines for kdb_symbol_print */
+#define KDB_SP_SPACEB 0x0001 /* Space before string */
+#define KDB_SP_SPACEA 0x0002 /* Space after string */
+#define KDB_SP_PAREN 0x0004 /* Parenthesis around string */
+#define KDB_SP_VALUE 0x0008 /* Print the value of the address */
+#define KDB_SP_SYMSIZE 0x0010 /* Print the size of the symbol */
+#define KDB_SP_NEWLINE 0x0020 /* Newline after string */
+#define KDB_SP_DEFAULT (KDB_SP_VALUE|KDB_SP_PAREN)
+
+#define KDB_TSK(cpu) (kgdb_info[cpu].task)
+#define KDB_TSKREGS(cpu) (kgdb_info[cpu].debuggerinfo)
+
+extern struct task_struct *kdb_curr_task(int);
+
+#define kdb_task_has_cpu(p) (task_curr(p))
+
+/* Simplify coexistence with NPTL */
+#define kdb_do_each_thread(g, p) do_each_thread(g, p)
+#define kdb_while_each_thread(g, p) while_each_thread(g, p)
+
+#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
+
+extern void *debug_kmalloc(size_t size, gfp_t flags);
+extern void debug_kfree(void *);
+extern void debug_kusage(void);
+
+extern void kdb_set_current_task(struct task_struct *);
+extern struct task_struct *kdb_current_task;
#else /* ! CONFIG_KGDB_KDB */
static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; }
static inline void kdb_init(int level) {}
@@ -157,6 +245,7 @@ static inline int kdb_register_repeat(ch
char *help, short minlen,
kdb_repeat_t repeat) { return 0; }
static inline int kdb_unregister(char *cmd) { return 0; }
+
#endif /* CONFIG_KGDB_KDB */
enum {
KDB_NOT_INITIALIZED,
--- linux.orig/kernel/debug/debug_core.h
+++ linux/kernel/debug/debug_core.h
@@ -71,7 +71,6 @@ extern int dbg_kdb_mode;
#ifdef CONFIG_KGDB_KDB
extern int kdb_stub(struct kgdb_state *ks);
-extern int kdb_parse(const char *cmdstr);
extern int kdb_common_init_state(struct kgdb_state *ks);
extern int kdb_common_deinit_state(void);
#else /* ! CONFIG_KGDB_KDB */
--- linux.orig/kernel/debug/kdb/kdb_private.h
+++ linux/kernel/debug/kdb/kdb_private.h
@@ -68,51 +68,6 @@
*/
#define KDB_MAXBPT 16
-/* Symbol table format returned by kallsyms. */
-typedef struct __ksymtab {
- unsigned long value; /* Address of symbol */
- const char *mod_name; /* Module containing symbol or
- * "kernel" */
- unsigned long mod_start;
- unsigned long mod_end;
- const char *sec_name; /* Section containing symbol */
- unsigned long sec_start;
- unsigned long sec_end;
- const char *sym_name; /* Full symbol name, including
- * any version */
- unsigned long sym_start;
- unsigned long sym_end;
- } kdb_symtab_t;
-extern int kallsyms_symbol_next(char *prefix_name, int flag);
-extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
-
-/* Exported Symbols for kernel loadable modules to use. */
-extern int kdb_getarea_size(void *, unsigned long, size_t);
-extern int kdb_putarea_size(unsigned long, void *, size_t);
-
-/*
- * Like get_user and put_user, kdb_getarea and kdb_putarea take variable
- * names, not pointers. The underlying *_size functions take pointers.
- */
-#define kdb_getarea(x, addr) kdb_getarea_size(&(x), addr, sizeof((x)))
-#define kdb_putarea(addr, x) kdb_putarea_size(addr, &(x), sizeof((x)))
-
-extern int kdb_getphysword(unsigned long *word,
- unsigned long addr, size_t size);
-extern int kdb_getword(unsigned long *, unsigned long, size_t);
-extern int kdb_putword(unsigned long, unsigned long, size_t);
-
-extern int kdbgetularg(const char *, unsigned long *);
-extern int kdbgetu64arg(const char *, u64 *);
-extern char *kdbgetenv(const char *);
-extern int kdbgetaddrarg(int, const char **, int*, unsigned long *,
- long *, char **);
-extern int kdbgetsymval(const char *, kdb_symtab_t *);
-extern int kdbnearsym(unsigned long, kdb_symtab_t *);
-extern void kdbnearsym_cleanup(void);
-extern char *kdb_strdup(const char *str, gfp_t type);
-extern void kdb_symbol_print(unsigned long, const kdb_symtab_t *, unsigned int);
-
/* Routine for debugging the debugger state. */
extern void kdb_print_state(const char *, int);
@@ -205,42 +160,8 @@ extern unsigned long kdb_task_state_stri
extern char kdb_task_state_char (const struct task_struct *);
extern unsigned long kdb_task_state(const struct task_struct *p,
unsigned long mask);
-extern void kdb_ps_suppressed(void);
-extern void kdb_ps1(const struct task_struct *p);
-extern void kdb_print_nameval(const char *name, unsigned long val);
-extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
-extern void kdb_meminfo_proc_show(void);
-extern char *kdb_getstr(char *, size_t, char *);
extern void kdb_gdb_state_pass(char *buf);
-/* Defines for kdb_symbol_print */
-#define KDB_SP_SPACEB 0x0001 /* Space before string */
-#define KDB_SP_SPACEA 0x0002 /* Space after string */
-#define KDB_SP_PAREN 0x0004 /* Parenthesis around string */
-#define KDB_SP_VALUE 0x0008 /* Print the value of the address */
-#define KDB_SP_SYMSIZE 0x0010 /* Print the size of the symbol */
-#define KDB_SP_NEWLINE 0x0020 /* Newline after string */
-#define KDB_SP_DEFAULT (KDB_SP_VALUE|KDB_SP_PAREN)
-
-#define KDB_TSK(cpu) kgdb_info[cpu].task
-#define KDB_TSKREGS(cpu) kgdb_info[cpu].debuggerinfo
-
-extern struct task_struct *kdb_curr_task(int);
-
-#define kdb_task_has_cpu(p) (task_curr(p))
-
-/* Simplify coexistence with NPTL */
-#define kdb_do_each_thread(g, p) do_each_thread(g, p)
-#define kdb_while_each_thread(g, p) while_each_thread(g, p)
-
-#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
-
-extern void *debug_kmalloc(size_t size, gfp_t flags);
-extern void debug_kfree(void *);
-extern void debug_kusage(void);
-
-extern void kdb_set_current_task(struct task_struct *);
-extern struct task_struct *kdb_current_task;
#ifdef CONFIG_KDB_KEYBOARD
extern void kdb_kbd_cleanup_state(void);
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 05/15] KDB: add more exports for supporting KDB modules v2
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (3 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 04/15] KDB: allow KDB modules to be external modules Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-26 2:38 ` Eric W. Biederman
2013-03-25 18:50 ` [PATCH 06/15] KDB: consolidate KDB grep code Mike Travis
` (9 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird, Anton Vorontsov,
Sasha Levin, Rusty Russell, Greg Kroah-Hartman, Cong Wang,
Stephen Boyd, Al Viro, Oleg Nesterov, Eric W. Biederman,
Serge Hallyn
[-- Attachment #1: kdb-add-module-support.patch --]
[-- Type: text/plain, Size: 8054 bytes --]
This patch adds some significant KDB functions to be usable by
externally built and loadable KDB modules. All added functions
have been marked EXPORT_SYMBOL_GPL as that seems to be the norm.
No 'EXPORT_SYMBOL's were changed from previous instances to avoid
breaking existing modules.
Cc: Tim Bird <tim.bird@am.sony.com>
Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Cong Wang <amwang@redhat.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
v2: change in handling of EXPORT_SYMBOLS.
---
kernel/debug/kdb/kdb_io.c | 3 +++
kernel/debug/kdb/kdb_main.c | 14 ++++++++++++++
kernel/debug/kdb/kdb_support.c | 17 +++++++++++++++++
kernel/kallsyms.c | 1 +
4 files changed, 35 insertions(+)
--- linux.orig/kernel/debug/kdb/kdb_io.c
+++ linux/kernel/debug/kdb/kdb_io.c
@@ -30,6 +30,7 @@
char kdb_prompt_str[CMD_BUFLEN];
int kdb_trap_printk;
+EXPORT_SYMBOL_GPL(kdb_trap_printk);
static int kgdb_transition_check(char *buffer)
{
@@ -447,6 +448,7 @@ char *kdb_getstr(char *buffer, size_t bu
kdb_nextline = 1; /* Prompt and input resets line number */
return kdb_read(buffer, bufsize);
}
+EXPORT_SYMBOL_GPL(kdb_getstr);
/*
* kdb_input_flush
@@ -839,6 +841,7 @@ kdb_print_out:
preempt_enable();
return retlen;
}
+EXPORT_SYMBOL_GPL(vkdb_printf);
int kdb_printf(const char *fmt, ...)
{
--- linux.orig/kernel/debug/kdb/kdb_main.c
+++ linux/kernel/debug/kdb/kdb_main.c
@@ -53,6 +53,7 @@ int kdb_grep_trailing;
* Kernel debugger state flags
*/
int kdb_flags;
+EXPORT_SYMBOL_GPL(kdb_flags);
atomic_t kdb_event;
/*
@@ -60,12 +61,14 @@ atomic_t kdb_event;
* single thread processors through the kernel debugger.
*/
int kdb_initial_cpu = -1; /* cpu number that owns kdb */
+EXPORT_SYMBOL_GPL(kdb_initial_cpu);
int kdb_nextline = 1;
int kdb_state; /* General KDB state */
struct task_struct *kdb_current_task;
EXPORT_SYMBOL(kdb_current_task);
struct pt_regs *kdb_current_regs;
+EXPORT_SYMBOL_GPL(kdb_current_regs);
const char *kdb_diemsg;
static int kdb_go_count;
@@ -186,6 +189,7 @@ struct task_struct *kdb_curr_task(int cp
#endif
return p;
}
+EXPORT_SYMBOL_GPL(kdb_curr_task);
/*
* kdbgetenv - This function will return the character string value of
@@ -217,6 +221,7 @@ char *kdbgetenv(const char *match)
}
return NULL;
}
+EXPORT_SYMBOL_GPL(kdbgetenv);
/*
* kdballocenv - This function is used to allocate bytes for
@@ -293,6 +298,7 @@ int kdbgetintenv(const char *match, int
*value = (int) val;
return diag;
}
+EXPORT_SYMBOL_GPL(kdbgetintenv);
/*
* kdbgetularg - This function will convert a numeric string into an
@@ -325,6 +331,7 @@ int kdbgetularg(const char *arg, unsigne
return 0;
}
+EXPORT_SYMBOL_GPL(kdbgetularg);
int kdbgetu64arg(const char *arg, u64 *value)
{
@@ -344,6 +351,7 @@ int kdbgetu64arg(const char *arg, u64 *v
return 0;
}
+EXPORT_SYMBOL_GPL(kdbgetu64arg);
/*
* kdb_set - This function implements the 'set' command. Alter an
@@ -425,6 +433,7 @@ int kdb_set(int argc, const char **argv)
return KDB_ENVFULL;
}
+EXPORT_SYMBOL_GPL(kdb_set);
static int kdb_check_regs(void)
{
@@ -585,6 +594,7 @@ int kdbgetaddrarg(int argc, const char *
return 0;
}
+EXPORT_SYMBOL_GPL(kdbgetaddrarg);
static void kdb_cmderror(int diag)
{
@@ -1049,6 +1059,7 @@ int kdb_parse(const char *cmdstr)
return 0;
}
}
+EXPORT_SYMBOL_GPL(kdb_parse);
static int handle_ctrl_cmd(char *cmd)
@@ -1109,6 +1120,7 @@ void kdb_set_current_task(struct task_st
}
kdb_current_regs = NULL;
}
+EXPORT_SYMBOL_GPL(kdb_set_current_task);
/*
* kdb_local - The main code for kdb. This routine is invoked on a
@@ -2249,6 +2261,7 @@ void kdb_ps_suppressed(void)
kdb_printf(" suppressed,\nuse 'ps A' to see all.\n");
}
}
+EXPORT_SYMBOL_GPL(kdb_ps_suppressed);
/*
* kdb_ps - This function implements the 'ps' command which shows a
@@ -2281,6 +2294,7 @@ void kdb_ps1(const struct task_struct *p
}
}
}
+EXPORT_SYMBOL_GPL(kdb_ps1);
static int kdb_ps(int argc, const char **argv)
{
--- linux.orig/kernel/debug/kdb/kdb_support.c
+++ linux/kernel/debug/kdb/kdb_support.c
@@ -157,6 +157,7 @@ out:
debug_kfree(knt1);
return ret;
}
+EXPORT_SYMBOL_GPL(kdbnearsym);
void kdbnearsym_cleanup(void)
{
@@ -168,6 +169,7 @@ void kdbnearsym_cleanup(void)
}
}
}
+EXPORT_SYMBOL_GPL(kdbnearsym_cleanup);
static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
@@ -214,6 +216,7 @@ int kallsyms_symbol_complete(char *prefi
memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
return number;
}
+EXPORT_SYMBOL_GPL(kallsyms_symbol_complete);
/*
* kallsyms_symbol_next
@@ -242,6 +245,7 @@ int kallsyms_symbol_next(char *prefix_na
}
return 0;
}
+EXPORT_SYMBOL_GPL(kallsyms_symbol_next);
/*
* kdb_symbol_print - Standard method for printing a symbol name and offset.
@@ -292,6 +296,7 @@ void kdb_symbol_print(unsigned long addr
if (punc & KDB_SP_NEWLINE)
kdb_printf("\n");
}
+EXPORT_SYMBOL_GPL(kdb_symbol_print);
/*
* kdb_strdup - kdb equivalent of strdup, for disasm code.
@@ -312,6 +317,7 @@ char *kdb_strdup(const char *str, gfp_t
return NULL;
return strcpy(s, str);
}
+EXPORT_SYMBOL_GPL(kdb_strdup);
/*
* kdb_getarea_size - Read an area of data. The kdb equivalent of
@@ -337,6 +343,7 @@ int kdb_getarea_size(void *res, unsigned
}
return ret;
}
+EXPORT_SYMBOL_GPL(kdb_getarea_size);
/*
* kdb_putarea_size - Write an area of data. The kdb equivalent of
@@ -362,6 +369,7 @@ int kdb_putarea_size(unsigned long addr,
}
return ret;
}
+EXPORT_SYMBOL_GPL(kdb_putarea_size);
/*
* kdb_getphys - Read data from a physical address. Validate the
@@ -439,6 +447,7 @@ int kdb_getphysword(unsigned long *word,
}
return diag;
}
+EXPORT_SYMBOL_GPL(kdb_getphysword);
/*
* kdb_getword - Read a binary value. Unlike kdb_getarea, this treats
@@ -488,6 +497,7 @@ int kdb_getword(unsigned long *word, uns
}
return diag;
}
+EXPORT_SYMBOL_GPL(kdb_getword);
/*
* kdb_putword - Write a binary value. Unlike kdb_putarea, this
@@ -532,6 +542,7 @@ int kdb_putword(unsigned long addr, unsi
}
return diag;
}
+EXPORT_SYMBOL_GPL(kdb_putword);
/*
* kdb_task_state_string - Convert a string containing any of the
@@ -681,6 +692,7 @@ void kdb_print_nameval(const char *name,
else
kdb_printf("0x%lx\n", val);
}
+EXPORT_SYMBOL_GPL(kdb_print_nameval);
/* Last ditch allocator for debugging, so we can still debug even when
* the GFP_ATOMIC pool has been exhausted. The algorithms are tuned
@@ -799,6 +811,7 @@ out:
spin_unlock(&dap_lock);
return p;
}
+EXPORT_SYMBOL_GPL(debug_kmalloc);
void debug_kfree(void *p)
{
@@ -858,6 +871,7 @@ void debug_kfree(void *p)
}
spin_unlock(&dap_lock);
}
+EXPORT_SYMBOL_GPL(debug_kfree);
void debug_kusage(void)
{
@@ -907,6 +921,7 @@ void debug_kusage(void)
out:
spin_unlock(&dap_lock);
}
+EXPORT_SYMBOL_GPL(debug_kusage);
/* Maintain a small stack of kdb_flags to allow recursion without disturbing
* the global kdb state.
@@ -919,9 +934,11 @@ void kdb_save_flags(void)
BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack));
kdb_flags_stack[kdb_flags_index++] = kdb_flags;
}
+EXPORT_SYMBOL_GPL(kdb_save_flags);
void kdb_restore_flags(void)
{
BUG_ON(kdb_flags_index <= 0);
kdb_flags = kdb_flags_stack[--kdb_flags_index];
}
+EXPORT_SYMBOL_GPL(kdb_restore_flags);
--- linux.orig/kernel/kallsyms.c
+++ linux/kernel/kallsyms.c
@@ -588,6 +588,7 @@ const char *kdb_walk_kallsyms(loff_t *po
}
}
#endif /* CONFIG_KGDB_KDB */
+EXPORT_SYMBOL_GPL(kdb_walk_kallsyms);
static const struct file_operations kallsyms_operations = {
.open = kallsyms_open,
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 06/15] KDB: consolidate KDB grep code
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (4 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 05/15] KDB: add more exports for supporting KDB modules v2 Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 07/15] KDB: clean up KDB grep code, add some options Mike Travis
` (8 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird, Anton Vorontsov,
Sasha Levin, Rusty Russell, Greg Kroah-Hartman,
Vincent Stehlé, Andrei Warkentin
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: kdb-consolidate-grep-cmd.patch --]
[-- Type: text/plain, Size: 10017 bytes --]
This patch consolidates various parts of the grep code in KDB
into a new file, kdb_grep.c, in preparation of various cleanups
and additions.
Cc: Tim Bird <tim.bird@am.sony.com>
Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Vincent Stehlé" <vincent.stehle@laposte.net>
Cc: Andrei Warkentin <andrey.warkentin@gmail.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
kernel/debug/kdb/Makefile | 2
kernel/debug/kdb/kdb_grep.c | 145 +++++++++++++++++++++++++++++++++++++++++
kernel/debug/kdb/kdb_io.c | 38 ----------
kernel/debug/kdb/kdb_main.c | 92 --------------------------
kernel/debug/kdb/kdb_private.h | 4 +
5 files changed, 152 insertions(+), 129 deletions(-)
--- linux.orig/kernel/debug/kdb/Makefile
+++ linux/kernel/debug/kdb/Makefile
@@ -7,7 +7,7 @@
#
CCVERSION := $(shell $(CC) -v 2>&1 | sed -ne '$$p')
-obj-y := kdb_io.o kdb_main.o kdb_support.o kdb_bt.o gen-kdb_cmds.o kdb_bp.o kdb_debugger.o
+obj-y := kdb_io.o kdb_main.o kdb_support.o kdb_bt.o gen-kdb_cmds.o kdb_bp.o kdb_grep.o kdb_debugger.o
obj-$(CONFIG_KDB_KEYBOARD) += kdb_keyboard.o
clean-files := gen-kdb_cmds.c
--- /dev/null
+++ linux/kernel/debug/kdb/kdb_grep.c
@@ -0,0 +1,145 @@
+/*
+ * Kernel Debugger Architecture Grep Support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999-2004,2013 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
+ */
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/kdb.h>
+#include "kdb_private.h"
+
+#define GREP_LEN 256
+char kdb_grep_string[GREP_LEN];
+int kdb_grepping_flag;
+EXPORT_SYMBOL(kdb_grepping_flag);
+int kdb_grep_leading;
+int kdb_grep_trailing;
+
+/*
+ * The "str" argument may point to something like | grep xyz
+ */
+void kdb_grep_parse(const char *str)
+{
+ int len;
+ char *cp = (char *)str, *cp2;
+
+ /* sanity check: we should have been called with the \ first */
+ if (*cp != '|')
+ return;
+ cp++;
+ while (isspace(*cp))
+ cp++;
+ if (strncmp(cp, "grep ", 5)) {
+ kdb_printf("invalid 'pipe', see grephelp\n");
+ return;
+ }
+ cp += 5;
+ while (isspace(*cp))
+ cp++;
+ cp2 = strchr(cp, '\n');
+ if (cp2)
+ *cp2 = '\0'; /* remove the trailing newline */
+ len = strlen(cp);
+ if (len == 0) {
+ kdb_printf("invalid 'pipe', see grephelp\n");
+ return;
+ }
+ /* now cp points to a nonzero length search string */
+ if (*cp == '"') {
+ /* allow it be "x y z" by removing the "'s - there must
+ be two of them */
+ cp++;
+ cp2 = strchr(cp, '"');
+ if (!cp2) {
+ kdb_printf("invalid quoted string, see grephelp\n");
+ return;
+ }
+ *cp2 = '\0'; /* end the string where the 2nd " was */
+ }
+ kdb_grep_leading = 0;
+ if (*cp == '^') {
+ kdb_grep_leading = 1;
+ cp++;
+ }
+ len = strlen(cp);
+ kdb_grep_trailing = 0;
+ if (*(cp+len-1) == '$') {
+ kdb_grep_trailing = 1;
+ *(cp+len-1) = '\0';
+ }
+ len = strlen(cp);
+ if (!len)
+ return;
+ if (len >= GREP_LEN) {
+ kdb_printf("search string too long\n");
+ return;
+ }
+ strcpy(kdb_grep_string, cp);
+ kdb_grepping_flag++;
+ return;
+}
+
+
+/*
+ * search arg1 to see if it contains arg2
+ * (kdmain.c provides flags for ^pat and pat$)
+ *
+ * return 1 for found, 0 for not found
+ */
+int kdb_grep_search(char *searched)
+{
+ char firstchar, *cp;
+ char *searchfor = kdb_grep_string;
+ int len1, len2;
+
+ /* not counting the newline at the end of "searched" */
+ len1 = strlen(searched)-1;
+ len2 = strlen(searchfor);
+ if (len1 < len2)
+ return 0;
+ if (kdb_grep_leading && kdb_grep_trailing && len1 != len2)
+ return 0;
+ if (kdb_grep_leading) {
+ if (!strncmp(searched, searchfor, len2))
+ return 1;
+ } else if (kdb_grep_trailing) {
+ if (!strncmp(searched+len1-len2, searchfor, len2))
+ return 1;
+ } else {
+ firstchar = *searchfor;
+ cp = searched;
+ while ((cp = strchr(cp, firstchar))) {
+ if (!strncmp(cp, searchfor, len2))
+ return 1;
+ cp++;
+ }
+ }
+ return 0;
+}
+
+
+
+/*
+ * display help for the use of cmd | grep pattern
+ */
+int kdb_grep_help(int argc, const char **argv)
+{
+ kdb_printf("Usage of cmd args | grep pattern:\n");
+ kdb_printf(" Any command's output may be filtered through an ");
+ kdb_printf("emulated 'pipe'.\n");
+ kdb_printf(" 'grep' is just a key word.\n");
+ kdb_printf(
+ " The pattern may include a very limited set of metacharacters:\n");
+ kdb_printf(" pattern or ^pattern or pattern$ or ^pattern$\n");
+ kdb_printf(
+ " And if there are spaces in the pattern, you may quote it:\n");
+ kdb_printf(
+ " \"pat tern\" or \"^pat tern\" or \"pat tern$\" or \"^pat tern$\"\n");
+ return 0;
+}
--- linux.orig/kernel/debug/kdb/kdb_io.c
+++ linux/kernel/debug/kdb/kdb_io.c
@@ -514,42 +514,6 @@ static char *next_avail = kdb_buffer;
static int size_avail;
static int suspend_grep;
-/*
- * search arg1 to see if it contains arg2
- * (kdmain.c provides flags for ^pat and pat$)
- *
- * return 1 for found, 0 for not found
- */
-static int kdb_search_string(char *searched, char *searchfor)
-{
- char firstchar, *cp;
- int len1, len2;
-
- /* not counting the newline at the end of "searched" */
- len1 = strlen(searched)-1;
- len2 = strlen(searchfor);
- if (len1 < len2)
- return 0;
- if (kdb_grep_leading && kdb_grep_trailing && len1 != len2)
- return 0;
- if (kdb_grep_leading) {
- if (!strncmp(searched, searchfor, len2))
- return 1;
- } else if (kdb_grep_trailing) {
- if (!strncmp(searched+len1-len2, searchfor, len2))
- return 1;
- } else {
- firstchar = *searchfor;
- cp = searched;
- while ((cp = strchr(cp, firstchar))) {
- if (!strncmp(cp, searchfor, len2))
- return 1;
- cp++;
- }
- }
- return 0;
-}
-
int vkdb_printf(const char *fmt, va_list ap)
{
int diag;
@@ -668,7 +632,7 @@ int vkdb_printf(const char *fmt, va_list
* Only continue with this output if it contains the
* search string.
*/
- fnd = kdb_search_string(kdb_buffer, kdb_grep_string);
+ fnd = kdb_grep_search(kdb_buffer);
if (!fnd) {
/*
* At this point the complete line at the start
--- linux.orig/kernel/debug/kdb/kdb_main.c
+++ linux/kernel/debug/kdb/kdb_main.c
@@ -42,13 +42,6 @@
#include <linux/slab.h>
#include "kdb_private.h"
-#define GREP_LEN 256
-char kdb_grep_string[GREP_LEN];
-int kdb_grepping_flag;
-EXPORT_SYMBOL(kdb_grepping_flag);
-int kdb_grep_leading;
-int kdb_grep_trailing;
-
/*
* Kernel debugger state flags
*/
@@ -768,70 +761,6 @@ static char cmd_hist[KDB_CMD_HISTORY_COU
static char cmd_cur[CMD_BUFLEN];
/*
- * The "str" argument may point to something like | grep xyz
- */
-static void parse_grep(const char *str)
-{
- int len;
- char *cp = (char *)str, *cp2;
-
- /* sanity check: we should have been called with the \ first */
- if (*cp != '|')
- return;
- cp++;
- while (isspace(*cp))
- cp++;
- if (strncmp(cp, "grep ", 5)) {
- kdb_printf("invalid 'pipe', see grephelp\n");
- return;
- }
- cp += 5;
- while (isspace(*cp))
- cp++;
- cp2 = strchr(cp, '\n');
- if (cp2)
- *cp2 = '\0'; /* remove the trailing newline */
- len = strlen(cp);
- if (len == 0) {
- kdb_printf("invalid 'pipe', see grephelp\n");
- return;
- }
- /* now cp points to a nonzero length search string */
- if (*cp == '"') {
- /* allow it be "x y z" by removing the "'s - there must
- be two of them */
- cp++;
- cp2 = strchr(cp, '"');
- if (!cp2) {
- kdb_printf("invalid quoted string, see grephelp\n");
- return;
- }
- *cp2 = '\0'; /* end the string where the 2nd " was */
- }
- kdb_grep_leading = 0;
- if (*cp == '^') {
- kdb_grep_leading = 1;
- cp++;
- }
- len = strlen(cp);
- kdb_grep_trailing = 0;
- if (*(cp+len-1) == '$') {
- kdb_grep_trailing = 1;
- *(cp+len-1) = '\0';
- }
- len = strlen(cp);
- if (!len)
- return;
- if (len >= GREP_LEN) {
- kdb_printf("search string too long\n");
- return;
- }
- strcpy(kdb_grep_string, cp);
- kdb_grepping_flag++;
- return;
-}
-
-/*
* kdb_parse - Parse the command line, search the command table for a
* matching command and invoke the command function. This
* function may be called recursively, if it is, the second call
@@ -943,7 +872,7 @@ int kdb_parse(const char *cmdstr)
if (!argc)
return 0;
if (check_grep)
- parse_grep(cp);
+ kdb_grep_parse(cp);
if (defcmd_in_progress) {
int result = kdb_defcmd2(cmdstr, argv[0]);
if (!defcmd_in_progress) {
@@ -2680,25 +2609,6 @@ static int kdb_per_cpu(int argc, const c
return 0;
}
-/*
- * display help for the use of cmd | grep pattern
- */
-static int kdb_grep_help(int argc, const char **argv)
-{
- kdb_printf("Usage of cmd args | grep pattern:\n");
- kdb_printf(" Any command's output may be filtered through an ");
- kdb_printf("emulated 'pipe'.\n");
- kdb_printf(" 'grep' is just a key word.\n");
- kdb_printf(" The pattern may include a very limited set of "
- "metacharacters:\n");
- kdb_printf(" pattern or ^pattern or pattern$ or ^pattern$\n");
- kdb_printf(" And if there are spaces in the pattern, you may "
- "quote it:\n");
- kdb_printf(" \"pat tern\" or \"^pat tern\" or \"pat tern$\""
- " or \"^pat tern$\"\n");
- return 0;
-}
-
/*
* kdb_register_repeat - This function is used to register a kernel
* debugger command.
--- linux.orig/kernel/debug/kdb/kdb_private.h
+++ linux/kernel/debug/kdb/kdb_private.h
@@ -159,6 +159,10 @@ extern int kdb_grepping_flag;
extern char kdb_grep_string[];
extern int kdb_grep_leading;
extern int kdb_grep_trailing;
+extern void kdb_grep_parse(const char *str);
+extern int kdb_grep_search(char *searched);
+extern int kdb_grep_help(int argc, const char **argv);
+
extern char *kdb_cmds[];
extern unsigned long kdb_task_state_string(const char *);
extern char kdb_task_state_char (const struct task_struct *);
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 07/15] KDB: clean up KDB grep code, add some options
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (5 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 06/15] KDB: consolidate KDB grep code Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 08/15] KDB: Restore call to kdump from KDB Mike Travis
` (7 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird, Anton Vorontsov,
Sasha Levin, Rusty Russell, Greg Kroah-Hartman,
Vincent Stehlé, Andrei Warkentin
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: kdb-update-grep-cmd.patch --]
[-- Type: text/plain, Size: 18912 bytes --]
This patch cleans up the grep 'pipe' code in KDB and adds some new options:
* allows multiple '| grep' options to be used.
* adds '-v' flag to invert the search.
* adds '-o' flag for optional ('OR') patterns.
* adds '-u' flag to delay printing until match found.
Options may be mixed in any combination.
Cc: Tim Bird <tim.bird@am.sony.com>
Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Vincent Stehlé" <vincent.stehle@laposte.net>
Cc: Andrei Warkentin <andrey.warkentin@gmail.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
kernel/debug/kdb/kdb_grep.c | 352 +++++++++++++++++++++++++++++++++--------
kernel/debug/kdb/kdb_io.c | 39 ++--
kernel/debug/kdb/kdb_main.c | 10 -
kernel/debug/kdb/kdb_private.h | 55 +++++-
4 files changed, 361 insertions(+), 95 deletions(-)
--- linux.orig/kernel/debug/kdb/kdb_grep.c
+++ linux/kernel/debug/kdb/kdb_grep.c
@@ -11,80 +11,224 @@
#include <linux/ctype.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <linux/kdb.h>
#include "kdb_private.h"
-#define GREP_LEN 256
-char kdb_grep_string[GREP_LEN];
-int kdb_grepping_flag;
+#define KDB_GREP_PATT_LEN 511
+#define KDB_GREP_MAX 8
+
+static char kdb_grep_patterns[KDB_GREP_PATT_LEN+1];
+static int kdb_grep_pattern_idx;
+
+/* Note: kdb_grep_stack[0] intentially left zero */
+struct kdb_grep_stack_s kdb_grep_stack[KDB_GREP_MAX+1];
+int kdb_grepping_flag; /* now kdb_grep_stack index */
EXPORT_SYMBOL(kdb_grepping_flag);
-int kdb_grep_leading;
-int kdb_grep_trailing;
-/*
- * The "str" argument may point to something like | grep xyz
- */
-void kdb_grep_parse(const char *str)
+static void kdb_grep_stack_clear(void)
{
- int len;
- char *cp = (char *)str, *cp2;
+ kdb_grep_stack[kdb_grepping_flag].flags = 0;
+ kdb_grep_stack[kdb_grepping_flag].pattern_idx = 0;
+}
+
+static int kdb_grep_push(void)
+{
+ if (kdb_grepping_flag < KDB_GREP_MAX) {
+ ++kdb_grepping_flag;
+ kdb_grep_stack_clear();
+ kdb_grep_set(enabled);
+ return 1;
+ }
+ return 0;
+}
+
+static void kdb_grep_pop(void)
+{
+ if (kdb_grepping_flag > 0) {
+ kdb_grep_pattern_idx =
+ kdb_grep_stack[kdb_grepping_flag].pattern_idx;
+
+ kdb_grep_patterns[kdb_grep_pattern_idx] = '\0';
+
+ if (kdb_grep(suspended))
+ kdb_grep_set_lvl(suspended, kdb_grepping_flag - 1);
+
+ kdb_grep_stack_clear();
+ --kdb_grepping_flag;
+
+ if (!kdb_grep(enabled))
+ kdb_grep_pop();
+ }
+}
+
+void kdb_grep_clear_all(void)
+{
+ kdb_grepping_flag = 0;
+ kdb_grep_pattern_idx = 0;
+ kdb_grep_patterns[0] = 0;
+ memset(kdb_grep_stack, 0, sizeof(kdb_grep_stack));
+}
+
+static int kdb_grep_error(const char *str)
+{
+ kdb_grep_clear_all();
+ kdb_printf("grep error: %s, see grephelp\n", str);
+ return -1;
+}
- /* sanity check: we should have been called with the \ first */
+static const char *kdb_grep_pattern(int lvl)
+{
+ return &kdb_grep_patterns[kdb_grep_stack[lvl].pattern_idx];
+}
+
+static int kdb_grep_add_pattern(char *str)
+{
+ int len = strlen(str);
+
+ if (!len) {
+ kdb_grep_error("empty search pattern");
+ return 0;
+ }
+
+ if ((kdb_grep_pattern_idx + len) >= KDB_GREP_PATT_LEN) {
+ kdb_grep_error("search string(s) too long");
+ return 0;
+ }
+
+ /* copy string into pattern(s) buffer */
+ kdb_grep_stack[kdb_grepping_flag].pattern_idx = kdb_grep_pattern_idx;
+ strcpy((char *)kdb_grep_pattern(kdb_grepping_flag), str);
+ kdb_grep_pattern_idx += len + 1;
+ kdb_grep_patterns[kdb_grep_pattern_idx] = '\0';
+ return 1;
+}
+
+static char *is_grep(const char *cp)
+{
+ /* sanity check: we should have been called with the | first */
if (*cp != '|')
- return;
+ return 0;
cp++;
while (isspace(*cp))
cp++;
+
if (strncmp(cp, "grep ", 5)) {
- kdb_printf("invalid 'pipe', see grephelp\n");
- return;
+ kdb_grep_error("invalid 'pipe'");
+ return NULL;
}
cp += 5;
+ return (char *)cp;
+}
+
+/*
+ * The "str" argument may point to something like | grep xyz
+ */
+int kdb_grep_parse(char *str)
+{
+ int len;
+ char *cp, *cp2;
+ char *newgrep;
+
+ cp = is_grep(str);
+ if (!cp)
+ return -1;
+repeat:
+ if (!kdb_grep_push())
+ return kdb_grep_error("too many grep's");
+
+ newgrep = NULL;
+
while (isspace(*cp))
cp++;
+
+ /* process possible options */
+ for (cp2 = cp; *cp2 == '-'; cp2 = cp) {
+ if (*++cp2 == '\0' || isspace(*cp2))
+ return kdb_grep_error("illegal option");
+
+ while (*cp2) {
+ switch (*cp2) {
+ case 'o':
+ kdb_grep_set(optional);
+ cp2++;
+ continue;
+ case 'u':
+ kdb_grep_set(until);
+ cp2++;
+ continue;
+ case 'v':
+ kdb_grep_set(inverted);
+ cp2++;
+ continue;
+ case ' ':
+ case '-':
+ break;
+ default:
+ return kdb_grep_error("illegal option");
+ }
+ break;
+ }
+ cp = cp2;
+ if (*cp == '-') {
+ cp++;
+ break;
+ }
+ while (isspace(*cp))
+ cp++;
+ }
+
+ cp2 = strchr(cp, '|');
+ if (cp2) { /* another '| grep' follows */
+ newgrep = is_grep(cp2);
+ if (!newgrep)
+ return -1;
+ *cp2 = '\0';
+ }
+
cp2 = strchr(cp, '\n');
- if (cp2)
- *cp2 = '\0'; /* remove the trailing newline */
+ if (cp2) /* remove the trailing newline */
+ *cp2 = '\0';
+
len = strlen(cp);
- if (len == 0) {
- kdb_printf("invalid 'pipe', see grephelp\n");
- return;
- }
+ while (len > 0 && isspace(cp[len-1])) /* trim trailing spaces */
+ cp[--len] = '\0';
+
+ if (len == 0)
+ return kdb_grep_error("pattern missing");
+
/* now cp points to a nonzero length search string */
if (*cp == '"') {
- /* allow it be "x y z" by removing the "'s - there must
- be two of them */
+ /*
+ * allow it be "x y z" by removing the "'s,
+ * - there must be two of them
+ */
cp++;
cp2 = strchr(cp, '"');
- if (!cp2) {
- kdb_printf("invalid quoted string, see grephelp\n");
- return;
- }
+ if (!cp2)
+ return kdb_grep_error("invalid quoted string");
+
*cp2 = '\0'; /* end the string where the 2nd " was */
}
- kdb_grep_leading = 0;
if (*cp == '^') {
- kdb_grep_leading = 1;
+ kdb_grep_set(leading);
cp++;
}
len = strlen(cp);
- kdb_grep_trailing = 0;
if (*(cp+len-1) == '$') {
- kdb_grep_trailing = 1;
+ kdb_grep_set(trailing);
*(cp+len-1) = '\0';
}
- len = strlen(cp);
- if (!len)
- return;
- if (len >= GREP_LEN) {
- kdb_printf("search string too long\n");
- return;
- }
- strcpy(kdb_grep_string, cp);
- kdb_grepping_flag++;
- return;
-}
+ if (!kdb_grep_add_pattern(cp))
+ return kdb_grep_error("too many pattern characters");
+ if (newgrep) {
+ cp = newgrep;
+ goto repeat;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(kdb_grep_parse);
/*
* search arg1 to see if it contains arg2
@@ -92,10 +236,11 @@ void kdb_grep_parse(const char *str)
*
* return 1 for found, 0 for not found
*/
-int kdb_grep_search(char *searched)
+static int kdb_search_string(const char *searched, int lvl)
{
- char firstchar, *cp;
- char *searchfor = kdb_grep_string;
+ char firstchar;
+ const char *cp;
+ const char *searchfor = kdb_grep_pattern(lvl);
int len1, len2;
/* not counting the newline at the end of "searched" */
@@ -103,12 +248,15 @@ int kdb_grep_search(char *searched)
len2 = strlen(searchfor);
if (len1 < len2)
return 0;
- if (kdb_grep_leading && kdb_grep_trailing && len1 != len2)
+ if (kdb_grep_lvl(leading, lvl)
+ && kdb_grep_lvl(trailing, lvl)
+ && len1 != len2)
return 0;
- if (kdb_grep_leading) {
+
+ if (kdb_grep_lvl(leading, lvl)) {
if (!strncmp(searched, searchfor, len2))
return 1;
- } else if (kdb_grep_trailing) {
+ } else if (kdb_grep_lvl(trailing, lvl)) {
if (!strncmp(searched+len1-len2, searchfor, len2))
return 1;
} else {
@@ -123,23 +271,105 @@ int kdb_grep_search(char *searched)
return 0;
}
+int kdb_grep_search(const char *searched)
+{
+ int lvl;
+ int pmatch;
+ int match = 1;
+ int oc = 0, om = 0;
+
+ if (!kdb_grepping_flag)
+ return 1;
+
+ for (lvl = 1; lvl <= kdb_grepping_flag; lvl++) {
+ if (!kdb_grep_lvl(enabled, lvl))
+ continue;
+
+ if (!kdb_grep_lvl(optional, lvl)) {
+ if (oc && !om)
+ break;
+ oc = om = 0;
+ }
+
+ pmatch = kdb_search_string(searched, lvl);
+ if (kdb_grep_lvl(inverted, lvl))
+ pmatch ^= 1;
+
+ if (kdb_grep_lvl(optional, lvl)) {
+ oc++;
+ if (pmatch)
+ om++;
+
+ } else if (!pmatch) {
+ match = 0;
+ break;
+ }
+
+ if (pmatch && kdb_grep_lvl(until, lvl)) {
+ if (lvl == kdb_grepping_flag)
+ kdb_grep_pop();
+ else
+ kdb_grep_clear_lvl(enabled, lvl);
+ }
+ }
+
+ if (oc && !om)
+ return 0;
+
+ return match;
+}
+EXPORT_SYMBOL(kdb_grep_search);
/*
- * display help for the use of cmd | grep pattern
+ * display help for the use of <cmd> <args> | grep <pattern>
*/
-int kdb_grep_help(int argc, const char **argv)
+static char *kdb_grep_help_list[] = {
+ "Usage of <cmd> <args> | grep <pattern> [| grep <pattern> ...]\n",
+ " Any command's output may be filtered through an emulated 'pipe'.\n",
+ " 'grep' is just a key word.\n",
+ " 'grep -v' to invert the search.\n",
+ " 'grep -o' for optional ('OR') <pattern>.\n",
+ " 'grep -u' to delay printing until <pattern> found.\n",
+ " Flags may be mixed and matched. Use '--' before patterns starting with '-'.\n",
+ " If consecutive patterns are 'optional' at least one must match.\n",
+ " The pattern may include a very limited set of metacharacters:\n",
+ " pattern or ^pattern or pattern$ or ^pattern$\n",
+ " And if there are spaces in the pattern, you may quote it:\n",
+ " \"pat tern\" or \"^pat tern\" or \"pat tern$\" or \"^pat tern$\"\n",
+ ""
+};
+
+static int kdb_grep_help(int argc, const char **argv)
{
- kdb_printf("Usage of cmd args | grep pattern:\n");
- kdb_printf(" Any command's output may be filtered through an ");
- kdb_printf("emulated 'pipe'.\n");
- kdb_printf(" 'grep' is just a key word.\n");
- kdb_printf(
- " The pattern may include a very limited set of metacharacters:\n");
- kdb_printf(" pattern or ^pattern or pattern$ or ^pattern$\n");
- kdb_printf(
- " And if there are spaces in the pattern, you may quote it:\n");
- kdb_printf(
- " \"pat tern\" or \"^pat tern\" or \"pat tern$\" or \"^pat tern$\"\n");
+ int i;
+
+ for (i = 0; *kdb_grep_help_list[i]; i++)
+ kdb_printf(kdb_grep_help_list[i]);
+
+ kdb_printf(" The '| grep' may be repeated up to %d times.\n",
+ KDB_GREP_MAX);
+
+ kdb_printf(" Max chars in all patterns (incl. NULLs) is %d.\n",
+ KDB_GREP_PATT_LEN);
return 0;
}
+
+static int __init kdb_grep_init(void)
+{
+ kdb_register_repeat("grephelp", kdb_grep_help, "",
+ "Display help on | grep", 0, KDB_REPEAT_NONE);
+
+ kdb_grep_clear_all();
+ pr_info("kdb_grep registered\n");
+ return 0;
+}
+
+static void __exit kdb_grep_exit(void)
+{
+ kdb_unregister("grephelp");
+}
+
+module_init(kdb_grep_init);
+module_exit(kdb_grep_exit);
+
--- linux.orig/kernel/debug/kdb/kdb_io.c
+++ linux/kernel/debug/kdb/kdb_io.c
@@ -504,7 +504,7 @@ empty:
* kdb output.
*
* If the user is doing a cmd args | grep srch
- * then kdb_grepping_flag is set.
+ * then kdb_grep(enabled) is set.
* In that case we need to accumulate full lines (ending in \n) before
* searching for the pattern.
*/
@@ -512,7 +512,6 @@ empty:
static char kdb_buffer[256]; /* A bit too big to go on stack */
static char *next_avail = kdb_buffer;
static int size_avail;
-static int suspend_grep;
int vkdb_printf(const char *fmt, va_list ap)
{
@@ -523,7 +522,7 @@ int vkdb_printf(const char *fmt, va_list
int saved_trap_printk;
int got_printf_lock = 0;
int retlen = 0;
- int fnd, len;
+ int len;
char *cp, *cp2, *cphold = NULL, replaced_byte = ' ';
const char *ostring;
char *moreprompt = "more> ";
@@ -560,7 +559,7 @@ int vkdb_printf(const char *fmt, va_list
if (diag)
logging = 0;
- if (!kdb_grepping_flag || suspend_grep) {
+ if (!kdb_grep(enabled) || kdb_grep(suspended)) {
/* normally, every vsnprintf starts a new buffer */
next_avail = kdb_buffer;
size_avail = sizeof(kdb_buffer);
@@ -568,15 +567,15 @@ int vkdb_printf(const char *fmt, va_list
vsnprintf(next_avail, size_avail, fmt, ap);
/*
- * If kdb_parse() found that the command was cmd xxx | grep yyy
- * then kdb_grepping_flag is set, and kdb_grep_string contains yyy
+ * If kdb_grep(enabled) is set, accumulate the print data up to a
+ * newline before 'kdb_grep_search'ing for it. kdb_grep(suspended)
+ * is disable it temporarily for kdb_printf to output prompts, etc.
*
- * Accumulate the print data up to a newline before searching it.
* (vsnprintf does null-terminate the string that it generates)
*/
/* skip the search if prints are temporarily unconditional */
- if (!suspend_grep && kdb_grepping_flag) {
+ if (!kdb_grep(suspended) && kdb_grep(enabled)) {
cp = strchr(kdb_buffer, '\n');
if (!cp) {
/*
@@ -588,7 +587,7 @@ int vkdb_printf(const char *fmt, va_list
* The "[nn]more " prompt should also be
* (MOREPROMPT -> moreprompt)
* written * but we print that ourselves,
- * we set the suspend_grep flag to make
+ * we set the kdb_grep(suspended) flag to make
* it unconditional.
*
*/
@@ -606,7 +605,7 @@ int vkdb_printf(const char *fmt, va_list
* command, so we can go back
* to normal mode.
*/
- kdb_grepping_flag = 0;
+ kdb_grep_clear_all();
goto kdb_printit;
}
}
@@ -632,8 +631,7 @@ int vkdb_printf(const char *fmt, va_list
* Only continue with this output if it contains the
* search string.
*/
- fnd = kdb_grep_search(kdb_buffer);
- if (!fnd) {
+ if (!kdb_grep_search(kdb_buffer)) {
/*
* At this point the complete line at the start
* of kdb_buffer can be discarded, as it does
@@ -753,23 +751,23 @@ kdb_printit:
KDB_FLAG_SET(CMD_INTERRUPT); /* command interrupted */
KDB_STATE_CLEAR(PAGER);
/* end of command output; back to normal mode */
- kdb_grepping_flag = 0;
+ kdb_grep_clear_all();
kdb_printf("\n");
} else if (buf1[0] == ' ') {
kdb_printf("\r");
- suspend_grep = 1; /* for this recursion */
+ kdb_grep_set(suspended); /* for this recursion */
} else if (buf1[0] == '\n') {
kdb_nextline = linecount - 1;
kdb_printf("\r");
- suspend_grep = 1; /* for this recursion */
+ kdb_grep_set(suspended); /* for this recursion */
} else if (buf1[0] && buf1[0] != '\n') {
/* user hit something other than enter */
- suspend_grep = 1; /* for this recursion */
+ kdb_grep_set(suspended); /* for this recursion */
kdb_printf("\nOnly 'q' or 'Q' are processed at more "
"prompt, input ignored\n");
- } else if (kdb_grepping_flag) {
+ } else if (kdb_grep(enabled)) {
/* user hit enter */
- suspend_grep = 1; /* for this recursion */
+ kdb_grep_set(suspended); /* for this recursion */
kdb_printf("\n");
}
kdb_input_flush();
@@ -781,7 +779,7 @@ kdb_printit:
* the terminating null, and cphold points to the null.
* Then adjust the notion of available space in the buffer.
*/
- if (kdb_grepping_flag && !suspend_grep) {
+ if (kdb_grep(enabled) && !kdb_grep(suspended)) {
*cphold = replaced_byte;
strcpy(kdb_buffer, cphold);
len = strlen(kdb_buffer);
@@ -790,7 +788,8 @@ kdb_printit:
}
kdb_print_out:
- suspend_grep = 0; /* end of what may have been a recursive call */
+ /* end of what may have been a recursive call */
+ kdb_grep_clear(suspended);
if (logging)
console_loglevel = saved_loglevel;
if (KDB_STATE(PRINTF_LOCK) && got_printf_lock) {
--- linux.orig/kernel/debug/kdb/kdb_main.c
+++ linux/kernel/debug/kdb/kdb_main.c
@@ -812,13 +812,13 @@ int kdb_parse(const char *cmdstr)
char *cp;
char *cpp, quoted;
kdbtab_t *tp;
- int i, escaped, ignore_errors = 0, check_grep;
+ int i, escaped, ignore_errors = 0, check_grep = 0;
/*
* First tokenize the command string.
*/
cp = (char *)cmdstr;
- kdb_grepping_flag = check_grep = 0;
+ kdb_grep_clear_all();
if (KDB_FLAG(CMD_INTERRUPT)) {
/* Previous command was interrupted, newline must not
@@ -887,8 +887,8 @@ int kdb_parse(const char *cmdstr)
}
if (!argc)
return 0;
- if (check_grep)
- kdb_grep_parse(cp);
+ if (check_grep && kdb_grep_parse(cp))
+ return KDB_NOTFOUND; /* '| grep' error */
if (defcmd_in_progress) {
int result = kdb_defcmd2(cmdstr, argv[0]);
if (!defcmd_in_progress) {
@@ -2758,8 +2758,6 @@ static void __init kdb_inittab(void)
"Summarize the system", 4, KDB_REPEAT_NONE);
kdb_register_repeat("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
"Display per_cpu variables", 3, KDB_REPEAT_NONE);
- kdb_register_repeat("grephelp", kdb_grep_help, "",
- "Display help on | grep", 0, KDB_REPEAT_NONE);
}
/* Execute any commands defined in kdb_cmds. */
--- linux.orig/kernel/debug/kdb/kdb_private.h
+++ linux/kernel/debug/kdb/kdb_private.h
@@ -151,14 +151,6 @@ extern int kdb_main_loop(kdb_reason_t, k
int, kdb_dbtrap_t, struct pt_regs *);
/* Miscellaneous functions and data areas */
-extern int kdb_grepping_flag;
-extern char kdb_grep_string[];
-extern int kdb_grep_leading;
-extern int kdb_grep_trailing;
-extern void kdb_grep_parse(const char *str);
-extern int kdb_grep_search(char *searched);
-extern int kdb_grep_help(int argc, const char **argv);
-
extern char *kdb_cmds[];
extern unsigned long kdb_task_state_string(const char *);
extern char kdb_task_state_char (const struct task_struct *);
@@ -181,5 +173,52 @@ extern char kdb_prompt_str[];
#define KDB_WORD_SIZE ((int)sizeof(unsigned long))
+/* kdb grep options */
+enum kdb_grep_flags {
+ kdb_grep_enabled,
+ kdb_grep_suspended,
+ kdb_grep_leading,
+ kdb_grep_trailing,
+ kdb_grep_inverted,
+ kdb_grep_until,
+ kdb_grep_optional
+};
+
+struct kdb_grep_stack_s {
+ unsigned short flags;
+ unsigned short pattern_idx;
+};
+
+extern int kdb_grepping_flag;
+extern struct kdb_grep_stack_s kdb_grep_stack[];
+extern void kdb_grep_clear_all(void);
+extern int kdb_grep_search(const char *searched);
+extern int kdb_grep_parse(char *str);
+
+#define kdb_grep_flag(flag) (1 << kdb_grep_##flag)
+
+#define kdb_grep_lvl(f, l) __kdb_grep_lvl(kdb_grep_flag(f), l)
+#define kdb_grep_set_lvl(f, l) __kdb_grep_set_lvl(kdb_grep_flag(f), l)
+#define kdb_grep_clear_lvl(f, l) __kdb_grep_clear_lvl(kdb_grep_flag(f), l)
+
+#define kdb_grep(flag) kdb_grep_lvl(flag, kdb_grepping_flag)
+#define kdb_grep_set(flag) kdb_grep_set_lvl(flag, kdb_grepping_flag)
+#define kdb_grep_clear(flag) kdb_grep_clear_lvl(flag, kdb_grepping_flag)
+
+static inline int __kdb_grep_lvl(unsigned short flag, int lvl)
+{
+ return !!(kdb_grep_stack[lvl].flags & flag);
+}
+
+static inline void __kdb_grep_set_lvl(unsigned int flag, int lvl)
+{
+ kdb_grep_stack[lvl].flags |= flag;
+}
+
+static inline void __kdb_grep_clear_lvl(unsigned int flag, int lvl)
+{
+ kdb_grep_stack[lvl].flags &= ~flag;
+}
+
#endif /* CONFIG_KGDB_KDB */
#endif /* !_KDBPRIVATE_H */
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 08/15] KDB: Restore call to kdump from KDB
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (6 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 07/15] KDB: clean up KDB grep code, add some options Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 09/15] KDB: Add pshelp command Mike Travis
` (6 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Anton Vorontsov, Sasha Levin,
Rusty Russell, Greg Kroah-Hartman
[-- Attachment #1: kdb-add-kdump-cmd.patch --]
[-- Type: text/plain, Size: 3942 bytes --]
This patch restores the capability of calling kdump from inside
KDB. First it returns to the original CPU that KDB was called
by, and also verifies that the crash_kexec kernel has been loaded.
Both are better than just using the 'sr c' option and possibly
hanging the system.
Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
include/linux/kdb.h | 7 +++
kernel/debug/kdb/kdb_main.c | 79 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+)
--- linux.orig/include/linux/kdb.h
+++ linux/include/linux/kdb.h
@@ -144,6 +144,13 @@ static inline const char *kdb_walk_kalls
}
#endif /* ! CONFIG_KALLSYMS */
+#if defined(CONFIG_KEXEC)
+enum {
+ KDB_KDUMP_RESET,
+ KDB_KDUMP_KDUMP,
+};
+#endif
+
/* Dynamic kdb shell command registration */
extern int kdb_register(char *, kdb_func_t, char *, char *, short);
extern int kdb_register_repeat(char *, kdb_func_t, char *, char *,
--- linux.orig/kernel/debug/kdb/kdb_main.c
+++ linux/kernel/debug/kdb/kdb_main.c
@@ -42,6 +42,10 @@
#include <linux/slab.h>
#include "kdb_private.h"
+#if defined(CONFIG_KEXEC)
+#include <linux/kexec.h>
+#endif
+
/*
* Kernel debugger state flags
*/
@@ -1052,6 +1056,73 @@ void kdb_set_current_task(struct task_st
}
EXPORT_SYMBOL(kdb_set_current_task);
+#if defined(CONFIG_KEXEC)
+
+static int kdb_kdump_state = KDB_KDUMP_RESET; /* KDB kdump state */
+
+static int kdb_cpu(int argc, const char **argv);
+
+/*
+ * kdb_kdump_check
+ *
+ * This is where the kdump on monarch cpu is handled.
+ *
+ */
+void kdb_kdump_check(struct pt_regs *regs)
+{
+ if (kdb_kdump_state != KDB_KDUMP_RESET) {
+ crash_kexec(regs);
+
+ /*
+ * If the call above returned then something didn't work
+ */
+ kdb_printf("kdb_kdump_check: crash_kexec failed!\n");
+ kdb_printf
+ ("Please check if the kdump kernel has been properly loaded\n");
+ kdb_kdump_state = KDB_KDUMP_RESET;
+ }
+}
+
+
+/*
+ * kdb_kdump
+ * This function implements the 'kdump' command.
+ *
+ * Returns:
+ * zero for success, a kdb diagnostic if error
+ */
+
+static int
+kdb_kdump(int argc, const char **argv)
+{
+ char cpu_id[8];
+ const char *cpu_argv[] = {NULL, cpu_id, NULL};
+ int ret = KDB_CMD_CPU;
+
+ if (!kexec_crash_image) {
+ kdb_printf("kdump error: crash kernel not loaded\n");
+ return KDB_NOTFOUND;
+ }
+
+ kdb_kdump_state = KDB_KDUMP_KDUMP;
+
+ /* Switch back to the initial cpu before process kdump command */
+ if (smp_processor_id() != kdb_initial_cpu) {
+ scnprintf(cpu_id, sizeof(cpu_id), "%d", kdb_initial_cpu);
+ ret = kdb_cpu(1, cpu_argv);
+ if (ret != KDB_CMD_CPU) {
+ kdb_printf
+ ("kdump: Failed to switch to initial cpu %d; aborted\n",
+ kdb_initial_cpu);
+ kdb_kdump_state = KDB_KDUMP_RESET;
+ }
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_KEXEC */
+
/*
* kdb_local - The main code for kdb. This routine is invoked on a
* specific processor, it is not global. The main kdb() routine
@@ -1079,6 +1150,10 @@ static int kdb_local(kdb_reason_t reason
struct task_struct *kdb_current =
kdb_curr_task(raw_smp_processor_id());
+#if defined(CONFIG_KEXEC)
+ kdb_kdump_check(regs);
+#endif
+
KDB_DEBUG_STATE("kdb_local 1", reason);
kdb_go_count = 0;
if (reason == KDB_REASON_DEBUG) {
@@ -2726,6 +2801,10 @@ static void __init kdb_inittab(void)
"Display Help Message", 0, KDB_REPEAT_NONE);
kdb_register_repeat("cpu", kdb_cpu, "<cpunum>",
"Switch to new cpu", 0, KDB_REPEAT_NONE);
+#if defined(CONFIG_KEXEC)
+ kdb_register_repeat("kdump", kdb_kdump, "",
+ "Enter kdump crash kexec", 0, KDB_REPEAT_NONE);
+#endif
kdb_register_repeat("kgdb", kdb_kgdb, "",
"Enter kgdb mode", 0, KDB_REPEAT_NONE);
kdb_register_repeat("ps", kdb_ps, "[<flags>|A]",
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 09/15] KDB: Add pshelp command.
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (7 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 08/15] KDB: Restore call to kdump from KDB Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 10/15] KGDB/KDB: add support for external NMI handler to call KGDB/KDB Mike Travis
` (5 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Anton Vorontsov, Sasha Levin,
Rusty Russell, Greg Kroah-Hartman
[-- Attachment #1: kdb-add-pshelp.patch --]
[-- Type: text/plain, Size: 2043 bytes --]
This patch restores the capability for providing help with the
PS and BT arguments.
Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
kernel/debug/kdb/kdb_main.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
--- linux.orig/kernel/debug/kdb/kdb_main.c
+++ linux/kernel/debug/kdb/kdb_main.c
@@ -2787,6 +2787,32 @@ static int kdb_grep_help(int argc, const
}
/*
+ * display help for the ps and bt status flag
+ */
+static int kdb_ps_help(int argc, const char **argv)
+{
+ kdb_printf("The meaning of the State flag in ps command output:\n");
+ kdb_printf(" R RUNNING\n");
+ kdb_printf(" D TASK_UNINTERRUPTIBLE\n");
+ kdb_printf(" S TASK_INTERRUPTIBLE\n");
+ kdb_printf(" T TASK_STOPPED\n");
+ kdb_printf(" C TASK_TRACED\n");
+ kdb_printf(" Z EXIT_ZOMBIE\n");
+ kdb_printf(" E EXIT_DEAD\n");
+ kdb_printf(" U UNRUNNABLE\n");
+ kdb_printf(" M sleeping DAEMON\n");
+ kdb_printf(" I IDLE\n");
+ kdb_printf(" (note that most idles are named 'kworker/NN')\n");
+ kdb_printf("\n");
+ kdb_printf(
+ "The above can be specified to ps and bta to select tasks\n");
+ kdb_printf(" A all of above\n");
+ kdb_printf(" default is RDSTCZEU (not Idle or sleeping Daemon)\n");
+ return 0;
+}
+
+
+/*
* kdb_register_repeat - This function is used to register a kernel
* debugger command.
* Inputs:
@@ -2972,6 +2998,8 @@ static void __init kdb_inittab(void)
"Enter kgdb mode", 0, KDB_REPEAT_NONE);
kdb_register_repeat("ps", kdb_ps, "[<flags>|A]",
"Display active task list", 0, KDB_REPEAT_NONE);
+ kdb_register_repeat("pshelp", kdb_ps_help, "",
+ "Display help for the ps and bt task State flag", 0, KDB_REPEAT_NONE);
kdb_register_repeat("pid", kdb_pid, "<pidnum>",
"Switch to another task", 0, KDB_REPEAT_NONE);
kdb_register_repeat("reboot", kdb_reboot, "",
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 10/15] KGDB/KDB: add support for external NMI handler to call KGDB/KDB.
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (8 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 09/15] KDB: Add pshelp command Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 11/15] KDB: add new system NMI entry code to KDB Mike Travis
` (4 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel
[-- Attachment #1: kgdb-add-nmi-callin.patch --]
[-- Type: text/plain, Size: 3068 bytes --]
This patch adds an interface (kgdb_nmicallin) that can be used by
external NMI handlers to call the KGDB/KDB handler. The primary need
for this is for those types of NMI interrupts where all the CPUs
have already received the NMI signal. Therefore no send_IPI(NMI)
is required, and in fact it will cause a 2nd unhandled NMI to occur.
Since all the CPUs are getting the NMI at roughly the same time, it's not
guaranteed that the first CPU that hits the NMI handler will manage to
enter KGDB and set the dbg_master_lock before the slaves start entering.
The new argument "send_ready" is used by KGDB to signal the NMI handler
to release the slave CPUs for entry into KGDB.
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
include/linux/kgdb.h | 1 +
kernel/debug/debug_core.c | 41 +++++++++++++++++++++++++++++++++++++++++
kernel/debug/debug_core.h | 1 +
3 files changed, 43 insertions(+)
--- linux.orig/include/linux/kgdb.h
+++ linux/include/linux/kgdb.h
@@ -310,6 +310,7 @@ extern int
kgdb_handle_exception(int ex_vector, int signo, int err_code,
struct pt_regs *regs);
extern int kgdb_nmicallback(int cpu, void *regs);
+extern int kgdb_nmicallin(int cpu, int trapnr, void *regs, atomic_t *snd_rdy);
extern void gdbstub_exit(int status);
extern int kgdb_single_step;
--- linux.orig/kernel/debug/debug_core.c
+++ linux/kernel/debug/debug_core.c
@@ -578,6 +578,10 @@ return_normal:
/* Signal the other CPUs to enter kgdb_wait() */
if ((!kgdb_single_step) && kgdb_do_roundup)
kgdb_roundup_cpus(flags);
+
+ /* If optional send ready pointer, signal CPUs to proceed */
+ if (kgdb_info[cpu].send_ready)
+ atomic_set(kgdb_info[cpu].send_ready, 1);
#endif
/*
@@ -729,6 +733,43 @@ int kgdb_nmicallback(int cpu, void *regs
return 0;
}
#endif
+ return 1;
+}
+
+int kgdb_nmicallin(int cpu, int trapnr, void *regs, atomic_t *send_ready)
+{
+#ifdef CONFIG_SMP
+ if (!kgdb_io_ready(0))
+ return 1;
+
+ if (kgdb_info[cpu].enter_kgdb == 0) {
+ struct kgdb_state kgdb_var;
+ struct kgdb_state *ks = &kgdb_var;
+ int save_kgdb_do_roundup = kgdb_do_roundup;
+
+ memset(ks, 0, sizeof(struct kgdb_state));
+ ks->cpu = cpu;
+ ks->ex_vector = trapnr;
+ ks->signo = SIGTRAP;
+ ks->err_code = 0;
+ ks->kgdb_usethreadid = 0;
+ ks->linux_regs = regs;
+
+ /* Do not broadcast NMI */
+ kgdb_do_roundup = 0;
+
+ /* Indicate there are slaves waiting */
+ kgdb_info[cpu].send_ready = send_ready;
+ kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER);
+ kgdb_do_roundup = save_kgdb_do_roundup;
+ kgdb_info[cpu].send_ready = NULL;
+
+ /* Wait till all the CPUs have quit from the debugger. */
+ while (atomic_read(&slaves_in_kgdb))
+ cpu_relax();
+ return 0;
+ }
+#endif
return 1;
}
--- linux.orig/kernel/debug/debug_core.h
+++ linux/kernel/debug/debug_core.h
@@ -37,6 +37,7 @@ struct kgdb_state {
struct debuggerinfo_struct {
void *debuggerinfo;
struct task_struct *task;
+ atomic_t *send_ready;
int exception_state;
int ret_state;
int irq_depth;
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 11/15] KDB: add new system NMI entry code to KDB
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (9 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 10/15] KGDB/KDB: add support for external NMI handler to call KGDB/KDB Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 12/15] x86/UV: Move NMI support Mike Travis
` (3 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel
[-- Attachment #1: kdb-add-system-nmi.patch --]
[-- Type: text/plain, Size: 2962 bytes --]
This patch adds a new "KDB_REASON" code (KDB_REASON_SYSTEM_NMI).
This is purely cosmetic to distinguish it from the other various
reasons that NMI may occur and are usually after an error occurred.
Also the dumping of registers is not done to more closely match
what happens when KDB is entered manually via the sysreq 'g' key.
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
include/linux/kdb.h | 1 +
include/linux/kgdb.h | 1 +
kernel/debug/debug_core.c | 5 +++++
kernel/debug/kdb/kdb_debugger.c | 5 ++++-
kernel/debug/kdb/kdb_main.c | 3 +++
5 files changed, 14 insertions(+), 1 deletion(-)
--- linux.orig/include/linux/kdb.h
+++ linux/include/linux/kdb.h
@@ -110,6 +110,7 @@ typedef enum {
KDB_REASON_RECURSE, /* Recursive entry to kdb;
* regs probably valid */
KDB_REASON_SSTEP, /* Single Step trap. - regs valid */
+ KDB_REASON_SYSTEM_NMI, /* In NMI due to SYSTEM cmd; regs valid */
} kdb_reason_t;
extern int kdb_trap_printk;
--- linux.orig/include/linux/kgdb.h
+++ linux/include/linux/kgdb.h
@@ -52,6 +52,7 @@ extern int kgdb_connected;
extern int kgdb_io_module_registered;
extern atomic_t kgdb_setting_breakpoint;
+extern atomic_t kgdb_system_nmi;
extern atomic_t kgdb_cpu_doing_single_step;
extern struct task_struct *kgdb_usethread;
--- linux.orig/kernel/debug/debug_core.c
+++ linux/kernel/debug/debug_core.c
@@ -125,6 +125,7 @@ static atomic_t masters_in_kgdb;
static atomic_t slaves_in_kgdb;
static atomic_t kgdb_break_tasklet_var;
atomic_t kgdb_setting_breakpoint;
+atomic_t kgdb_system_nmi;
struct task_struct *kgdb_usethread;
struct task_struct *kgdb_contthread;
@@ -760,7 +761,11 @@ int kgdb_nmicallin(int cpu, int trapnr,
/* Indicate there are slaves waiting */
kgdb_info[cpu].send_ready = send_ready;
+
+ /* Use new reason code "SYSTEM_NMI" */
+ atomic_inc(&kgdb_system_nmi);
kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER);
+ atomic_dec(&kgdb_system_nmi);
kgdb_do_roundup = save_kgdb_do_roundup;
kgdb_info[cpu].send_ready = NULL;
--- linux.orig/kernel/debug/kdb/kdb_debugger.c
+++ linux/kernel/debug/kdb/kdb_debugger.c
@@ -69,7 +69,10 @@ int kdb_stub(struct kgdb_state *ks)
if (atomic_read(&kgdb_setting_breakpoint))
reason = KDB_REASON_KEYBOARD;
- if (in_nmi())
+ if (atomic_read(&kgdb_system_nmi))
+ reason = KDB_REASON_SYSTEM_NMI;
+
+ else if (in_nmi())
reason = KDB_REASON_NMI;
for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {
--- linux.orig/kernel/debug/kdb/kdb_main.c
+++ linux/kernel/debug/kdb/kdb_main.c
@@ -1216,6 +1216,9 @@ static int kdb_local(kdb_reason_t reason
instruction_pointer(regs));
kdb_dumpregs(regs);
break;
+ case KDB_REASON_SYSTEM_NMI:
+ kdb_printf("due to System NonMaskable Interrupt\n");
+ break;
case KDB_REASON_NMI:
kdb_printf("due to NonMaskable Interrupt @ "
kdb_machreg_fmt "\n",
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 12/15] x86/UV: Move NMI support
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (10 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 11/15] KDB: add new system NMI entry code to KDB Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 13/15] x86/UV: Add uvtrace support Mike Travis
` (2 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Alex Shi, Cliff Wickman,
Alexander Gordeev, Suresh Siddha, Michael S. Tsirkin,
Steffen Persvold
[-- Attachment #1: uv-move-nmi-support.patch --]
[-- Type: text/plain, Size: 7738 bytes --]
This patch moves the UV NMI support from the x2apic file to a
new separate uv_nmi.c file in preparation for the next sequence
of patches. It minimizes bloat of the x2apic file, and has the
added benefit of putting the upcoming /sys/module parameters under
the name 'uv_nmi' instead of 'x2apic_uv_x', which was obscure.
Cc: Alex Shi <alex.shi@intel.com>
Cc: Cliff Wickman <cpw@sgi.com>
Cc: Alexander Gordeev <agordeev@redhat.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Steffen Persvold <sp@numascale.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
arch/x86/include/asm/uv/uv.h | 2
arch/x86/kernel/apic/x2apic_uv_x.c | 69 -------------------------
arch/x86/platform/uv/Makefile | 2
arch/x86/platform/uv/uv_nmi.c | 101 +++++++++++++++++++++++++++++++++++++
4 files changed, 104 insertions(+), 70 deletions(-)
--- linux.orig/arch/x86/include/asm/uv/uv.h
+++ linux/arch/x86/include/asm/uv/uv.h
@@ -12,6 +12,7 @@ extern enum uv_system_type get_uv_system
extern int is_uv_system(void);
extern void uv_cpu_init(void);
extern void uv_nmi_init(void);
+extern void uv_register_nmi_notifier(void);
extern void uv_system_init(void);
extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct mm_struct *mm,
@@ -25,6 +26,7 @@ static inline enum uv_system_type get_uv
static inline int is_uv_system(void) { return 0; }
static inline void uv_cpu_init(void) { }
static inline void uv_system_init(void) { }
+static inline void uv_register_nmi_notifier(void) { }
static inline const struct cpumask *
uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm,
unsigned long start, unsigned long end, unsigned int cpu)
--- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c
+++ linux/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -39,12 +39,6 @@
#include <asm/emergency-restart.h>
#include <asm/nmi.h>
-/* BMC sets a bit this MMR non-zero before sending an NMI */
-#define UVH_NMI_MMR UVH_SCRATCH5
-#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8)
-#define UV_NMI_PENDING_MASK (1UL << 63)
-DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
-
DEFINE_PER_CPU(int, x2apic_extra_bits);
#define PR_DEVEL(fmt, args...) pr_devel("%s: " fmt, __func__, args)
@@ -56,7 +50,6 @@ int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
unsigned int uv_apicid_hibits;
EXPORT_SYMBOL_GPL(uv_apicid_hibits);
-static DEFINE_SPINLOCK(uv_nmi_lock);
static struct apic apic_x2apic_uv_x;
@@ -795,68 +788,6 @@ void __cpuinit uv_cpu_init(void)
set_x2apic_extra_bits(uv_hub_info->pnode);
}
-/*
- * When NMI is received, print a stack trace.
- */
-int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
-{
- unsigned long real_uv_nmi;
- int bid;
-
- /*
- * Each blade has an MMR that indicates when an NMI has been sent
- * to cpus on the blade. If an NMI is detected, atomically
- * clear the MMR and update a per-blade NMI count used to
- * cause each cpu on the blade to notice a new NMI.
- */
- bid = uv_numa_blade_id();
- real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
-
- if (unlikely(real_uv_nmi)) {
- spin_lock(&uv_blade_info[bid].nmi_lock);
- real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
- if (real_uv_nmi) {
- uv_blade_info[bid].nmi_count++;
- uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);
- }
- spin_unlock(&uv_blade_info[bid].nmi_lock);
- }
-
- if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
- return NMI_DONE;
-
- __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
-
- /*
- * Use a lock so only one cpu prints at a time.
- * This prevents intermixed output.
- */
- spin_lock(&uv_nmi_lock);
- pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
- dump_stack();
- spin_unlock(&uv_nmi_lock);
-
- return NMI_HANDLED;
-}
-
-void uv_register_nmi_notifier(void)
-{
- if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
- printk(KERN_WARNING "UV NMI handler failed to register\n");
-}
-
-void uv_nmi_init(void)
-{
- unsigned int value;
-
- /*
- * Unmask NMI on all cpus
- */
- value = apic_read(APIC_LVT1) | APIC_DM_NMI;
- value &= ~APIC_LVT_MASKED;
- apic_write(APIC_LVT1, value);
-}
-
void __init uv_system_init(void)
{
union uvh_rh_gam_config_mmr_u m_n_config;
--- linux.orig/arch/x86/platform/uv/Makefile
+++ linux/arch/x86/platform/uv/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
+obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o
--- /dev/null
+++ linux/arch/x86/platform/uv/uv_nmi.c
@@ -0,0 +1,101 @@
+/*
+ * SGI NMI support routines
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Mike Travis
+ */
+
+#include <linux/cpu.h>
+#include <linux/nmi.h>
+
+#include <asm/apic.h>
+#include <asm/uv/uv.h>
+#include <asm/uv/uv_hub.h>
+#include <asm/uv/uv_mmrs.h>
+
+/* BMC sets a bit this MMR non-zero before sending an NMI */
+#define UVH_NMI_MMR UVH_SCRATCH5
+#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8)
+#define UV_NMI_PENDING_MASK (1UL << 63)
+DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
+static DEFINE_SPINLOCK(uv_nmi_lock);
+
+/*
+ * When NMI is received, print a stack trace.
+ */
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
+{
+ unsigned long real_uv_nmi;
+ int bid;
+
+ /*
+ * Each blade has an MMR that indicates when an NMI has been sent
+ * to cpus on the blade. If an NMI is detected, atomically
+ * clear the MMR and update a per-blade NMI count used to
+ * cause each cpu on the blade to notice a new NMI.
+ */
+ bid = uv_numa_blade_id();
+ real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
+
+ if (unlikely(real_uv_nmi)) {
+ spin_lock(&uv_blade_info[bid].nmi_lock);
+ real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) &
+ UV_NMI_PENDING_MASK);
+ if (real_uv_nmi) {
+ uv_blade_info[bid].nmi_count++;
+ uv_write_local_mmr(UVH_NMI_MMR_CLEAR,
+ UV_NMI_PENDING_MASK);
+ }
+ spin_unlock(&uv_blade_info[bid].nmi_lock);
+ }
+
+ if (likely(__get_cpu_var(cpu_last_nmi_count) ==
+ uv_blade_info[bid].nmi_count))
+ return NMI_DONE;
+
+ __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
+
+ /*
+ * Use a lock so only one cpu prints at a time.
+ * This prevents intermixed output.
+ */
+ spin_lock(&uv_nmi_lock);
+ pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
+ dump_stack();
+ spin_unlock(&uv_nmi_lock);
+
+ return NMI_HANDLED;
+}
+
+void uv_register_nmi_notifier(void)
+{
+ if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
+ pr_warn("UV NMI handler failed to register\n");
+}
+
+void uv_nmi_init(void)
+{
+ unsigned int value;
+
+ /*
+ * Unmask NMI on all cpus
+ */
+ value = apic_read(APIC_LVT1) | APIC_DM_NMI;
+ value &= ~APIC_LVT_MASKED;
+ apic_write(APIC_LVT1, value);
+}
+
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 13/15] x86/UV: Add uvtrace support
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (11 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 12/15] x86/UV: Move NMI support Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 14/15] x86/UV: Update UV support for external NMI signals Mike Travis
2013-03-25 18:50 ` [PATCH 15/15] x86/UV: Add call to KGDB/KDB from NMI handler Mike Travis
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Alex Shi, Cliff Wickman,
Alexander Gordeev, Suresh Siddha, Michael S. Tsirkin,
Steffen Persvold
[-- Attachment #1: uv-add-trace-support.patch --]
[-- Type: text/plain, Size: 2948 bytes --]
This patch adds support for the uvtrace KDB module by providing a
skeleton call to the registered trace function. It also provides
another separate 'NMI' tracer that is triggered by the system wide
'power nmi' command.
Cc: Alex Shi <alex.shi@intel.com>
Cc: Cliff Wickman <cpw@sgi.com>
Cc: Alexander Gordeev <agordeev@redhat.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Steffen Persvold <sp@numascale.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
arch/x86/include/asm/uv/uv.h | 12 ++++++++++--
arch/x86/platform/uv/uv_nmi.c | 10 +++++++++-
2 files changed, 19 insertions(+), 3 deletions(-)
--- linux.orig/arch/x86/include/asm/uv/uv.h
+++ linux/arch/x86/include/asm/uv/uv.h
@@ -14,24 +14,32 @@ extern void uv_cpu_init(void);
extern void uv_nmi_init(void);
extern void uv_register_nmi_notifier(void);
extern void uv_system_init(void);
+extern void (*uv_trace_nmi_func)(int cpu, struct pt_regs *regs, int ignored);
+extern void (*uv_trace_func)(const char *f, const int l, const char *fmt, ...);
+#define uvtrace(fmt, ...) \
+do { \
+ if (unlikely(uv_trace_func)) \
+ (uv_trace_func)(__func__, __LINE__, fmt, ##__VA_ARGS__);\
+} while (0)
extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct mm_struct *mm,
unsigned long start,
unsigned long end,
unsigned int cpu);
-#else /* X86_UV */
+#else /* !X86_UV */
static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; }
static inline int is_uv_system(void) { return 0; }
static inline void uv_cpu_init(void) { }
static inline void uv_system_init(void) { }
+static inline void uvtrace(void *fmt, ...) { }
static inline void uv_register_nmi_notifier(void) { }
static inline const struct cpumask *
uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm,
unsigned long start, unsigned long end, unsigned int cpu)
{ return cpumask; }
-#endif /* X86_UV */
+#endif /* !X86_UV */
#endif /* _ASM_X86_UV_UV_H */
--- linux.orig/arch/x86/platform/uv/uv_nmi.c
+++ linux/arch/x86/platform/uv/uv_nmi.c
@@ -1,5 +1,5 @@
/*
- * SGI NMI support routines
+ * SGI NMI/TRACE support routines
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
*/
#include <linux/cpu.h>
+#include <linux/module.h>
#include <linux/nmi.h>
#include <asm/apic.h>
@@ -34,6 +35,13 @@
DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
static DEFINE_SPINLOCK(uv_nmi_lock);
+void (*uv_trace_func)(const char *f, const int l, const char *fmt, ...);
+EXPORT_SYMBOL(uv_trace_func);
+
+void (*uv_trace_nmi_func)(int cpu, struct pt_regs *regs, int ignored);
+EXPORT_SYMBOL(uv_trace_nmi_func);
+
+
/*
* When NMI is received, print a stack trace.
*/
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 14/15] x86/UV: Update UV support for external NMI signals
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (12 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 13/15] x86/UV: Add uvtrace support Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
2013-03-25 18:50 ` [PATCH 15/15] x86/UV: Add call to KGDB/KDB from NMI handler Mike Travis
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Russ Anderson,
Alexander Gordeev, Suresh Siddha, Michael S. Tsirkin,
Steffen Persvold
[-- Attachment #1: uv-update-nmi-support.patch --]
[-- Type: text/plain, Size: 24423 bytes --]
This patch updates the UV NMI handler for the external SMM
'POWER NMI' command. This command sets a special flag in one
of the MMRs on each HUB and sends the NMI signal to all cpus
in the system.
The code has also been optimized to minimize reading of the MMRs as
much as possible, by using a per HUB atomic NMI flag. Too high a
rate of reading MMRs not only disrupts the UV Hub's primary function
of directing NumaLink traffic, but can also cause problems. And to
avoid excessive overhead when perf tools are causing millions of
NMIs per second (when running on a large number of CPUS), this
handler uses primarily the NMI_UNKNOWN notifier chain.
There is an exception where the NMI_LOCAL notifier chain is used.
When the perf tools are in use, it's possible that our NMI was
captured by some other NMI handler and then ignored. We set a
per_cpu flag for those CPUs that ignored the initial NMI, and then
send them an IPI NMI signal.
There are also some new parameters introduced to alter and tune the
behavior of the NMI handler. These parameters are not documented in
Documentation/kernel-parameters.txt as they are only useful to SGI
support personnel, and are not generally useful to system users.
Cc: Russ Anderson <rja@sgi.com>
Cc: Alexander Gordeev <agordeev@redhat.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Steffen Persvold <sp@numascale.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
arch/x86/include/asm/uv/uv_hub.h | 57 +++
arch/x86/include/asm/uv/uv_mmrs.h | 31 +
arch/x86/kernel/apic/x2apic_uv_x.c | 1
arch/x86/platform/uv/uv_nmi.c | 610 ++++++++++++++++++++++++++++++++++---
4 files changed, 658 insertions(+), 41 deletions(-)
--- linux.orig/arch/x86/include/asm/uv/uv_hub.h
+++ linux/arch/x86/include/asm/uv/uv_hub.h
@@ -502,8 +502,8 @@ struct uv_blade_info {
unsigned short nr_online_cpus;
unsigned short pnode;
short memory_nid;
- spinlock_t nmi_lock;
- unsigned long nmi_count;
+ spinlock_t nmi_lock; /* obsolete, see uv_hub_nmi */
+ unsigned long nmi_count; /* obsolete, see uv_hub_nmi */
};
extern struct uv_blade_info *uv_blade_info;
extern short *uv_node_to_blade;
@@ -576,6 +576,59 @@ static inline int uv_num_possible_blades
return uv_possible_blades;
}
+/* Per Hub NMI support */
+extern void uv_nmi_setup(void);
+
+/* BMC sets a bit this MMR non-zero before sending an NMI */
+#define UVH_NMI_MMR UVH_SCRATCH5
+#define UVH_NMI_MMR_CLEAR UVH_SCRATCH5_ALIAS
+#define UVH_NMI_MMR_SHIFT 63
+#define UVH_NMI_MMR_TYPE "SCRATCH5"
+
+/* Newer SMM NMI handler, not present in all systems */
+#define UVH_NMI_MMRX UVH_EVENT_OCCURRED0
+#define UVH_NMI_MMRX_CLEAR UVH_EVENT_OCCURRED0_ALIAS
+#define UVH_NMI_MMRX_SHIFT (is_uv1_hub() ? \
+ UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :\
+ UVXH_EVENT_OCCURRED0_EXTIO_INT0_SHFT)
+#define UVH_NMI_MMRX_TYPE "EXTIO_INT0"
+
+/* Non-zero indicates newer SMM NMI handler present */
+#define UVH_NMI_MMRX_SUPPORTED UVH_EXTIO_INT0_BROADCAST
+
+/* Indicates to BIOS that we want to use the newer SMM NMI handler */
+#define UVH_NMI_MMRX_REQ UVH_SCRATCH5_ALIAS_2
+#define UVH_NMI_MMRX_REQ_SHIFT 62
+
+struct uv_hub_nmi_s {
+ raw_spinlock_t nmi_lock;
+ atomic_t in_nmi; /* flag this node in UV NMI IRQ */
+ atomic_t cpu_owner; /* last locker of this struct */
+ atomic_t read_mmr_count; /* count of MMR reads */
+ atomic_t nmi_count; /* count of true UV NMIs */
+ unsigned long nmi_value; /* last value read from NMI MMR */
+};
+
+struct uv_cpu_nmi_s {
+ struct uv_hub_nmi_s *hub;
+ atomic_t state;
+ atomic_t pinging;
+ int queries;
+ int pings;
+};
+
+DECLARE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi);
+#define uv_cpu_nmi (__get_cpu_var(__uv_cpu_nmi))
+#define uv_hub_nmi (uv_cpu_nmi.hub)
+#define uv_cpu_nmi_per(cpu) (per_cpu(__uv_cpu_nmi, cpu))
+#define uv_hub_nmi_per(cpu) (uv_cpu_nmi_per(cpu).hub)
+
+/* uv_cpu_nmi_states */
+#define UV_NMI_STATE_OUT 0
+#define UV_NMI_STATE_IN 1
+#define UV_NMI_STATE_DUMP 2
+#define UV_NMI_STATE_DUMP_DONE 3
+
/* Update SCIR state */
static inline void uv_set_scir_bits(unsigned char value)
{
--- linux.orig/arch/x86/include/asm/uv/uv_mmrs.h
+++ linux/arch/x86/include/asm/uv/uv_mmrs.h
@@ -461,6 +461,23 @@ union uvh_event_occurred0_u {
/* ========================================================================= */
+/* UVH_EXTIO_INT0_BROADCAST */
+/* ========================================================================= */
+#define UVH_EXTIO_INT0_BROADCAST 0x61448UL
+#define UVH_EXTIO_INT0_BROADCAST_32 0x3f0
+
+#define UVH_EXTIO_INT0_BROADCAST_ENABLE_SHFT 0
+#define UVH_EXTIO_INT0_BROADCAST_ENABLE_MASK 0x0000000000000001UL
+
+union uvh_extio_int0_broadcast_u {
+ unsigned long v;
+ struct uvh_extio_int0_broadcast_s {
+ unsigned long enable:1; /* RW */
+ unsigned long rsvd_1_63:63;
+ } s;
+};
+
+/* ========================================================================= */
/* UVH_GR0_TLB_INT0_CONFIG */
/* ========================================================================= */
#define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
@@ -2606,6 +2623,20 @@ union uvh_scratch5_u {
};
/* ========================================================================= */
+/* UVH_SCRATCH5_ALIAS */
+/* ========================================================================= */
+#define UVH_SCRATCH5_ALIAS 0x2d0208UL
+#define UVH_SCRATCH5_ALIAS_32 0x780
+
+
+/* ========================================================================= */
+/* UVH_SCRATCH5_ALIAS_2 */
+/* ========================================================================= */
+#define UVH_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UVH_SCRATCH5_ALIAS_2_32 0x788
+
+
+/* ========================================================================= */
/* UVXH_EVENT_OCCURRED2 */
/* ========================================================================= */
#define UVXH_EVENT_OCCURRED2 0x70100UL
--- linux.orig/arch/x86/kernel/apic/x2apic_uv_x.c
+++ linux/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -925,6 +925,7 @@ void __init uv_system_init(void)
map_mmr_high(max_pnode);
map_mmioh_high(min_pnode, max_pnode);
+ uv_nmi_setup();
uv_cpu_init();
uv_scir_register_cpu_notifier();
uv_register_nmi_notifier();
--- linux.orig/arch/x86/platform/uv/uv_nmi.c
+++ linux/arch/x86/platform/uv/uv_nmi.c
@@ -20,79 +20,584 @@
*/
#include <linux/cpu.h>
+#include <linux/delay.h>
#include <linux/module.h>
#include <linux/nmi.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#if defined(CONFIG_KEXEC)
+#include <linux/kexec.h>
+#endif
#include <asm/apic.h>
+#include <asm/current.h>
+#include <asm/kdebug.h>
+#include <asm/local64.h>
#include <asm/uv/uv.h>
#include <asm/uv/uv_hub.h>
#include <asm/uv/uv_mmrs.h>
-/* BMC sets a bit this MMR non-zero before sending an NMI */
-#define UVH_NMI_MMR UVH_SCRATCH5
-#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8)
-#define UV_NMI_PENDING_MASK (1UL << 63)
-DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
-static DEFINE_SPINLOCK(uv_nmi_lock);
-
void (*uv_trace_func)(const char *f, const int l, const char *fmt, ...);
EXPORT_SYMBOL(uv_trace_func);
void (*uv_trace_nmi_func)(int cpu, struct pt_regs *regs, int ignored);
EXPORT_SYMBOL(uv_trace_nmi_func);
+/*
+ * UV handler for NMI
+ *
+ * Handle system-wide NMI events generated by the global 'power nmi' command.
+ *
+ * Basic operation is to field the NMI interrupt on each cpu and wait
+ * until all cpus have arrived into the nmi handler. If some cpus do not
+ * make it into the handler, try and force them in with the IPI(NMI) signal.
+ *
+ * We also have to lessen UV Hub MMR accesses as much as possible as this
+ * disrupts the UV Hub's primary mission of directing NumaLink traffic and
+ * can cause system problems to occur.
+ *
+ * To do this we register our primary NMI notifier on the NMI_UNKNOWN
+ * chain. This reduces the number of false NMI calls when the perf
+ * tools are running which generate an enormous number of NMIs per
+ * second (~4M/s for 1024 cpu threads). Our secondary NMI handler is
+ * very short as it only checks that if it has been "pinged" with the
+ * IPI(NMI) signal as mentioned above, and does not read the UV Hub's MMR.
+ *
+ */
+
+static struct uv_hub_nmi_s **uv_hub_nmi_list;
+
+DEFINE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi);
+EXPORT_PER_CPU_SYMBOL_GPL(__uv_cpu_nmi);
+
+static unsigned long nmi_mmr;
+static unsigned long nmi_mmr_clear;
+static unsigned long nmi_mmr_pending;
+
+static atomic_t uv_in_nmi;
+static atomic_t uv_nmi_cpu = ATOMIC_INIT(-1);
+static atomic_t uv_nmi_cpus_in_nmi = ATOMIC_INIT(-1);
+static atomic_t uv_nmi_slave_continue;
+static cpumask_var_t uv_nmi_cpu_mask;
+
+static int param_get_local64(char *buffer, const struct kernel_param *kp)
+{
+ return sprintf(buffer, "%lu\n", local64_read((local64_t *)kp->arg));
+}
+
+static int param_set_local64(const char *val, const struct kernel_param *kp)
+{
+ /* clear on any write */
+ local64_set((local64_t *)kp->arg, 0);
+ return 0;
+}
+
+static struct kernel_param_ops param_ops_local64 = {
+ .get = param_get_local64,
+ .set = param_set_local64,
+};
+#define param_check_local64(name, p) __param_check(name, p, local64_t)
+
+static local64_t uv_nmi_count;
+module_param_named(nmi_count, uv_nmi_count, local64, 0644);
+
+static local64_t uv_nmi_misses;
+module_param_named(nmi_misses, uv_nmi_misses, local64, 0644);
+
+static local64_t uv_nmi_ping_count;
+module_param_named(ping_count, uv_nmi_ping_count, local64, 0644);
+
+static local64_t uv_nmi_ping_misses;
+module_param_named(ping_misses, uv_nmi_ping_misses, local64, 0644);
+
+static int uv_nmi_loglevel = 1;
+module_param_named(dump_loglevel, uv_nmi_loglevel, int, 0644);
+
+static int uv_nmi_ips_only;
+module_param_named(dump_ips_only, uv_nmi_ips_only, int, 0644);
+
+static int uv_nmi_kdump_requested;
+module_param_named(nmi_does_kdump, uv_nmi_kdump_requested, int, 0644);
+
+static int uv_nmi_initial_delay = 100;
+module_param_named(initial_delay, uv_nmi_initial_delay, int, 0644);
+
+static int uv_nmi_slave_delay = 100;
+module_param_named(slave_delay, uv_nmi_slave_delay, int, 0644);
+
+static int uv_nmi_loop_delay = 100;
+module_param_named(loop_delay, uv_nmi_loop_delay, int, 0644);
+
+static int uv_nmi_wait_count = 100;
+module_param_named(wait_count, uv_nmi_wait_count, int, 0644);
+
+static int uv_nmi_retry_count = 500;
+module_param_named(retry_count, uv_nmi_retry_count, int, 0644);
+
+#if defined(CONFIG_KEXEC)
+static void uv_nmi_kdump(struct pt_regs *regs)
+{
+ if (!kexec_crash_image) {
+ pr_err("UV: NMI kdump error: crash kernel not loaded\n");
+ return;
+ }
+
+ /* Call crash to dump system state */
+ pr_err("UV: NMI executing kdump [crash_kexec] on CPU%d\n",
+ smp_processor_id());
+ crash_kexec(regs);
+
+ /* If the above call returned then something didn't work */
+ pr_err("UV: NMI kdump error: crash_kexec failed!\n");
+}
+
+#else /* !CONFIG_KEXEC */
+static inline void uv_nmi_kdump(struct pt_regs *regs)
+{
+ pr_err("UV: NMI kdump error: KEXEC not supported in this kernel\n");
+}
+
+#endif /* !CONFIG_KEXEC */
+
+/* Setup which NMI support is present in system */
+static void uv_nmi_setup_mmrs(void)
+{
+ if (uv_read_local_mmr(UVH_NMI_MMRX_SUPPORTED)) {
+ uv_write_local_mmr(UVH_NMI_MMRX_REQ,
+ 1UL << UVH_NMI_MMRX_REQ_SHIFT);
+ nmi_mmr = UVH_NMI_MMRX;
+ nmi_mmr_clear = UVH_NMI_MMRX_CLEAR;
+ nmi_mmr_pending = 1UL << UVH_NMI_MMRX_SHIFT;
+ pr_info("UV: SMM NMI support: %s\n", UVH_NMI_MMRX_TYPE);
+ } else {
+ nmi_mmr = UVH_NMI_MMR;
+ nmi_mmr_clear = UVH_NMI_MMR_CLEAR;
+ nmi_mmr_pending = 1UL << UVH_NMI_MMR_SHIFT;
+ pr_info("UV: SMM NMI support: %s\n", UVH_NMI_MMR_TYPE);
+ }
+}
+
+/* Read NMI MMR and check if NMI flag was set by BMC. */
+static inline int uv_nmi_test_mmr(struct uv_hub_nmi_s *hub_nmi)
+{
+ hub_nmi->nmi_value = uv_read_local_mmr(nmi_mmr);
+ atomic_inc(&hub_nmi->read_mmr_count);
+ return !!(hub_nmi->nmi_value & nmi_mmr_pending);
+}
+
+static inline void uv_local_mmr_clear_nmi(void)
+{
+ uv_write_local_mmr(nmi_mmr_clear, nmi_mmr_pending);
+}
/*
- * When NMI is received, print a stack trace.
+ * If first cpu in on this hub, set hub_nmi "in_nmi" and "owner" values and
+ * return true. If first cpu in on the system, set global "in_nmi" flag.
*/
-int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
+static int uv_set_in_nmi(int cpu, struct uv_hub_nmi_s *hub_nmi)
{
- unsigned long real_uv_nmi;
- int bid;
+ int first = atomic_add_unless(&hub_nmi->in_nmi, 1, 1);
- /*
- * Each blade has an MMR that indicates when an NMI has been sent
- * to cpus on the blade. If an NMI is detected, atomically
- * clear the MMR and update a per-blade NMI count used to
- * cause each cpu on the blade to notice a new NMI.
- */
- bid = uv_numa_blade_id();
- real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
+ if (first) {
+ atomic_set(&hub_nmi->cpu_owner, cpu);
+ if (atomic_add_unless(&uv_in_nmi, 1, 1))
+ atomic_set(&uv_nmi_cpu, cpu);
+
+ atomic_inc(&hub_nmi->nmi_count);
+ }
+ return first;
+}
+
+/* Check if this is a system NMI event */
+static int uv_check_nmi(struct uv_hub_nmi_s *hub_nmi)
+{
+ int cpu = smp_processor_id();
+ int nmi = 0;
+
+ local64_inc(&uv_nmi_count);
+ uv_cpu_nmi.queries++;
+
+ do {
+ nmi = atomic_read(&hub_nmi->in_nmi);
+ if (nmi)
+ break;
+
+ if (raw_spin_trylock(&hub_nmi->nmi_lock)) {
+
+ /* check hub MMR NMI flag */
+ if (uv_nmi_test_mmr(hub_nmi)) {
+ uv_set_in_nmi(cpu, hub_nmi);
+ nmi = 1;
+ break;
+ }
+
+ /* MMR NMI flag is clear */
+ raw_spin_unlock(&hub_nmi->nmi_lock);
+
+ } else {
+ /* wait a moment for the hub nmi locker to set flag */
+ cpu_relax();
+ udelay(uv_nmi_slave_delay);
+
+ /* re-check hub in_nmi flag */
+ nmi = atomic_read(&hub_nmi->in_nmi);
+ if (nmi)
+ break;
+ }
+
+ /*
+ * check system-wide uv_in_nmi flag
+ * (this check because on large UV1000 systems, the NMI signal
+ * may arrive before the BMC has set this hub's NMI flag in
+ * the MMR.)
+ */
+ if (!nmi) {
+ nmi = atomic_read(&uv_in_nmi);
+ if (nmi)
+ uv_set_in_nmi(cpu, hub_nmi);
+ }
+
+ } while (0);
+
+ if (!nmi)
+ local64_inc(&uv_nmi_misses);
+
+ return nmi;
+}
+
+/* Need to reset the NMI MMR register, but only once per hub. */
+static inline void uv_clear_nmi(int cpu)
+{
+ struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi;
+
+ if (cpu == atomic_read(&hub_nmi->cpu_owner)) {
+ atomic_set(&hub_nmi->cpu_owner, -1);
+ atomic_set(&hub_nmi->in_nmi, 0);
+ uv_local_mmr_clear_nmi();
+ raw_spin_unlock(&hub_nmi->nmi_lock);
+ }
+}
+
+/* Print non-responding cpus */
+static void uv_nmi_nr_cpus_pr(char *fmt)
+{
+ static char cpu_list[1024];
+ int len = sizeof(cpu_list);
+ int c = cpumask_weight(uv_nmi_cpu_mask);
+ int n = cpulist_scnprintf(cpu_list, len, uv_nmi_cpu_mask);
+
+ if (n >= len-1)
+ strcpy(&cpu_list[len - 6], "...\n");
+
+ /* (can't use pr_* with variable fmt) */
+ printk(fmt, c, cpu_list);
+}
+
+/* Ping non-responding cpus attemping to force them into the NMI handler */
+static void uv_nmi_nr_cpus_ping(void)
+{
+ int cpu;
+
+ for_each_cpu(cpu, uv_nmi_cpu_mask)
+ atomic_set(&uv_cpu_nmi_per(cpu).pinging, 1);
- if (unlikely(real_uv_nmi)) {
- spin_lock(&uv_blade_info[bid].nmi_lock);
- real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) &
- UV_NMI_PENDING_MASK);
- if (real_uv_nmi) {
- uv_blade_info[bid].nmi_count++;
- uv_write_local_mmr(UVH_NMI_MMR_CLEAR,
- UV_NMI_PENDING_MASK);
+ apic->send_IPI_mask(uv_nmi_cpu_mask, APIC_DM_NMI);
+}
+
+/* Clean up flags for cpus that ignored both NMI and ping */
+static void uv_nmi_cleanup_mask(void)
+{
+ int cpu;
+
+ for_each_cpu(cpu, uv_nmi_cpu_mask) {
+ atomic_set(&uv_cpu_nmi_per(cpu).pinging, 0);
+ atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_OUT);
+ cpumask_clear_cpu(cpu, uv_nmi_cpu_mask);
+ }
+}
+
+/* Loop waiting as cpus enter nmi handler */
+static int uv_nmi_wait_cpus(int cpu, int first)
+{
+ int i, j, k, n = num_online_cpus();
+ int last_k = 0, waiting = 0;
+
+ if (first) {
+ cpumask_copy(uv_nmi_cpu_mask, cpu_online_mask);
+ k = 0;
+ } else
+ k = n - cpumask_weight(uv_nmi_cpu_mask);
+
+ udelay(uv_nmi_initial_delay);
+ for (i = 0; i < uv_nmi_retry_count; i++) {
+ int loop_delay = uv_nmi_loop_delay;
+
+ for_each_cpu(j, uv_nmi_cpu_mask) {
+ if (atomic_read(&uv_cpu_nmi_per(j).state)) {
+ cpumask_clear_cpu(j, uv_nmi_cpu_mask);
+ if (++k >= n)
+ break;
+ }
+ }
+ if (k >= n) { /* all in? */
+ k = n;
+ break;
+ }
+ if (last_k != k) { /* abort if none coming in */
+ last_k = k;
+ waiting = 0;
+ } else if (++waiting > uv_nmi_wait_count)
+ break;
+
+ /* extend delay if only waiting for cpu that sent the nmi */
+ if (waiting && (n - k) == 1 &&
+ cpumask_test_cpu(0, uv_nmi_cpu_mask))
+ loop_delay *= 100;
+
+ udelay(loop_delay);
+ }
+ atomic_set(&uv_nmi_cpus_in_nmi, k);
+ return n - k;
+}
+
+/* Wait until all cpus have entered NMI handler */
+static int uv_nmi_wait(int cpu)
+{
+ /* indicate this cpu is in */
+ atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_IN);
+
+ /* if we are not the first cpu in, we are a slave cpu */
+ if (atomic_read(&uv_nmi_cpu) != cpu)
+ return -1;
+
+ do {
+ /* wait for all other cpus to gather here */
+ if (!uv_nmi_wait_cpus(cpu, 1))
+ break;
+
+ /* if not all made it in, send IPI NMI to them */
+ uv_nmi_nr_cpus_pr(
+ "UV: Sending NMI IPI to %d non-responding CPUs: %s\n");
+ uv_nmi_nr_cpus_ping();
+
+ /* if some cpus are still not in, ignore them */
+ if (!uv_nmi_wait_cpus(cpu, 0))
+ break;
+
+ uv_nmi_nr_cpus_pr("UV: %d CPUs not in NMI loop: %s\n");
+ } while (0);
+
+ pr_err("UV: %d of %d CPUs in NMI\n",
+ atomic_read(&uv_nmi_cpus_in_nmi), num_online_cpus());
+
+ return cpu;
+}
+
+static void uv_nmi_dump_cpu_ip_hdr(void)
+{
+ printk("UV: NMI %4s %6s %16s %16s [PID 0 suppressed]\n",
+ "CPU", "PID", "COMMAND", "IP");
+}
+
+static void uv_nmi_dump_cpu_ip(int cpu, struct pt_regs *regs)
+{
+ printk("UV: NMI %4d %6d %-32.32s ",
+ cpu, current->pid, current->comm);
+
+ printk_address(regs->ip, 1);
+}
+
+/* Dump this cpu's state */
+static void uv_nmi_dump_state_cpu(int cpu, struct pt_regs *regs, int ignored)
+{
+ char *dots = " ................................. ";
+
+ /* call possible nmi trace function */
+ if (unlikely(uv_trace_nmi_func))
+ (uv_trace_nmi_func)(cpu, regs, ignored);
+
+ /* otherwise if dump has been requested */
+ else if (uv_nmi_loglevel) {
+ int saved_console_loglevel = console_loglevel;
+ console_loglevel = uv_nmi_loglevel;
+
+ if (uv_nmi_ips_only) {
+ if (cpu == 0)
+ uv_nmi_dump_cpu_ip_hdr();
+
+ if (ignored)
+ printk("UV: NMI %4d%signored NMI\n", cpu, dots);
+
+ else if (current->pid != 0)
+ uv_nmi_dump_cpu_ip(cpu, regs);
+
+ } else {
+ if (ignored) {
+ printk(
+ "UV:%sNMI ignored on CPU %d\n",
+ dots, cpu);
+ } else {
+ printk("UV:%sNMI process trace for CPU %d\n",
+ dots, cpu);
+ show_regs(regs);
+ }
+ }
+ console_loglevel = saved_console_loglevel;
+ }
+ atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_DUMP_DONE);
+}
+
+/* Trigger a slave cpu to dump it's state */
+static void uv_nmi_trigger_dump(int cpu)
+{
+ int retry = 10000;
+
+ if (atomic_read(&uv_cpu_nmi_per(cpu).state) != UV_NMI_STATE_IN)
+ return;
+
+ atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP);
+ do {
+ cpu_relax();
+ udelay(10);
+ if (atomic_read(&uv_cpu_nmi_per(cpu).state)
+ != UV_NMI_STATE_DUMP)
+ return;
+ } while (--retry > 0);
+
+ pr_err("UV: CPU %d stuck in process dump function\n", cpu);
+ atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP_DONE);
+}
+
+/* Wait until all cpus ready to exit */
+static void uv_nmi_sync_exit(int master)
+{
+ atomic_dec(&uv_nmi_cpus_in_nmi);
+ if (master) {
+ while (atomic_read(&uv_nmi_cpus_in_nmi) > 0)
+ cpu_relax();
+ atomic_set(&uv_nmi_slave_continue, 0);
+ } else {
+ while (atomic_read(&uv_nmi_slave_continue))
+ cpu_relax();
+ }
+}
+
+/* Walk through cpu list and dump state of each */
+static void uv_nmi_dump_state(int cpu, struct pt_regs *regs, int master)
+{
+ if (master) {
+ int tcpu;
+
+ pr_err("UV: tracing %s for %d CPUs from CPU %d\n",
+ uv_nmi_ips_only ? "IPs" : "processes",
+ atomic_read(&uv_nmi_cpus_in_nmi), cpu);
+
+ atomic_set(&uv_nmi_slave_continue, 2);
+ for_each_online_cpu(tcpu) {
+ if (cpumask_test_cpu(tcpu, uv_nmi_cpu_mask))
+ uv_nmi_dump_state_cpu(tcpu, regs, 1);
+ else if (tcpu == cpu)
+ uv_nmi_dump_state_cpu(tcpu, regs, 0);
+ else
+ uv_nmi_trigger_dump(tcpu);
}
- spin_unlock(&uv_blade_info[bid].nmi_lock);
+ pr_err("UV: process trace complete\n");
+ } else {
+ while (!atomic_read(&uv_nmi_slave_continue))
+ cpu_relax();
+ while (atomic_read(&uv_cpu_nmi.state) != UV_NMI_STATE_DUMP)
+ cpu_relax();
+ uv_nmi_dump_state_cpu(cpu, regs, 0);
}
+ uv_nmi_sync_exit(master);
+}
- if (likely(__get_cpu_var(cpu_last_nmi_count) ==
- uv_blade_info[bid].nmi_count))
+static void uv_nmi_touch_watchdogs(void)
+{
+ touch_softlockup_watchdog_sync();
+ clocksource_touch_watchdog();
+ rcu_cpu_stall_reset();
+ touch_nmi_watchdog();
+}
+
+/*
+ * UV NMI handler
+ */
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
+{
+ struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi;
+ int cpu = smp_processor_id();
+ int master = 0;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* If not a UV Global NMI, ignore */
+ if (!atomic_read(&uv_cpu_nmi.pinging) && !uv_check_nmi(hub_nmi)) {
+ local_irq_restore(flags);
return NMI_DONE;
+ }
- __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
+ /* Pause until all cpus are in NMI handler */
+ if (cpu == uv_nmi_wait(cpu))
+ master = 1;
+
+ /* If NMI kdump requested, attempt to do it */
+ if (master && uv_nmi_kdump_requested)
+ uv_nmi_kdump(regs);
+
+ /* Dump state of each cpu */
+ uv_nmi_dump_state(cpu, regs, master);
+
+ /* Clear per_cpu "in nmi" flag */
+ atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT);
+
+ /* Clear MMR NMI flag on each hub */
+ uv_clear_nmi(cpu);
+
+ /* Clear global flags */
+ if (master) {
+ if (cpumask_weight(uv_nmi_cpu_mask))
+ uv_nmi_cleanup_mask();
+ atomic_set(&uv_nmi_cpus_in_nmi, -1);
+ atomic_set(&uv_nmi_cpu, -1);
+ atomic_set(&uv_in_nmi, 0);
+ }
- /*
- * Use a lock so only one cpu prints at a time.
- * This prevents intermixed output.
- */
- spin_lock(&uv_nmi_lock);
- pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
- dump_stack();
- spin_unlock(&uv_nmi_lock);
+ uv_nmi_touch_watchdogs();
+ local_irq_restore(flags);
return NMI_HANDLED;
}
+/*
+ * NMI handler for pulling in CPUs when perf events are grabbing our NMI
+ */
+int uv_handle_nmi_ping(unsigned int reason, struct pt_regs *regs)
+{
+ int ret;
+
+ uv_cpu_nmi.queries++;
+ if (!atomic_read(&uv_cpu_nmi.pinging)) {
+ local64_inc(&uv_nmi_ping_misses);
+ return NMI_DONE;
+ }
+
+ uv_cpu_nmi.pings++;
+ local64_inc(&uv_nmi_ping_count);
+ ret = uv_handle_nmi(reason, regs);
+ atomic_set(&uv_cpu_nmi.pinging, 0);
+ return ret;
+}
+
void uv_register_nmi_notifier(void)
{
if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
pr_warn("UV NMI handler failed to register\n");
+
+ if (register_nmi_handler(NMI_LOCAL, uv_handle_nmi_ping, 0, "uvping"))
+ pr_warn("UV PING NMI handler failed to register\n");
}
void uv_nmi_init(void)
@@ -107,3 +612,30 @@ void uv_nmi_init(void)
apic_write(APIC_LVT1, value);
}
+void uv_nmi_setup(void)
+{
+ int size = sizeof(void *) * (1 << NODES_SHIFT);
+ int cpu, nid;
+
+ /* Setup hub nmi info */
+ uv_nmi_setup_mmrs();
+ uv_hub_nmi_list = kzalloc(size, GFP_KERNEL);
+ pr_info("UV: NMI hub list @ 0x%p (%d)\n", uv_hub_nmi_list, size);
+ BUG_ON(!uv_hub_nmi_list);
+ size = sizeof(struct uv_hub_nmi_s);
+ for_each_present_cpu(cpu) {
+ nid = cpu_to_node(cpu);
+ if (uv_hub_nmi_list[nid] == NULL) {
+ uv_hub_nmi_list[nid] = kzalloc_node(size,
+ GFP_KERNEL, nid);
+ BUG_ON(!uv_hub_nmi_list[nid]);
+ raw_spin_lock_init(&(uv_hub_nmi_list[nid]->nmi_lock));
+ atomic_set(&uv_hub_nmi_list[nid]->cpu_owner, -1);
+ }
+ uv_hub_nmi_per(cpu) = uv_hub_nmi_list[nid];
+ }
+ alloc_cpumask_var(&uv_nmi_cpu_mask, GFP_KERNEL);
+ BUG_ON(!uv_nmi_cpu_mask);
+}
+
+
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 15/15] x86/UV: Add call to KGDB/KDB from NMI handler
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
` (13 preceding siblings ...)
2013-03-25 18:50 ` [PATCH 14/15] x86/UV: Update UV support for external NMI signals Mike Travis
@ 2013-03-25 18:50 ` Mike Travis
14 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 18:50 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Alexander Gordeev,
Suresh Siddha, Michael S. Tsirkin, Steffen Persvold
[-- Attachment #1: uv-add-nmi-call-kdb.patch --]
[-- Type: text/plain, Size: 3380 bytes --]
This patch restores the ability to enter KDB (and KGDB) from the UV
NMI handler. It utilizes the newly added kgdb_nmicallin function
to gain entry to KGDB/KDB by the master. The slaves still enter via
the standard kgdb_nmicallback function.
The handler also uses the new 'send_ready' pointer to tell KGDB/KDB
to signal the slaves when to proceed into the KGDB slave loop.
Cc: Alexander Gordeev <agordeev@redhat.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Steffen Persvold <sp@numascale.com>
Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
Signed-off-by: Mike Travis <travis@sgi.com>
---
arch/x86/platform/uv/uv_nmi.c | 73 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)
--- linux.orig/arch/x86/platform/uv/uv_nmi.c
+++ linux/arch/x86/platform/uv/uv_nmi.c
@@ -21,6 +21,8 @@
#include <linux/cpu.h>
#include <linux/delay.h>
+#include <linux/kgdb.h>
+#include <linux/kdb.h>
#include <linux/module.h>
#include <linux/nmi.h>
#include <linux/sched.h>
@@ -34,6 +36,7 @@
#include <asm/current.h>
#include <asm/kdebug.h>
#include <asm/local64.h>
+#include <asm/traps.h>
#include <asm/uv/uv.h>
#include <asm/uv/uv_hub.h>
#include <asm/uv/uv_mmrs.h>
@@ -521,6 +524,68 @@ static void uv_nmi_touch_watchdogs(void)
touch_nmi_watchdog();
}
+#ifdef CONFIG_KGDB_KDB
+
+/* Disable to force process dump instead of entering KDB or KGDB */
+static int uv_nmi_kdb_on = 1;
+module_param_named(kdb_on, uv_nmi_kdb_on, int, 0644);
+
+/* Call KDB from NMI handler */
+static void uv_call_kdb(int cpu, struct pt_regs *regs,
+ int master, unsigned long *flags)
+{
+ int ret;
+
+ if (master) {
+ /* call KGDB NMI handler as MASTER */
+ local_irq_restore(*flags);
+ ret = kgdb_nmicallin(cpu, X86_TRAP_NMI, regs,
+ &uv_nmi_slave_continue);
+ local_irq_save(*flags);
+
+ /*
+ * if KGDB/KDB did not handle the NMI, then signal slaves
+ * to do process dump instead.
+ */
+ if (ret) {
+ uv_nmi_dump_state(cpu, regs, 1);
+ return;
+ }
+ } else {
+ int sig;
+
+ /* wait for KGDB to say it's ready for slaves to enter */
+ do {
+ cpu_relax();
+ sig = atomic_read(&uv_nmi_slave_continue);
+ } while (!sig);
+
+ /*
+ * if KGDB/KDB did not handle the NMI for the master, then
+ * the master signals the slaves to do process dump instead.
+ */
+ if (sig == 2) {
+ uv_nmi_dump_state(cpu, regs, 0);
+ return;
+ }
+
+ /* call KGDB as slave */
+ local_irq_restore(*flags);
+ ret = kgdb_nmicallback(cpu, regs);
+ local_irq_save(*flags);
+ }
+ uv_nmi_sync_exit(master);
+}
+
+#else /* !CONFIG_KGDB_KDB */
+static inline void uv_call_kdb(int cpu, struct pt_regs *regs,
+ int master, unsigned long *flags)
+{
+ pr_err("UV: NMI error: KDB is not enabled in this kernel\n");
+ uv_nmi_dump_state(cpu, regs, master);
+}
+#endif /* !CONFIG_KGDB_KDB */
+
/*
* UV NMI handler
*/
@@ -547,8 +612,12 @@ int uv_handle_nmi(unsigned int reason, s
if (master && uv_nmi_kdump_requested)
uv_nmi_kdump(regs);
- /* Dump state of each cpu */
- uv_nmi_dump_state(cpu, regs, master);
+ /* Call KDB if enabled */
+ if (uv_nmi_kdb_on)
+ uv_call_kdb(cpu, regs, master, &flags);
+
+ else /* Otherwise dump state of each cpu */
+ uv_nmi_dump_state(cpu, regs, master);
/* Clear per_cpu "in nmi" flag */
atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT);
--
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 01/15] KDB: fix the interrupt of the KDB btc command
2013-03-25 18:50 ` [PATCH 01/15] KDB: fix the interrupt of the KDB btc command Mike Travis
@ 2013-03-25 21:11 ` Jason Wessel
0 siblings, 0 replies; 21+ messages in thread
From: Jason Wessel @ 2013-03-25 21:11 UTC (permalink / raw)
To: Mike Travis
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, David Howells
On 03/25/2013 01:50 PM, Mike Travis wrote:
> The KDB 'btc' (backtrace cpus) command ignores the 'quit' reply
> to the 'more>' prompt. This is quite annoying when you have a
> large number of processors and thousands of lines are being
> printed. This fixes that problem.
>
Merged to kgdb-next and added as a cc to -stable.
I'll be working my way through the rest of the patches in the series you sent and I'll merge anything that is going to -stable in the 3.9 series toward the end of the week assuming everything passes regression testing, and the rest will go into the 3.10 merge window.
Cheers,
Jason.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 03/15] KDB: up the default LINES value
2013-03-25 18:50 ` [PATCH 03/15] KDB: up the default LINES value Mike Travis
@ 2013-03-25 21:22 ` Jason Wessel
2013-03-25 21:31 ` Mike Travis
0 siblings, 1 reply; 21+ messages in thread
From: Jason Wessel @ 2013-03-25 21:22 UTC (permalink / raw)
To: Mike Travis
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird
On 03/25/2013 01:50 PM, Mike Travis wrote:
> Currently the default for the # of lines displayed by the KDB pager
> is 24. This does not allow all of the lines for the entry messages,
> reg dump and process trace. Increase it to something more reasonable.
>
Unfortunately this is something that breaks compatibility with the
standard VGA console, so this patch will not be merged.
Is it the case that your hardware specifies how many lines and columns
there are in the display? We have some hooks into the console VT code
to properly detect this but perhaps something is wrong there, or it is
only called in the KMS (kernel mode setting case). Example:
drivers/tty/vt/vt.c - look at con_debug_enter()
Another option might be to add a variable which allows you to change
the default at compile time, but I would prefer to get the auto detect
code working properly if it is an option.
Jason.
> Cc: Tim Bird <tim.bird@am.sony.com>
> Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
> Signed-off-by: Mike Travis <travis@sgi.com>
> ---
> kernel/debug/kdb/kdb_io.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> --- linux.orig/kernel/debug/kdb/kdb_io.c
> +++ linux/kernel/debug/kdb/kdb_io.c
> @@ -586,7 +586,7 @@ int vkdb_printf(const char *fmt, va_list
>
> diag = kdbgetintenv("LINES", &linecount);
> if (diag || linecount <= 1)
> - linecount = 24;
> + linecount = 60;
>
> diag = kdbgetintenv("COLUMNS", &colcount);
> if (diag || colcount <= 1)
>
> --
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 03/15] KDB: up the default LINES value
2013-03-25 21:22 ` Jason Wessel
@ 2013-03-25 21:31 ` Mike Travis
0 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-25 21:31 UTC (permalink / raw)
To: Jason Wessel
Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andrew Morton,
kgdb-bugreport, x86, linux-kernel, Tim Bird
On 3/25/2013 2:22 PM, Jason Wessel wrote:
> On 03/25/2013 01:50 PM, Mike Travis wrote:
>> Currently the default for the # of lines displayed by the KDB pager
>> is 24. This does not allow all of the lines for the entry messages,
>> reg dump and process trace. Increase it to something more reasonable.
>>
>
>
> Unfortunately this is something that breaks compatibility with the
> standard VGA console, so this patch will not be merged.
>
> Is it the case that your hardware specifies how many lines and columns
> there are in the display? We have some hooks into the console VT code
> to properly detect this but perhaps something is wrong there, or it is
> only called in the KMS (kernel mode setting case). Example:
> drivers/tty/vt/vt.c - look at con_debug_enter()
>
> Another option might be to add a variable which allows you to change
> the default at compile time, but I would prefer to get the auto detect
> code working properly if it is an option.
>
> Jason.
Nah, this was more of an annoyance before I added the "system nmi" entry
reason code, which changes the entry message to be more like it is for a
requested entry (like sysreq 'g') than it is for a real error which
dumps a ton of stuff. Our primary system console is a serial connection,
so we can't use the VT stuff (though the VT console is an option).
>
>
>
>> Cc: Tim Bird <tim.bird@am.sony.com>
>> Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
>> Signed-off-by: Mike Travis <travis@sgi.com>
>> ---
>> kernel/debug/kdb/kdb_io.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> --- linux.orig/kernel/debug/kdb/kdb_io.c
>> +++ linux/kernel/debug/kdb/kdb_io.c
>> @@ -586,7 +586,7 @@ int vkdb_printf(const char *fmt, va_list
>>
>> diag = kdbgetintenv("LINES", &linecount);
>> if (diag || linecount <= 1)
>> - linecount = 24;
>> + linecount = 60;
>>
>> diag = kdbgetintenv("COLUMNS", &colcount);
>> if (diag || colcount <= 1)
>>
>> --
>>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 05/15] KDB: add more exports for supporting KDB modules v2
2013-03-25 18:50 ` [PATCH 05/15] KDB: add more exports for supporting KDB modules v2 Mike Travis
@ 2013-03-26 2:38 ` Eric W. Biederman
2013-03-26 4:19 ` Mike Travis
0 siblings, 1 reply; 21+ messages in thread
From: Eric W. Biederman @ 2013-03-26 2:38 UTC (permalink / raw)
To: Mike Travis
Cc: Jason Wessel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner,
Andrew Morton, kgdb-bugreport, x86, linux-kernel, Tim Bird,
Anton Vorontsov, Sasha Levin, Rusty Russell, Greg Kroah-Hartman,
Cong Wang, Stephen Boyd, Al Viro, Oleg Nesterov, Serge Hallyn
Mike Travis <travis@sgi.com> writes:
> This patch adds some significant KDB functions to be usable by
> externally built and loadable KDB modules. All added functions
> have been marked EXPORT_SYMBOL_GPL as that seems to be the norm.
> No 'EXPORT_SYMBOL's were changed from previous instances to avoid
> breaking existing modules.
I don't have any real objections. Although the export of kallsyms
probably is enough to raise an eyebrow or two.
Are there plans for these external modules to be merged?
In general the policy is to not export things unless there are in tree
users. Otherwise maitenance can be a challenge if you can't update your
users when you update their helper functions. Certainly a symbol being
exported is not a guarantee that the exported function won't be changed.
Eric
> Cc: Tim Bird <tim.bird@am.sony.com>
> Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
> Cc: Sasha Levin <sasha.levin@oracle.com>
> Cc: Rusty Russell <rusty@rustcorp.com.au>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Cong Wang <amwang@redhat.com>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Al Viro <viro@zeniv.linux.org.uk>
> Cc: Oleg Nesterov <oleg@redhat.com>
> Cc: Eric W. Biederman <ebiederm@xmission.com>
> Cc: Serge Hallyn <serge.hallyn@canonical.com>
> Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
> Signed-off-by: Mike Travis <travis@sgi.com>
> ---
> v2: change in handling of EXPORT_SYMBOLS.
> ---
> kernel/debug/kdb/kdb_io.c | 3 +++
> kernel/debug/kdb/kdb_main.c | 14 ++++++++++++++
> kernel/debug/kdb/kdb_support.c | 17 +++++++++++++++++
> kernel/kallsyms.c | 1 +
> 4 files changed, 35 insertions(+)
>
> --- linux.orig/kernel/debug/kdb/kdb_io.c
> +++ linux/kernel/debug/kdb/kdb_io.c
> @@ -30,6 +30,7 @@
> char kdb_prompt_str[CMD_BUFLEN];
>
> int kdb_trap_printk;
> +EXPORT_SYMBOL_GPL(kdb_trap_printk);
>
> static int kgdb_transition_check(char *buffer)
> {
> @@ -447,6 +448,7 @@ char *kdb_getstr(char *buffer, size_t bu
> kdb_nextline = 1; /* Prompt and input resets line number */
> return kdb_read(buffer, bufsize);
> }
> +EXPORT_SYMBOL_GPL(kdb_getstr);
>
> /*
> * kdb_input_flush
> @@ -839,6 +841,7 @@ kdb_print_out:
> preempt_enable();
> return retlen;
> }
> +EXPORT_SYMBOL_GPL(vkdb_printf);
>
> int kdb_printf(const char *fmt, ...)
> {
> --- linux.orig/kernel/debug/kdb/kdb_main.c
> +++ linux/kernel/debug/kdb/kdb_main.c
> @@ -53,6 +53,7 @@ int kdb_grep_trailing;
> * Kernel debugger state flags
> */
> int kdb_flags;
> +EXPORT_SYMBOL_GPL(kdb_flags);
> atomic_t kdb_event;
>
> /*
> @@ -60,12 +61,14 @@ atomic_t kdb_event;
> * single thread processors through the kernel debugger.
> */
> int kdb_initial_cpu = -1; /* cpu number that owns kdb */
> +EXPORT_SYMBOL_GPL(kdb_initial_cpu);
> int kdb_nextline = 1;
> int kdb_state; /* General KDB state */
>
> struct task_struct *kdb_current_task;
> EXPORT_SYMBOL(kdb_current_task);
> struct pt_regs *kdb_current_regs;
> +EXPORT_SYMBOL_GPL(kdb_current_regs);
>
> const char *kdb_diemsg;
> static int kdb_go_count;
> @@ -186,6 +189,7 @@ struct task_struct *kdb_curr_task(int cp
> #endif
> return p;
> }
> +EXPORT_SYMBOL_GPL(kdb_curr_task);
>
> /*
> * kdbgetenv - This function will return the character string value of
> @@ -217,6 +221,7 @@ char *kdbgetenv(const char *match)
> }
> return NULL;
> }
> +EXPORT_SYMBOL_GPL(kdbgetenv);
>
> /*
> * kdballocenv - This function is used to allocate bytes for
> @@ -293,6 +298,7 @@ int kdbgetintenv(const char *match, int
> *value = (int) val;
> return diag;
> }
> +EXPORT_SYMBOL_GPL(kdbgetintenv);
>
> /*
> * kdbgetularg - This function will convert a numeric string into an
> @@ -325,6 +331,7 @@ int kdbgetularg(const char *arg, unsigne
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(kdbgetularg);
>
> int kdbgetu64arg(const char *arg, u64 *value)
> {
> @@ -344,6 +351,7 @@ int kdbgetu64arg(const char *arg, u64 *v
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(kdbgetu64arg);
>
> /*
> * kdb_set - This function implements the 'set' command. Alter an
> @@ -425,6 +433,7 @@ int kdb_set(int argc, const char **argv)
>
> return KDB_ENVFULL;
> }
> +EXPORT_SYMBOL_GPL(kdb_set);
>
> static int kdb_check_regs(void)
> {
> @@ -585,6 +594,7 @@ int kdbgetaddrarg(int argc, const char *
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(kdbgetaddrarg);
>
> static void kdb_cmderror(int diag)
> {
> @@ -1049,6 +1059,7 @@ int kdb_parse(const char *cmdstr)
> return 0;
> }
> }
> +EXPORT_SYMBOL_GPL(kdb_parse);
>
>
> static int handle_ctrl_cmd(char *cmd)
> @@ -1109,6 +1120,7 @@ void kdb_set_current_task(struct task_st
> }
> kdb_current_regs = NULL;
> }
> +EXPORT_SYMBOL_GPL(kdb_set_current_task);
>
> /*
> * kdb_local - The main code for kdb. This routine is invoked on a
> @@ -2249,6 +2261,7 @@ void kdb_ps_suppressed(void)
> kdb_printf(" suppressed,\nuse 'ps A' to see all.\n");
> }
> }
> +EXPORT_SYMBOL_GPL(kdb_ps_suppressed);
>
> /*
> * kdb_ps - This function implements the 'ps' command which shows a
> @@ -2281,6 +2294,7 @@ void kdb_ps1(const struct task_struct *p
> }
> }
> }
> +EXPORT_SYMBOL_GPL(kdb_ps1);
>
> static int kdb_ps(int argc, const char **argv)
> {
> --- linux.orig/kernel/debug/kdb/kdb_support.c
> +++ linux/kernel/debug/kdb/kdb_support.c
> @@ -157,6 +157,7 @@ out:
> debug_kfree(knt1);
> return ret;
> }
> +EXPORT_SYMBOL_GPL(kdbnearsym);
>
> void kdbnearsym_cleanup(void)
> {
> @@ -168,6 +169,7 @@ void kdbnearsym_cleanup(void)
> }
> }
> }
> +EXPORT_SYMBOL_GPL(kdbnearsym_cleanup);
>
> static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
>
> @@ -214,6 +216,7 @@ int kallsyms_symbol_complete(char *prefi
> memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
> return number;
> }
> +EXPORT_SYMBOL_GPL(kallsyms_symbol_complete);
>
> /*
> * kallsyms_symbol_next
> @@ -242,6 +245,7 @@ int kallsyms_symbol_next(char *prefix_na
> }
> return 0;
> }
> +EXPORT_SYMBOL_GPL(kallsyms_symbol_next);
>
> /*
> * kdb_symbol_print - Standard method for printing a symbol name and offset.
> @@ -292,6 +296,7 @@ void kdb_symbol_print(unsigned long addr
> if (punc & KDB_SP_NEWLINE)
> kdb_printf("\n");
> }
> +EXPORT_SYMBOL_GPL(kdb_symbol_print);
>
> /*
> * kdb_strdup - kdb equivalent of strdup, for disasm code.
> @@ -312,6 +317,7 @@ char *kdb_strdup(const char *str, gfp_t
> return NULL;
> return strcpy(s, str);
> }
> +EXPORT_SYMBOL_GPL(kdb_strdup);
>
> /*
> * kdb_getarea_size - Read an area of data. The kdb equivalent of
> @@ -337,6 +343,7 @@ int kdb_getarea_size(void *res, unsigned
> }
> return ret;
> }
> +EXPORT_SYMBOL_GPL(kdb_getarea_size);
>
> /*
> * kdb_putarea_size - Write an area of data. The kdb equivalent of
> @@ -362,6 +369,7 @@ int kdb_putarea_size(unsigned long addr,
> }
> return ret;
> }
> +EXPORT_SYMBOL_GPL(kdb_putarea_size);
>
> /*
> * kdb_getphys - Read data from a physical address. Validate the
> @@ -439,6 +447,7 @@ int kdb_getphysword(unsigned long *word,
> }
> return diag;
> }
> +EXPORT_SYMBOL_GPL(kdb_getphysword);
>
> /*
> * kdb_getword - Read a binary value. Unlike kdb_getarea, this treats
> @@ -488,6 +497,7 @@ int kdb_getword(unsigned long *word, uns
> }
> return diag;
> }
> +EXPORT_SYMBOL_GPL(kdb_getword);
>
> /*
> * kdb_putword - Write a binary value. Unlike kdb_putarea, this
> @@ -532,6 +542,7 @@ int kdb_putword(unsigned long addr, unsi
> }
> return diag;
> }
> +EXPORT_SYMBOL_GPL(kdb_putword);
>
> /*
> * kdb_task_state_string - Convert a string containing any of the
> @@ -681,6 +692,7 @@ void kdb_print_nameval(const char *name,
> else
> kdb_printf("0x%lx\n", val);
> }
> +EXPORT_SYMBOL_GPL(kdb_print_nameval);
>
> /* Last ditch allocator for debugging, so we can still debug even when
> * the GFP_ATOMIC pool has been exhausted. The algorithms are tuned
> @@ -799,6 +811,7 @@ out:
> spin_unlock(&dap_lock);
> return p;
> }
> +EXPORT_SYMBOL_GPL(debug_kmalloc);
>
> void debug_kfree(void *p)
> {
> @@ -858,6 +871,7 @@ void debug_kfree(void *p)
> }
> spin_unlock(&dap_lock);
> }
> +EXPORT_SYMBOL_GPL(debug_kfree);
>
> void debug_kusage(void)
> {
> @@ -907,6 +921,7 @@ void debug_kusage(void)
> out:
> spin_unlock(&dap_lock);
> }
> +EXPORT_SYMBOL_GPL(debug_kusage);
>
> /* Maintain a small stack of kdb_flags to allow recursion without disturbing
> * the global kdb state.
> @@ -919,9 +934,11 @@ void kdb_save_flags(void)
> BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack));
> kdb_flags_stack[kdb_flags_index++] = kdb_flags;
> }
> +EXPORT_SYMBOL_GPL(kdb_save_flags);
>
> void kdb_restore_flags(void)
> {
> BUG_ON(kdb_flags_index <= 0);
> kdb_flags = kdb_flags_stack[--kdb_flags_index];
> }
> +EXPORT_SYMBOL_GPL(kdb_restore_flags);
> --- linux.orig/kernel/kallsyms.c
> +++ linux/kernel/kallsyms.c
> @@ -588,6 +588,7 @@ const char *kdb_walk_kallsyms(loff_t *po
> }
> }
> #endif /* CONFIG_KGDB_KDB */
> +EXPORT_SYMBOL_GPL(kdb_walk_kallsyms);
>
> static const struct file_operations kallsyms_operations = {
> .open = kallsyms_open,
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 05/15] KDB: add more exports for supporting KDB modules v2
2013-03-26 2:38 ` Eric W. Biederman
@ 2013-03-26 4:19 ` Mike Travis
0 siblings, 0 replies; 21+ messages in thread
From: Mike Travis @ 2013-03-26 4:19 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Jason Wessel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner,
Andrew Morton, kgdb-bugreport, x86, linux-kernel, Tim Bird,
Anton Vorontsov, Sasha Levin, Rusty Russell, Greg Kroah-Hartman,
Cong Wang, Stephen Boyd, Al Viro, Oleg Nesterov, Serge Hallyn
On 3/25/2013 7:38 PM, Eric W. Biederman wrote:
> Mike Travis <travis@sgi.com> writes:
>
>> This patch adds some significant KDB functions to be usable by
>> externally built and loadable KDB modules. All added functions
>> have been marked EXPORT_SYMBOL_GPL as that seems to be the norm.
>> No 'EXPORT_SYMBOL's were changed from previous instances to avoid
>> breaking existing modules.
>
> I don't have any real objections. Although the export of kallsyms
> probably is enough to raise an eyebrow or two.
>
> Are there plans for these external modules to be merged?
>
> In general the policy is to not export things unless there are in tree
> users. Otherwise maitenance can be a challenge if you can't update your
> users when you update their helper functions. Certainly a symbol being
> exported is not a guarantee that the exported function won't be changed.
>
> Eric
I have a few of the older KDB modules converted to be built as
regular external kernel modules but I wasn't certain if they would be
accepted into the base kernel source tree. Both kdbm_dereference.c
and kdbm_debugtypes.c are there which support the following kdb cmds:
"print", "<expression>", "Type casting as in lcrash"
"px", "<expression>", "Print in hex (type casting) (see 'pxhelp')"
"whatis", or symbol>", "Display the type, or the address for a symbol"
"sizeof", "<type>", "Display the size of a structure, typedef, etc."
"pxhelp", "", "Display help for the px command"
"walk", "<expression>", "Walk linked structs (see walkhelp)",
"walkhelp", "", "Display help for the walk command"
These essentially use the kernel symtab to print structure members,
and to walk linked structures from within KDB. That was the primary
motivation for moving the ksymtab stuff to be externally exported.
It currently has a couple of problems but here's an example:
[8]kdb> md8c1 kdb_current_task
0xffffffff81c8ed00 ffff88081d714bf0 .Kq.....
[8]kdb> px *(task_struct *)0xffff88081d714bf0
struct task_struct {
state = 0x0
stack = 0xffff88081d71a000
usage = atomic_t {
counter = 0x2
}
flags = 0x10202040
ptrace = 0x0
wake_entry = struct llist_node {
next = (nil)
}
...
(First 'kdb_current_task' should have been taken as the argument to
the px cmd, and second the printout does not stop with 'q' to the
"more>" prompt.) I will sign up to merge these if there is interest?
Thanks,
Mike
>
>> Cc: Tim Bird <tim.bird@am.sony.com>
>> Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
>> Cc: Sasha Levin <sasha.levin@oracle.com>
>> Cc: Rusty Russell <rusty@rustcorp.com.au>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: Cong Wang <amwang@redhat.com>
>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> Cc: Al Viro <viro@zeniv.linux.org.uk>
>> Cc: Oleg Nesterov <oleg@redhat.com>
>> Cc: Eric W. Biederman <ebiederm@xmission.com>
>> Cc: Serge Hallyn <serge.hallyn@canonical.com>
>> Reviewed-by: Dimitri Sivanich <sivanich@sgi.com>
>> Signed-off-by: Mike Travis <travis@sgi.com>
>> ---
>> v2: change in handling of EXPORT_SYMBOLS.
>> ---
>> kernel/debug/kdb/kdb_io.c | 3 +++
>> kernel/debug/kdb/kdb_main.c | 14 ++++++++++++++
>> kernel/debug/kdb/kdb_support.c | 17 +++++++++++++++++
>> kernel/kallsyms.c | 1 +
>> 4 files changed, 35 insertions(+)
>>
>> --- linux.orig/kernel/debug/kdb/kdb_io.c
>> +++ linux/kernel/debug/kdb/kdb_io.c
>> @@ -30,6 +30,7 @@
>> char kdb_prompt_str[CMD_BUFLEN];
>>
>> int kdb_trap_printk;
>> +EXPORT_SYMBOL_GPL(kdb_trap_printk);
>>
>> static int kgdb_transition_check(char *buffer)
>> {
>> @@ -447,6 +448,7 @@ char *kdb_getstr(char *buffer, size_t bu
>> kdb_nextline = 1; /* Prompt and input resets line number */
>> return kdb_read(buffer, bufsize);
>> }
>> +EXPORT_SYMBOL_GPL(kdb_getstr);
>>
>> /*
>> * kdb_input_flush
>> @@ -839,6 +841,7 @@ kdb_print_out:
>> preempt_enable();
>> return retlen;
>> }
>> +EXPORT_SYMBOL_GPL(vkdb_printf);
>>
>> int kdb_printf(const char *fmt, ...)
>> {
>> --- linux.orig/kernel/debug/kdb/kdb_main.c
>> +++ linux/kernel/debug/kdb/kdb_main.c
>> @@ -53,6 +53,7 @@ int kdb_grep_trailing;
>> * Kernel debugger state flags
>> */
>> int kdb_flags;
>> +EXPORT_SYMBOL_GPL(kdb_flags);
>> atomic_t kdb_event;
>>
>> /*
>> @@ -60,12 +61,14 @@ atomic_t kdb_event;
>> * single thread processors through the kernel debugger.
>> */
>> int kdb_initial_cpu = -1; /* cpu number that owns kdb */
>> +EXPORT_SYMBOL_GPL(kdb_initial_cpu);
>> int kdb_nextline = 1;
>> int kdb_state; /* General KDB state */
>>
>> struct task_struct *kdb_current_task;
>> EXPORT_SYMBOL(kdb_current_task);
>> struct pt_regs *kdb_current_regs;
>> +EXPORT_SYMBOL_GPL(kdb_current_regs);
>>
>> const char *kdb_diemsg;
>> static int kdb_go_count;
>> @@ -186,6 +189,7 @@ struct task_struct *kdb_curr_task(int cp
>> #endif
>> return p;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_curr_task);
>>
>> /*
>> * kdbgetenv - This function will return the character string value of
>> @@ -217,6 +221,7 @@ char *kdbgetenv(const char *match)
>> }
>> return NULL;
>> }
>> +EXPORT_SYMBOL_GPL(kdbgetenv);
>>
>> /*
>> * kdballocenv - This function is used to allocate bytes for
>> @@ -293,6 +298,7 @@ int kdbgetintenv(const char *match, int
>> *value = (int) val;
>> return diag;
>> }
>> +EXPORT_SYMBOL_GPL(kdbgetintenv);
>>
>> /*
>> * kdbgetularg - This function will convert a numeric string into an
>> @@ -325,6 +331,7 @@ int kdbgetularg(const char *arg, unsigne
>>
>> return 0;
>> }
>> +EXPORT_SYMBOL_GPL(kdbgetularg);
>>
>> int kdbgetu64arg(const char *arg, u64 *value)
>> {
>> @@ -344,6 +351,7 @@ int kdbgetu64arg(const char *arg, u64 *v
>>
>> return 0;
>> }
>> +EXPORT_SYMBOL_GPL(kdbgetu64arg);
>>
>> /*
>> * kdb_set - This function implements the 'set' command. Alter an
>> @@ -425,6 +433,7 @@ int kdb_set(int argc, const char **argv)
>>
>> return KDB_ENVFULL;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_set);
>>
>> static int kdb_check_regs(void)
>> {
>> @@ -585,6 +594,7 @@ int kdbgetaddrarg(int argc, const char *
>>
>> return 0;
>> }
>> +EXPORT_SYMBOL_GPL(kdbgetaddrarg);
>>
>> static void kdb_cmderror(int diag)
>> {
>> @@ -1049,6 +1059,7 @@ int kdb_parse(const char *cmdstr)
>> return 0;
>> }
>> }
>> +EXPORT_SYMBOL_GPL(kdb_parse);
>>
>>
>> static int handle_ctrl_cmd(char *cmd)
>> @@ -1109,6 +1120,7 @@ void kdb_set_current_task(struct task_st
>> }
>> kdb_current_regs = NULL;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_set_current_task);
>>
>> /*
>> * kdb_local - The main code for kdb. This routine is invoked on a
>> @@ -2249,6 +2261,7 @@ void kdb_ps_suppressed(void)
>> kdb_printf(" suppressed,\nuse 'ps A' to see all.\n");
>> }
>> }
>> +EXPORT_SYMBOL_GPL(kdb_ps_suppressed);
>>
>> /*
>> * kdb_ps - This function implements the 'ps' command which shows a
>> @@ -2281,6 +2294,7 @@ void kdb_ps1(const struct task_struct *p
>> }
>> }
>> }
>> +EXPORT_SYMBOL_GPL(kdb_ps1);
>>
>> static int kdb_ps(int argc, const char **argv)
>> {
>> --- linux.orig/kernel/debug/kdb/kdb_support.c
>> +++ linux/kernel/debug/kdb/kdb_support.c
>> @@ -157,6 +157,7 @@ out:
>> debug_kfree(knt1);
>> return ret;
>> }
>> +EXPORT_SYMBOL_GPL(kdbnearsym);
>>
>> void kdbnearsym_cleanup(void)
>> {
>> @@ -168,6 +169,7 @@ void kdbnearsym_cleanup(void)
>> }
>> }
>> }
>> +EXPORT_SYMBOL_GPL(kdbnearsym_cleanup);
>>
>> static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1];
>>
>> @@ -214,6 +216,7 @@ int kallsyms_symbol_complete(char *prefi
>> memcpy(prefix_name, ks_namebuf_prev, prev_len+1);
>> return number;
>> }
>> +EXPORT_SYMBOL_GPL(kallsyms_symbol_complete);
>>
>> /*
>> * kallsyms_symbol_next
>> @@ -242,6 +245,7 @@ int kallsyms_symbol_next(char *prefix_na
>> }
>> return 0;
>> }
>> +EXPORT_SYMBOL_GPL(kallsyms_symbol_next);
>>
>> /*
>> * kdb_symbol_print - Standard method for printing a symbol name and offset.
>> @@ -292,6 +296,7 @@ void kdb_symbol_print(unsigned long addr
>> if (punc & KDB_SP_NEWLINE)
>> kdb_printf("\n");
>> }
>> +EXPORT_SYMBOL_GPL(kdb_symbol_print);
>>
>> /*
>> * kdb_strdup - kdb equivalent of strdup, for disasm code.
>> @@ -312,6 +317,7 @@ char *kdb_strdup(const char *str, gfp_t
>> return NULL;
>> return strcpy(s, str);
>> }
>> +EXPORT_SYMBOL_GPL(kdb_strdup);
>>
>> /*
>> * kdb_getarea_size - Read an area of data. The kdb equivalent of
>> @@ -337,6 +343,7 @@ int kdb_getarea_size(void *res, unsigned
>> }
>> return ret;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_getarea_size);
>>
>> /*
>> * kdb_putarea_size - Write an area of data. The kdb equivalent of
>> @@ -362,6 +369,7 @@ int kdb_putarea_size(unsigned long addr,
>> }
>> return ret;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_putarea_size);
>>
>> /*
>> * kdb_getphys - Read data from a physical address. Validate the
>> @@ -439,6 +447,7 @@ int kdb_getphysword(unsigned long *word,
>> }
>> return diag;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_getphysword);
>>
>> /*
>> * kdb_getword - Read a binary value. Unlike kdb_getarea, this treats
>> @@ -488,6 +497,7 @@ int kdb_getword(unsigned long *word, uns
>> }
>> return diag;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_getword);
>>
>> /*
>> * kdb_putword - Write a binary value. Unlike kdb_putarea, this
>> @@ -532,6 +542,7 @@ int kdb_putword(unsigned long addr, unsi
>> }
>> return diag;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_putword);
>>
>> /*
>> * kdb_task_state_string - Convert a string containing any of the
>> @@ -681,6 +692,7 @@ void kdb_print_nameval(const char *name,
>> else
>> kdb_printf("0x%lx\n", val);
>> }
>> +EXPORT_SYMBOL_GPL(kdb_print_nameval);
>>
>> /* Last ditch allocator for debugging, so we can still debug even when
>> * the GFP_ATOMIC pool has been exhausted. The algorithms are tuned
>> @@ -799,6 +811,7 @@ out:
>> spin_unlock(&dap_lock);
>> return p;
>> }
>> +EXPORT_SYMBOL_GPL(debug_kmalloc);
>>
>> void debug_kfree(void *p)
>> {
>> @@ -858,6 +871,7 @@ void debug_kfree(void *p)
>> }
>> spin_unlock(&dap_lock);
>> }
>> +EXPORT_SYMBOL_GPL(debug_kfree);
>>
>> void debug_kusage(void)
>> {
>> @@ -907,6 +921,7 @@ void debug_kusage(void)
>> out:
>> spin_unlock(&dap_lock);
>> }
>> +EXPORT_SYMBOL_GPL(debug_kusage);
>>
>> /* Maintain a small stack of kdb_flags to allow recursion without disturbing
>> * the global kdb state.
>> @@ -919,9 +934,11 @@ void kdb_save_flags(void)
>> BUG_ON(kdb_flags_index >= ARRAY_SIZE(kdb_flags_stack));
>> kdb_flags_stack[kdb_flags_index++] = kdb_flags;
>> }
>> +EXPORT_SYMBOL_GPL(kdb_save_flags);
>>
>> void kdb_restore_flags(void)
>> {
>> BUG_ON(kdb_flags_index <= 0);
>> kdb_flags = kdb_flags_stack[--kdb_flags_index];
>> }
>> +EXPORT_SYMBOL_GPL(kdb_restore_flags);
>> --- linux.orig/kernel/kallsyms.c
>> +++ linux/kernel/kallsyms.c
>> @@ -588,6 +588,7 @@ const char *kdb_walk_kallsyms(loff_t *po
>> }
>> }
>> #endif /* CONFIG_KGDB_KDB */
>> +EXPORT_SYMBOL_GPL(kdb_walk_kallsyms);
>>
>> static const struct file_operations kallsyms_operations = {
>> .open = kallsyms_open,
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2013-03-26 4:19 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-25 18:50 [PATCH 00/15] x86/UV/KDB/NMI: Updates for NMI/KDB handler for SGI UV Mike Travis
2013-03-25 18:50 ` [PATCH 01/15] KDB: fix the interrupt of the KDB btc command Mike Travis
2013-03-25 21:11 ` Jason Wessel
2013-03-25 18:50 ` [PATCH 02/15] KDB: fix errant character in KDB show regs Mike Travis
2013-03-25 18:50 ` [PATCH 03/15] KDB: up the default LINES value Mike Travis
2013-03-25 21:22 ` Jason Wessel
2013-03-25 21:31 ` Mike Travis
2013-03-25 18:50 ` [PATCH 04/15] KDB: allow KDB modules to be external modules Mike Travis
2013-03-25 18:50 ` [PATCH 05/15] KDB: add more exports for supporting KDB modules v2 Mike Travis
2013-03-26 2:38 ` Eric W. Biederman
2013-03-26 4:19 ` Mike Travis
2013-03-25 18:50 ` [PATCH 06/15] KDB: consolidate KDB grep code Mike Travis
2013-03-25 18:50 ` [PATCH 07/15] KDB: clean up KDB grep code, add some options Mike Travis
2013-03-25 18:50 ` [PATCH 08/15] KDB: Restore call to kdump from KDB Mike Travis
2013-03-25 18:50 ` [PATCH 09/15] KDB: Add pshelp command Mike Travis
2013-03-25 18:50 ` [PATCH 10/15] KGDB/KDB: add support for external NMI handler to call KGDB/KDB Mike Travis
2013-03-25 18:50 ` [PATCH 11/15] KDB: add new system NMI entry code to KDB Mike Travis
2013-03-25 18:50 ` [PATCH 12/15] x86/UV: Move NMI support Mike Travis
2013-03-25 18:50 ` [PATCH 13/15] x86/UV: Add uvtrace support Mike Travis
2013-03-25 18:50 ` [PATCH 14/15] x86/UV: Update UV support for external NMI signals Mike Travis
2013-03-25 18:50 ` [PATCH 15/15] x86/UV: Add call to KGDB/KDB from NMI handler Mike Travis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox