120 lines
3.3 KiB
Diff
120 lines
3.3 KiB
Diff
Subject: [PATCH] add syslog printing to xmon debugger.
|
|
From: Linas Vepstas <linas@austin.ibm.com>
|
|
Patch-mainline: Not yet
|
|
|
|
|
|
This patch 'dmesg'/printk log buffer printing to xmon. I find this
|
|
useful because crashes are almost always preceeded by interesting
|
|
printk's. This patch is simple & straightforward, except for one
|
|
possibly controversial aspect: it embeds a small snippet in
|
|
kernel/printk.c to return the location of the syslog. This is
|
|
needed because kallsyms and even CONFIG_KALLSYMS_ALL is not enough
|
|
to reveal the location of log_buf. This code is about 90%
|
|
cut-n-paste of earlier code from Keith Owens.
|
|
|
|
Signed-off-by: Olaf Hering <olh@suse.de>
|
|
---
|
|
|
|
arch/powerpc/xmon/xmon.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
kernel/printk.c | 2 -
|
|
2 files changed, 58 insertions(+), 1 deletion(-)
|
|
|
|
--- a/arch/powerpc/xmon/xmon.c
|
|
+++ b/arch/powerpc/xmon/xmon.c
|
|
@@ -138,6 +138,7 @@ static struct bpt *in_breakpoint_table(u
|
|
static int do_step(struct pt_regs *);
|
|
static void bpt_cmds(void);
|
|
static void cacheflush(void);
|
|
+static void xmon_show_dmesg(void);
|
|
static int cpu_cmd(void);
|
|
static void csum(void);
|
|
static void bootcmds(void);
|
|
@@ -197,6 +198,7 @@ Commands:\n\
|
|
#endif
|
|
"\
|
|
C checksum\n\
|
|
+ D show dmesg (printk) buffer\n\
|
|
d dump bytes\n\
|
|
di dump instructions\n\
|
|
df dump float values\n\
|
|
@@ -831,6 +833,9 @@ cmds(struct pt_regs *excp)
|
|
case 'd':
|
|
dump();
|
|
break;
|
|
+ case 'D':
|
|
+ xmon_show_dmesg();
|
|
+ break;
|
|
case 'l':
|
|
symbol_lookup();
|
|
break;
|
|
@@ -2607,6 +2612,58 @@ static void xmon_print_symbol(unsigned l
|
|
printf("%s", after);
|
|
}
|
|
|
|
+extern void kdb_syslog_data(char *syslog_data[]);
|
|
+#define SYSLOG_WRAP(p) if (p < syslog_data[0]) p = syslog_data[1]-1; \
|
|
+ else if (p >= syslog_data[1]) p = syslog_data[0];
|
|
+
|
|
+static void xmon_show_dmesg(void)
|
|
+{
|
|
+ char *syslog_data[4], *start, *end, c;
|
|
+ int logsize;
|
|
+
|
|
+ /* syslog_data[0,1] physical start, end+1.
|
|
+ * syslog_data[2,3] logical start, end+1.
|
|
+ */
|
|
+ kdb_syslog_data(syslog_data);
|
|
+ if (syslog_data[2] == syslog_data[3])
|
|
+ return;
|
|
+ logsize = syslog_data[1] - syslog_data[0];
|
|
+ start = syslog_data[0] + (syslog_data[2] - syslog_data[0]) % logsize;
|
|
+ end = syslog_data[0] + (syslog_data[3] - syslog_data[0]) % logsize;
|
|
+
|
|
+ /* Do a line at a time (max 200 chars) to reduce overhead */
|
|
+ c = '\0';
|
|
+ while(1) {
|
|
+ char *p;
|
|
+ int chars = 0;
|
|
+ if (!*start) {
|
|
+ while (!*start) {
|
|
+ ++start;
|
|
+ SYSLOG_WRAP(start);
|
|
+ if (start == end)
|
|
+ break;
|
|
+ }
|
|
+ if (start == end)
|
|
+ break;
|
|
+ }
|
|
+ p = start;
|
|
+ while (*start && chars < 200) {
|
|
+ c = *start;
|
|
+ ++chars;
|
|
+ ++start;
|
|
+ SYSLOG_WRAP(start);
|
|
+ if (start == end || c == '\n')
|
|
+ break;
|
|
+ }
|
|
+ if (chars)
|
|
+ printf("%.*s", chars, p);
|
|
+ if (start == end)
|
|
+ break;
|
|
+ }
|
|
+ if (c != '\n')
|
|
+ printf("\n");
|
|
+}
|
|
+
|
|
#ifdef CONFIG_PPC_BOOK3S_64
|
|
static void dump_slb(void)
|
|
{
|
|
--- a/kernel/printk.c
|
|
+++ b/kernel/printk.c
|
|
@@ -416,7 +416,7 @@ SYSCALL_DEFINE3(syslog, int, type, char
|
|
return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
|
|
}
|
|
|
|
-#ifdef CONFIG_KGDB_KDB
|
|
+#if defined(CONFIG_KGDB_KDB) || defined(CONFIG_DEBUG_KERNEL)
|
|
/* kdb dmesg command needs access to the syslog buffer. do_syslog()
|
|
* uses locks so it cannot be used during debugging. Just tell kdb
|
|
* where the start and end of the physical and logical logs are. This
|