qubes-linux-kernel/patches.arch/ppc64-xmon-dmesg-printing.patch
2011-04-19 22:09:59 +02:00

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